請注意,其實有兩種。在分配緩衝區時,您有CL_MEM_READ_ONLY
,CL_MEM_WRITE_ONLY
和CL_MEM_READ_WRITE
,但是您也有__read_only
,__write_only
和__read_write
用於在內核代碼中修飾您的指針。
這些可以用於優化和錯誤檢查。讓我們先看看演出。如果遇到只寫緩衝區,寫入不需要被緩存(如在寫入緩存中一樣),爲讀取保存更多緩存。這很大程度上取決於GPU硬件,至少NVIDIA硬件確實需要實際執行此指令(.cs
和.lu
修改器)。你可以參考他們的PTX ISA。我還沒有看到實際進行優化編譯器的任何證據,如:
__kernel void Memset4(__global __write_only unsigned int *p_dest,
const unsigned int n_dword_num)
{
unsigned int i = get_global_id(0);
if(i < n_dword_num)
p_dest[i] = 0; // this
}
被編譯爲:
st.global.u32 [%r10], %r11; // no cache operation specified
這使得作爲CUDA沒有爲那些預選賽所以編譯器等同意義很可能會默默地忽略這些。但把它們放在那裏並沒有什麼壞處,我們未來可能會更幸運。在CUDA中,使用__ldg
函數以及使用編譯器標誌來選擇是否在L1中緩存全局內存傳輸(-Xptxas -dlcm=cg
),從而公開了一些此功能。如果發現繞過緩存產生主要優勢,您也可以始終使用asm
。
至於錯誤檢查,在內核聲明中使用const
說明符很容易避免寫入只讀緩衝區。在純粹的「C」中不允許從只寫緩衝區讀取數據。
將這些緩衝區映射到主機內存時發生另一種可能的優化。映射CL_MEM_READ_ONLY
緩衝區時,映射區域可能會保持未初始化狀態,因爲主機只會寫入該內存,因此設備只能讀取該內存。同樣,在取消映射CL_MEM_WRITE_ONLY
緩衝區時,驅動程序不需要將主機內存(可能由主機修改)的內容從主機內存複製到設備內存。我沒有衡量這一點。
作爲一個方面說明,我已經嘗試使用:
inline unsigned int n_StreamingLoad(__global __read_only const unsigned int *p_src)
{
#ifdef NVIDIA
unsigned int n_result;
asm("ld.global.cs.u32 %r0, [%r1];" : "=r" (n_result) : "r" (p_src));
return n_result;
#else // NVIDIA
return *p_src; // generic
#endif // NVIDIA
}
inline void StreamingWrite(__global __write_only unsigned int *p_dest, const unsigned int n_value)
{
#ifdef NVIDIA
asm("st.global.cs.u32 [%r0], %r1;" : : "r" (p_dest), "r" (n_value) : "memory");
#else // NVIDIA
*p_dest = n_value; // generic
#endif // NVIDIA
}
它給你約15多GB /秒甚至與sm_35
設備的簡單的memcpy內核(對GTX 780和K40測試)。在sm_30
上沒有看到明顯的加速(不知道它是否意味着在那裏支持 - 雖然指令不會從ptx中剝離)。請注意,您需要自己定義NVIDIA
(或參閱Detect OpenCL device vendor in kernel code)。