简短的问题是,如果我有一个带两个向量的函数。一个是输入,另一个是输出(无别名)。我只能调整其中一个,我应该选择哪一个?
更长的版本是,考虑一个函数,
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;
}
如果in
和out
都是32字节对齐的,那么使用vmovdqu
代替vmovdqa
不会受到惩罚。最糟糕的情况是两者都是未对齐的,四分之一的加载/存储将跨越缓存行边界。
在这种情况下,我可以通过在进入循环之前先处理几个元素将其中一个对齐到缓存行边界。但是,问题是我应该选择哪个?在未对齐的加载和存储之间,哪一个更糟?
答案 0 :(得分:0)
冒险在这里说明显而易见:没有&#34;正确答案&#34;除了&#34;你需要用实际代码和实际数据进行基准测试&#34;。无论哪种变体更快,都取决于您使用的CPU,您在每个包装上执行的计算量以及许多其他事项。
如评论中所述,您还应该尝试非临时商店。有时可以帮助的是在当前循环中加载以下数据包的输入,即:
__m256i next = _mm256_loadu_si256(in256++);
for(...){
__m256i data = next; // usually 0 cost
next = _mm256_loadu_si256(in256++);
// do computations and store data
}
如果您正在进行的计算具有不可避免的数据延迟,您还应该考虑计算两个交错的包(尽管这会使用两倍的寄存器)。