2014-06-11 60 views
15

爲了減少我的應用程序從主機到設備的傳輸時間,我想使用固定內存。 NVIDIA's best practices guide提出映射緩衝劑,並使用下面的代碼寫入數據:如何在OpenCL中使用固定內存/映射內存

cDataIn = (unsigned char*)clEnqueueMapBuffer(cqCommandQue, cmPinnedBufIn, CL_TRUE,CL_MAP_WRITE, 0, memSize, 0, NULL, NULL, NULL); 

for(unsigned int i = 0; i < memSize; i++) 
{ 
    cDataIn[i] = (unsigned char)(i & 0xff); 
} 

clEnqueueWriteBuffer(cqCommandQue, cmDevBufIn, CL_FALSE, 0, 
szBuffBytes, cDataIn, 0, NULL, NULL); 

Intel's optimization guide推薦使用調用clEnqueueMapBuffer和clEnqueueUnmapBuffer代替調用clEnqueueReadBuffer或clEnqueueWriteBuffer的。

什麼是使用固定內存/映射內存的正確方法?是否有必要使用enqueueWriteBuffer寫入數據還是enqueueMapBuffer足夠?

另外,CL_MEM_ALLOC_HOST_PTR和CL_MEM_USE_HOST_PTR之間的區別是什麼?

回答

10

這是一個很有趣的話題,很少有人詳細說明。 我會嘗試定義它是如何工作的。

固定內存指的是與主機中存在設備一樣的內存,因此可以在這兩個內存之間進行DMA寫入。提高複製性能。 這就是爲什麼它在緩衝區創建參數中需要CL_MEM_ALLOC_HOST_PTR

另一方面,CL_MEM_USE_HOST_PTR將採取一個主機指針緩衝區創建,規範不清楚這是否可以是固定內存。但一般來說,它不應該以這種方式固定內存,因爲主機指針並未被OpenCL API保留,並且不清楚它駐留在內存中的位置。


關於Map/Read問題。 都可以。他們會有同樣的表現。 兩個技術之間的不同之處在於:

  • 供圖/取消映射:你需要讀/寫,並取消映射事後之前映射。這樣你可以確保數據的一致性。這些都是API調用,需要時間來完成以及異步。好的是,你不需要持有任何其他的東西,而不是緩衝對象。
  • 對於地圖+讀/寫:在創建內存區域時,您需要執行一次Map並保存指針值。然後,在破壞緩衝區時,您需要先取消映射然後將其銷燬。您一直需要持有buffer+Mapped_Buffer。好處是你現在可以將clEnqueueRead/Write映射到該映射的指針。該API將等待固定的數據保持一致,然後考慮完成。它使用起來更容易,因爲它就像在一個鏡頭中執行地圖+取消地圖一樣。

的讀/寫模式更容易使用,特別是對於重複讀,但不一樣多功能手動映射選項,因爲你不能寫一個read only地圖,也不會讀一個write only地圖。但是對於一般用途來說,讀取的變量永遠不會被寫入,反之亦然。


我的理解是,英特爾的建議,是指「使用地圖,而不是普通的讀/寫」,而不是「當你使用地圖,不要使用讀/寫上映射的指針」

您是否檢查過nVIDIA對英特爾硬件的推薦?我認爲它應該能夠工作,但是我不知道這個操作是否確實是最佳的(如AMD或nVIDIA HW)。

+0

真的很奇怪,你需要使用clEnqueueWriteBuffer()以及Map/Unmap。因爲當你做Map時,然後改變主機指針,你實際上正在改變CPU和GPU數據。當你進行unmap時,數據將在CPU和GPU之間同步。我不明白您需要在MAP +更改cDataIn和UNMAP之間執行clEnqueueWriteBuffer。很奇怪... –