【问题标题】:OpenCL Vector add programOpenCL 向量添加程序
【发布时间】:2015-11-20 00:48:44
【问题描述】:

我对 OpenCL 编程完全陌生。我已经安装了 OpenCL 库和驱动程序。但是我试图运行的程序没有产生预期的输出(输出全为零)。它只是一个简单的vector_add 程序。 提前感谢您的建议。

int main(int argc, char** argv)
{
cout << "Hello OpenCL" << endl;

vector<Platform> all_platforms;
int err = Platform::get(&all_platforms);
cout << "Getting Platform ... Error code " << err << endl;
if (all_platforms.size()==0)
    (cout << "No platforms" << endl, exit(0));
cout << "Platform info : " << all_platforms[0].getInfo<CL_PLATFORM_NAME>() << endl;
Platform default_platform = all_platforms[0];
cout << "Defaulting to it ..." << endl;

vector<Device> all_devices;
err = default_platform.getDevices(CL_DEVICE_TYPE_GPU, &all_devices);
cout << "Getting devices ... Error code : " << err << endl;
if (all_devices.size()==0)
    (cout << "No devices" << endl, exit(0));
Device default_device = all_devices[0];
cout << all_devices.size() << " devices & " << "Device info : " << all_devices[0].getInfo<CL_DEVICE_NAME>() << endl;
cout << "Defaulting to it ..." << endl;

Context context(default_device);
Program::Sources sources;

std::string kernel_code=
        "   void kernel simple_add(global const int* A, global const int* B, global int* C){"
        "   unsigned int i = get_global_id(0);  "
        "       C[i]=A[i]+B[i];                 "
        "   }                                                                               ";

sources.push_back(make_pair(kernel_code.c_str(), kernel_code.length()+1));
Program program(context, sources);

if (program.build(all_devices)==CL_SUCCESS)
    cout << "Built Successfully" << endl;

Buffer buffer_A(context,CL_MEM_READ_WRITE,sizeof(int)*10);
Buffer buffer_B(context,CL_MEM_READ_WRITE,sizeof(int)*10);
Buffer buffer_C(context,CL_MEM_READ_WRITE,sizeof(int)*10);

int A[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int B[] = {0, 1, 2, 0, 1, 2, 0, 1, 2, 0};

CommandQueue queue(context,default_device);
queue.enqueueWriteBuffer(buffer_A,CL_TRUE,0,sizeof(int)*10,A); // load data from host to device
queue.enqueueWriteBuffer(buffer_B,CL_TRUE,0,sizeof(int)*10,B);

Kernel kernel(program, "vector_add");
kernel.setArg(0, buffer_A);
kernel.setArg(1, buffer_B);
kernel.setArg(2, buffer_C);

queue.enqueueNDRangeKernel(kernel,cl::NullRange,cl::NDRange(10),cl::NullRange);
queue.finish();

int *C = new int[10];
queue.enqueueReadBuffer(buffer_C, CL_TRUE, 0, 10 * sizeof(int), C);

for (int i=0;i<10;i++)
    std::cout << A[i] << " + " << B[i] << " = " << C[i] << std::endl;

return 0;
}

【问题讨论】:

  • 您应该在每次调用时检查错误,或者为 OpenCL 启用 C++ 异常。否则你可能会错过任何返回错误的函数。
  • cl::NDRange(10) 必须无效。你至少应该做 32,64,128 或 8192,无论 64 的倍数适合你。 cl::NDRange(64)
  • 任何全局大小都应该是有效的,无论内部执行计划如何。因此,您可以根据需要使用 1、3、5、7、13、59。这不太可能是问题所在。

标签: opencl


【解决方案1】:

正如 cmets 中所指出的,您应该始终在使用 OpenCL API 函数时检查错误代码。这可以通过在 C++ 包装器中启用异常处理来实现:

#define __CL_ENABLE_EXCEPTIONS      // with cl.hpp
//#define CL_HPP_ENABLE_EXCEPTIONS  // with cl2.hpp

#include <CL/cl.hpp>

int main(int argc, char *argv[])
{
  try
  {
    // OpenCL code here
  }
  catch (cl::Error& err)
  {
    cout << err.what() << " failed with error code " << err.err() << endl;
  }
}

如果您这样做,您将收到有关您的代码的几个问题的有用信息。

clCreateKernel 函数返回CL_INVALID_NAME。在您的内核中,您使用名称 simple_add 定义内核函数,然后您尝试使用名称 vector_add 创建一个内核对象。

如果您的 OpenCL 平台具有多个设备,则在构建内核程序时也可能会收到错误消息。这是因为您正在使用单个设备创建 OpenCL 上下文,然后尝试为设备列表构建程序:

Context context(default_device);
// ...
if (program.build(all_devices)==CL_SUCCESS)
  cout << "Built Successfully" << endl;

最简单的解决方法是从 build 函数中删除参数,因为默认情况下它将为上下文中的所有设备构建程序(这几乎总是您真正想要的):

if (program.build()==CL_SUCCESS)
  cout << "Built Successfully" << endl;

【讨论】:

  • 很好的答案,用于实际测试代码并提供所有反馈。确实,启用异常是所有 C++ OpenCL 开发人员都应该立即完成的一项关键功能。
猜你喜欢
  • 1970-01-01
  • 2012-02-14
  • 2019-12-02
  • 2021-01-21
  • 1970-01-01
  • 2012-04-05
  • 1970-01-01
  • 2016-04-13
  • 2023-03-27
相关资源
最近更新 更多