我想并行计算GPU上的一些东西,并在每次内核调用之间显示结果。代码看起来像这样:
void execute(){
runthread = true;
float erg[128 * 2] = {};
float *d_a, *d_b, *d_c, *d_erg;
size_t sizeErg = sizeof(float) * 2 * N;
size_t sizeAB = sizeof(float)*N;
float c[2] = { 1, 2 };
gpuErrchk(cudaMalloc((void**)&d_a, sizeAB));
gpuErrchk(cudaMalloc((void**)&d_b, sizeAB));
gpuErrchk(cudaMalloc((void**)&d_c, sizeof(float) * 2));
gpuErrchk(cudaMalloc((void**)&d_erg, sizeErg));
gpuErrchk(cudaMemcpy(d_a, anode, sizeAB, cudaMemcpyHostToDevice));
gpuErrchk(cudaMemcpy(d_b, kathode, sizeAB, cudaMemcpyHostToDevice));
gpuErrchk(cudaMemcpy(d_c, c, 2 * sizeof(float), cudaMemcpyHostToDevice));
float time = 0;
int i = 0;
while (runthread){
kernel<<<(N * 2) / 64, 64 >>>(d_a, d_b, d_c, d_erg, N);
cudaDeviceSynchronize();
gpuErrchk(cudaMemcpy(erg, d_erg, sizeErg, cudaMemcpyDeviceToHost));
float acc = 0;
for (int j = 0; j < N * 2; j++){
acc += erg[j];
}
std::cout << "Erg" << i << "=" << acc << std::endl;
std::cout << "Kernel Execution took" << time << "ms" << std::endl;
i++;
}
cudaFree(d_a);
cudaFree(d_b);
cudaFree(d_c);
cudaFree(d_erg);
}
此函数是bool变量runthread的类的一部分。我的想法是调用另一个成员函数,它将使用执行函数启动一个新的CPU线程并在main函数中等待,直到用户输入一些东西来调用另一个设置runthreads = false的成员函数。因此线程将在下一个内核完成后完成。 我总是从Visual Studio收到错误消息。现在我想知道这是否可能,或者CPU是否忙于控制GPU执行?有关GPU和CPU上的并行执行的多线程有没有人参与?或者我应该在while循环中查找userinput吗?
答案 0 :(得分:3)
GPU上的执行与CPU上的执行是异步的。除了等待操作,您可以继续在CPU上进行处理。另外,根据配置标志,请参阅cudaSetDeviceFlags,等待操作将使用或不使用CPU周期。
cudaDeviceScheduleSpin:指示CUDA在等待设备结果时主动旋转。这可以减少等待设备时的延迟,但如果它们与CUDA线程并行执行工作,则可能会降低CPU线程的性能。
您想要实现的目标是完全可行的(这是Windows上的一个示例):
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
volatile int runthread ;
__global__ void kernel() { }
#include <Windows.h>
int execute(void* p)
{
int count = 0 ;
while (runthread)
{
kernel<<<1,1>>>();
cudaDeviceSynchronize();
++count;
}
printf ("Executed kernel %d times\n", count);
::ExitThread(count);
return count ;
}
int main()
{
runthread = 1 ;
HANDLE hThread = ::CreateThread (0, 0, (LPTHREAD_START_ROUTINE)execute, 0, 0, 0) ;
printf ("Press key\n") ;
int c = getc(stdin);
printf ("Stopping\n") ;
runthread = 0 ;
::WaitForSingleObject (hThread, INFINITE) ;
printf ("DONE\n");
return 0 ;
}
但是,您要小心执行cuda调用的线程,因为每个线程存储了一些cuda配置和状态元素。如果你想从不同的线程使用cuda,我推荐this帖子。实质上,您希望使用cuCtxSetCurrent API调用将cuda环境附加到线程。最简单的方法是让所有的cuda代码都由一个线程执行。