OpenCL C++ HelloWorld
OpenCL C++ HelloWorld
下午好!
我在本教程中学习 OpenCL C++:Click(不是必需的)
视频使用CLAPI版本1.2,所以我下载了来自 link 的 OpenCL 1.2 headers 回复:
Visual Studio 2022 显示没有错误,但是程序输出这些符号:
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
应该是"Hello World!"
。
这是程序本身。
主持人:
#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';
}
谢谢 ;)
三个错误:
- 是
__kernel
或kernel
,但不是_kernel
带一个下划线; __global
相同
cl::Buffer memBuf(context, CL_MEM_READ_WRITE, 16*sizeof(buf));
- 这里有两处错误:CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY
标志意味着设备端的缓冲区完全不可访问,它只为第一个字符分配内存(忘了 16*sizeof(buf)
)
queue.enqueueReadBuffer(memBuf, CL_TRUE, 0, 16*sizeof(buf), (void*)buf);
- 忘记了 16*sizeof(buf)
我也不得不 auto err = program.build();
没有任何争论。
另请注意:
- 虽然有效,但堆栈分配 (
char buf[16];
) 限制了缓冲区大小。改用堆分配 (char* buf = new char[16];
)(不要忘记 delete[] buf;
)。
- 不要使用
queue.enqueueTask(kernel);
,而是使用 queue.enqueueNDRangeKernel(cl_kernel, cl::NullRange, cl::NDRange(...), cl::NDRange(32));
。有了这个,您可以指定全局和局部范围。
最后,做一点广告:我创建了一个 OpenCL-Wrapper 来大大简化学习和使用 OpenCL 的工作。此包装器消除了跟踪缓冲区大小或为 CPU 和设备设置重复缓冲区的需要。您需要为 HelloWorld 示例编写的代码更短更容易:
#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 #####################################################################
下午好! 我在本教程中学习 OpenCL C++:Click(不是必需的)
视频使用CLAPI版本1.2,所以我下载了来自 link 的 OpenCL 1.2 headers 回复:
Visual Studio 2022 显示没有错误,但是程序输出这些符号:
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
应该是"Hello World!"
。
这是程序本身。 主持人:
#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';
}
谢谢 ;)
三个错误:
- 是
__kernel
或kernel
,但不是_kernel
带一个下划线;__global
相同
cl::Buffer memBuf(context, CL_MEM_READ_WRITE, 16*sizeof(buf));
- 这里有两处错误:CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY
标志意味着设备端的缓冲区完全不可访问,它只为第一个字符分配内存(忘了16*sizeof(buf)
)queue.enqueueReadBuffer(memBuf, CL_TRUE, 0, 16*sizeof(buf), (void*)buf);
- 忘记了16*sizeof(buf)
我也不得不 auto err = program.build();
没有任何争论。
另请注意:
- 虽然有效,但堆栈分配 (
char buf[16];
) 限制了缓冲区大小。改用堆分配 (char* buf = new char[16];
)(不要忘记delete[] buf;
)。 - 不要使用
queue.enqueueTask(kernel);
,而是使用queue.enqueueNDRangeKernel(cl_kernel, cl::NullRange, cl::NDRange(...), cl::NDRange(32));
。有了这个,您可以指定全局和局部范围。
最后,做一点广告:我创建了一个 OpenCL-Wrapper 来大大简化学习和使用 OpenCL 的工作。此包装器消除了跟踪缓冲区大小或为 CPU 和设备设置重复缓冲区的需要。您需要为 HelloWorld 示例编写的代码更短更容易:
#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 #####################################################################