在CUDA中,使用**cudaMalloc()
來分配設(shè)備內(nèi)存,使用cudaFree()
**來釋放設(shè)備內(nèi)存。
cudaMallocManaged 統(tǒng)一內(nèi)存管理
**統(tǒng)一虛擬尋址(Unified Memory):使用cudaMallocManaged()
**來分配可以在CPU和GPU之間共享的內(nèi)存。無需關(guān)心數(shù)據(jù)在主機或設(shè)備上。
cudaMallocManaged
是一個CUDA運行時應(yīng)用程序接口(API)函數(shù),用于分配統(tǒng)一內(nèi)存(unified memory)。統(tǒng)一內(nèi)存是CUDA的一種內(nèi)存管理模型,它提供了一個單一的、在主機和設(shè)備間共享的內(nèi)存空間。
這個函數(shù)的原型如下:
__host__ cudaError_t cudaMallocManaged ( void** devPtr, size_t size, unsigned int flags = cudaMemAttachGlobal );
-
devPtr
是一個指針,指向分配的內(nèi)存的地址。 -
size
是請求分配的內(nèi)存的字節(jié)數(shù)。 -
flags
是一個可選的參數(shù),用于指示內(nèi)存的附著行為。默認值是cudaMemAttachGlobal
,意味著這塊內(nèi)存在所有的CUDA流中都是可見的。
cudaMallocManaged
函數(shù)的工作原理是基于按需頁面遷移"(on-demand page migration)的機制。當(dāng)GPU要訪問一塊統(tǒng)一內(nèi)存時,如果這塊內(nèi)存當(dāng)前并不在GPU的物理內(nèi)存中,就會觸發(fā)一個頁面遷移,將數(shù)據(jù)從CPU內(nèi)存遷移到GPU內(nèi)存。同樣,當(dāng)CPU要訪問一塊統(tǒng)一內(nèi)存時,如果這塊內(nèi)存當(dāng)前在GPU內(nèi)存中,就會觸發(fā)一個頁面遷移,將數(shù)據(jù)從GPU內(nèi)存遷移到CPU內(nèi)存。
頁面遷移可能引發(fā)的性能開銷。如果主機和設(shè)備頻繁地對同一塊內(nèi)存進行訪問,可能會導(dǎo)致"抖動"現(xiàn)象,即數(shù)據(jù)不斷地在主機和設(shè)備間遷移,這會大大降低程序的性能。
cudaDeviceSynchronize() &cudaStreamSynchronize()等待操作完成
cudaDeviceSynchronize()
是一個CUDA運行時應(yīng)用程序接口(API)函數(shù),用于阻塞主機代碼的執(zhí)行,直到設(shè)備上所有先前的任務(wù)都完成為止。這包括內(nèi)核執(zhí)行以及設(shè)備與主機之間的內(nèi)存?zhèn)鬏敗?/p>
這個函數(shù)在調(diào)試和性能測量中非常有用,因為它可以確保所有設(shè)備上的任務(wù)在繼續(xù)執(zhí)行主機代碼之前都已完成。例如,如果你想測量GPU內(nèi)核的執(zhí)行時間,你需要在內(nèi)核啟動和停止之間插入cudaDeviceSynchronize()
來確保內(nèi)核完成執(zhí)行。
然而,cudaDeviceSynchronize()
應(yīng)謹慎使用,因為它會阻塞主機代碼的執(zhí)行,這可能會導(dǎo)致性能下降。在生產(chǎn)代碼中,通常優(yōu)先使用非阻塞同步函數(shù)(如cudaStreamSynchronize()
),這樣可以在設(shè)備執(zhí)行任務(wù)時讓主機執(zhí)行其他任務(wù)。
cudaMemPrefetchAsync 預(yù)遷移數(shù)據(jù)
cudaMemPrefetchAsync
用于管理和優(yōu)化數(shù)據(jù)在主機和設(shè)備之間的遷移,此函數(shù)可以預(yù)先遷移數(shù)據(jù)。
cudaMemPrefetchAsync
的工作原理主要是基于CUDA內(nèi)存管理系統(tǒng)和硬件的協(xié)作。當(dāng)調(diào)用此函數(shù)時,CUDA運行時系統(tǒng)會在后臺發(fā)起一個數(shù)據(jù)遷移操作,將數(shù)據(jù)從源設(shè)備遷移到目標(biāo)設(shè)備。
如果目標(biāo)設(shè)備是GPU,系統(tǒng)會將數(shù)據(jù)從主機內(nèi)存復(fù)制到GPU內(nèi)存。這個操作通常在CPU調(diào)用cudaMemPrefetchAsync
之后立即開始,但實際的開始時間取決于系統(tǒng)的調(diào)度策略和設(shè)備的負載情況。一旦數(shù)據(jù)遷移到GPU,GPU上的CUDA內(nèi)核就可以直接訪問這些數(shù)據(jù),而無需等待從主機內(nèi)存的遷移。這可以大大減少內(nèi)存訪問的延遲,提高程序的性能。
如果目標(biāo)設(shè)備是CPU,系統(tǒng)會將數(shù)據(jù)從GPU內(nèi)存復(fù)制回主機內(nèi)存。這個操作在GPU完成其上的所有先前操作之后才開始,以保證數(shù)據(jù)的一致性。一旦數(shù)據(jù)遷回主機,CPU就可以直接訪問這些數(shù)據(jù),無需等待從GPU內(nèi)存的遷移。這對于需要在CPU上進一步處理的數(shù)據(jù)非常有用。cudaMemPrefetchAsync
函數(shù)還可以接受一個CUDA流作為參數(shù),用于控制數(shù)據(jù)遷移的執(zhí)行順序。在同一個流中,操作按照它們被提交的順序執(zhí)行。這意味著,如果在同一個流中先后調(diào)用cudaMemPrefetchAsync
和一個CUDA內(nèi)核,那么CUDA運行時系統(tǒng)會確保數(shù)據(jù)遷移完成后才開始執(zhí)行內(nèi)核。這種機制提供了一種在GPU和CPU之間精細控制數(shù)據(jù)流的方式。
函數(shù)的原型如下:
cudaError_t cudaMemPrefetchAsync(const void* devPtr, size_t count, int dstDevice, cudaStream_t stream = 0);
其中,
-
devPtr
是一個指向需要遷移的數(shù)據(jù)的指針。 -
count
是需要遷移的數(shù)據(jù)的字節(jié)數(shù)。 -
dstDevice
是目標(biāo)設(shè)備。例如,可以設(shè)置為特定的GPU設(shè)備ID,或者設(shè)置為cudaCpuDeviceId
表示CPU。 -
stream
是一個可選參數(shù),表示CUDA流,用于異步操作。
通過使用cudaMemPrefetchAsync
,可以控制何時以及如何將數(shù)據(jù)遷移至GPU或CPU,從而優(yōu)化程序性能,減少內(nèi)存訪問的延遲。
CUDA Stream
在CUDA編程模型中,Stream可以被看作是設(shè)備上執(zhí)行的一系列命令的隊列。這些命令可以包括內(nèi)核的執(zhí)行、內(nèi)存?zhèn)鬏數(shù)?。在同一個stream中,這些命令是按照它們入隊列的順序來執(zhí)行的。而不同的stream之間則可以并發(fā)執(zhí)行,這使得我們可以通過合理地使用多個stream來提高程序的并行度,從而提高程序的執(zhí)行效率。
在CUDA中,我們可以通過cudaStreamCreate
函數(shù)來創(chuàng)建一個新的stream。以下是一個簡單的例子:
cudaStream_t stream;
cudaStreamCreate(&stream);
首先定義了一個cudaStream_t
類型的變量stream
,然后調(diào)用了cudaStreamCreate
函數(shù)來創(chuàng)建一個新的stream,這個新創(chuàng)建的stream的句柄被存儲在stream
變量中。
我們可以在調(diào)用內(nèi)核或者內(nèi)存?zhèn)鬏敽瘮?shù)時指定stream參數(shù),例如:
myKernel<<<gridDim, blockDim, 0, stream>>>(...);
cudaMemcpyAsync(dst, src, count, cudaMemcpyHostToDevice, stream);
在這個例子中,我們在調(diào)用myKernel
內(nèi)核和cudaMemcpyAsync
函數(shù)時分別指定了stream參數(shù),這意味著這兩個操作將會在我們創(chuàng)建的stream
中被執(zhí)行。文章來源:http://www.zghlxwxcb.cn/news/detail-800088.html
在使用完stream后,我們需要調(diào)用cudaStreamDestroy
函數(shù)來釋放stream占用的資源,例如:文章來源地址http://www.zghlxwxcb.cn/news/detail-800088.html
cudaStreamDestroy(stream);// 銷毀流
到了這里,關(guān)于【cuda】二、基礎(chǔ)知識: 內(nèi)存管理 同步的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!