2013-11-23 21 views
1

我寫了一些高度優化的代碼,這裏是一兩件事,已竊聽我相當長一段時間,我有一個三重for循環一樣研究員:在x86指令中寫入非阻塞存儲器?

for(int ii = 0; ii < ny; ii++){ 
    for(int jj = 0; jj < nx; jj++){ 
     ....some serious calculation.... 
     for(int kk = 0; kk < CONSTANT; kk++){ 
      _mm_storeu_ps(&((cells.dir[kk])[ii * nx +jj],result); // Writing result to correct location 
     } 
    } 
} 

細胞只是一個9個指針結構,每個指向一個大尺寸的陣列。該代碼最初是以struct(AoS)模式的數組編寫的,我手動重寫了整個事物以使用數組的結構,因此我可以使用SSE加速它。但由於代碼的原始結構,上面的代碼必須以緩存不友好的方式將結果寫入正確的位置,如果我評論這一行,我整個程序的運行時間可能會減少超過40% 。我只是想知道是否有任何可用於x86的非阻塞式內存寫入指令,我可以利用它?或者我可以使用這種內存寫入其他一些技巧?請不要建議改變循環的結構,這太耗費時間了。

感謝, 鮑勃

+2

幾乎所有現代非嵌入式處理器的寫入都是非阻塞的。他們只是被推到隊列中,並在後臺完成。也就是說,在隊列阻塞之前,隊列的大小是有限制的。也就是說,也要注意你如何使用緩存線。 – Mysticial

+0

@Mysticial我剛剛發現它更可能是因爲''_mm_storeu_ps''非常昂貴,而不是緩存未命中,這會減慢我的程序。你有什麼建議嗎? – dorafmon

+0

@dorafmon:你需要將結果放在那些確切的存儲位置,或者你打算在以後讀回來進行更多的計算?您可以通過將緩存更容易地寫入臨時緩衝區來提高性能。過去我已經做到了這一點,取得了一些成功。但是,如果這些商店的最終結果需要按照輸出數組中的特定順序進行,那麼您可能只是運氣不好。 –

回答

1

見9.11 顯式高速緩存控制在昂納霧手冊optimizing cpp。特別看看第99頁的示例9.6b(下面發佈),其中介紹瞭如何在不讀取使用_mm_stream_pi內在函數的緩存行的情況下執行寫操作。我還沒有嘗試過,但值得一看。這有助於矩陣大小是關鍵步幅的倍數。但是,更好的解決方案可能是更改代碼並使用循環平鋪(請參見示例9.5b),但是您說您不想更改循環的結構,因此使用_mm_stream_ps可能是最佳選擇。

// From Agner Fog's manual optimizing cpp on page 99 
// Example 9.6b 
#include "xmmintrin.h" // header for intrinsic functions 
// This function stores a double without loading a cache line: 
static inline void StoreNTD(double * dest, double const & source) { 
    _mm_stream_pi((__m64*)dest, *(__m64*)&source); // MOVNTQ 
    _mm_empty(); // EMMS 
} 
const int SIZE = 512; // number of rows and columns in matrix 
// function to transpose and copy matrix 
void TransposeCopy(double a[SIZE][SIZE], double b[SIZE][SIZE]) { 
    int r, c; 
    for (r = 0; r < SIZE; r++) { 
     for (c = 0; c < SIZE; c++) { 
      StoreNTD(&a[c][r], b[r][c]); 
     } 
    } 
}