Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在我的cuda运行时程序中,cpu和gpu可以异步计算,但不能协同计算,为什么?_C++_Cuda - Fatal编程技术网

C++ 在我的cuda运行时程序中,cpu和gpu可以异步计算,但不能协同计算,为什么?

C++ 在我的cuda运行时程序中,cpu和gpu可以异步计算,但不能协同计算,为什么?,c++,cuda,C++,Cuda,在我的cuda运行时程序中,cpu和gpu可以异步计算,但不能协同计算,为什么 我测量程序的时间,总时间是cpu计算时间和gpu计算时间的总和。通过可视化配置文件,我发现gpu在cpu完成之前不会计算。我的目的是cpu的计算与gpu的计算相同 站台: 窗口10 cuda 7.5 vs2013 在调试模式下编译的代码(无优化) #包括“cuda_runtime.h” #包括“设备启动参数.h” #包括 #包括 __全局\uuuu_uu无效addKernel() { INTA; 对于(int i=0

在我的cuda运行时程序中,cpu和gpu可以异步计算,但不能协同计算,为什么

我测量程序的时间,总时间是cpu计算时间和gpu计算时间的总和。通过可视化配置文件,我发现gpu在cpu完成之前不会计算。我的目的是cpu的计算与gpu的计算相同

站台: 窗口10
cuda 7.5
vs2013

在调试模式下编译的代码(无优化)

#包括“cuda_runtime.h”
#包括“设备启动参数.h”
#包括
#包括
__全局\uuuu_uu无效addKernel()
{
INTA;
对于(int i=0;i<10000;i++)
对于(int j=0;j<10000;j++)
a=i;
}
无效计算机()
{
INTA=1;
对于(int i=0;i<10000;i++)
对于(int j=0;j<10000;j++)
{
对于(int k=0;k<100;k++)
a=j;
}
}
int main()
{
cudaSetDevice(0);
cudaEvent\u t启动,停止1;
cudaEventCreate(&start);
cudaEventCreate(&stop1);
时钟=时钟();
cudaEventRecord(开始,0);
addKernel();
cudaEventRecord(stop1,0);
时钟=时钟();
计算机();
clock_t ctt=clock();
cudaEventSynchronize(stop1);
cudaDeviceSynchronize();
时钟=时钟();
浮动t1;
CUDAEVENTERSEPDTIME(&t1,start,stop1);
printf(“时钟GPU:%.4fsn”,t1/1000);
printf(“时钟cpu:%f s\n”,(浮点)(ctt-ct)/每秒时钟数);
printf(“时钟总时间:%f s\n”,(浮点)(sss-ss)/每秒时钟数);
cudaEventDestroy(启动);
cudaEventDestroy(stop1);
cudaDeviceReset();
}
来自:

通过将CUDA_LAUNCH_BLOCKING环境变量设置为1,程序员可以全局禁用系统上运行的所有CUDA应用程序内核启动的异步性。此功能仅用于调试目的,不应用作使生产软件可靠运行的方法

如果通过探查器(Nsight,visualprofiler)收集硬件计数器,则内核启动是同步的。除非启用了并发内核评测。如果异步内存拷贝涉及未锁定页的主机内存,则它们也将是同步的

此外,如果没有优化,主机函数将运行很长时间,可能是内核的百万倍。如果使用优化,它实际上不会运行任何东西,并立即返回

我建议尝试分别使用
CUDA\u LAUNCH\u BLOCKING=1和
CUDA\u LAUNCH\u BLOCKING=0运行二进制文件,以测试运行时间。还要将内核和主机函数修改为有意义的函数。

来自:

通过将CUDA_LAUNCH_BLOCKING环境变量设置为1,程序员可以全局禁用系统上运行的所有CUDA应用程序内核启动的异步性。此功能仅用于调试目的,不应用作使生产软件可靠运行的方法

如果通过探查器(Nsight,visualprofiler)收集硬件计数器,则内核启动是同步的。除非启用了并发内核评测。如果异步内存拷贝涉及未锁定页的主机内存,则它们也将是同步的

此外,如果没有优化,主机函数将运行很长时间,可能是内核的百万倍。如果使用优化,它实际上不会运行任何东西,并立即返回


我建议尝试分别使用
CUDA\u LAUNCH\u BLOCKING=1和
CUDA\u LAUNCH\u BLOCKING=0运行二进制文件,以测试运行时间。还要将内核和主机函数修改为有意义的函数。

这里有几个问题(可能)在起作用:

  • 如果您使用的是WDDM驱动程序(与TCC驱动程序相反),那么内核启动会被分批处理,以减少WDDM驱动程序较高启动开销的影响。这意味着驱动程序将推迟启动
    addKernel()
    等待更多的工作,直到遇到
    cudaEventSynchronize()
    调用⁾ 但是此时,
    comput()
    已经完成。

    因此,在您的示例中,CPU和GPU的工作确实不是并行运行的,但是GPU上的
    addKernel()
    实际上是在CPU上的
    comput()
    之后运行的。
    在调用
    comput()
    之前,可以防止(进一步)批处理并强制立即启动
    addKernel()

  • addKernel()
    compute()
    没有外部可见的效果(它们只设置局部变量
    a
    ),编译器可能会对其进行完全优化。在调试模式下编译可能不会阻止所有这些优化。这将使演示异步执行变得更加困难,因为您只需要测量内核启动和计时开销。
    因此,将它们替换为执行实际工作的代码,如向量求和,并将结果存储到全局变量

  • 正如halfelf在他的回答中指出的,分析器可以在特定条件下同步启动内核



⑨⁾ 如果一段时间内没有进一步的工作,等待也可能超时,并且在调用
cudaEventSynchronize()
之前可能会启动
addKernel()

这里可能有几个问题:

  • 如果您使用的是WDDM驱动程序(与TCC驱动程序相反),那么内核启动会被分批处理,以减少WDDM驱动程序较高启动开销的影响。这意味着驱动程序将推迟启动
    addKernel()
    等待更多的工作,直到遇到
    cudaEventSynchronize()
    调用⁾ 但是此时,
    comput()
    已经完成。

    因此,在您的示例中,CPU和GPU的工作确实不是并行运行的,但是
    addKernel()
    在GPU上运行
    #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();
    
    }