我同时使用GPU和CPU。当我评测内存传输时,我发现cuBLAS中的异步调用并不是异步的。
我有一个代码,它的作用类似于下面的
cudaEvent_t event;
cudaEventCreate(&event);
// time-point A
cublasSetVectorAsync(n, elemSize, x, incx, y, incy, 0);
cudaEventRecord(event);
// time-point B
cudaEventSynchronize(event);
// time-point C
我使用sys/time.h
来配置文件(为了清楚起见,省略了代码)。我发现cublasSetVectorAsync
调用在时间上占主导地位,就好像它的行为是同步的。即,持续时间A-B比持续时间B-C长得多,并且随着转移大小的增加而增加。
造成这种情况的可能原因是什么?是否有我需要在某个地方设置的环境变量或我需要使用的更新驱动程序?
我使用的是带有Cuda编译工具的GeForce GTX 285,4.1版,V0.2.1221
cublasSetVectorAsync
是围绕cudaMemcpyAsync
的一个薄包装。不幸的是,在某些情况下,该函数的名称用词不当,如CUDA参考手册中本页所述。
值得注意的是:
对于从可分页主机内存到设备内存的传输,在启动复制之前执行流同步。一旦可分页缓冲区被复制到暂存内存,用于DMA传输到设备内存,该函数就会返回,但DMA到最终目的地可能尚未完成。
和
对于从可分页主机内存到设备内存的传输,主机内存会立即复制到暂存缓冲区(不执行设备同步)。一旦可分页缓冲区被复制到暂存内存,函数就会返回。到最终目的地的DMA传输可能尚未完成。
因此,问题的解决方案可能只是使用cudaHostAlloc
而不是标准的malloc
(或C++new
)来分配主机数据阵列x
。
或者,如果您的GPU和CUDA版本支持它,您可以使用malloc
,然后在malloc
-ed指针上调用cudaHostRegister
。请注意文档中的条件,即必须使用cudaDeviceMapHost
标志创建CUDA上下文,才能使cudaHostRegister
生效(请参阅cudaSetDeviceFlags
的文档。
在cuBLAS/cuSPARSE中,如果不指定不同的流,则会在流0中发生。要指定流,必须使用cublasStream(请参阅cuBLAS文档)。