2017-07-01 17 views
0

我正在尝试将MJPEG解码器的顺序C代码翻译成OpenCL。我从this github项目获得了C代码。在Eclipse上说COULD NOT CREATE KERNEL之后终止代码

我现在试图将IDCT的原始C代码转换为OpenCL。

我复制并粘贴了.c IDCT文件的代码,并粘贴到我的.cl文件中,我的文件名为invCosine.cl

invCosine.cl

 #define IDCT_INT_MIN (- IDCT_INT_MAX - 1) 
     #define IDCT_INT_MAX 2147483647 

     /* 
     * Useful constants: 
     */ 

     /* 
     * ck = cos(k*pi/16) = s8-k = sin((8-k)*pi/16) times 1 << C_BITS and 
     * rounded 
     */ 
     #define c0_1 16384 
     #define c0_s2 23170 
     #define c1_1 16069 
     #define c1_s2 22725 

    .... 
    .... 
    .... 
    .... 
    .... 
    .... 

__kernel void idct1D(__global cl_int *Y) { 
    cl_int z1[8], z2[8], z3[8]; 

    /* 
    * Stage 1: 
    */ 

    but(Y[0], Y[4], z1[1], z1[0]); 
    rot(1, 6, Y[2], Y[6], &z1[2], &z1[3]); 
    but(Y[1], Y[7], z1[4], z1[7]); 
    z1[5] = CMUL(sqrt2, Y[3]); 
    z1[6] = CMUL(sqrt2, Y[5]); 

    /* 
    * Stage 2: 
    */ 
    but(z1[0], z1[3], z2[3], z2[0]); 
    but(z1[1], z1[2], z2[2], z2[1]); 
    but(z1[4], z1[6], z2[6], z2[4]); 
    but(z1[7], z1[5], z2[5], z2[7]); 

    /* 
    * Stage 3: 
    */ 
    z3[0] = z2[0]; 
    z3[1] = z2[1]; 
    z3[2] = z2[2]; 
    z3[3] = z2[3]; 
    rot(0, 3, z2[4], z2[7], &z3[4], &z3[7]); 
    rot(0, 1, z2[5], z2[6], &z3[5], &z3[6]); 

    /* 
    * Final stage 4: 
    */ 
    but(z3[0], z3[7], Y[7], Y[0]); 
    but(z3[1], z3[6], Y[6], Y[1]); 
    but(z3[2], z3[5], Y[5], Y[2]); 
    but(z3[3], z3[4], Y[4], Y[3]); 
} 

我基本上是复制和粘贴从原始文件中的#define语句称为idct.c。我也复制并粘贴了来自同一.c文件的内核代码,并将关键字__kernel__globalcl_int添加到此内核中。目前,我不想编写优化的OpenCL代码。我只是想将IDCT计算卸载到GPU上。

在主文件我的主机代码如下:

//////////////OpenCL parameters///////////////////////////// 

      int out; 
      cl_platform_id platform_id; 
      cl_uint ret_num_platforms; 
      cl_device_id device_id; 
      cl_uint ret_num_devices; 
      cl_context context; 
      cl_command_queue command_queue; 
      cl_program program; 
      //size_t kernel_code_size; 
      int *result; 
      cl_int ret; 
      cl_kernel kernel; 
      int storeResult; 


          FILE *fp; 
          const char fileName[] = "/root/Downloads/tima_seq_version/src/invCosine.cl"; 
          size_t source_size; 
          char *source_str; 

         /* Load kernel source file */ 
         fp = fopen(fileName, "rb"); 
         if (!fp) { 
          fprintf(stderr, "Failed to load kernel.\n"); 
          exit(1); 
         } 


         source_str = (char *)malloc(MAX_SOURCE_SIZE); 
        source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp); 
        fclose(fp); 

     /////////Set platform, context, command-queue...........///////////////////////// 

      /* Get Platform */ 
       ret= clGetPlatformIDs(1, &platform_id, &ret_num_platforms); 
       if (ret_num_platforms == 0) 
        { 
         printf("Found 0 platforms!\n"); 
        return EXIT_FAILURE; 
        } 
       /* Get Device */ 
       ret= clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 1, &device_id, &ret_num_devices); 
       printf("Number of devices: %d\n", ret_num_devices); 

       /* Create Context */ 
       context = clCreateContext(0, 1, &device_id, NULL, NULL, &ret); 

       if (!context) 
       { 
        printf("NO cCONTEXT\n"); 
        return EXIT_FAILURE; 

       } 

       /* Create Command Queue */ 
       command_queue = clCreateCommandQueue(context, device_id, 0, &ret); 

       if (!command_queue) 
       { 
        printf("NO command queue\n"); 
        return EXIT_FAILURE; 

       } 

       /* Create kernel from source */ 
          program = clCreateProgramWithSource(context, 1, (const char **)&source_str, (const size_t *)&source_size, &ret); 

          if (!program) 
          { 
           printf("NO PROGRAM!!!!\n"); 
           return EXIT_FAILURE; 
          } 

          clBuildProgram(program, 1, &device_id, "", NULL, NULL); 

         if (ret != CL_SUCCESS) { 
           printf("building program failed\n"); 
           if (ret == CL_BUILD_PROGRAM_FAILURE) { 
            size_t log_size; 
            clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size); 
            char *log = (char *) malloc(log_size); 
            clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, log_size, log, NULL); 
            printf("%s\n", log); 
           } 
          } 

       kernel= clCreateKernel(program, "idct1D", &ret); 

       if(!kernel || ret != CL_SUCCESS) 
       { 
        printf("-----COULD NOT CREATE KERNEL!!---\n"); 
        exit(1); 
       } 

当我运行应用程序,我得到下面的输出:

Number of devices: 2 
-----COULD NOT CREATE KERNEL!!--- 

为了理解为什么内核不是我删除了所有的idct代码,并将this链接的内核代码复制并粘贴到我的.cl文件中:

__kernel void taskParallelAdd(__global float* A, __global float* B, __global float* C) 
{ 
    int base = 0; 

    C[base+0] = A[base+0] + B[base+0]; 
    C[base+4] = A[base+4] + B[base+4]; 
    C[base+8] = A[base+8] + B[base+8]; 
    C[base+12] = A[base+12] + B[base+12]; 
} 

当我再次运行应用程序时,它运行平稳,并没有产生相同的错误。

为什么我的idct内核没有被检测到?

P.S.我正在使用Eclipse IDE编写和运行我的代码。

+2

您不测试'clBuildProgram'的返回值。我怀疑它可能会失败,并且通过'clGetProgramBuildInfo'获取的结果错误消息可能会显示此问题。 – doynax

回答

1

你得到内核错误的原因是,你实际上并没有检查你的错误代码clBuildProgram调用。如果您运行的是ret = clBuildProgram(program, 1, &device_id, "", NULL, NULL);,则会在clBuildProgram调用中发生错误。

您得到该错误的原因是,OpenCL C语言没有cl_int数据类型。这意味着你不能在内核中使用它。 cl_ *类型用于主机端使用。里面像你这样.CL文件,你需要使用常规的类型,如整数,浮点,焦炭等

假设你提供的代码拥有所有butrot宏必要的定义,改变内核使用int代替cl_int应该解决你的问题。