代码在说 COULD NOT CREATE KERNEL on Eclipse 后终止
Code terminates after saying COULD NOT CREATE KERNEL on Eclipse
我正在尝试将 MJPEG 解码器的顺序 C 代码转换运行到 OpenCL。我从 this github 项目中获得了 C 代码。
我现在正在尝试将 IDCT 的原始 C 代码转换为 OpenCL。
我从 .c
文件中复制并粘贴了 IDCT 的代码,并粘贴到我命名为 invCosine.cl
的 .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]);
}
我实际上是从名为 idct.c
的原始文件中复制并粘贴了 #define
语句。我还从同一个 .c
文件中复制并粘贴了内核代码,并向该内核添加了关键字 __kernel
、__global
和 cl_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 link 复制并粘贴到我的 .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 编写和 运行 宁我的代码。
您收到内核错误的原因是,您实际上并没有检查 clBuildProgram
调用中的错误代码。如果您 运行 ret = clBuildProgram(program, 1, &device_id, "", NULL, NULL);
相反,您将在 clBuildProgram 调用中遇到错误。
您收到该错误的原因是,OpenCL C 语言没有 cl_int
数据类型。这意味着你不能在内核中使用它。 cl_* 类型供主机端使用。在像您这样的 .cl 文件中,您需要使用常规类型,例如 int、float、char 等。
假设您提供的代码具有 but
和 rot
宏的所有必要定义,将内核更改为使用 int
而不是 cl_int
应该可以解决您的问题.
我正在尝试将 MJPEG 解码器的顺序 C 代码转换运行到 OpenCL。我从 this github 项目中获得了 C 代码。
我现在正在尝试将 IDCT 的原始 C 代码转换为 OpenCL。
我从 .c
文件中复制并粘贴了 IDCT 的代码,并粘贴到我命名为 invCosine.cl
的 .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]);
}
我实际上是从名为 idct.c
的原始文件中复制并粘贴了 #define
语句。我还从同一个 .c
文件中复制并粘贴了内核代码,并向该内核添加了关键字 __kernel
、__global
和 cl_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 link 复制并粘贴到我的 .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 编写和 运行 宁我的代码。
您收到内核错误的原因是,您实际上并没有检查 clBuildProgram
调用中的错误代码。如果您 运行 ret = clBuildProgram(program, 1, &device_id, "", NULL, NULL);
相反,您将在 clBuildProgram 调用中遇到错误。
您收到该错误的原因是,OpenCL C 语言没有 cl_int
数据类型。这意味着你不能在内核中使用它。 cl_* 类型供主机端使用。在像您这样的 .cl 文件中,您需要使用常规类型,例如 int、float、char 等。
假设您提供的代码具有 but
和 rot
宏的所有必要定义,将内核更改为使用 int
而不是 cl_int
应该可以解决您的问题.