第一个cudaMalloc(K40 vs K20)的缓慢,即使在cudaSetDevice之后

时间:2015-10-29 00:57:33

标签: c++ cuda nsight tesla

我理解CUDA会在第一次API调用期间进行初始化,但花费的时间太多了。即使在单独的cudaSetDevice之后

测试计划:

使用CUDA 7.0(compute_35)+ Visual Studio 2012 + NSight 4.5构建相同的程序,然后在2台独立的机器上运行(无需重建)

在第一个cudaMalloc之前,我称之为“cudaSetDevice”

在我的电脑上:Win7 + Tesla K20,第一个cudaMalloc需要150毫秒

在我的服务器上:Win2012 + Tesla K40,需要1100毫秒!!

对于这两台机器,后续的cudaMalloc要快得多。

我的问题是:

1,为什么K40需要更长的时间(1100ms vs 150ms)才能获得第一个cudaMalloc?因为K40应该比K20更好

2,我想" cudaSetDevice"可以捕获Init时间吗?例如This Answer from talonmies

3,如果初始化是不可避免的,那么当进程B在同一GPU中运行时,处理A是否可以在GPU中保持其状态(或上下文)?我明白我最好在"独家"中运行GPU。模式,但可以处理A"暂停"所以它以后不需要再次初始化GPU?

提前致谢

2 个答案:

答案 0 :(得分:5)

  

1,为什么K40需要更长的时间(1100ms vs 150ms)才能获得第一个cudaMalloc?因为K40应该比K20更好

未指定初始化过程的详细信息,但通过观察,系统内存量会影响初始化时间。 CUDA初始化通常包括UVM的建立,其涉及设备和主机存储器映射的协调。如果您的服务器具有比PC更多的系统内存,则可以解释初始化时间的差异。操作系统也可能有效,最后GPU的内存大小可能会产生影响。

  

2,我想" cudaSetDevice"可以捕获Init时间吗?例如本答案来自talonmies

CUDA初始化过程是一个"懒惰的"初始化。这意味着将完成足够的初始化过程以支持所请求的操作。如果请求的操作是cudaSetDevice,则与请求的操作是cudaMalloc相比,这可能需要更少的初始化(这意味着所需的表观时间可能更短)。这意味着一些初始化开销可能被吸收到cudaSetDevice操作中,而一些额外的初始化开销可能被吸收到后续的cudaMalloc操作中。

  

3,如果初始化是不可避免的,那么当进程B在同一GPU中运行时,处理A是否可以在GPU中保持其状态(或上下文)?我明白我最好在"独家"中运行GPU。模式,但可以处理A"暂停"所以它以后不需要再次初始化GPU?

独立主机进程通常会产生独立的CUDA contexts。 CUDA上下文具有与之关联的初始化要求,因此如果需要初始化新的CUDA上下文(可能来自单独的主机进程),则可能已经在设备上初始化了另一个单独的cuda上下文的事实将不会提供太多益处。通常,保持进程处于活动状态涉及保持应用程序在该进程中运行。应用程序有各种机制来睡眠"或暂停行为。只要应用程序没有终止,该应用程序建立的任何上下文都不应该要求重新初始化(除非调用cudaDeviceReset,否则可能除外)。

通常,通过设置GPU持久性模式(使用nvidia-smi),可以在允许GPU进入深度空闲模式的系统上获得一些好处。然而,这与GeForce GPU无关,也不一定与Windows系统相关。

此外,在多GPU系统上,如果应用程序不需要多个GPU,则通常可以通过使用CUDA_VISIBLE_DEVICES environment variable来避免某些初始化时间,以限制CUDA运行时仅使用必要的设备。

答案 1 :(得分:2)

根据编译代码的目标体系结构和运行代码的体系结构,JIT编译可以使用第一个cudaMalloc(或任何其他)调用启动。 "如果找不到二进制代码但是PTX可用,那么驱动程序将编译PTX代码。"更多细节:

http://devblogs.nvidia.com/parallelforall/cuda-pro-tip-understand-fat-binaries-jit-caching/