如何使用线程同时运行CPU和GPU功能?

时间:2018-12-09 09:07:37

标签: multithreading cuda gpgpu

我有两个要使用线程运行的功能。

1)CPU功能,我可以使用以下功能加入线程:

thread t1(vector_add, p->iNum1, p->iNum2, p->iNumAns, p->flag);
t1.join();

2)和GPU内核

vectorAdd_gpu <<<blocksPerGrid, threadsPerBlock >>>(s.a1, s.a2, s.a2, s.flag);

但是我的问题是如何使用线程调用GPU内核调用并将其加入,以便它可以与CPU功能同时运行。

vectorAdd_gpu <<<blocksPerGrid, threadsPerBlock >>>(s.a1, s.a2, s.a2, s.flag);

thread t2(vectorAdd_gpu);
t2.join();

还有其他使用线程同时运行CPU和GPU功能的方法吗?

1 个答案:

答案 0 :(得分:1)

如爪子所言,

将其调用放入lambda函数

auto myFunc = [&](){
    cudaStream_t stream2;
    cudaSetDevice(device2); 
    cudaStreamCreate (&stream2);
    vectorAdd_gpu <<<blocksPerGrid, threadsPerBlock,0,stream2 >>>(s.a1, s.a2, s.a2, s.flag);
    cudaStreamSynchronize(stream2);
    cudaStreamDestroy(stream2);
};

然后将其提供给线程。

thread t2(myFunc);
t2.join();

但是,除此之外,您仍然可以在CPU工作时异步使用流的应用程序相同主线程。我刚刚展示了您想看的东西。根据工作量的不同,异步使用相同的线程可能比重新创建流和重新加入线程更有效。也许重新加入比在这里同步和启动内核有更多的开销。您每秒要进行几次内核调用?

在Nvidia的以下博客中,https://devblogs.nvidia.com/how-overlap-data-transfers-cuda-cc/有一个关于单线程异步CUDA的很好的示例:

for (int i = 0; i < nStreams; ++i) {
  int offset = i * streamSize;
  cudaMemcpyAsync(&d_a[offset], &a[offset], 
                  streamBytes, cudaMemcpyHostToDevice, cudaMemcpyHostToDevice, stream[i]);
}

for (int i = 0; i < nStreams; ++i) {
  int offset = i * streamSize;
  kernel<<<streamSize/blockSize, blockSize, 0, stream[i]>>>(d_a, offset);
}

for (int i = 0; i < nStreams; ++i) {
  int offset = i * streamSize;
  cudaMemcpyAsync(&a[offset], &d_a[offset], 
                  streamBytes, cudaMemcpyDeviceToHost, cudaMemcpyDeviceToHost, stream[i]);
}

这只是异步流重叠的不同方法之一。