8

如果我定义了一个具有一定对齐要求的简单类型,那么std::vector<t>所述类型不应该尊重每个元素的对齐方式吗?

考虑以下示例

typedef std::array<double,3> alignas(32) avx_point;
std::vector<avx_point> x(10);
assert(!(std::ptrdiff_t(&(x[0]))&31) &&   // assert that x[0] is 32-byte aligned
       !(std::ptrdiff_t(&(x[1]))&31));    // assert that x[1] is 32-byte aligned

我发现clang 3.2(有或没有-stdlib=libc++)无声地(没有任何警告)违反了对齐要求,而gcc 4.8.0发出一个警告,它忽略了模板参数上的属性std::vector(intel编译器太愚蠢以至于无法理解alignas,但如果我改用__declspec(align(32))它,它的行为就像铿锵声)。两者都创建触发断言的代码。

那么,这是正确的行为还是clang(和icpc)的错误以及gcc的问题?

编辑 以回答评论中提出的问题:如果我定义

typedef typename std::aligned_storage<sizeof (avx_point),
                                      alignof(avx_point)>::type avx_storage;

我明白了

sizeof (avx_storage) == 32;
alignof(avx_storage) == 32;

std::vector<avx_storage>仍然无法为 clang 和 gcc 对齐第一个元素(因此也对齐所有其他元素)(这次没有警告)。因此,实现显然存在两个问题:首先,std::allocator<type>即使对于第一个元素(非法?)也忽略任何对齐要求,其次,没有应用填充来确保后续元素的对齐。

––––––––––––</p>

编辑 有一个相关的,更实际的问题是如何获得适合 SSE/AVX 操作对齐的内存。相反,我想知道std::vector<>(或std::allocator<>)是否不应该遵守alignasC++ 标准(截至 2011 年)。其他问题的答案都不是这个问题的合适答案。

4

1 回答 1

3

首先,即使是第一个元素,std::allocator 也会忽略任何对齐要求(非法?)

我远非分配器专家,但在我看来,不幸的是,这是合法行为。更准确地说,分配器可能会忽略请求的对齐。事实上,[allocator.requirements], 17.6.3.5/6 指出:

如果分配器不支持与特定过度对齐类型关联的对齐,则该类型的分配器的实例化可能会失败。分配器也可以默默地忽略请求的对齐

您可以编写自己的分配器来为您提供对齐的内存。我以前在工作中这样做过,但不幸的是,出于版权原因,我不能透露代码 :-( 我只能说,很明显:它基于_aligned_mallocand _aligned_free(它们是 Microsoft 扩展)。或者你可以谷歌搜索“对齐分配器”,会出现一些选项,其中之一是

https://gist.github.com/donny-dont/1471329

我强调我不是这个对齐分配器的作者,我从未使用过它。

更新

上面的对齐分配器适用于 Visual Studio/Windows,但它可以用作在其他平台上实现对齐分配器的基础。您可以使用 posixmemalign系列函数或 C11 函数aligned_alloc

看到这个帖子。

于 2013-05-07T21:48:17.430 回答