10
簡短的問題是,如果我有一個函數需要兩個向量。一個是輸入,另一個是輸出(沒有別名)。我只能對其中一個,我應該選擇哪一個?未對齊的負載與未對齊的存儲
較長的版本是,考慮功能,
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
的處罰。最糟糕的情況是兩者都未對齊,四分之一的加載/存儲將跨越緩存線邊界。
在這種情況下,我可以通過在進入循環之前首先處理幾個元素來將它們中的一個與高速緩存行邊界對齊。但是,問題是我應該選擇哪一個?未對齊的加載和存儲之間,哪一個更糟?
看看一些memcpy的實現;我認爲這有一個通常的方式,但我忘記了它是什麼。雖然也許這取決於你在做什麼。對齊的加載將避免緩存行邊界,所以沒有加載使用延遲懲罰(如果指針增量是可預測的,則不太相關,因爲OOO可以使加載地址遠遠超出餘下的循環)。由於在對象外部讀取通常是安全的,但是寫入不是,如果可以避免清理循環的完整標量版本,那麼這可能會影響決策。 –
我對此進行了一些測試,並確定至少在我測試過的處理器(Pentium 4,Core 2,Sandy Bridge和Haswell)上,對齊輸入向量明顯快於對齊輸出向量。你的旅費可能會改變。我不願意將此作爲答案發布,因爲我不再有測試代碼,不想再次編寫測試代碼並再次運行測試,也沒有官方參考指向任何類型的文檔。所以有一個upvote代替! :-) –
@CodyGray無論如何感謝。我一直在研究這個問題的一些測試。到目前爲止,我可以告訴的只是「它取決於」 –