CUDA CDP实现遇报错:__device__函数调用无法配置
问题:CUDA动态并行(CDP)实现前向函数时编译报错
我想给基础前向函数实现CDP(需要从CUDA函数中多次调用该前向函数),已经启用-rdc=true编译选项,使用的架构是sm_75(支持CDP),但编译时一直报错:Error: a __device__ function call cannot be configured。
尝试的代码1:直接在__global__函数中启动核函数
__device__ void NNFeedForwardNormalMultiple(double* __restrict__ values, double* __restrict__ weigths, double* result, int inputsize, int outputsize) { int idx = threadIdx.x + blockIdx.x * blockDim.x; int outputidx = idx / outputsize; int inputidx = idx % outputsize; if (outputidx >= outputsize || inputidx >= inputsize) { return; } atomicAdd(&result[outputidx], values[inputidx] * weigths[outputsize*outputidx + inputidx]); } __device__ void NNFeedForwardNormalActivate(double* __restrict__ biases, double* result, int size) { int idx = threadIdx.x + blockIdx.x * blockDim.x; if (idx >= size) { return; } result[idx] = 1.0 / (1.0 + exp(-(result[idx] + biases[idx]))); } __global__ void NNFeedForwardNormal(double* __restrict__ values, double* __restrict__ weigths, double* result, double* __restrict__ biases, int inputsize, int outputsize) { int blocksize = (inputsize * outputsize + THREADS_PER_BLOCK - 1)/THREADS_PER_BLOCK; NNFeedForwardNormalMultiple<<<blocksize, THREADS_PER_BLOCK>>>(values, weigths, result, inputsize, outputsize); cudaDeviceSynchronize(); NNFeedForwardNormalActivate<<<(outputsize + THREADS_PER_BLOCK - 1)/THREADS_PER_BLOCK, THREADS_PER_BLOCK>>>(biases, result, outputsize); }
尝试的代码2:通过__device__函数间接启动核函数
__device__ void NNFeedForwardNormalMultiple(double* __restrict__ values, double* __restrict__ weigths, double* result, int inputsize, int outputsize) { int idx = threadIdx.x + blockIdx.x * blockDim.x; int outputidx = idx / outputsize; int inputidx = idx % outputsize; if (outputidx >= outputsize || inputidx >= inputsize) { return; } atomicAdd(&result[outputidx], values[inputidx] * weigths[outputsize*outputidx + inputidx]); } __device__ void NNFeedForwardNormalActivate(double* __restrict__ biases, double* result, int size) { int idx = threadIdx.x + blockIdx.x * blockDim.x; if (idx >= size) { return; } result[idx] = 1.0 / (1.0 + exp(-(result[idx] + biases[idx]))); } __device__ void NNFeedForwardNormal(double* __restrict__ values, double* __restrict__ weigths, double* result, double* __restrict__ biases, int inputsize, int outputsize) { int blocksize = (inputsize * outputsize + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; NNFeedForwardNormalMultiple<<<blocksize, THREADS_PER_BLOCK>>>(values, weigths, result, inputsize, outputsize); NNFeedForwardNormalActivate<<<(outputsize + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK, THREADS_PER_BLOCK>>>(biases, result, outputsize); } __global__ void NNFeedForwardNormalWrapper(double* __restrict__ values, double* __restrict__ weigths, double* result, double* __restrict__ biases, int inputsize, int outputsize) { NNFeedForwardNormal(values, weigths, result, biases, inputsize, outputsize); }
我还试过用cudaLaunchKernel函数,也把__device__改成__global__,但都没用,还是报同样的错。
解决方案
问题核心:CDP要求被动态启动的必须是__global__函数,而你试图配置并启动的是__device__函数。<<<>>>语法仅支持启动__global__函数,无论从主机端还是设备端(CDP场景)。
修正步骤:
- 将
NNFeedForwardNormalMultiple和NNFeedForwardNormalActivate的修饰符从__device__改为__global__,因为它们是要被动态启动的子核函数。 - 设备端启动子核后,若需等待其执行完成,要调用
cudaDeviceSynchronize()(你的第一个代码已添加,无需修改)。 - 编译时保持
-rdc=true和-arch=sm_75参数,链接阶段也要同步使用相同配置。
修正后的示例代码:
// 改为__global__,作为动态并行的子核函数 __global__ void NNFeedForwardNormalMultiple(double* __restrict__ values, double* __restrict__ weigths, double* result, int inputsize, int outputsize) { int idx = threadIdx.x + blockIdx.x * blockDim.x; int outputidx = idx / outputsize; int inputidx = idx % outputsize; if (outputidx >= outputsize || inputidx >= inputsize) { return; } atomicAdd(&result[outputidx], values[inputidx] * weigths[outputsize*outputidx + inputidx]); } // 改为__global__ __global__ void NNFeedForwardNormalActivate(double* __restrict__ biases, double* result, int size) { int idx = threadIdx.x + blockIdx.x * blockDim.x; if (idx >= size) { return; } result[idx] = 1.0 / (1.0 + exp(-(result[idx] + biases[idx]))); } __global__ void NNFeedForwardNormal(double* __restrict__ values, double* __restrict__ weigths, double* result, double* __restrict__ biases, int inputsize, int outputsize) { int blocksize = (inputsize * outputsize + THREADS_PER_BLOCK - 1)/THREADS_PER_BLOCK; // 现在启动的是__global__函数,符合CDP要求 NNFeedForwardNormalMultiple<<<blocksize, THREADS_PER_BLOCK>>>(values, weigths, result, inputsize, outputsize); cudaDeviceSynchronize(); // 等待子核完成 NNFeedForwardNormalActivate<<<(outputsize + THREADS_PER_BLOCK - 1)/THREADS_PER_BLOCK, THREADS_PER_BLOCK>>>(biases, result, outputsize); }
额外注意事项:
- 动态并行的子核会消耗设备资源,需确保网格大小配置合理,避免资源耗尽。
- 若使用
cudaLaunchKernel,同样要保证目标函数为__global__类型,并正确传递参数与配置信息。
内容的提问来源于stack exchange,提问作者ug0x01
相关产品推荐
相关产品推荐

