如何对齐 std::array 包含的数据?

问题描述 投票:0回答:1

既然

std::array
不允许改变它的分配器,有没有办法保证指向数据地址的指针是对齐的?

例如,在 GNU g++ 4.8.4 和 6.1.0 中,以下代码

#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;
}

提供以下输出,显示容器数据与 16 字节地址对齐,无论针对 x86-64 位架构进行编译时包含的数据类型如何。

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

但是,对于 Intel 的 icpc v16.0.3,即使使用

-align
,结果也如下所示。虽然大多数容器都与 16 字节地址对齐,但有些(
char
float
数组)与较小的字节地址(分别为 2 字节和 8 字节)对齐。

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

编辑

只是为了举例说明 RustyX 的提案,这是更改后的代码

#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;
}

这是用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
c++ arrays c++11 std memory-alignment
1个回答
20
投票

默认情况下,编译器在对齐时会做正确的事情。

但是您可以使用

alignas
覆盖(增加)它:

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

有趣的是,英特尔编译器认为将

char[]
对齐到 8 个字节就足够了。就好像它知道,在 x86 平台上,通过将其对齐得更宽,你不会获得什么好处。

请记住,过多的对齐会由于内存使用增加和缓存效率降低而“降低性能”。现代 x86 架构(Sandy Bridge 和更新版本)可以非常高效地处理未对齐的数据,但无法补偿部分使用的缓存行(更多信息)。

© www.soinside.com 2019 - 2024. All rights reserved.