cudaMemcpy太慢了

Cal*_*han 10 cuda bus

我用cudaMemcpy()一次将1GB的数据准确复制到设备上.这需要5.9秒.反过来需要5.1s.这是正常的吗?
在复制之前,函数本身是否有这么多开销?理论上,PCIe总线的吞吐量至少应为4GB/s.
没有内存传输重叠,因为特斯拉C870不支持它.任何提示?

编辑2:我的测试程序+更新的时间; 我希望阅读不是太多!
cutCreateTimer()功能不会编译我:"错误:标识符'cutCreateTimer’不确定" -这可能与安装在计算机上的旧版本的CUDA(2.0)

 __host__ void time_int(int print){
static struct timeval t1; /* var for previous time stamp */
static struct timeval t2; /* var of current time stamp */
double time;
if(gettimeofday(&t2, 0) == -1) return;
if(print != 0){
  time = (double) (t2.tv_sec - t1.tv_sec) + ((double) (t2.tv_usec - t1.tv_usec)) / 1000000.0;
  printf(...);
}
t1 = t2;
}

main:
time(0);
void *x;
cudaMallocHost(&x,1073741824);
void *y;
cudaMalloc(&y, 1073741824);
time(1);
cudaMemcpy(y,x,1073741824, cudaMemcpyHostToDevice);
time(1);
cudaMemcpy(x,y,1073741824, cudaMemcpyDeviceToHost);
time(1);
Run Code Online (Sandbox Code Playgroud)

显示时序为:
0.86大学拨款
0.197第一个副本
5.02的第二个副本,
奇怪的是:虽然它显示0.197s的第一个副本需要,如果我看的程序运行更长的时间.

osg*_*sgx 9

是的,这很正常.cudaMemcpy()做了很多检查和工程(中如果主机内存是由平常分配malloc()mmap()).它应检查每页数据是否在内存中,并将页面(逐个)移动到驱动程序.

您可以使用cudaHostAlloc函数cudaMallocHost分配内存而不是malloc.它将分配固定存储器,该存储器始终存储在RAM中,并且可以直接由GPU的DMA访问(更快cudaMemcpy()).引用第一个链接:

分配计数页面锁定且设备可访问的主机内存字节.驱动程序跟踪使用此功能分配的虚拟内存范围,并自动加速对cudaMemcpy()等函数的调用.

唯一的限制因素是系统中固定内存的总量是有限的(不超过RAM大小;最好使用不超过RAM - 1Gb):

分配过多的固定内存可能会降低系统性能,因为它会减少系统可用于分页的内存量.因此,最好谨慎地使用此功能来为主机和设备之间的数据交换分配暂存区域.


nju*_*ffa 6

假设传输时间准确,从固定内存传输1 GB的1.1秒似乎很慢.您确定PCIe插槽配置的宽度是否正确?要获得完整性能,您需要x16配置.一些平台提供两个插槽,其中一个配置为x16,另一个配置为x4.因此,如果您的机器有两个插槽,您可能需要尝试将卡移动到另一个插槽中.其他系统有两个插槽,如果只占用一个插槽,则可获得x16,但如果两个插槽都被占用,则会获得两个x8插槽.BIOS设置可以帮助确定如何配置PCIe插槽.

特斯拉C870是一项相当古老的技术,但如果我没记错的话,使用第一代PCIe接口的这些部件应该可以正确地从固定存储器传输大约2 GB/s的速率.目前的Fermi级GPU使用PCIe gen 2接口,并且可以从固定存储器传输5+ GB/s(用于吞吐量测量,1 GB/s = 10 ^ 9字节/秒).

请注意,PCIe使用分组传输,并且在通用芯片组支持的分组大小处,分组开销可能很大,而较新的芯片组通常支持稍长的分组.一个不太可能超过标称每个方向最大值的70%(对于PCIe 1.0 x16为4 GB/s,对于PCIe 2.0 x16为8 GB/s),即使是从/到固定主机内存的传输也是如此.这是一份白皮书,解释了开销问题,并有一个方便的图表显示了各种数据包大小可实现的利用率:

http://www.plxtech.com/files/pdf/technical/expresslane/Choosing_PCIe_Packet_Payload_Size.pdf