与第三方CUDA库链接会降低cudaMalloc的速度

时间:2012-07-26 07:44:14

标签: cuda gpu gpgpu gpu-programming

在CUDA 4.x上第一次调用cudaMalloc并不是秘密 可能是非常缓慢(有几次报道),似乎是CUDA驱动程序中的一个错误。

最近,我注意到了奇怪的行为:cudaMalloc的运行时间 直接取决于我链接到我的程序的第三方CUDA库的数量 (请注意,我不使用这些库,只需将程序与它们链接起来)

我使用以下程序运行了一些测试:

int main() {
  cudaSetDevice(0);
  unsigned int *ptr = 0;
  cudaMalloc((void **)&ptr, 2000000 * sizeof(unsigned int));   
  cudaFree(ptr);
return 1;
}

结果如下:

  • 链接:-lcudart -lnpp -lcufft -lcublas -lcusparse -lcurand      运行时间:5.852449

  • 链接:-lcudart -lnpp -lcufft -lcublas运行时间:1.425120

  • 链接:-lcudart -lnpp -lcufft运行时间:0.905424

  • 链接:-lcudart运行时间:0.394558

根据'gdb',时间确实进入我的cudaMalloc,所以它不是由某些人引起的 库初始化例程..

我想知道是否有人对此有合理的解释?

1 个答案:

答案 0 :(得分:11)

在您的示例中,cudaMalloc调用会在GPU上启动延迟上下文建立。当包含运行时API库时,必须检查它们的二进制有效负载,并且它们包含的GPU elf符号和对象合并到上下文中。库中存在的库越多,您可以预期该过程的时间越长。此外,如果任何Cubin中存在体系结构不匹配并且您具有向后兼容的GPU,则它还可以触发驱动程序重新编译目标GPU的设备代码。在一个非常极端的情况下,我看到一个与旧版CUBLAS相关联的旧应用程序需要10秒才能在Fermi GPU上运行时加载和初始化。

您可以通过发出cudaFree这样的调用来明确强制延迟上下文建立:

int main() {
    cudaSetDevice(0);
    cudaFree(0); // context establishment happens here
    unsigned int *ptr = 0;
    cudaMalloc((void **)&ptr, 2000000 * sizeof(unsigned int));   
    cudaFree(ptr);
  return 1;
}

如果您使用计时器对此版本进行配置或检测,您会发现第一个cudaFree调用消耗了大部分运行时间,cudaMalloc调用几乎完全免费。