*更多测试显示CPU的Ram缓慢与CUDA无关。事实证明,Func2(CPU)是CPU密集型但不是内存密集型,然后对于我的program1,内存压力较小,因为它占用了CPU的Func2。对于program2(GPU),随着Func2与GPU变得非常快,Func1占用CPU并对内存施加很大压力,导致Func1的缓慢*
简短版本:如果我在同一台服务器上同时运行20个进程,我注意到当涉及GPU时CPU的运行速度要慢得多(与纯CPU进程相比)
长版:
我的服务器:Win Server 2012,48个核心(24个超线程),192 GB Ram(20个进程仅使用~40GB),4个K40卡
我的程序1(CPU版本):
For 30 iterations:
Func1(CPU): 6s (lot's CPU memory access)
Func2(CPU): 60s (lot's CPU memory access)
我的程序2(GPU版本,为Func1使用CPU核心,为Func2使用K40s):
//1 K40 will hold 5 contexts at the same time, till end of the 30 iterations
cudaSetDevice //very slow, can be few seconds
cudaMalloc ~1GB //can be another few seconds
For 30 iterations:
Func1(CPU): 6s
Func2(GPU), 1s (60X speedup) //share GPU via named_mutex
如果我一起运行20个program1(CPU),我注意到Func1的6s平均变为12s
对于20 program2(GPU),Func1需要 ~42s 来完成,而我的Func2(GPU)仍然是~1s(这1s包括锁定GPU,一些cudaMemcpy和内核调用。我认为这也包括GPU上下文切换)。所以看来GPU自身的性能不会受到太大影响,而CPU确实(通过GPU)
所以我怀疑cudaSetDevice / cudaMalloc / cudaMemcpy正在影响CPU的Ram访问?如果是真的,使用多核CPU和& GPU会受到影响。 感谢。
答案 0 :(得分:2)
这几乎肯定是由资源争用引起的。
在标准API中运行20个进程时,您有20个单独的GPU上下文。每当其中一个进程希望执行API调用时,必须有一个上下文切换到该进程上下文。上下文切换很昂贵并且具有很多延迟。这将是你所看到的减速的根源。与记忆表现无关。
NVIDIA发布了一个名为MPS(多进程服务器)的系统,该系统将CUDA API重新实现为服务,并在内部利用现代TesLa卡的Hyper-Q功能将操作推送到Hyper-Q支持的宽命令队列。这将删除所有上下文切换延迟。听起来你可能想调查这一点,如果性能对你很重要,你的代码需要大量的进程共享一个设备