我有四个uint64_t
个数字,我希望将它们合并为__m256i
的一部分,但是,我对如何解决这个问题感到迷茫。
此处有一次尝试(rax
,rbx
,rcx
和rdx
为uint64_t
):
uint64_t a [4] = {rax,rbx,rcx,rcx};
__m256i t = _mm256_load_si256((__m256i *) &a);
答案 0 :(得分:1)
首先,确保您的CPU甚至支持这些AVX指令:Performing AVX integer operation。
其次,从https://software.intel.com/en-us/node/514151开始,指针参数必须是对齐的位置。传统上在堆栈上分配的存储器地址是随机的,并且取决于先前调用的堆栈帧的大小,因此可能不对齐。
相反,只需使用内在类型__m256i
强制编译器来对齐它; OR ,根据https://software.intel.com/en-us/node/582952,在__declspec(align)
数组上使用a
。
答案 1 :(得分:1)
使用_mm_set
内在函数,让编译器决定如何操作。请注意,他们首先使用编号最高的元素的args:例如
__m256i vt = _mm256_set_epi64x(rdx, rcx, rbx, rax);
您通常不希望asm看起来像您的标量商店 - > vector load C source,因为这会产生一个存储转发停顿。
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链接中的编译选项。)