使用cuda并行化嵌套for循环有很大的限制

时间:2017-07-25 15:28:47

标签: cuda

我是CUDA的新手。我正在尝试编写一个CUDA内核来执行以下代码。

for(int oz=0;oz<count1;oz++)
    {
        for(int ox=0;ox<scale+1;ox++)
        {

            for(int xhn=0;xhn<Wjh;xhn++)
            {
                for(int yhn=0;yhn<Wjv;yhn++)
                {
                    //int numx=xhn+ox*Wjh;
                    int numx=oz*(scale+1)*Wjh+ox*Wjh+xhn;
                    int src2=yhn+xhn*Wjv;
                    Ic_real[src2]=Ic_real[src2]+Sr[oz*(scale+1)*Wjv+ox*Wjv+yhn]*Hr_table[numx]-Si[oz*(scale+1)*Wjv+ox*Wjv+yhn]*Hi_table[numx];
                    Ic_img[src2]=Ic_img[src2]+Sr[oz*(scale+1)*Wjv+ox*Wjv+yhn]*Hi_table[numx]+Si[oz*(scale+1)*Wjv+ox*Wjv+yhn]*Hr_table[numx];
                }

            }

        }
    }

值Wjh = 1080,Wjv = 1920,scale = 255; oz&gt; = 4.这是我目前所拥有的,但我的代码只能在count1&lt; = 4时执行,如果oz> 4,它不会&#39工作,有谁知道我该怎么办?干杯

__global__ void lut_kernel(float *Sr,float *Si,dim3 size,int Wjh,int Wjv,float *vr,float *vi,
                           float *hr,float *hi,float *Ic_re,float *Ic_im)
{     
    __shared__ float cachere[threadPerblock];
    __shared__ float cacheim[threadPerblock];
    int blockId=blockIdx.x + blockIdx.y * gridDim.x;
    int cacheIndex=threadIdx.y*blockDim.x+threadIdx.x;
    int z=threadIdx.x;
    int x=threadIdx.y;
    int tid1=threadIdx.y*blockDim.x+threadIdx.x;

    //int tid= blockId * (blockDim.x * blockDim.y)  
                     //  + (threadIdx.y * blockDim.x) + threadIdx.x;
    int countnum=0;
    float re=0.0f;
    float im=0.0f;
    float re_value=0.0f;
    float im_value=0.0f;
    if (z<4 && x<256)
    {    

        int src2=z*(scale+1)*Wjh+x*Wjh+blockIdx.y;
        re=Sr[z*(scale+1)*Wjv+x*Wjv+blockIdx.x]*hr[src2]-Si[z*(scale+1)*Wjv+x*Wjv+blockIdx.x]*hi[src2];
        im=Sr[z*(scale+1)*Wjv+x*Wjv+blockIdx.x]*hi[src2]+Si[z*(scale+1)*Wjv+x*Wjv+blockIdx.x]*hr[src2];


        }
       cachere[cacheIndex]=re;
       cacheim[cacheIndex]=im;

       __syncthreads();

       int index=threadPerblock/2;
       while(index!=0)
       {
          if(cacheIndex<index)
          {
              cachere[cacheIndex]+=cachere[cacheIndex+index];
              cacheim[cacheIndex]+=cacheim[cacheIndex+index];
          }
             index/=2;

       }
       if(cacheIndex==0)
       {
         Ic_re[blockId]=cachere[0];
         Ic_im[blockId]=cacheim[0];
         //printf("Ic= %d,blockId= %d\n",Ic_re[blockId],blockId);
       }

    }

内核参数是: dim3 dimBlock(count1,256);     dim3 dimGrid(Wjv,Wjh);

lut_kernel<<<dimGrid,dimBlock>>>(d_Sr,d_Si,size,Wjh,Wjv,dvr_table,dvi_table,dhr_table,dhi_table,dIc_re,dIc_im);

如果count1> 4,我会做什么来并行化嵌套代码?

1 个答案:

答案 0 :(得分:1)

我简单检查了一下代码,似乎Ic_img和Ic_real元素的计算很容易并行化( count1 scale + 1 Wjh Wjv 彼此之间没有任何依赖关系)。因此,内核中不需要共享变量和while循环;它很容易实现,如下所示,其中一个额外的参数int numElements = count1 *(scale + 1)* Wjh * Wjv。

int i = blockDim.x * blockIdx.x + threadIdx.x;
if (i < numElements) {
    //....
}

代码将更容易维护,并消除像您的示例那样容易出现长代码的错误。如果src2值在最内层循环中根本不重复,那么性能也接近最佳。如果'src2'可能重复,请使用带有'atomicAdd'的表达式,以便结果按预期正确;使用atomicAdd,性能可能不是最佳的,但至少有一个正确实现的无bug内核已成功实现。如果它导致性能瓶颈,那么通过尝试和试验一些不同的实现来修改它。