使用SSE/AVX存储打包双精度向量的非时态部分

3
这是对我之前有关将__m256d向量的各个元素传送到不同内存位置(散布操作)的上一个问题的补充。我的代码将许多不再访问的数据存储到内存中,希望通过使用非暂态提示指令来减少由所有这些存储生成的缓存污染。但是,我无法想出一个好的方法来实现这一点。以下是我的代码概述:
__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寄存器实现此操作的方法。最佳实现方式是什么?

2个回答

4
避免使用带有非暂态提示的部分寄存器存储有很好的理由。如果您尝试散布许多小数据片段到完全不相关的内存位置,CPU的写组合缓冲区会溢出,您只会得到常规的缓存写入(可能会带来额外的性能损失)。
使用写组合(非暂态提示)的正确方法是填充整个缓存行。因此通常将数据片段组合成完整的寄存器,然后一次使用MOVNTDQ写入。

好的想法。你和史蒂芬的回答表明我需要重新思考我的算法结构。我可能一次写了太多分散的部分(我有两种模式,一种是每次写出8个64位值,另一种是写出16个)。 - Jason R

2
您可以使用MASKMOVDQU指令并带有非临时提示来存储SSE向量的部分。虽然语义与您的示例不完全相同,但可以使其正常工作。但是,通常只有在避免分支的情况下才应使用此指令(即使在这种情况下,使用选择和普通存储通常更好)。此外,它的使用也有些麻烦,因为存储的地址在指令中是隐含的。
您正在执行的操作看起来很像矩阵转置(或90度图像旋转)的一部分。您最终会将其他数据存储到相邻的地址吗?是否有办法修改您的算法以批处理这些存储并写入完整的向量(可能甚至通过对小型可缓存的临时缓冲区进行连续写入并在软件中进行一些写组合来实现)?

我正在实现一个包含类似矩阵转置的函数的操作。最终,我会将数据存储到相邻的地址中。我认为整个算法现在受到内存访问时间的限制,因此我已经将其结构化以最小化存储量(所有计算都在SSE/AVX寄存器中完成,堆栈上没有任何计算)。我考虑过你提出的方法,但我还没有编写代码来比较它们。一个复杂的因素是我不能保证所有存储的128位对齐,这就是为什么我一直在使用MOVHPD/MOVLPD每次写入64位的原因。 - Jason R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接