gpt4 book ai didi

c++ - clang c++17 std::vector 在使用 -mavx 编译时元素 SIGSEGV 的对齐类型拷贝

转载 作者:可可西里 更新时间:2023-11-01 15:25:06 28 4
gpt4 key购买 nike

根据这个question我认为在 C++17 中,带有默认分配器的 std::vector 应该处理对齐类型。但是,下面的代码

#include <iostream>
#include <iterator>
#include <array>
#include <vector>

template<typename T, size_t N, size_t Alignment>
struct alignas(Alignment) AlignedArray : public std::array<T, N>
{
friend std::ostream& operator<<(std::ostream& o, const AlignedArray& a)
{
std::copy(a.cbegin(), a.cend(), std::ostream_iterator<T>(o, " "));
return o;
}
};

int main()
{
using Array = AlignedArray<double, 24, 64>;
std::vector<Array> v(10);
for(const auto& e : v)
{
auto arr(e);
std::cout << arr << std::endl;
}
return 0;
}

创建 arr 时出现段错误当我用 clang 6.0.1 和 -mavx 编译它时.没有 -mavx切换它运行良好(CPU 是 E5-2697 v2)。我编译它 clang++ -I<path_to_libcxx>/include/c++/v1 -g -mavx -std=c++17 main.cpp -stdlib=libc++ -lc++abi -o alignastest -L<path_to_libcxx>/lib -L<path_to_libcxxabi>/lib .我在旧的 RHEL 6.9 上运行它,我在其中编译了 clang 6.0.1 和 libcxx、libcxxabi。我在另一个系统(Ubuntu 18.10、gcc 8)上对其进行了测试,它没有任何问题。

子问题

关于对齐,我发现 std::aligned_alloc 的实现在 libc++ 中依赖于 C11 功能,该功能仅在最近的 glibc 版本(__config.h)中启用:

#if __GLIBC_PREREQ(2, 17)
#define _LIBCPP_HAS_C11_FEATURES
#endif

不幸的是 RHEL 6.9 只有 ldd (GNU libc) 2.12安装。是alignas还取决于 glibc 版本?

最佳答案

我发现了编译代码的问题,但是,我还没有找到解决方案。但它接缝,这只是一个 clang 问题,使用 g++ 修复它。

通过显示一些生成的汇编代码可以最好地说明问题。 auto arr(e); 代码行被编译为一些移动指令以将数据从 vector 复制到堆栈,clang 使用(当使用 -mavx 编译时)avx2 指令,如下所示(AT&T 语法):

vmovaps 0xa0(%rax),%ymm0
vmovaps %ymm0,0x120(%rsp)
...

其中 %rax 是 vector 中当前数组的地址。目标 arr 位于 0x80(%rsp)。该程序将以 32 字节 block (256 位 avx2 指令)进行复制。

然而,在我的调试测试中查看值时,问题变得很清楚:%rax = 0x55555556be70。问题是,vmovaps(移动对齐压缩单精度)到 256 位 avx2 寄存器期望目标和源在 256 位或 32 字节(0x20)边界对齐,但是 %rax 仅对齐 16 字节。在没有 alignas 的情况下编译时,clang 使用 vmovups(相同的指令,但不需要对齐数据)。

所以问题是,std::vector 的分配器不遵守 alignas 并且不在 64 字节边界对齐数组。 g++ 也不会将 vector 内的数组与 32 字节边界对齐,并且在不使用 -O[not 0] 时不使用 avx 指令。然而,g++ 始终使用 128 位 xmm 寄存器,它只需要对齐到 16 字节,分配器将数据与两个编译器对齐。

编辑:

我刚刚意识到,我忘记使用 -std=c++17 进行编译。使用该标志,它适用于 clang++。代码看起来一样,但分配器正确地将代码对齐到 64 字节边界。所以我想这与旧图书馆有关。也许您可以将您的二进制文件发送给我,然后我可以更详细地查看它。

关于c++ - clang c++17 std::vector 在使用 -mavx 编译时元素 SIGSEGV 的对齐类型拷贝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52000359/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com