2016-12-01 74 views
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; 
} 

如果inout排列了32個字節,那麼就沒有使用vmovdqu代替vmovdqa的處罰。最糟糕的情況是兩者都未對齊,四分之一的加載/存儲將跨越緩存線邊界。

在這種情況下,我可以通過在進入循環之前首先處理幾個元素來將它們中的一個與高速緩存行邊界對齊。但是,問題是我應該選擇哪一個?未對齊的加載和存儲之間,哪一個更糟?

+3

看看一些memcpy的實現;我認爲這有一個通常的方式,但我忘記了它是什麼。雖然也許這取決於你在做什麼。對齊的加載將避免緩存行邊界,所以沒有加載使用延遲懲罰(如果指針增量是可預測的,則不太相關,因爲OOO可以使加載地址遠遠超出餘下的循環)。由於在對象外部讀取通常是安全的,但是寫入不是,如果可以避免清理循環的完整標量版本,那麼這可能會影響決策。 –

+0

我對此進行了一些測試,並確定至少在我測試過的處理器(Pentium 4,Core 2,Sandy Bridge和Haswell)上,對齊輸入向量明顯快於對齊輸出向量。你的旅費可能會改變。我不願意將此作爲答案發布,因爲我不再有測試代碼,不想再次編寫測試代碼並再次運行測試,也沒有官方參考指向任何類型的文檔。所以有一個upvote代替! :-) –

+0

@CodyGray無論如何感謝。我一直在研究這個問題的一些測試。到目前爲止,我可以告訴的只是「它取決於」 –

回答

0

冒着風險說明這裏顯而易見:除了「你需要用實際代碼和實際數據進行基準測試」之外,沒有「正確的答案」。無論哪種變體速度更快取決於您使用的CPU,您在每個軟件包上執行的計算量以及其他許多事情。

正如評論中指出的那樣,您還應該嘗試非臨時商店。什麼有時也可以幫助加載電流回路內的下列數據包的輸入,即:

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

如果你正在做的計算有不可避免的數據延遲,你也應該考慮計算兩個包交錯(儘管使用了兩倍的寄存器)。