问题: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核函数未能有效并行执行的问题。
很奇怪的现象,当我把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的动态并行度功能。具体步骤如下:
确保你的GPU支持动态并行度功能,可以通过查询GPU的计算能力(CUDA compute capability)来确认。
在C++端创建一个默认cuda流并为其设置独立的设备ID。这样可以确保每个线程都在不同的设备上执行。
在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()
在不同的设备上并行执行核函数,并等待所有核函数执行完毕后返回。
请注意,这仅仅是一个简单示例,实际情况可能需要根据你的具体需求进行修改。同时,动态并行度功能在某些情况下可能不适用或效果有限,需要根据具体情况进行评估和调整。