CUDA程式設計 zero copy

2021-07-09 20:19:09 字數 2963 閱讀 3247

zero copy(零複製)是一種特殊形式的記憶體對映,它允許你將host記憶體直接對映到裝置記憶體空間上。其實就是裝置可以通過直接記憶體訪問(direct memory access,dma)方式來訪問主機的鎖頁記憶體。

現代作業系統都支援虛擬記憶體,作業系統實現虛擬記憶體的主要方法就是通過分頁機制。作業系統將記憶體中暫時不使用的內容換出到外存(硬碟等大容量儲存)上,從而騰出空間存放將要調入記憶體的資訊。這樣,系統好像為使用者提供了乙個比實際記憶體大得多的儲存器,稱為虛擬儲存器。

鎖頁就是將記憶體頁面標記為不可被作業系統換出的記憶體。所以裝置驅動程式給這些外設程式設計時,可以使用頁面的實體地址直接訪問記憶體(dma),從而避免從外存到記憶體的複製操作。cpu 仍然可以訪問上述鎖頁記憶體,但是此記憶體是不能移動或換頁到磁碟上的。cuda 中把鎖頁記憶體稱為pinned host memory 或者page-locked host memory。

使用鎖頁記憶體(page-locked host memory)有一些優勢:

然而鎖頁主機儲存器是稀缺資源,所以鎖頁記憶體分配得多的話,分配會失敗。另外由於減少了系統可分頁的物理儲存器數量,分配太多的分頁鎖定記憶體會降低系統的整體效能

在gpu 上分配的記憶體預設都是鎖頁記憶體,這只是因為gpu 不支援將記憶體交換到磁碟上。在主機上分配的記憶體預設都是可分頁,如果需要分配鎖頁記憶體,則需要使用cudamallochost() 或者cudahostalloc()。釋放時需要使用cudafreehost() 釋放這一塊記憶體。呼叫常規的c函式釋放,可能會崩潰或者出現一些不常見的錯誤。也可以通過函式cudahostregister() 把可分頁記憶體標記為鎖頁記憶體。

__host__ ​cudaerror_t cudamallochost ( void** ptr, size_t size )

__host__ ​cudaerror_t cudahostalloc ( void** phost, size_t size, unsigned

int flags )

__host__ ​cudaerror_t cudafreehost ( void* ptr )

cudahostalloc() 多了乙個可選形參flags ,功能更強大。flags 的值可以取如下值。

#define cudahostallocdefault 0x00

default page-locked allocation flag

map allocation into device space

#define cudahostallocportable 0x01

pinned memory accessible by

all cuda contexts

#define cudahostallocwritecombined 0x04

write-combined memory

cudahostregister() 函式用於把已經的存在的可分頁記憶體註冊為分頁鎖定的。

__host__ ​cudaerror_t cudahostregister ( void* ptr, size_t size, unsigned

int flags )

flags 是乙個可選形參,可以取如下值。

#define cudahostregisterdefault 0x00

default host memory registration flag

#define cudahostregisteriomemory 0x04

map registered memory into device space

#define cudahostregisterportable 0x01

pinned memory accessible by all cuda contexts

下面分別介紹這些flags 的作用。

一塊鎖頁記憶體可被系統中的所有裝置使用(乙個系統中有多個cuda裝置時)。 啟用這個特性需要在呼叫cudahostalloc() 時使用cudahostallocportable 選項,或者在呼叫cudahostregister() 使用cudahostregisterportable 選項。

預設情況下,鎖頁主機儲存是可快取的。可以在呼叫cudahostalloc() 時傳入cudahostallocwritecombined 標籤使其被分配為寫結合的(write-combining memory)。寫結合儲存不使用l1 和l2 cache,所以程式的其它部分就有更多的快取可用。此外,寫結合記憶體通過pci-e 傳輸資料時不會被監視(snoop),這能夠獲得高達40%的傳輸加速。 從主機讀取寫結合儲存非常慢(因為沒有使用l1、l2cache),所以寫結合儲存應當只用於那些主機只寫的儲存。

因為對映的鎖頁主機記憶體是主機和裝置之間共享的,所以在使用cuda stream 或者cuda event 時必須對記憶體讀寫同步;避免潛在的寫後讀,讀後寫或者寫後寫等多執行緒同步問題。

為了能夠對任何對映的鎖頁主機記憶體解引用裝置指標,必須在呼叫任何cuda 執行時函式前呼叫cudasetdeviceflags(),並傳入cudadevicemaphost 標籤。否則,cudahostgetdevicepointer() 將會返回錯誤。

如果裝置不支援被對映分頁鎖定儲存,cudahostgetdevicepointer() 將會返回錯誤。程式設計師可以檢查canmaphostmemory 屬性,如果裝置支援對映鎖頁主機記憶體,將會返回1。

注意:使用對映鎖頁主機記憶體看,原子操作將不再保證原子性。cudahostregisteriomemory 是cudahostregister() 特有的選項,可以把主機記憶體對映到io 位址空間。

[1][2] cook, shane (2013). cuda programming: a developer』s guide to parallel computing with gpus (1st ed.). morgan kaufmann publishers inc. pp. 334–335. isbn 9780124159334.

CUDA程式設計

cuda目前支援linux和windows作業系統。進行cuda開發需要依次安裝驅動 toolkit sdk三個軟體。在 安裝目錄 c src目錄下有很多的例程可以進行學習。cuda 的核心有三個重要抽象概念 執行緒組層次結構 共享儲存器 遮蔽同步 barrier synchronization 可...

cuda程式設計

參照 一 gpu與cpu的聯絡與區別 gpu上可以進行資料結構統一的運算,gpu上整合大量相對cpu邏輯計算單元簡單的計算部件,利於序列。cpu上可以邏輯計算 流程控制等複雜的過程,利於並行。總而言之,gpu是乙個 人多力量大 的部件,而cpu是乙個 單兵作戰力強 的部件。基於cpu gpu的異構計...

cuda程式設計初探

指標有了一點心得,定義跟使用是有區別的,其實指標就是乙個位址變數,定義指標的時候會加乙個 使用的時候,p是指指標p指向的那個值,p就為位址。當然可以定義多重指標,原理都是一樣。指標從根本上來說就是一種索引的概念,從這個意義上說,將陣列理解成乙個指標就好理解了,a i 中i表示索引,a i 表示指向的...