2011-12-09 50 views
3

這個在previous question上搭載我關於將矢量的各個元素分散到不同的存儲位置(分散操作)。我的代碼會將很多數據存儲到內存中,而這些數據不會再「長時間」訪問。我想通過使用非時間提示指令來減少所有這些商店生成的緩存污染量。但是,我不能想出一個好辦法來做到這一點。這裏是我的代碼看起來像現在的總結:使用SSE/AVX打包的雙向量的部分非臨時存儲

__m256d src = ... // data 
double *dst; 
int dst_dist; 

__m128d a = _mm256_extractf128_pd(src, 0); 
__m128d b = _mm256_extractf128_pd(src, 1); 

_mm_storel_pd(dst + 0*dst_dist, a); 
_mm_storeh_pd(dst + 1*dst_dist, a); 
_mm_storel_pd(dst + 2*dst_dist, b); 
_mm_storeh_pd(dst + 3*dst_dist, b); 

我想使用非暫時提示執行64位的商店,但似乎沒有成爲一種從做直接一個XMM寄存器。什麼是實現這一目標的最佳方式?

回答

4

有一個很好的理由避免使用非暫時性提示使用部分寄存器存儲。如果您嘗試將許多小塊數據分散到完全不相關的內存位置,則CPU的寫入組合緩衝區會溢出,並且您只能通過緩存進行常規寫入(可能會帶來額外的性能成本)。

使用寫入組合(非時間提示)的正確方法是填充整個緩存行。所以通常將數據塊組合到一個完整的寄存器中,然後用MOVNTDQ一次性寫入。

+0

好想法。你和斯蒂芬的答案表明我需要重新思考我的算法結構。我可能一次寫很多零散的東西(我有兩種模式,一種是我一次寫8個64位的值,另一種是我寫16的值)。 –

2

使用MASKMOVDQU指令可以存儲具有非暫時提示的SSE向量部分。語義不會精確映射到您的示例,但可以使其工作。但是,這個指令通常只能用於避免分支(即使這樣,通常使用select和normal store也會更好)。這也使用起來有點麻煩,因爲要存儲的地址隱含在指令中。

您正在執行的操作看起來很像一塊矩陣轉置(或90度圖像旋轉)。你最終將其他數據存儲到相鄰的地址?有沒有什麼方法可以修改算法來批量修改這些存儲並寫入完整的向量(甚至可以通過使用連續寫入小型可緩存暫存緩衝區並在軟件中進行一些寫入組合)?

+0

類似矩陣轉置的函數是我正在實現的操作的一部分。我最終將數據存儲到相鄰的地址。我相信現在整體算法存儲訪問時間受到限制,所以我已經構建了它以最大限度地減少存儲量(所有計算都在SSE/AVX寄存器中完成,而堆棧中沒有任何內容)。我已經考慮過按照你的建議去做,但是我沒有把它編碼,看看它是如何比較的。一個複雜的因素是我無法保證我的所有商店都有128位對齊,這就是爲什麼我一直使用MOVHPD/MOVLPD來寫​​入64位數據的原因。 –