将 uint64_t 的数组转换为 __m256i
convert array of uint64_t to __m256i
我有四个 uint64_t
号码,我希望将它们合并为一个 __m256i
的一部分,但是,我不知道该怎么做。
这是一次尝试(其中 rax
、rbx
、rcx
和 rdx
是 uint64_t
):
uint64_t a [4] = {rax,rbx,rcx,rcx};
__m256i t = _mm256_load_si256((__m256i *) &a);
首先,请确保您的 CPU 甚至支持这些 AVX 指令:Performing AVX integer operation。
其次,从https://software.intel.com/en-us/node/514151开始,指针参数必须是对齐的位置。通常在堆栈上分配的内存地址是随机的,并且取决于先前调用的堆栈帧的大小,因此可能不会对齐。
相反,只需使用内部类型__m256i
来强制编译器对齐它; 或,根据https://software.intel.com/en-us/node/582952,在你的a
数组上使用__declspec(align)
。
如果你已经有一个数组,那么绝对使用_mm256_loadu_si256
(甚至对齐版本,_mm256_load_si256
如果你的数组是alignas(32)
.) 但通常不要创建一个数组只是为了存储到/重新加载。
使用 _mm_set
内在函数,让编译器决定如何做。请注意,他们首先采用编号最高的元素作为参数:例如
__m256i vt = _mm256_set_epi64x(rdx, rcx, rbx, rax);
您通常不希望 asm 看起来像您的标量存储 -> 矢量加载 C 源代码,因为那样会产生存储转发停顿。
gcc 6.1 在这种情况下“看穿”了本地数组(并使用 2x vmovq
/ 2x vpinsrq
/ 1x vinserti128
),但它仍然生成代码来对齐堆栈到 32B。 (尽管不需要它,因为它最终不需要任何 32B 对齐的局部变量)。
正如你在 Godbolt Compiler Explorer 上看到的那样,两种方式的实际数据移动部分是相同的,但是数组方式有一堆浪费的指令,gcc 在决定避免后未能优化掉消息来源暗示的糟糕方式。
_mm256_set_epi64x
适用于 32 位代码(至少使用 gcc)。你得到 2x vmovq
和 2x vmovhps
来对 xmm 寄存器的上半部分进行 64 位加载。 (将 -m32
添加到 godbolt link 的编译选项中。
我有四个 uint64_t
号码,我希望将它们合并为一个 __m256i
的一部分,但是,我不知道该怎么做。
这是一次尝试(其中 rax
、rbx
、rcx
和 rdx
是 uint64_t
):
uint64_t a [4] = {rax,rbx,rcx,rcx};
__m256i t = _mm256_load_si256((__m256i *) &a);
首先,请确保您的 CPU 甚至支持这些 AVX 指令:Performing AVX integer operation。
其次,从https://software.intel.com/en-us/node/514151开始,指针参数必须是对齐的位置。通常在堆栈上分配的内存地址是随机的,并且取决于先前调用的堆栈帧的大小,因此可能不会对齐。
相反,只需使用内部类型__m256i
来强制编译器对齐它; 或,根据https://software.intel.com/en-us/node/582952,在你的a
数组上使用__declspec(align)
。
如果你已经有一个数组,那么绝对使用_mm256_loadu_si256
(甚至对齐版本,_mm256_load_si256
如果你的数组是alignas(32)
.) 但通常不要创建一个数组只是为了存储到/重新加载。
使用 _mm_set
内在函数,让编译器决定如何做。请注意,他们首先采用编号最高的元素作为参数:例如
__m256i vt = _mm256_set_epi64x(rdx, rcx, rbx, rax);
您通常不希望 asm 看起来像您的标量存储 -> 矢量加载 C 源代码,因为那样会产生存储转发停顿。
gcc 6.1 在这种情况下“看穿”了本地数组(并使用 2x vmovq
/ 2x vpinsrq
/ 1x vinserti128
),但它仍然生成代码来对齐堆栈到 32B。 (尽管不需要它,因为它最终不需要任何 32B 对齐的局部变量)。
正如你在 Godbolt Compiler Explorer 上看到的那样,两种方式的实际数据移动部分是相同的,但是数组方式有一堆浪费的指令,gcc 在决定避免后未能优化掉消息来源暗示的糟糕方式。
_mm256_set_epi64x
适用于 32 位代码(至少使用 gcc)。你得到 2x vmovq
和 2x vmovhps
来对 xmm 寄存器的上半部分进行 64 位加载。 (将 -m32
添加到 godbolt link 的编译选项中。