CUDA中的动态规划:与子内核交换数据的全局内存分配

CUDA中的动态规划:与子内核交换数据的全局内存分配,cuda,parallel-processing,gpgpu,Cuda,Parallel Processing,Gpgpu,我有以下代码的密码: __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.

我有以下代码的密码:

__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];

             }
    }

}

}
}

问题是第一个例程需要
5ms
才能运行,而第二个例程,即使对
child\u内核启动进行注释,也需要
23ms
,几乎所有的时间都花在
cudamaloc
API上

由于在动态规划中,通常需要分配内存空间来与子内核交换数据,而唯一的解决方案似乎是占用大量时间的全局内存,因此在我看来,动态规划实用性的一个严重瓶颈是数据交换,除非有办法绕过全局内存分配问题

接下来的问题是:上述问题是否有解决办法,即从内核中分配全局内存需要花费这么多时间?。谢谢

评论中提出的解决方案


从父内核外部分配所需的全局内存。我已经验证了从父内核外部分配所需的全局内存要快得多。

您正在从I M越大,情况就越糟

相反,您可以从块的第一个线程执行单个cudamaloc调用,分配M倍于您以前使用的大小(实际上在您的情况下,您应该分配更多,以便每个块都正确对齐)。在同步线程之后,您就可以使用正确计算的每个子内核的phi_cap地址启动子内核


或者(如果您的特定情况允许您分配足够的内存,以便在内核调用之间保持不变),您可以在内核外部分配内存并重用它。那会快得多。如果M在内核调用之间变化,您可以为最大的M分配所需的数量。

您正在从i M越大,情况就越糟

相反,您可以从块的第一个线程执行单个cudamaloc调用,分配M倍于您以前使用的大小(实际上在您的情况下,您应该分配更多,以便每个块都正确对齐)。在同步线程之后,您就可以使用正确计算的每个子内核的phi_cap地址启动子内核


或者(如果您的特定情况允许您分配足够的内存,以便在内核调用之间保持不变),您可以在内核外部分配内存并重用它。那会快得多。如果M在不同的内核调用之间变化,您可以为最大的M分配所需的资源。

问题很清楚:有人知道解决这一难题的方法吗?请仔细阅读文章的最后一句。@JackOLantern:当你发布代码时,请记住其他人必须在大约100列宽的滚动框中阅读。代码很难读取。@Jackolanten发布内核代码时,请始终为gridDim、blockDim和任何常量指定期望值(或范围)。在代码中,每个线程调用cudamaloc。在主机启动之前,按块调用或分配内存可能要快得多。@JackOLantern您正在从i__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]; } } }