CUDA学习笔记- cudaMemPrefetchAsync
统一内存(CUDA Unified Memory)让数据在GPU和CPU之间的搬运对用户透明,在编写程序时无需频繁的手动搬移,简化了程序编写。但是,有些情况我们需要对数据进行大规模IO并且已知操作设备,此时如果操作到内存页再进行自动搬移会在计算过程中插入很多内存搬移,导致性能下降。为了防止这种情况,可以通过cudaMemPrefetchAsync预取函数,在操作前将内存显式迁移。
函数功能
在数据被使用之前,提前将数据迁移到对应处理器的内存中,并在处理器开始访问该数据前将其映射到该处理器的页表中。
函数原型
CUDA<=12.9
cudaError_t cudaMemPrefetchAsync(
const void *devPtr,
size_t count,
int dstDevice,
cudaStream_t stream=0);
调用 CudaMemPrefetchAsync() API 后,将在给定流 stream 内把统一内存空间中 [DevPtr,DevPtr+count] 区间的数据迁移到目的地设备 dstDevice 的内存上,如果要迁移到主机内存上,则 dstDevice 参数应传入 cudaCpuDeviceID。
stream 使用NULL/0表示默认流。
CUDA>=13/0
cudaError_t cudaMemPrefetchAsync(
const void *devPtr,
size_t count,
struct cudaMemLocation location,
unsigned int flags,
cudaStream_t stream=0);
其中:
struct cudaMemLocation{
int id,
enumcudaMemLocationType type};
id指定GPU位置(当type为cudaMemLocationTypeDevice时);当type为cudaMemLocationTypeHost时,表示CPU且id无用。flages暂时无用,必须为0(in cuda13)。
使用注意事项
WSL2/Win上受限支持
由于统一内存在Windows上的支持是受限的,一些功能无法使用,包括预取函数。直接使用该函数会报CUDA error: invalid device ordinal。此时,cudaDeviceProp::concurrentManagedAccess 的值为0.
cudaDeviceProp prop;
cudaGetDeviceProperties(&prop, device);
printf("CUDA device properties concurrentManagedAccess: %d\n", prop.concurrentManagedAccess);
Jetson使用
Jetson的统一内存是物理上的统一,因此理论上不需要调用该函数,但是在多平台中可能会出现调用情况,此时会出现invalid device ordinal。
这是因为cudaMemPrefetchAsync() 在一些设备不支持(cudaDeviceProp::concurrentManagedAccess=0,受限的统一内存支持),此时,内存必须用cudaMallocManaged分配,而且不支持CPU/GPU同时读写。
在更新的平台(Thor -cudaDeviceProp::concurrentManagedAccess=1 ),支持真正意义上的统一,malloc分配的也可以,CPU/GPU同时读写,如同普通内存。

浙公网安备 33010602011771号