Good afternoon! I am learning OpenCL C++ in this tutorial: Click (it's not necessary)
The video uses CL API version 1.2, so I downloaded the OpenCL 1.2 headers from the link in this reply: https://stackoverflow.com/a/57017982/11968932
Visual Studio 2022 shows no errors, but the program outputs these symbols:
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
It's supposed to say "Hello World!"
.
Here is the program itself. Host:
#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
#include <CL/cl.hpp>
#include <iostream>
#include <fstream>
int main()
{
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
auto platform = platforms.front();
std::vector<cl::Device> devices;
platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);
auto device = devices.front();
std::ifstream helloWorldFile("HelloWorld.cl");
std::string src(std::istreambuf_iterator<char>(helloWorldFile), (std::istreambuf_iterator<char>()) );
cl::Program::Sources sources(1, std::make_pair(src.c_str(), src.length() + 1));
cl::Context context(device);
cl::Program program(context, sources);
auto err = program.build("cl-std=CL1.2");
char buf[16];
cl::Buffer memBuf(context, CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY, sizeof(buf));
cl::Kernel kernel(program, "HelloWorld", &err);
kernel.setArg(0, memBuf);
cl::CommandQueue queue(context, device);
queue.enqueueTask(kernel);
queue.enqueueReadBuffer(memBuf, CL_TRUE, 0, sizeof(buf), buf);
std::cout << buf << " - buf" << std::endl;
}
HelloWorld.cl:
_kernel void HelloWorld(_global char* data)
{
data[0] = 'H';
data[1] = 'e';
data[2] = 'l';
data[3] = 'l';
data[4] = 'o';
data[5] = ' ';
data[6] = 'W';
data[7] = 'o';
data[8] = 'r';
data[9] = 'l';
data[10] = 'd';
data[11] = '!';
data[12] = '\n';
}
Thanks ;)
Three mistakes:
__kernel
or kernel
, but not _kernel
with one underscore; same for __global
cl::Buffer memBuf(context, CL_MEM_READ_WRITE, 16*sizeof(buf));
- here 2 things were wrong: the CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY
flags meant the buffer on the device side was entirely inaccessible, and it only allocated memory for the first character (forgot the 16*sizeof(buf)
)queue.enqueueReadBuffer(memBuf, CL_TRUE, 0, 16*sizeof(buf), (void*)buf);
- forgot the 16*sizeof(buf)
I also had to do auto err = program.build();
without any arguments.
Also note:
char buf[16];
) limits the buffer size. Use heap allocation (char* buf = new char[16];
) instead (and don't forget delete[] buf;
).queue.enqueueTask(kernel);
, but queue.enqueueNDRangeKernel(cl_kernel, cl::NullRange, cl::NDRange(...), cl::NDRange(32));
instead. With this you can specify the global and local ranges.Lastly, a bit of an advertising: I created an OpenCL-Wrapper to greatly simplify learning and working with OpenCL. This Wrapper eliminates the need to keep track of for example buffer sizes or to have duplicate buffers for CPU and device. The code you need to write for the HelloWorld example is significantly shorter and easier:
#include "opencl.hpp"
int main() {
const Device device(select_device_with_most_flops()); // compile OpenCL C code for the fastest available device
const uint N = 16u; // size of vectors
Memory<char> buf(device, N); // allocate memory on both host and device
const Kernel HelloWorld(device, N, "HelloWorld", buf); // kernel that runs on the device
HelloWorld.run(); // run add_kernel on the device
buf.read_from_device(); // copy data from device memory to host memory
println(buf.data());
}
#include "kernel.hpp" // note: string literals can't be arbitrarily long, so periodically interrupt with )+R(
string opencl_c_container() { return R( // ########################## begin of OpenCL C code ####################################################################
kernel void HelloWorld(global char* data) {
data[0] = 'H';
data[1] = 'e';
data[2] = 'l';
data[3] = 'l';
data[4] = 'o';
data[5] = 32; // spaces are wrongly converted with stringification macro, so use ascii code here instead of ' '
data[6] = 'W';
data[7] = 'o';
data[8] = 'r';
data[9] = 'l';
data[10] = 'd';
data[11] = '!';
data[12] = '\n';
}
);} // ############################################################### end of OpenCL C code #####################################################################