我有以下代码:
__global__ void interpolation(const double2* __restrict__ data, double2* __restrict__ result, const double* __restrict__ x, const double* __restrict__ y, const int N1, const int N2, int M)
{
int i = threadIdx.x + blockDim.x * blockIdx.x;
[...]
double phi_cap1, phi_cap2;
if(i<M) {
for(int m=0; m<(2*K+1); m++) {
[calculate phi_cap1];
for(int n=0; n<(2*K+1); n++) {
[calculate phi_cap2];
[calculate phi_cap=phi_cap1*phi_cap2];
[use phi_cap];
}
}
}
}
我想在Kepler K20卡上使用动态编程将phi_cap1
和phi_cap2
的处理并行发送到一堆线程,以减少计算时间。我的代码中K=6
,所以我发布了一个13x13
个线程块。
根据CUDA动态并行编程指南,我正在分配phi_cap
169
个phi_cap1
元素的矩阵(由phi_cap2
和__global__ void interpolation(const double2* __restrict__ data, double2* __restrict__ result, const double* __restrict__ x, const double* __restrict__ y, const int N1, const int N2, int M)
{
int i = threadIdx.x + blockDim.x * blockIdx.x;
[...]
dim3 dimBlock(2*K+1,2*K+1); dim3 dimGrid(1,1);
if(i<M) {
double* phi_cap; cudaMalloc((void**)&phi_cap,sizeof(double)*(2*K+1)*(2*K+1));
child_kernel<<<dimGrid,dimBlock>>>(cc_diff1,cc_diff2,phi_cap);
for(int m=0; m<(2*K+1); m++) {
for(int n=0; n<(2*K+1); n++) {
[use phi_cap];
}
}
}
的产品组成),需要在全局内存中与子内核交换数据。的确,引用了指南,
作为一般规则,传递给子内核的所有存储都应该从全局内存堆中显式分配。
然后我用以下代码
结束了5ms
}
问题是第一个例程需要child_kernel
才能运行,而第二个例程,即使通过评论23ms
启动,也会花费cudaMalloc
,几乎所有花费在{{1}} API。
因为在动态编程中,人们经常需要分配内存空间来与子内核交换数据,唯一的解决方案似乎是全局内存需要花费很多时间,在我看来,动态编程的有用性是一个严重的瓶颈是数据交换,除非有办法规避全局内存分配问题。
那么问题是:是否有针对上述问题的解决方法,即从内核中分配全局内存需要花费大量时间?。感谢
评论中提出的解决方案
从父内核外部分配所需的全局内存。我已经验证从父内核外部分配所需的全局内存多更快。
答案 0 :(得分:4)
你从每个线程调用cudaMalloc,其中i&lt; M表示您正在进行M cudaMalloc调用。
M越大越好。
相反,你可以从块的第一个线程调用一个cudaMalloc,分配M次你之前使用的大小(实际上在你的情况下你应该分配更多,所以每个块都正确对齐)。在同步线程之后,您可以为每个子内核使用正确计算的phi_cap地址启动子内核。
或者(如果您的特定情况允许您在内核调用之间分配足够的内存),您可以在内核之外分配一次内存并重用它。那会更快。如果M在内核调用之间变化,则可以根据最大M的需要进行分配。