?Abstract: 本文主要介紹CUDA內存管理,以及CUDA內存模型下的各種內存的特點。

Keywords: CUDA內存管理,CUDA內存分配和釋放,CUDA內存傳輸,固定內存,零拷貝內存,統一虛擬定址,統一內存定址

開篇廢話

迷茫和困惑會影響我們的前進,徹底擺脫也許不太可能,但是我們必須肯定信仰的力量,專註你所熱愛的,就會走出迷霧。

CUDA編程的目的是給我們的程序加速,尤其是機器學習,人工智慧類的計算,CPU不能高效完成,說白了,我們在控制硬體,控制硬體的語言屬於底層語言,比如C語言,最頭疼的就是管理內存,python,php這些語言有自己的內存管理機制,c語言的內存管理機制——程序員管理。這樣的好處是學起來特別困難,但是學會了又會覺得特別爽,因為自由,你可以隨意的控制計算機的計算過程。CUDA是C語言的擴展,內存方面基本集成了C語言的方式,由程序員控制CUDA內存,當然,這些內存的物理設備是在GPU上的,而且與CPU內存分配不同,CPU內存分配完就完事了,GPU還涉及到數據傳輸,主機和設備之間的傳輸。

接下來我們要了解的是:- 分配釋放設備內存- 在主機和設備間傳輸內存

為達到最優性能,CUDA提供了在主機端準備設備內存的函數,並且顯式地向設備傳遞數據,顯式的從設備取回數據。

內存分配和釋放

內存的分配和釋放我們在前面已經用過很多次了,前面所有的要計算的例子都包含這一步:

cudaError_t cudaMalloc(void ** devPtr,size_t count)

這個函數用過很多次了,唯一要注意的是第一個參數,是指針的指針,一般的用法是首先我們生命一個指針變數,然後調用這個函數:

float * devMem=NULL;
cudaError_t cudaMalloc((float**) devMem, count)

這裡是這樣的,devMem是一個指針,定義時初始化指向NULL,這樣做是安全的,避免出現野指針,cudaMalloc函數要修改devMem的值,所以必須把他的指針傳遞給函數,如果把devMem當做參數傳遞,經過函數後,指針的內容還是NULL。

不知道這個解釋有沒有聽明白,通俗的講,如果一個參數想要在函數中被修改,那麼一定要傳遞他的地址給函數,如果只傳遞本身,函數是值傳遞的,不會改變參數的值。內存分配支持所有的數據類型,什麼int,float。。。這些都無所謂,因為他是按照位元組分配的,只要是正數位元組的變數都能分配,當然我們根本沒有半個位元組的東西。函數執行失敗返回:cudaErrorMemoryAllocation.當分配完地址後,可以使用下面函數進行初始化:

cudaError_t cudaMemset(void * devPtr,int value,size_t count)

用法和Memset類似,但是注意,這些被我們操作的內存對應的物理內存都在GPU上。

當分配的內存不被使用時,使用下面語句釋放程序。

cudaError_t cudaFree(void * devPtr)

注意這個參數一定是前面cudaMalloc類的函數(還有其他分配函數)分配到空間,如果輸入非法指針參數,會返回 cudaErrorInvalidDevicePointer 錯誤,如果重複釋放一個空間,也會報錯。

目前為止,套路基本和C語言一致。但是,設備內存的分配和釋放非常影響性能,所以,盡量重複利用!

內存傳輸

完整內容參考https://face2ai.com/CUDA-F-4-2-內存管理/


推薦閱讀:
相關文章