在CUDA C程序中并行化if和else条件方面需要帮助

时间:2017-05-02 07:43:38

标签: image-processing parallel-processing cuda

我在C中编写了一个用于图像模糊的过滤器,它工作正常,我正在尝试使用CUDA C在GPU上运行以加快处理速度。该程序有一些if和else条件,如下面的C代码版本所示,   函数的输入是输入图像,输出图像和列的大小。

  void convolve_young1D(double * in, double * out, int datasize) {
        int i, j;

    /* Compute first 3 output elements */
    out[0] = B*in[0];
    out[1] = B*in[1] + bf[2]*out[0];
    out[2] = B*in[2] + (bf[1]*out[0]+bf[2]*out[1]);

    /* Recursive computation of output in forward direction using filter parameters bf and B */
    for (i=3; i<datasize; i++) {
        out[i] = B*in[i];
        for (j=0; j<3; j++) {
            out[i] += bf[j]*out[i-(3-j)];
        }
    }

}
    //Calling function below
void convolve_young2D(int rows, int columns, int sigma, double ** ip_padded) {

        /** \brief Filter radius */
        w = 3*sigma;
        /** \brief Filter parameter q */
        double q;
        if (sigma < 2.5)
            q = 3.97156 - 4.14554*sqrt(1-0.26891*sigma);
        else
            q = 0.98711*sigma - 0.9633;

        /** \brief Filter parameters b0, b1, b2, b3 */
        double b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q;
        double b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q;
        double b2 = -(1.4281*q*q + 1.26661*q*q*q);
        double b3 = 0.422205*q*q*q;

        /** \brief Filter parameters bf, bb, B */
        bf[0] = b3/b0; bf[1] = b2/b0; bf[2] = b1/b0;
        bb[0] = b1/b0; bb[1] = b2/b0; bb[2] = b3/b0;
        B = 1 - (b1+b2+b3)/b0;

        int i,j;

        /* Convolve each row with 1D Gaussian filter */
        double  *out_t = calloc(columns+(2*w),sizeof(double ));
        for (i=0; i<rows+2*w; i++) {
            convolve_young1D(ip_padded[i], out_t, columns+2*w);
         }
    free(out_t);

尝试使用CUDA C中的块和线程相同的方法,但是没有成功我已经将零作为输出,甚至输入值似乎变为零也不知道我哪里出错了请帮助。我是CUDA C编程的新手。这是我尝试的CUDA内核版本。

__global__ void convolve_young2D( float *in, float *out,int rows,int columns, int j,float B,float bf[3],int w) {

int k;

int x = blockIdx.x * blockDim.x + threadIdx.x;

if((x>0) && (x<(rows+2*w))) 
{
//printf("%d \t",x);

if(j ==0)
{
 // Compute first output elements  
 out[x*columns] = B*in[x*columns];
}

else if(j==1)
{ 
  out[x*columns +1 ] = B*in[x*columns +1] + bf[2]*out[x*columns];
}
else if (j== 2)
 {
   out[2] = B*in[x*columns +2] + (bf[1]*out[x*columns]+bf[2]*out[x*columns+1]);
 }  
else{
 //  Recursive computation of output in forward direction using filter parameters bf and B 
       out[x*columns+j] = B*in[x*columns+j];
        for (k=0; k<3; k++) {
            out[x*columns + j] += bf[k]*out[(x*columns+j)-(3-k)];
         }
    }
 }   

}

//Calling function below
void convolve_young2D(int rows, int columns, int sigma, const float * const ip_padded, float * const op_padded) {   
 float bf[3], bb[3];
 float  B;
 int w;

    /** \brief Filter radius */

    w = 3*sigma;
    /** \brief Filter parameter q */
    float q;
    if (sigma < 2.5)
        q = 3.97156 - 4.14554*sqrt(1-0.26891*sigma);
    else
        q = 0.98711*sigma - 0.9633;
    /** \brief Filter parameters b0, b1, b2, b3 */
    float b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q;
    float b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q;

    float b2 = -(1.4281*q*q + 1.26661*q*q*q);
    float b3 = 0.422205*q*q*q;
 /** \brief Filter parameters bf, bb, B */
    bf[0] = b3/b0; bf[1] = b2/b0; bf[2] = b1/b0;
    bb[0] = b1/b0; bb[1] = b2/b0; bb[2] = b3/b0;
    B = 1 - (b1+b2+b3)/b0;      
   int p;
 const int inputBytes = (rows+2*w) * (columns+2*w) * sizeof(float);
 float *d_input, *d_output; // arrays in the GPU´s global memory
cudaMalloc(&d_input, inputBytes);
cudaMemcpy(d_input, ip_padded, inputBytes, cudaMemcpyHostToDevice);
 cudaMalloc(&d_output,inputBytes);
for (p = 0; p<columns+2*w; p++){
convolve_young<<<4,500>>>(d_input,d_output,rows,columns,p,B,bf,w);
}
cudaMemcpy(op_padded, d_input, inputBytes, cudaMemcpyDeviceToHost);
cudaFree(d_input);

1 个答案:

答案 0 :(得分:1)

第一个问题是你调用了convolve_young<<<4,500>>>(d_input,d_output,rows,columns,p,B,bf,w);,但你定义了一个名为convolve_young 2D 的内核。

另一个可能的问题是你要进行卷积:

for (p = 0; p<columns+2*w; p++){
    convolve_young<<<4,500>>>(d_input,d_output,rows,columns,p,B,bf,w);
}

与CPU算法相比,这里循环遍历列而不是行:

for (i=0; i<rows+2*w; i++) {
    convolve_young1D(ip_padded[i], out_t, columns+2*w);
}

首先,您应该尝试直接移植CPU算法,一次计算一行,然后修改它以传输整个图像。