我有四个 uint64_t
数字,我希望将它们组合为 __m256i
的一部分,但是,我不知道如何进行此操作。
这是一种尝试(其中 rax
、rbx
、rcx
和 rdx
是 uint64_t
):
uint64_t a [4] = {rax,rbx,rcx,rcx};
__m256i t = _mm256_load_si256((__m256i *) &a);
最佳答案
如果您已经有一个数组,那么绝对使用_mm256_loadu_si256
(或者甚至对齐版本,_mm256_load_si256
,如果您的数组是alignas(32)
。)但通常不要创建一个数组只是为了存储或重新加载。
使用_mm_set
内在函数并让编译器决定如何做。请注意,它们首先采用编号最高的元素作为参数:例如
__m256i vt = _mm256_set_epi64x(rdx, rcx, rbx, rax);
您通常不希望 asm 看起来像标量存储 -> vector 加载 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 链接的编译选项中)。
关于将 uint64_t 数组转换为 __m256i,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38165525/