OpenCL简单的“Hello World!”程序正确编译,但在执行时吐出垃圾。但是安装了Nvidia驱动程序

时间:2015-02-12 12:36:35

标签: c linux opencl nvidia opensuse

我有完全相同的问题,如在这篇文章中:

OpenCL Simple "Hello World!" program compiles correctly but spits out garbage when executed

但我实际安装了Nvidia驱动程序。

我想让这个程序工作: http://www.fixstars.com/en/opencl/book/OpenCLProgrammingBook/first-opencl-program/

所以我得到了来自https://www.khronos.org/

的标题文件

我编译它是这样的:

  

gcc -I / usr / include / hello.c -L / usr / lib64 -lOpenCL

这是输出:

  

hello.c:在函数'main'中:

     

hello.c:56:1:警告:'clCreateCommandQueue'已弃用(已声明   at /usr/include/CL/cl.h:1359)[-Wdeprecated-declarations]

     

hello.c:75:1:警告:'clEnqueueTask'已弃用(声明于   /usr/include/CL/cl.h:1373)[-Wdeprecated-declarations]

如果我运行程序,我会得到:

  

-

这是我的设置:

OpenSuse 12.3

通过yast安装的Nvidia驱动程序:

nvidia-computeG03 340.65-32.1

glxinfo的输出| grep -i vendor:

服务器glx供应商字符串:NVIDIA Corporation 客户端glx供应商字符串:NVIDIA公司 OpenGL供应商字符串:NVIDIA Corporation

输出lspci -nnk | grep -i vga -A3

  <03> 00.0 VGA兼容控制器[0300]:NVIDIA Corporation GF119   [Quadro NVS 310] [10de:107d](rev a1)

     

子系统:NVIDIA Corporation设备[10de:094e]

     

正在使用的内核驱动程序:nvidia

     

03:00.1音频设备[0403]:NVIDIA Corporation GF119 HDMI Audio   控制器[10de:0e08](rev a1)

也许openCL不使用nvidia驱动程序,但我不知道如何检查这个。 我希望有人可以帮助我。

谢谢。


编辑12.02.15 17:08

非常感谢jprice,

我用你的函数来绘制错误信息。我的代码如下所示:

/* Get Platform and Device Info */ ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms); checkError(ret, "clGetPlatformIDs");

我得到了这个输出:

操作'clGetPlatformIDs'时出错:-1001

按照建议查看CL.h后,似乎找不到任何设备。

来自cl.h:

#define CL_DEVICE_NOT_FOUND -1

正如我已经发布的那样,我的系统中有一个Quadro NVS 310,它位于cl兼容设备的列表中。你知道出了什么问题吗?

这是我编译的竞争CODE:

#include <stdio.h>
#include <stdlib.h>


#ifdef __APPLE__
#include <OpenCL/opencl.h>
#else
#include <CL/cl.h>
#endif

#define MEM_SIZE (128)
#define MAX_SOURCE_SIZE (0x100000)

void checkError(cl_int err, const char *operation)
{
  if (err != CL_SUCCESS)
  {
    fprintf(stderr, "Error during operation '%s': %d\n", operation, err);
    exit(1);
  }
}



int main()
{
cl_device_id device_id = NULL;
cl_context context = NULL;
cl_command_queue command_queue = NULL;
cl_mem memobj = NULL;
cl_program program = NULL;
cl_kernel kernel = NULL;
cl_platform_id platform_id = NULL;
cl_uint ret_num_devices;
cl_uint ret_num_platforms;
cl_int ret;

char string[MEM_SIZE];
char test_string[20];
/*strcpy(test_string, "ENDE");*/

FILE *fp;
char fileName[] = "./hello.cl";
char *source_str;
size_t source_size;

/* Load the source code containing the kernel*/
fp = fopen(fileName, "r");
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);

/* Get Platform and Device Info */
ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
checkError(ret, "clGetPlatformIDs");

ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &device_id,     &ret_num_devices);
checkError(ret, "clGetDeviceIDs");

/* Create OpenCL context */
context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);
checkError(ret, "clCreateContext");

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

/* Create Memory Buffer */
memobj = clCreateBuffer(context, CL_MEM_READ_WRITE,MEM_SIZE * sizeof(char),     NULL, &ret);
checkError(ret, "clCreateBuffer");

/* Create Kernel Program from the source */
program = clCreateProgramWithSource(context, 1, (const char **)&source_str,
(const size_t *)&source_size, &ret);
checkError(ret, "clCreateProgramWithSource");

/* Build Kernel Program */
ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
checkError(ret, "clBuildProgram");

/* Create OpenCL Kernel */
kernel = clCreateKernel(program, "hello", &ret);
checkError(ret, "clCreateKernel");

/* Set OpenCL Kernel Parameters */
ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memobj);
checkError(ret, "clSetKernelArg");

/* Execute OpenCL Kernel */
ret = clEnqueueTask(command_queue, kernel, 0, NULL,NULL);
checkError(ret, "clEnqueueTask");

/* Copy results from the memory buffer */
ret = clEnqueueReadBuffer(command_queue, memobj, CL_TRUE, 0,
MEM_SIZE * sizeof(char),string, 0, NULL, NULL);

/* Display Result */
puts(string);


/* Finalization */
ret = clFlush(command_queue);
ret = clFinish(command_queue);
ret = clReleaseKernel(kernel);
ret = clReleaseProgram(program);
ret = clReleaseMemObject(memobj);
ret = clReleaseCommandQueue(command_queue);
ret = clReleaseContext(context);

free(source_str);

return 0;
}´

更新13.02.15 谢谢你的建议。

我检查了/etc/OpenCL/vendors/nvidia.icd是否存在。它确实如此:

libnvidia-opencl.so.1

该库存在于

/usr/lib64/libnvidia-opencl.so.1

我不明白的是,我可以编译代码和库lopencl 找到了。我通过yast安装驱动程序,并手动将头文件复制到usr / include。我还没有安装cuda包,因为我只想使用opencl。这可能是问题吗?

谢谢

1 个答案:

答案 0 :(得分:2)

您正在使用的示例代码无法检查所有OpenCL API调用返回的错误代码。这些功能中的一个或多个可能会失败,但您的代码只是忽略失败并尝试继续。

我通常在实用程序函数中包含OpenCL错误检查,如下所示:

void checkError(cl_int err, const char *operation)
{
  if (err != CL_SUCCESS)
  {
    fprintf(stderr, "Error during operation '%s': %d\n", operation, err);
    exit(1);
  }
}

然后您可以在代码中添加错误检查,如下所示:

/* Create OpenCL context */
context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);
checkError(ret, "creating context");

/* Create Command Queue */
command_queue = clCreateCommandQueue(context, device_id, 0, &ret);
checkError(ret, "creating command queue");

/* Create Memory Buffer */
memobj = clCreateBuffer(context, CL_MEM_READ_WRITE,MEM_SIZE * sizeof(char), NULL, &ret);
checkError(ret, "creating buffer");

/* Create Kernel Program from the source */
program = clCreateProgramWithSource(context, 1, (const char **)&source_str,
                                    (const size_t *)&source_size, &ret);
checkError(ret, "creating program");

/* Build Kernel Program */
ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
checkError(ret, "building program");

// etc 

现在,当OpenCL API调用失败时,程序将打印出哪个函数失败以及错误代码是什么。您可以在CL/cl.h标头中查找错误代码的人类可读名称,并阅读OpenCL规范以找出导致该错误的原因。您还可以在checkError函数中创建一个查找表,以自动检索人类可读的名称。