SSE2:如何从非连续内存位置加载数据?

dsi*_*cha 6 optimization performance assembly sse simd

我正在尝试对一些极其性能关键的代码进行矢量化.在较高级别,每个循环迭代从小数组中的非连续位置读取六个浮点数,然后将这些值转换为双精度并将它们添加到六个不同的双精度累加器.这些累加器在迭代中是相同的,因此它们可以存在于寄存器中.由于算法的性质,使存储器访问模式连续是不可行的.尽管如此,该阵列足够小以适应L1缓存,因此内存延迟/带宽不是瓶颈.

我愿意使用汇编语言或SSE2内在函数来并行化.我知道我需要一次将两个浮点数加载到XMM寄存器的两个低位双字中,使用它们将它们转换为两个双精度数cvtps2pd,然后一次将它们添加到两个累加器中addpd.

我的问题是,如果它们在内存中彼此不相邻,如何将两个浮点数放入单个XMM寄存器的两个低位字中?显然,任何技术都是如此之慢以至于无法实现并行化的目的并没有用.ASM或英特尔/ GCC内在函数的答案将不胜感激.

编辑:

  1. 严格来说,浮点数组的大小在编译时是不知道的,但它几乎总是256,所以这可以是特殊的.

  2. 应该读取的float数组的元素是通过从字节数组加载值来确定的.有六个字节数组,每个累加器一个.来自字节数组的读取是顺序的,每个循环迭代的每个数组一个,因此不应该有很多缓存未命中.

  3. 浮点数组的访问模式是出于所有实际目的随机的.

gsg*_*gsg 3

对于这种特定情况,请查看说明参考手册中的解包和交错说明。会是这样的

movss xmm0, <addr1>
movss xmm1, <addr2>
unpcklps xmm0, xmm1
Run Code Online (Sandbox Code Playgroud)

另请查看shufps,每当您所需的数据顺序错误时,它都会很方便。