多线程cuda无法并行

问题:CUDA无法并行
设计:C++端创建了100个线程,每个线程实例类,类中创建了一个独立的cuda流。程序运行后,nvvp显示,cuda核函数未并行执行。
请问,这样设计有问题吗?
一个奇怪的现象,我把cudaFree注释了,就能并行了?但这个怎么能注释呢?
另外问一下,各个流的cpu/gpu拷贝无法并行吗

https://developer.nvidia.com/zh-cn/blog/gpu-pro-tip-cuda-7-streams-simplify-concurrency/

你用的CUDA核函数规模是什么样的?过小也不会并行,如果规模大可以用CUDA Streams在试一试

可能会导致CUDA核函数未能有效并行执行的问题。

【cuda基础】2.2 组织并行线程
可以参考下


CUDA从入门到精通(五):线程并行_cuda线程并行_wozhengtao的博客-CSDN博客 多线程我们应该都不陌生,在操作系统中,进程是资源分配的基本单元,而线程是CPU时间调度的基本单元(这里假设只有1个CPU)。将线程的概念引申到CUDA程序设计中,我们可以认为线程就是执行CUDA程序的最小单元,前面我们建立的工程代码中,有个核函数概念不知各位童鞋还记得没有,在GPU上每个线程都会运行一次该核函数。但GPU上的线程调度方式与CPU有很大不同。CPU上会有优先级分配,从_cuda线程并行 https://blog.csdn.net/wozhengtao/article/details/51582665

很奇怪的现象,当我把cudaFree注释了,就并行了,但不可能注释的。咋办?

如果线程之间存在竞争条件或者同步问题,可能会导致CUDA核函数的执行受到影响。或者如果同时执行的CUDA核函数数量超过了设备的资源限制,可能会导致无法并行执行。
注释了cudaFree,CUDA核函数就能够并行执行,这是因为cudaFree操作会导致GPU上的资源释放,从而影响后续的CUDA核函数的执行。
在CUDA中,流的CPU/GPU拷贝是串行执行的。如果希望实现CPU/GPU拷贝的并行执行,可以考虑使用多个CUDA流来实现。

可以尝试在每个线程的CUDA核函数执行完成后,显式地调用cudaStreamSynchronize函数来同步CUDA流。这样可以确保先前的CUDA核函数执行完成,然后再执行后续的CUDA核函数。

【以下回答由 GPT 生成】

回答:

这样的设计有问题,CUDA在执行核函数时会创建一个kernel grid,而每个kernel grid中只能有一个kernel在执行。所以,无论你创建了多少个线程和cuda流,只有一个核函数可以在任意时间点被执行。因此,你的核函数可能被依次执行而不是并行执行。

为了解决这个问题,你可以考虑使用CUDA的动态并行度功能。具体步骤如下:

  1. 确保你的GPU支持动态并行度功能,可以通过查询GPU的计算能力(CUDA compute capability)来确认。

  2. 在C++端创建一个默认cuda流并为其设置独立的设备ID。这样可以确保每个线程都在不同的设备上执行。

  3. 在CUDA核函数中使用动态并行度功能。首先使用cudaDeviceEnablePeerAccess()函数启用对其他设备的直接访问,并使用cudaSetDevice()函数切换到目标设备。然后,在核函数中使用cudaLaunchCooperativeKernel()函数来启动核函数的执行,并传入需要的参数。

这样,你就可以利用动态并行度功能,在不同的设备上并行执行核函数。

以下是一个示例代码的简单实现:

#include <cuda_runtime.h>
#include <iostream>

#define NUM_THREADS 100

__global__ void kernel(int deviceID)
{
    // 核函数的具体操作
    // 使用deviceID来区分不同的设备
}

int main()
{
    cudaSetDevice(0); // 切换到设备0,创建默认cuda流
    cudaDeviceEnablePeerAccess(1, 0); // 启用对设备1的直接访问

    for (int i = 0; i < NUM_THREADS; i++)
    {
        // 创建单独的设备上下文并设置设备ID
        cudaSetDevice(i);

        // 启动核函数的执行
        cudaLaunchCooperativeKernel((void*)kernel, 1, 1, &i);
    }

    cudaDeviceSynchronize(); // 等待所有核函数执行完毕
    return 0;
}

这段示例代码假设你有两个GPU设备,并启用了对设备1的直接访问。它会使用cudaLaunchCooperativeKernel()在不同的设备上并行执行核函数,并等待所有核函数执行完毕后返回。

请注意,这仅仅是一个简单示例,实际情况可能需要根据你的具体需求进行修改。同时,动态并行度功能在某些情况下可能不适用或效果有限,需要根据具体情况进行评估和调整。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^