Caching 使用SSE/AVX的压缩双向量部分的非时间存储

Caching 使用SSE/AVX的压缩双向量部分的非时间存储,caching,x86,x86-64,sse,avx,Caching,X86,X86 64,Sse,Avx,这是一个关于将\uuuum256d向量的各个元素扇出到不同内存位置(分散操作)的方法。我的代码将大量数据存储到内存中,这些数据在“很长时间”内不会再次被访问。我希望通过使用非时态提示指令来减少所有这些存储所产生的缓存污染量。然而,我想不出一个好办法来做到这一点。下面是我的代码现在的摘要: __m256d src = ... // data double *dst; int dst_dist; __m128d a = _mm256_extractf128_pd(src, 0); __m128

这是一个关于将
\uuuum256d
向量的各个元素扇出到不同内存位置(分散操作)的方法。我的代码将大量数据存储到内存中,这些数据在“很长时间”内不会再次被访问。我希望通过使用非时态提示指令来减少所有这些存储所产生的缓存污染量。然而,我想不出一个好办法来做到这一点。下面是我的代码现在的摘要:

__m256d src = ...  //  data
double *dst;
int dst_dist;

__m128d a = _mm256_extractf128_pd(src, 0);
__m128d b = _mm256_extractf128_pd(src, 1);

_mm_storel_pd(dst + 0*dst_dist, a);
_mm_storeh_pd(dst + 1*dst_dist, a);
_mm_storel_pd(dst + 2*dst_dist, b);
_mm_storeh_pd(dst + 3*dst_dist, b);

我想使用非时态提示执行64位存储,但似乎没有直接从XMM寄存器执行的方法。实现这一点的最佳方法是什么?

您可以使用
MASKMOVDQU
指令使用非时态提示存储SSE向量的部分。语义不能精确地映射到您的示例中,但可以使其工作。但是,此指令通常仅用于避免分支(即使如此,通常最好使用select和normal存储)。使用起来也有点麻烦,因为存储地址在指令中是隐式的


您正在执行的操作看起来非常像矩阵转置(或90度图像旋转)的一部分。您是否最终将其他数据存储到相邻的地址?是否有某种方法可以修改算法以批量存储并写入完整向量(甚至可能使用连续写入到小型可缓存的暂存缓冲区,并在软件中进行写入组合)?

有一个很好的理由避免使用带有非时态提示的部分寄存器存储。如果您试图将许多小块数据分散到完全不相关的内存位置,CPU的写组合缓冲区会溢出,您只能通过缓存进行正常写入(可能会增加性能成本)


使用写合并(非时态提示)的正确方法是填充整个缓存线。因此,通常将数据段合并到一个完整的寄存器中,然后立即用MOVNTDQ写入。

类似矩阵转置的函数是我正在实现的操作的一部分。我最终会将数据存储到相邻的地址。我相信现在整个算法的内存访问时间是有限的,所以我将其构造为最小化存储量(所有计算都在SSE/AVX寄存器中完成,堆栈中没有任何内容)。我曾考虑过按照你的建议去做,但我还没有把它编码好,看看它是如何比较的。一个复杂的因素是,我不能保证我所有的存储上都有128位对齐,这就是为什么我一直使用MOVHPD/MOVLPD一次写入64位。好主意。你和Stephen的回答表明我需要重新思考算法的结构。我可能一次写了太多零散的片段(我有两种模式,一种是一次写8个64位的值,另一种是16位)。