2013-10-21 42 views
1

我们有一个多GPU架构(在Windows上),其中可以指定'作业'(这也指定他们应该在哪个GPU上完成),然后在特定的GPU上执行。 目前,我们的方法是在框架的启动我们为每个GPU创建一个“工作线程”,然后等待作业被处理。具体而言,我们使用“GPUWorker”类从https://devtalk.nvidia.com/search/more/sitecommentsearch/GPUworker/好的策略多GPU处理与CPU线程,cuda上下文创建开销

它可以很好地,到目前为止,但有一些严重的性能相关的缺点:

  • 在我们frameowrk,特定的GPU被锁定的全部时间即使GPU只在50%的工作时间内实际使用,也是“工作”的一部分。注意作业具有非常粗糙的粗糙度,例如'做光流计算',其可以采取例如50 - 100毫秒。

  • 人们不能具体的“异步”的工作(例如一个aysnchronous主机设备拷贝),它不锁GPU

所以我现在想对这个问题“好”的策略。 我的想法如下:对于'已启动'的每个新作业,我创建一个新的'临时'CPU线程。 CPU线程然后设置将在其上完成工作的GPU的设备编号(通过'cudaSetDevice')。我想在这个时候(对我来说很简单,就是创建一个Cuda环境,在发布正确的设备之后,作业的'doWork'功能由CPU线程执行,取决于作业是同步的还是异步的,一个“加入”完成(等待CPU线程完成)或不

我现在有几个问题:

  • 那是一个“好”的策略,或者是否有人知道的更好当然这应该是一个线程安全的策略

  • 在我提出的策略中,典型的是什么新CPU线程创建的开销(以毫秒为单位)以及Cuda上下文的(隐藏)创建)?此外,如果例如Cuda上下文的创建是有意义的,有没有办法(例如使用cuda设备api和某种'上下文迁移')来减少这种开销?

回答

1

您的第一种方法听起来比您正在考虑的替代方案更有前途。

创建CPU线程并初始化CUDA上下文非常昂贵,而且要使该操作更快,这很难做到。 NVIDIA有意将大量操作前置到上下文创建过程中,所以您不会因资源分配失败而导致意外的延迟或故障。

最好的选择是投资异步。没有CPU/GPU并发性,你肯定会在表上留下性能,因为你没有隐藏内置在CUDA驱动程序中的CPU开销。