Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Gcc 未对齐向量指针异常(AVX512)_Gcc_Clang_Vectorization_Simd_Avx512 - Fatal编程技术网

Gcc 未对齐向量指针异常(AVX512)

Gcc 未对齐向量指针异常(AVX512),gcc,clang,vectorization,simd,avx512,Gcc,Clang,Vectorization,Simd,Avx512,我的问题是导出一个未对齐的m512指针,该指针指向一个包含浮点数的内存空间。我发现GCC和Clang在通过这种装置访问内存时,在生成正确的uop(未对齐与对齐)方面有些不稳定 首先,工作案例: typedef float MyFloatVector __attribute__((vector_size(64), aligned(4))); MyFloatVector* vec_ptr = reinterpret_cast<MyFloatVector*>(float_ptr); Som

我的问题是导出一个未对齐的m512指针,该指针指向一个包含浮点数的内存空间。我发现GCC和Clang在通过这种装置访问内存时,在生成正确的uop(未对齐与对齐)方面有些不稳定

首先,工作案例:

typedef float MyFloatVector __attribute__((vector_size(64), aligned(4)));
MyFloatVector* vec_ptr = reinterpret_cast<MyFloatVector*>(float_ptr);
Something(*vec_ptr);
typedef float MyFloatVector属性((向量大小(64),对齐(4));
MyFloatVector*vec_ptr=重新解释强制转换(float_ptr);
某物(*vec_ptr);
Clang和GCC都会为上述内容生成movUp。但是,如果vec_ptr的类型留给编译器:

typedef float MyFloatVector __attribute__((vector_size(64), aligned(4)));
auto vec_ptr = reinterpret_cast<MyFloatVector *>(float_ptr);
Something(*vec_ptr);
typedef float MyFloatVector属性((向量大小(64),对齐(4));
自动矢量转换=重新解释转换(浮动转换);
某物(*vec_ptr);
现在,Clang将在线路上生成MOVAP和segfault。GCC仍然会生成MOVUP,但也会生成三条不做任何事情的指令(push rbp、load rsp to rbp、pop rbp)

此外,如果我从typedef更改为使用:

using MyFloatVector = float __attribute__((vector_size(64), aligned(4)));
MyFloatVector*vec_ptr = reinterpret_cast<MyFloatVector*>(float_ptr);
Something(*vec_ptr);
使用MyFloatVector=float uuu属性(向量大小(64),对齐(4));
MyFloatVector*vec_ptr=重新解释强制转换(float_ptr);
某物(*vec_ptr);
同样,GCC生成fluff指令,Clang生成movap。在这里使用auto会得到相同的结果

那么,有没有人知道引擎盖下发生了什么,有没有安全的方法进行转换。虽然存在一个可行的解决方案,但在我看来,typedef/using和explicit/auto产生的差异使得它太不可靠,无法放心地使用——至少我需要一个静态断言来检查在取消引用指针时生成的uop是否未对齐,这在AIK中是不存在的

在某些情况下,我可能希望有一个对内存区域的MyFloatVector引用,这就排除了使用内部函数的可能性


示例代码:。包括用于“fun”的ICC,它在整个过程中生成MOVUPS。

当您使用
重新解释\u cast
时,您告诉编译器参数指向请求类型的有效对象。这意味着它具有相同的对齐要求

ICC在这里更加保守,而clang和GCC则试图通过假设您实际上遵守了该标准来加快代码的运行速度

请记住,aligned属性只能用于增加对齐要求,而不是减少对齐要求,因此在代码中,您只是说类型的最小对齐长度为4字节。如果您添加一个
static\u断言(alignof(MyFloatVector)==4,“对齐应该是4”)
您可能会看到一些失败,具体取决于您如何声明它


由于您没有使用
\uuuum512
\umm512\uloadu\ups
可以工作,但可能不是正确的方法。加载未对齐数据的正确方法是使用
memcpy
(或者
\uuu内置\uu memcpy
,因为您无论如何都在使用向量扩展)。编译器非常擅长使用已知大小优化memcpy,只要您使用相对较新的编译器,就应该在x86上使用启用AVX-512F的vmovups。

当您使用
reinterpret\u cast
时,您告诉编译器参数指向请求类型的有效对象。这意味着它具有相同的对齐要求

ICC在这里更加保守,而clang和GCC则试图通过假设您实际上遵守了该标准来加快代码的运行速度

请记住,aligned属性只能用于增加对齐要求,而不是减少对齐要求,因此在代码中,您只是说类型的最小对齐长度为4字节。如果您添加一个
static\u断言(alignof(MyFloatVector)==4,“对齐应该是4”)
您可能会看到一些失败,具体取决于您如何声明它


由于您没有使用
\uuuum512
\umm512\uloadu\ups
可以工作,但可能不是正确的方法。加载未对齐数据的正确方法是使用
memcpy
(或者
\uuu内置\uu memcpy
,因为您无论如何都在使用向量扩展)。编译器在优化已知大小的memcpy方面非常出色,只要您使用的是相对较新的编译器,就应该在启用AVX-512F的x86上使用vmovups。

reinterpret\u cast
通常使用起来不安全。有什么问题吗?它排除了使用引用的可能性,例如MyFloatVector&vec_ref=*vec_ptr;目标是实现一个std::vector-like容器,该容器可以对矢量化数据类型进行操作,因此,例如,[]-运算符需要能够形成对内部存储的引用。也许可以实现一个自定义引用对象(该对象在内部保存指针,但重载
运算符
运算符=(\uuuuuum512)
--类似于在
vector
中处理引用的方式。是的--这似乎是唯一的方法。我有点希望在这里变得懒惰,仅仅依靠编译器来完成这项工作:-)谢谢你的帮助<代码>重新解释强制转换
通常使用起来不安全。有什么问题吗?它排除了使用引用的可能性,例如MyFloatVector&vec_ref=*vec_ptr;目标是实现一个std::vector-like容器,该容器可以对矢量化数据类型进行操作,因此,例如,[]-运算符需要能够形成对内部存储的引用。也许可以实现一个自定义引用对象(该对象在内部保存指针,但重载
运算符
运算符=(\uuuuuum512)
--类似于在
vector
中处理引用的方式。是的--这似乎是唯一的方法。我有点希望在这里变得懒惰,仅仅依靠编译器来完成这项工作:-)谢谢你的帮助<恰好对齐的地址上的code>vmovdqu
vmovdqa
一样快。GCC和clang所做的是帮助您验证您承诺的对齐方式,前提是您做到了这一点