【问题标题】:Non-temporal stores of portions of a packed double vector using SSE/AVX使用 SSE/AVX 对压缩双向量部分进行非时间存储
【发布时间】:2011-12-09 20:13:06
【问题描述】:

这搭载了previous question,我曾将__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 寄存器执行此操作。实现这一目标的最佳方法是什么?

【问题讨论】:

    标签: caching x86 x86-64 sse avx


    【解决方案1】:

    有充分的理由避免使用带有非临时提示的部分寄存器存储。如果您尝试将许多小块数据分散到完全不相关的内存位置,CPU 的写入组合缓冲区会溢出,并且您只能通过缓存进行常规写入(可能会带来额外的性能成本)。

    使用写入组合(非临时提示)的正确方法是填满整个缓存行。所以通常将数据块组合成一个完整的寄存器,然后用 MOVNTDQ 一次写入。

    【讨论】:

    • 好主意。你和斯蒂芬的回答表明我需要重新考虑我的算法结构。我可能一次写了太多分散的片段(我有两种模式,一种是我一次写 8 个 64 位值,另一种是我写 16 个)。
    【解决方案2】:

    您可以使用MASKMOVDQU 指令存储具有非时间提示的 SSE 向量部分。语义不能精确地映射到您的示例,但可以使其工作。然而,这条指令通常应该只用于避免分支(即使那样,通常最好使用选择和普通存储)。使用起来也有点麻烦,因为要存储的地址在指令中是隐含的。

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

    【讨论】:

    • 类似矩阵转置的函数是我正在实现的操作的一部分。我最终将数据存储到相邻的地址。我相信整个算法现在是受内存访问时间限制的,所以我对其进行了结构化以最小化存储量(所有计算都在 SSE/AVX 寄存器中完成,堆栈上没有任何内容)。我已经考虑过按照您的建议进行操作,但我还没有对其进行编码以查看它的比较情况。一个复杂的因素是我不能保证我所有的存储都是 128 位对齐的,这就是我一直使用 MOVHPD/MOVLPD 一次写入 64 位的原因。
    猜你喜欢
    • 2023-04-08
    • 2017-12-16
    • 2014-01-04
    • 1970-01-01
    • 2014-07-12
    • 1970-01-01
    • 1970-01-01
    • 2013-09-14
    • 2021-03-25
    相关资源
    最近更新 更多