我將改進OCL內核性能,並且想要闡明內存事務如何工作以及哪種內存訪問模式真的更好(以及爲什麼)。 內核提供了8個整數的向量,這些整數被定義爲數組:int v [8],這意味着,在進行任何計算之前,必須將整個向量加載到GPR中。所以,我相信這個代碼的瓶頸是初始數據加載。向量化數據的OpenCL(AMD GCN)全局內存訪問模式:跨步與連續
首先,我考慮一些理論基礎知識。
目標硬件是Radeon RX 480/580,具有256位GDDR5存儲器總線,突發讀/寫事務有8個字粒度,因此,一個存儲器事務讀取2048位或256字節。也就是說,我相信,什麼CL_DEVICE_MEM_BASE_ADDR_ALIGN是指:
Alignment (bits) of base address: 2048.
因此,我的第一個問題:什麼是128字節的緩存行的物理意義?它是否保留通過單個突發讀取獲取的數據部分,但沒有真正請求?如果我們要求32或64個字節,剩餘部分會發生什麼 - 因此,剩餘的部分超過了緩存行的大小? (我想,它將被丟棄 - 然後,哪個部分:頭部,尾部...?)
現在回到我的內核,我認爲緩存不起作用在我的情況下,因爲一個突發讀取64個整數 - >理論上一個內存事務可以一次輸入8個工作項,沒有額外的數據要讀取,並且內存總是合併的。
但是,我可以把我的數據有兩個不同的訪問模式:
1)連續
a[i] = v[get_global_id(0) * get_global_size(0) + i];
(至極實際上perfomed爲)
*(int8*)a = *(int8*)v;
2)交錯
a[i] = v[get_global_id(0) + i * get_global_size(0)];
我期望在我的情況下連續會更快,因爲如上所述,一個內存事務可以完全填充8個工作項與數據。但是,我不知道,計算單元中的調度程序如何在物理上工作:是否需要爲所有SIMD通道準備好所有數據,或者只需要4個並行SIMD元素的第一部分就足夠了?儘管如此,我認爲只要CU可以獨立執行命令流,它就足夠聰明,可以首先完全提供至少一個CU的數據。 在第二種情況下,我們需要執行8 * global_size/64個事務來獲取完整的向量。
所以,我的第二個問題:我的假設是正確的嗎?
現在,練習。
實際上,我將整個任務分成兩個內核,因爲一個部分的註冊壓力低於另一個,因此可以使用更多的工作項目。所以我首先用模式演示瞭如何在內核之間轉換時存儲的數據(使用vload8/vstore8或轉換爲int8給出相同的結果),結果有點奇怪:以相鄰方式讀取數據的內核工作速度快10% CodeXL和操作系統時間測量),但連續存儲數據的內核執行速度驚人地更慢。兩個內核的總體時間大致相同。在我的想法中,兩者必須至少以相同的方式行事 - 要麼更慢,要麼更快,但是這些相反的結果似乎無法解釋。
而我的第三個問題是:任何人都可以解釋這樣的結果嗎?或者可能是我做錯了什麼? (或完全錯誤?)
謝謝你的回答。但是我不是在談論合併vs交錯訪問。可能是我的着作不那麼清楚,但訪問總是合併 - 區別僅在於讀取數據矢量明智與元素明智。爲了澄清一點,我糾正了這個問題。 – qpdb
@qpdb從內核的角度來看,你稱之爲連續的東西是連續的,並且在給定的週期內從內存的角度進行交錯,因此讀取每個工作項的第一個元素可以緩存剩餘的數據。但是在寫作時,沒有這種行爲,所以它變得更慢。由於讀/寫調度器(或者讀/寫組合的任何部分)可以提供n個工作項,這些工作項可以在大量相鄰元素上統一讀寫,所以稱爲「交錯」的內容在內存的給定週期內實際上是連續的。 –
順便說一句,再次感謝指出文檔。我從那裏瞭解到:「南島設備不支持合併寫入;但是,工作組內的連續地址提供了最佳性能。」這個信息看起來很奇怪,因爲我的實驗給出了完全不同的結果。還是我完全相反地理解「合併」的整個概念? – qpdb