OpenCL C ++包装器。是否可以从Context类提取平台和设备?

时间:2018-12-12 21:17:11

标签: c++ opencl

我正在学习OpenCL,我已经知道可以通过首先以适当的方式设置平台和设备来解决此问题。

我想找出的是。 在免费的在线课程https://handsonopencl.github.io/中,他们开始以我喜欢的更简便的方式设置环境。

我现在在Exercise9上工作,应该从头开始编写内核和主机程序。我想以一种简化的方式解决该问题,该方法跳过了设置平台和设备的工作,而是直接调用Context类。 这样。

    #define DEVICE CL_DEVICE_TYPE_GPU
    try {
    // Create a context
    cl::Context context(DEVICE);

    // Load source and build
    cl::Program program(context, kernelSource, true);

    // Get command queue
    cl::CommandQueue queue(context);

    // Create kernel functor
    auto pi = cl::make_kernel<int>(program, "pi");


}
catch (cl::Error err) {
    std::cout << "Exception" << std::endl;
    std::cerr << "ERROR: " << err.what() << "(" << err_code(err.err()) << ")" << std::endl;

}

现在。我一切都设置正确。 C ++代码会编译,如果我提供正确的kernelSource,则程序也会编译。

到目前为止很好。

当我在内核源代码中犯了一个错误并想获取CL_PROGRAM_BUILD_LOG时,问题就来了。我发现的唯一调用要求我传递cl :: device(显然应该在Context构造函数中的某个位置存在)。但是因为我采用了速记路线,所以在构造函数之外就没有这个了。

我知道我可以执行跳过的电话并获得所需的值。但是我觉得这简直就是徒劳无益。

是否可以从Context类内部获取设备和平台标识符? 我的C ++不是最强,但是从看课时我找不到方法。

此包装器或调用中是否有其他我遗漏的方法可以为我检索构建日志,而无需先设置设备和平台?

我是否有确凿的理由不应该这样设置代码?

通过平台和设备进行扫描的唯一好处是,如果我有兴趣获得功能并做出明智的选择。在这种情况下,我就不知道自己已经要使用哪个设备了。

编辑: 添加此代码段以显示如何使用答案中提供的context.getInfo()解决问题。

    cl::Context context;
cl::Program program;
cl::CommandQueue queue;

try {
    // Create a context
    context = cl::Context(DEVICE);

    // Load source and build
    //program = cl::Program(context, kernelSource, true); // Don't do this. It will error with "abort() has been called
    program = cl::Program(context, kernelSource);
    program.build();

    // Bind variables
    d_sum = cl::Buffer(context, CL_MEM_WRITE_ONLY, sizeof(float) * 1);

    // Get command queue
    queue = cl::CommandQueue(context);

    // Create kernel functor
    auto clpi = cl::make_kernel<int, cl::Buffer, cl::LocalSpaceArg>(program, "pi");

    // Run kernel
    clpi(cl::EnqueueArgs(queue, cl::NDRange(num_steps), cl::NDRange(workgroup_size)), num_steps, d_sum, d_local_sums);

    // Extract sum
    cl::copy(queue, d_sum, h_sum.begin(), h_sum.end());

}
catch (cl::Error err) {
    std::cout << "Exception" << std::endl;
    std::cerr << "ERROR: " << err.what() << "(" << err_code(err.err()) << ")" << std::endl;

    if (err.err() == CL_BUILD_PROGRAM_FAILURE)
    {
        for (cl::Device dev : context.getInfo<CL_CONTEXT_DEVICES>())
        {
            // Check the build status
            cl_build_status status = program.getBuildInfo<CL_PROGRAM_BUILD_STATUS>(dev);
            if (status != CL_BUILD_ERROR)
                continue;
            // Get the build log
            std::string name = dev.getInfo<CL_DEVICE_NAME>();
            std::string buildlog = program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(dev);
            std::cerr << "Build log for " << name << ":" << std::endl
                << buildlog << std::endl;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

您可以使用clGetContextInfo(CL_CONTEXT_DEVICES)函数(对于C ++为Context::getInfo())找到与上下文关联的设备列表。然后,您可以遍历这些设备并询问每个设备的程序构建状态或构建日志。

可以使用相同的函数从上下文中获取平台:对于CL_CONTEXT_PROPERTIES,查询将返回属性数组,其中应包含CL_CONTEXT_PLATFORM的值。