CUDA程式設計中全局記憶體分為分頁記憶體,固定記憶體,零拷貝記憶體,統一虛拟尋址,統一記憶體位址。
一.分頁記憶體
利用malloc()申請的主機記憶體,即可分頁記憶體。
特點:可分頁記憶體傳輸資料到裝置時,首先需要配置設定固定記憶體,再傳遞到裝置端。
對主機而言,分頁記憶體可提高主機性能。
float* data;
malloc((void**)&data,sizeof(float)*N);
二.固定記憶體(pinned)- 鎖頁記憶體
利用cudaMallocHost()申請固定記憶體。
特點:裝置可直接通路固定記憶體,可提高傳輸性能,如圖所示。
float*data;
cudaMallocHost((void**)&data,sizeof(float)*N);
三.零拷貝記憶體
利用cudaHostAlloc()申請零拷貝記憶體。使用情況:(1)裝置不足時,可利用主機記憶體;(2)避免裝置和主機間的顯式傳輸; (3)提高PCI-e傳輸率。
特點:通常,主機無法通路裝置變量,裝置無法通路主機變量,但主機和裝置均可通路零拷貝記憶體。
float* data;
cudaHostAlloc((void**)&data,N*sizeof(float),unsigned int flags);
flags有4種:cudaHostAllocDefalt,
cudaHostAllocPortable,
cudaHostAllocWriteCombined,
cudaHostAllocMapped。
最後一種标示就是零拷貝記憶體。
使用方式:
1.主機通路零拷貝記憶體:直接使用可以。
2.裝置通路零拷貝記憶體:利用cudaGetDevicePointer((void**)&DevicePtr,void* HostPtr,unsiged int flag)擷取裝置零拷貝主機記憶體對應的裝置指針,然後将裝置指針傳入kernel函數。裝置就可直接通路主機記憶體了。
四.統一虛拟位址
利用cudaHostAlloc()擷取的零拷貝記憶體,在UVA(統一虛拟位址)之前,核函數使用的指針必須為經過cudaGetDevicePointer()獲得的裝置指針。而有了UVA之後,則省去了這一步,核函數可直接使用主機指針。
如圖所示。
五.統一記憶體位址
利用cudaMallocManaged()申請托管記憶體,“統一記憶體”建立了一個托管記憶體池,記憶體池中已配置設定的空間,可以用相同的記憶體位址(指針)在CPU和GPU上進行通路。
float* data;
cudaMallocManaged((void**)&data,sizeof(float)*N,unsiged int flags)
特點:完成了主機與裝置資料的自動拷貝,消除重複指針。