未对齐的加载与未对齐的商店

Yan*_*hou 14 c++ performance x86 memory-alignment avx

简短的问题是,如果我有一个带两个向量的函数.一个是输入,另一个是输出(无别名).我只能调整其中一个,我应该选择哪一个?

更长的版本是,考虑一个功能,

void func(size_t n, void *in, void *out)
{
    __m256i *in256 = reinterpret_cast<__m256i *>(in);
    __m256i *out256 = reinterpret_cast<__m256i *>(out);
    while (n >= 32) {
         __m256i data = _mm256_loadu_si256(in256++);
         // process data
         _mm256_storeu_si256(out256++, data);
         n -= 32;
    }
    // process the remaining n % 32 bytes;
}
Run Code Online (Sandbox Code Playgroud)

如果inout都是32字节对齐,那么使用vmovdqu而不是代价vmovdqa.最糟糕的情况是两者都是未对齐的,并且四分之一的加载/存储将跨越缓存行边界.

在这种情况下,我可以通过在进入循环之前先处理几个元素将其中一个与高速缓存行边界对齐.但是,问题是我应该选择哪个?在未对齐的加载和存储之间,哪一个更糟?

cht*_*htz 2

在这里冒着风险声明显而易见的事实:除了“您需要使用实际代码和实际数据进行基准测试”之外,没有“正确答案”。无论哪种变体速度更快,很大程度上取决于您所使用的 CPU、您在每个包上执行的计算量以及许多其他因素。

正如评论中所述,您还应该尝试非临时存储。有时也帮助的是在当前循环内加载以下数据包的输入,即:

__m256i next =  _mm256_loadu_si256(in256++);
for(...){
    __m256i data = next; // usually 0 cost
    next = _mm256_loadu_si256(in256++);
    // do computations and store data
}
Run Code Online (Sandbox Code Playgroud)

如果您正在进行的计算存在不可避免的数据延迟,您还应该考虑计算两个交错的包(尽管这使用了两倍的寄存器)。