【问题标题】:Want to execute a loop with cuda Kernel till user cancels想要使用 cuda 内核执行一个循环,直到用户取消
【发布时间】:2017-08-26 14:19:18
【问题描述】:

我想在 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);
}

此函数是具有布尔变量runthread 的类的一部分。我的想法是调用另一个成员函数,它将使用执行函数启动一个新的 CPU 线程,并在主函数中等待,直到用户输入一些内容来调用另一个设置 runthreads = false 的成员函数。所以线程将在下一个内核完成后完成。 我总是从 Visual Studio 收到错误消息。现在我想知道这是否可能,或者 CPU 是否忙于控制 GPU 执行?有人在 GPU 和 CPU 上并行执行多线程方面有经验吗?还是我应该只在 while 循环中查找用户输入?

【问题讨论】:

    标签: c++ cuda infinite-loop


    【解决方案1】:

    GPU 上的执行与 CPU 上的执行是异步的。除了等待操作之外,您还可以继续在 CPU 上进行处理。还取决于配置标志参见 cudaSetDeviceFlags ,等待操作将使用或不使用 CPU 周期。

    cudaDeviceScheduleSpin:指示 CUDA 在等待来自设备的结果时主动旋转。这可以减少等待设备时的延迟,但如果 CPU 线程与 CUDA 线程并行执行工作,则可能会降低它们的性能。

    您想要实现的目标是完全可行的(这里是 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 post。本质上,您希望使用 cuCtxSetCurrent API 调用将 cuda 环境附加到线程。最简单的方法是让你的所有 cuda 代码由单个线程执行。

    【讨论】:

      猜你喜欢
      • 2020-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-22
      • 2021-07-23
      • 2015-01-27
      • 2021-05-15
      • 1970-01-01
      相关资源
      最近更新 更多