我有两个要使用线程运行的功能。
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功能的方法吗?
答案 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]);
}
这只是异步流重叠的不同方法之一。