在我的运行时cuda程序中,cpu和gpu可以异步计算,但不能协同计算,为什么?
我测量了程序的时间,总时间是 cpu 计算时间和 gpu 计算时间的总和。通过可视化配置文件,我发现 gpu 在 cpu 完成之前不计算。我的目的是 cpu 计算与 gpu 计算同时进行。
平台:
窗口 10
库达 7.5
vs2013
在 Debug模式下编译的代码(没有优化)
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include<time.h>
__global__ void addKernel()
{
int a ;
for (int i = 0; i < 10000;i++)
for (int j = 0; j < 10000;j++)
a = i;
}
void comput()
{
int a = 1;
for (int i = 0; i < 10000;i++)
for (int j = 0; j < 10000; j++)
{
for (int k = 0; k < 100;k++)
a = j;
}
}
int main()
{
cudaSetDevice(0);
cudaEvent_t start, stop1;
cudaEventCreate(&start);
cudaEventCreate(&stop1);
clock_t ss = clock();
cudaEventRecord(start,0);
addKernel<<<1,64>>>();
cudaEventRecord(stop1,0);
clock_t ct = clock();
comput();
clock_t ctt = clock();
cudaEventSynchronize(stop1);
cudaDeviceSynchronize();
clock_t sss = clock();
float t1;
cudaEventElapsedTime(&t1, start, stop1);
printf("clock GPU :%.4f s\n", t1/1000);
printf("clock cpu:%f s\n",(float) (ctt - ct)/CLOCKS_PER_SEC);
printf("clock total time: %f s\n", (float)(sss - ss) / CLOCKS_PER_SEC);
cudaEventDestroy(start);
cudaEventDestroy(stop1);
cudaDeviceReset();
}
最佳答案
这里有几个(潜在的)问题:
如果您使用的是 WDDM 驱动程序(而不是 TCC 驱动程序),内核启动会进行批处理以减少 WDDM 驱动程序较高启动开销的影响。这意味着驱动程序将推迟
addKernel()
的启动以等待更多工作,直到它遇到cudaEventSynchronize()
调用。¹⁾ 但是此时comput()
已经完成了。
因此,在您的示例中,CPU 和 GPU 工作确实不会并行运行,但是 GPU 上的addKernel()
实际上在 aftercomput()
上运行中央处理器。
您可以通过 inserting a call tocudaStreamQuery(0)
阻止(进一步)批处理并强制立即启动addKernel()
在调用comput()
之前。addKernel()
和compute()
没有外部可见的效果(它们只设置局部变量a
)并且可能被编译器完全优化掉。在 Debug模式下编译可能不会阻止所有这些优化。这将使演示异步执行变得更加困难,因为您只测量内核启动和计时开销。
因此,请将它们替换为执行实际工作的代码,例如对 vector 求和,并将结果存储到全局变量。正如 halelf 在他的回答中指出的那样,分析器可能会在特定条件下同步启动内核。
¹⁾ 如果一段时间内没有进一步的工作,等待也可能超时并且 addKernel()
可能会在 cudaEventSynchronize()
调用之前启动。
关于c++ - 在我的运行时cuda程序中,cpu和gpu可以异步计算,但不能协同计算,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40969977/