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

Multithreading 如何使用线程同时运行CPU和GPU功能?,multithreading,cuda,gpgpu,Multithreading,Cuda,Gpgpu,我有两个我想用线程运行的函数 1) CPU函数,我可以使用以下方法将其加入线程: thread t1(vector_add, p->iNum1, p->iNum2, p->iNumAns, p->flag); t1.join(); 2) 和一个GPU内核 vectorAdd\u gpu(s.a1、s.a2、s.a2、s.flag) 但我的问题是如何使用线程调用GPU内核调用并加入它,以便它可以与CPU功能同时运行 vectorAdd_gpu <<<bl

我有两个我想用线程运行的函数

1) CPU函数,我可以使用以下方法将其加入线程:

thread t1(vector_add, p->iNum1, p->iNum2, p->iNumAns, p->flag);
t1.join();
2) 和一个GPU内核

vectorAdd\u gpu(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();
vectorAdd\u gpu(s.a1、s.a2、s.a2、s.flag);
线程t2(矢量添加gpu);
t2.连接();
用线程同时运行CPU和GPU功能还有其他方法吗?

正如talonmies所说

将其调用放入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);
};
但与此相反,您仍然可以在CPU工作上异步使用应用程序的同一主线程和流。我只是展示了你想看的。根据工作量大小,异步使用同一线程可能比重新创建流和重新连接线程更有效。在这里,重新加入可能比同步和启动内核的开销更大。您每秒进行多少内核调用

在Nvidia的以下博客中,有一个关于单线程异步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]);
}
for(int i=0;i

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

编写包装函数?这是什么语言?@AnttiHaapala:CUDA,即不是C。我不知道Jack关于GPU编程的知识,但如果GPU上运行的代码和CPU上运行的代码不在同一虚拟地址空间中运行,那么线程不是一个可以使用的模型。GPU内核启动无论如何都是异步的。只要在调用CPU函数之前启动内核,并且在CPU函数之后只有cudaMemcpy()将结果返回给CPU,它们就可以并发运行,而不需要使用线程。如何将应用程序的主线程与流异步使用?只使用了一个GPU内核调用。我添加了一个来自nvidia博客的示例,其中多个流用于主线程中的数据拷贝和内核启动。谢谢@huseyin tugrul buyukisik。我会试试这个方法。
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]);
}