How to align std :: array data?

Since std::array does not allow changing its allocator, is there a way to make sure that the pointer to the data address is aligned?

For example, in GNU g ++ 4.8.4 and 6.1.0, the code is below

 #include <array> #include <iostream> int main(void) { std::array<bool, 10> a; std::array<char, 10> b; std::array<int,10> c; std::array<long long, 10> d; std::array<float, 10> e; std::array<double, 10> f; std::cout << "array<bool,10>.data() = " << a.data() << std::endl; std::cout << "array<char,10>.data() = " << (void*) b.data() << std::endl; std::cout << "array<int,10>.data() = " << c.data() << std::endl; std::cout << "array<long long, 10>.data() = " << d.data() << std::endl; std::cout << "array<float, 10>.data() = " << e.data() << std::endl; std::cout << "array<double, 10>.data() = " << f.data() << std::endl; return 0; } 

provides the following output, which shows that the container data is aligned at 16-byte addresses regardless of the type of data contained during compilation for the x86-64 bit architecture.

 array<bool,10>.data() = 0x7ffe660a2e40 array<char,10>.data() = 0x7ffe660a2e30 array<int,10>.data() = 0x7ffe660a2e00 array<long long, 10>.data() = 0x7ffe660a2db0 array<float, 10>.data() = 0x7ffe660a2d80 array<double, 10>.data() = 0x7ffe660a2d30 

However, for Intel icpc v16.0.3, the result is shown below, even using -align . Although most containers are aligned at 16-byte addresses, some ( char and float arrays) are aligned with lower byte addresses (2 byte and 8 byte, respectively).

 array<bool,10>.data() = 0x7ffdedcb6bf0 array<char,10>.data() = 0x7ffdedcb6bfa array<int,10>.data() = 0x7ffdedcb6ba0 array<long long, 10>.data() = 0x7ffdedcb6b00 array<float, 10>.data() = 0x7ffdedcb6bc8 array<double, 10>.data() = 0x7ffdedcb6b50 

EDIT

To illustrate this suggestion from RustyX, this is modified code

 #include <array> #include <iostream> int main(void) { alignas(16) std::array<bool, 10> a; alignas(16) std::array<char, 10> b; alignas(16) std::array<int,10> c; alignas(16) std::array<long long, 10> d; alignas(16) std::array<float, 10> e; alignas(16) std::array<double, 10> f; std::cout << "array<bool,10>.data() = " << a.data() << std::endl; std::cout << "array<char,10>.data() = " << (void*) b.data() << std::endl; std::cout << "array<int,10>.data() = " << c.data() << std::endl; std::cout << "array<long long, 10>.data() = " << d.data() << std::endl; std::cout << "array<float, 10>.data() = " << e.data() << std::endl; std::cout << "array<double, 10>.data() = " << f.data() << std::endl; return 0; } 

and this is the result when compiling with Intel icpc v16.0.3.

 array<bool,10>.data() = 0x7ffe42433500 array<char,10>.data() = 0x7ffe42433510 array<int,10>.data() = 0x7ffe424334a0 array<long long, 10>.data() = 0x7ffe42433400 array<float, 10>.data() = 0x7ffe424334d0 array<double, 10>.data() = 0x7ffe42433450 
+8
c ++ arrays c ++ 11 std memory-alignment
source share
1 answer

By default, the compiler will do the right thing when it comes to alignment.

But you can override it with alignas :

 alignas(16) std::array<char, 10> b; 

P.S

Interestingly, the Intel compiler believes that it is enough to align char[] with 8 bytes. It is as if he knew that on the x86 platform you won little, aligning it more and more.

Keep in mind that too much alignment can reduce performance due to increased memory usage and reduced cache efficiency. Modern x86 architectures (Sandy Bridge and newer) work very efficiently with low data, but cannot compensate for partially used cache lines ( more ).

+9
source share

All Articles