核心对象与属性
| 对象/属性 |
描述 |
示例 |
cl::Platform |
表示OpenCL平台 |
cl::Platform::get(&platforms) |
cl::Device |
表示计算设备 |
cl::Device::getDefault() |
cl::Context |
管理设备、内存和命令队列的上下文 |
cl::Context(contextDevices) |
cl::CommandQueue |
命令队列,用于提交命令 |
cl::CommandQueue(context, device) |
cl::Program |
OpenCL程序对象 |
cl::Program(context, sources) |
cl::Kernel |
内核函数对象 |
cl::Kernel(program, "kernel_name") |
cl::Buffer |
内存缓冲区对象 |
cl::Buffer(context, flags, size) |
| cl::Image1D/Image2D等 |
图像对象 |
cl::Image1D(context, flags, format, width, host_ptr) |
| cl::Pipe |
管道对象 |
cl::Pipe(context, flags, packet_size, max_packets) |
Platform 属性与函数
Platform 对象代表 OpenCL 实现平台,通常对应不同的硬件供应商(如 NVIDIA、AMD、Intel 等)。选择适当的平台对应用性能有重要影响。
Platform 对象创建与获取
| 对象/函数 |
描述 |
示例 |
cl::Platform |
Platform 对象 |
cl::Platform::get(&platforms) |
cl::Platform::get(vector<Platform>*) |
获取所有可用平台 |
cl::Platform::get(&platformList) |
cl::Platform::getDefault() |
获取默认平台 |
cl::Platform platform = cl::Platform::getDefault() |
Platform 信息查询函数
| 函数 |
描述 |
返回类型 |
cl::Platform::getInfo<info_type>(param_name) |
获取平台信息 |
取决于查询参数 |
cl::Platform::getDevices(device_type, vector<Device>*) |
获取平台关联的设备 |
vector<cl::Device> |
Platform 查询参数
| 查询参数 |
描述 |
返回类型 |
CL_PLATFORM_PROFILE |
平台支持的OpenCL规范 |
string |
CL_PLATFORM_VERSION |
OpenCL版本信息 |
string |
CL_PLATFORM_NAME |
平台名称 |
string |
CL_PLATFORM_VENDOR |
平台供应商 |
string |
CL_PLATFORM_EXTENSIONS |
支持的扩展 |
string |
CL_PLATFORM_ICD_SUFFIX_KHR |
ICD后缀(需要扩展) |
string |
Platform 扩展函数
| 函数 |
描述 |
备注 |
cl::Platform::getHostTimerResolution() |
获取主机计时器分辨率(OpenCL 2.1+) |
需要 cl_khr_host_timer_resolution 扩展 |
cl::Platform::unloadCompiler() |
卸载编译器资源 |
|
Platform 属性常量
| 常量 |
值 |
描述 |
CL_PLATFORM_PROFILE_FULL |
“FULL_PROFILE” |
完整规范支持 |
CL_PLATFORM_PROFILE_EMBEDDED |
“EMBEDDED_PROFILE” |
嵌入式规范支持 |
示例代码
cpp
// 1. 获取所有平台
vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
// 2. 遍历平台信息
for (auto &platform : platforms) {
string name = platform.getInfo<CL_PLATFORM_NAME>();
string vendor = platform.getInfo<CL_PLATFORM_VENDOR>();
string version = platform.getInfo<CL_PLATFORM_VERSION>();
cout << "Platform: " << name << "
"
<< "Vendor: " << vendor << "
"
<< "Version: " << version << endl;
// 3. 获取设备列表
vector<cl::Device> devices;
platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);
// 4. 检查扩展支持
string extensions = platform.getInfo<CL_PLATFORM_EXTENSIONS>();
if (extensions.find("cl_khr_icd") != string::npos) {
cout << "ICD extension supported" << endl;
}
}
// 5. 获取默认平台
cl::Platform defaultPlatform = cl::Platform::getDefault();
// 6. 卸载编译器(减少资源占用)
defaultPlatform.unloadCompiler();
平台选择实用技巧
cpp
// 1. 按供应商选择平台
cl::Platform selectPlatform(const string &vendor) {
vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
for (auto &platform : platforms) {
string platformVendor = platform.getInfo<CL_PLATFORM_VENDOR>();
if (platformVendor.find(vendor) != string::npos) {
return platform;
}
}
throw runtime_error("No platform found for vendor: " + vendor);
}
// 2. 检查平台版本
bool checkPlatformVersion(cl::Platform &platform, int major, int minor) {
string version = platform.getInfo<CL_PLATFORM_VERSION>();
int platMajor, platMinor;
sscanf(version.c_str(), "OpenCL %d.%d", &platMajor, &platMinor);
return (platMajor > major) || (platMajor == major && platMinor >= minor);
}
错误处理
| 错误码 |
描述 |
CL_INVALID_PLATFORM |
无效的平台对象 |
CL_INVALID_VALUE |
无效的查询参数 |
CL_OUT_OF_HOST_MEMORY |
主机内存不足 |
Device属性与函数
Device 对象代表 OpenCL 可用的计算设备,了解设备属性和能力对于优化 OpenCL 程序性能至关重要。实际编程中应根据设备特性调整内核参数和工作组大小。
Device 对象获取
| 对象/函数 |
描述 |
示例 |
cl::Device |
Device 对象 |
cl::Device::getDefault() |
cl::Platform::getDevices(device_type, devices) |
获取平台关联的设备 |
platform.getDevices(CL_DEVICE_TYPE_GPU, &devices) |
cl::Device::getDefault() |
获取默认设备 |
cl::Device device = cl::Device::getDefault() |
设备信息查询函数
| 函数 |
描述 |
cl::Device::getInfo<info_type>(param_name) |
获取设备信息 |
cl::Device::getSupportedImageFormats(context, flags, image_type) |
获取支持的图像格式 |
设备类型常量
| 常量 |
描述 |
CL_DEVICE_TYPE_CPU |
CPU 设备 |
CL_DEVICE_TYPE_GPU |
GPU 设备 |
CL_DEVICE_TYPE_ACCELERATOR |
加速器设备 |
CL_DEVICE_TYPE_CUSTOM |
自定义设备 |
CL_DEVICE_TYPE_ALL |
所有设备类型 |
设备基本信息查询
| 查询参数 |
描述 |
返回类型 |
CL_DEVICE_NAME |
设备名称 |
string |
CL_DEVICE_VENDOR |
设备供应商 |
string |
CL_DEVICE_VERSION |
OpenCL 版本 |
string |
CL_DRIVER_VERSION |
驱动版本 |
string |
CL_DEVICE_PROFILE |
支持规范(FULL/EMBEDDED) |
string |
CL_DEVICE_TYPE |
设备类型 |
cl_device_type |
设备能力信息
| 查询参数 |
描述 |
返回类型 |
CL_DEVICE_MAX_COMPUTE_UNITS |
计算单元数量 |
cl_uint |
CL_DEVICE_MAX_CLOCK_FREQUENCY |
最大时钟频率(MHz) |
cl_uint |
CL_DEVICE_ADDRESS_BITS |
地址宽度(位) |
cl_uint |
CL_DEVICE_AVAILABLE |
设备是否可用 |
cl_bool |
CL_DEVICE_COMPILER_AVAILABLE |
编译器是否可用 |
cl_bool |
内存信息
| 查询参数 |
描述 |
返回类型 |
CL_DEVICE_GLOBAL_MEM_SIZE |
全局内存大小(字节) |
cl_ulong |
CL_DEVICE_LOCAL_MEM_SIZE |
局部内存大小(字节) |
cl_ulong |
CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE |
常量内存大小(字节) |
cl_ulong |
CL_DEVICE_GLOBAL_MEM_CACHE_SIZE |
全局内存缓存大小 |
cl_ulong |
CL_DEVICE_MAX_MEM_ALLOC_SIZE |
最大内存分配大小 |
cl_ulong |
执行限制
| 查询参数 |
描述 |
返回类型 |
CL_DEVICE_MAX_WORK_GROUP_SIZE |
最大工作组大小 |
size_t |
CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS |
最大工作项维度 |
cl_uint |
CL_DEVICE_MAX_WORK_ITEM_SIZES |
各维度最大工作项大小 |
vector<size_t> |
图像支持
| 查询参数 |
描述 |
返回类型 |
CL_DEVICE_IMAGE_SUPPORT |
是否支持图像 |
cl_bool |
CL_DEVICE_IMAGE2D_MAX_WIDTH |
2D图像最大宽度 |
size_t |
CL_DEVICE_IMAGE2D_MAX_HEIGHT |
2D图像最大高度 |
size_t |
CL_DEVICE_IMAGE3D_MAX_WIDTH |
3D图像最大宽度 |
size_t |
CL_DEVICE_IMAGE3D_MAX_HEIGHT |
3D图像最大高度 |
size_t |
CL_DEVICE_IMAGE3D_MAX_DEPTH |
3D图像最大深度 |
size_t |
扩展功能
| 查询参数 |
描述 |
返回类型 |
CL_DEVICE_EXTENSIONS |
支持的扩展 |
string |
CL_DEVICE_PREFERRED_VECTOR_WIDTH_<type> |
各种类型的向量宽度 |
cl_uint |
设备分区相关(OpenCL 2.0+)
| 查询参数 |
描述 |
CL_DEVICE_PARTITION_MAX_SUB_DEVICES |
最大子设备数量 |
CL_DEVICE_PARTITION_PROPERTIES |
支持的分区类型 |
CL_DEVICE_PARTITION_AFFINITY_DOMAIN |
支持的亲和域 |
实用函数示例
cpp
// 1. 获取设备基本信息
void printDeviceInfo(cl::Device &device) {
cout << "Device: " << device.getInfo<CL_DEVICE_NAME>() << "
"
<< "Vendor: " << device.getInfo<CL_DEVICE_VENDOR>() << "
"
<< "Version: " << device.getInfo<CL_DEVICE_VERSION>() << "
"
<< "Compute Units: " << device.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>() << "
"
<< "Global Memory: " << device.getInfo<CL_DEVICE_GLOBAL_MEM_SIZE>()/1024/1024 << " MB
"
<< "Max Work Group Size: " << device.getInfo<CL_DEVICE_MAX_WORK_GROUP_SIZE>() << endl;
}
// 2. 检查扩展支持
bool checkDeviceExtension(cl::Device &device, const string &extension) {
string extensions = device.getInfo<CL_DEVICE_EXTENSIONS>();
return extensions.find(extension) != string::npos;
}
// 3. 选择最合适的设备
cl::Device selectMostPowerfulDevice() {
vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
cl::Device bestDevice;
int maxCUs = 0;
for (auto &platform : platforms) {
vector<cl::Device> devices;
platform.getDevices(CL_DEVICE_TYPE_GPU, &devices);
for (auto &device : devices) {
int cu = device.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>();
if (cu > maxCUs) {
maxCUs = cu;
bestDevice = device;
}
}
}
return bestDevice;
}
错误处理
| 错误码 |
描述 |
CL_INVALID_DEVICE |
无效的设备对象 |
CL_INVALID_VALUE |
无效的查询参数 |
CL_OUT_OF_HOST_MEMORY |
主机内存不足 |
Context属性与函数
Context 是 OpenCL 资源管理的核心对象,负责内存、命令队列等资源的生命周期管理。合理选择上下文创建方式和属性对程序性能和功能有重要影响。
Context 对象创建
| 对象/函数 |
描述 |
示例 |
cl::Context |
上下文对象 |
cl::Context(device_type) |
cl::Context::Context(properties, devices, pfn_notify, user_data, err) |
完整构造函数 |
|
cl::Context::Context(device_type, properties, pfn_notify, user_data, err) |
按类型创建 |
|
cl::createContext(properties, devices, pfn_notify, user_data, err) |
工厂函数创建 |
|
Context 属性常量
| 属性常量 |
描述 |
值类型 |
CL_CONTEXT_PLATFORM |
关联的平台 |
cl_platform_id |
CL_CONTEXT_INTEROP_USER_SYNC |
互操作同步 |
cl_bool |
CL_GL_CONTEXT_KHR |
OpenGL 上下文共享 |
平台相关 |
CL_WGL_HDC_KHR |
Windows GL 设备上下文 |
HDC |
CL_GLX_DISPLAY_KHR |
Linux GL 显示连接 |
Display* |
CL_CGL_SHAREGROUP_APPLE |
MacOS GL 共享组 |
CGLShareGroupObj |
Context 信息查询
| 查询函数 |
描述 |
返回类型 |
cl::Context::getInfo<info_type>() |
获取上下文信息 |
取决于参数 |
cl::Context::getDevices() |
获取关联设备列表 |
vector<cl::Device> |
Context 信息查询参数
| 查询参数 |
描述 |
返回类型 |
CL_CONTEXT_REFERENCE_COUNT |
引用计数 |
cl_uint |
CL_CONTEXT_NUM_DEVICES |
关联设备数量 |
cl_uint |
CL_CONTEXT_DEVICES |
关联设备列表 |
vector<cl::Device> |
CL_CONTEXT_PROPERTIES |
上下文属性 |
vector<cl_context_properties> |
图像支持函数
| 函数 |
描述 |
cl::Context::getSupportedImageFormats(flags, image_type) |
获取支持的图像格式 |
互操作函数
| 函数 |
描述 |
平台 |
cl::Context::getGLContextInfoKHR(name) |
获取GL共享信息 |
跨平台 |
clCreateFromGLBuffer |
从GL缓冲创建CL缓冲 |
跨平台 |
clCreateFromGLTexture |
从GL纹理创建CL图像 |
跨平台 |
回调函数
| 函数 |
描述 |
cl::Context::setExceptionHandler(enable, handler) |
设置异常回调 |
实用函数示例
cpp
// 1. 创建基本上下文
cl::Context context(CL_DEVICE_TYPE_GPU);
// 2. 创建带属性的上下文
cl_context_properties props[] = {
CL_CONTEXT_PLATFORM,
(cl_context_properties)platform(),
0
};
cl::Context context2(CL_DEVICE_TYPE_ALL, props);
// 3. OpenGL共享上下文创建(MacOS示例)
#ifdef __APPLE__
CGLContextObj glContext = CGLGetCurrentContext();
CGLShareGroupObj shareGroup = CGLGetShareGroup(glContext);
cl_context_properties osx_props[] = {
CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
(cl_context_properties)shareGroup,
0
};
cl::Context glSharedContext(CL_DEVICE_TYPE_GPU, osx_props);
#endif
// 4. 查询上下文信息
vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
cout << "Context has " << devices.size() << " devices" << endl;
// 5. 获取支持的图像格式
vector<cl::ImageFormat> formats;
context.getSupportedImageFormats(CL_MEM_READ_WRITE,
CL_MEM_OBJECT_IMAGE2D,
&formats);
错误处理
| 错误码 |
描述 |
CL_INVALID_PLATFORM |
无效的平台属性 |
CL_INVALID_VALUE |
无效的属性值 |
CL_INVALID_DEVICE |
无效的设备列表 |
CL_DEVICE_NOT_AVAILABLE |
设备不可用 |
CL_OUT_OF_HOST_MEMORY |
主机内存不足 |
上下文使用建议
资源共享:同一上下文内的对象可共享资源
设备选择:创建时可指定特定设备或设备类型
生命周期:确保上下文生命周期覆盖所有依赖对象
性能考虑:多设备上下文可能有额外开销
CommandQueue属性与函数
命令队列是OpenCL程序性能的关键因素,合理选择队列类型和适当使用事件同步可以显著提高性能。
CommandQueue 对象创建
| 对象/函数 |
描述 |
示例 |
cl::CommandQueue |
命令队列对象 |
cl::CommandQueue(context, device) |
cl::CommandQueue::CommandQueue(context, device, properties, err) |
带属性的构造函数 |
|
cl::CommandQueue::getDefault() |
获取默认命令队列 |
|
命令队列属性
属性标志
| 属性 |
描述 |
值 |
CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE |
启用乱序执行 |
cl_bitfield |
CL_QUEUE_PROFILING_ENABLE |
启用性能分析 |
cl_bitfield |
CL_QUEUE_ON_DEVICE |
设备端队列(OpenCL 2.0+) |
cl_bitfield |
CL_QUEUE_ON_DEVICE_DEFAULT |
默认设备端队列 |
cl_bitfield |
命令队列操作函数
基本控制
| 函数 |
描述 |
cl::CommandQueue::finish() |
阻塞直到所有命令完成 |
cl::CommandQueue::flush() |
提交所有命令到设备(非阻塞) |
内存操作命令
| 函数 |
描述 |
参数说明 |
enqueueReadBuffer() |
读取缓冲区 |
queue, buffer, blocking, offset, size, ptr |
enqueueWriteBuffer() |
写入缓冲区 |
queue, buffer, blocking, offset, size, ptr |
enqueueCopyBuffer() |
缓冲区间拷贝 |
queue, src, dst, src_offset, dst_offset, size |
enqueueFillBuffer() |
填充缓冲区 |
queue, buffer, pattern, offset, size |
内核执行命令
| 函数 |
描述 |
cl::CommandQueue::enqueueNDRangeKernel() |
执行NDRange内核 |
cl::CommandQueue::enqueueTask() |
执行任务内核 |
同步命令
| 函数 |
描述 |
cl::CommandQueue::enqueueMarker() |
插入标记点 |
cl::CommandQueue::enqueueBarrier() |
插入屏障 |
cl::CommandQueue::enqueueMarkerWithWaitList() |
带等待列表的标记 |
cl::CommandQueue::enqueueBarrierWithWaitList() |
带等待列表的屏障 |
命令队列信息查询
| 查询参数 |
描述 |
返回类型 |
CL_QUEUE_CONTEXT |
关联的上下文 |
cl::Context |
CL_QUEUE_DEVICE |
关联的设备 |
cl::Device |
CL_QUEUE_REFERENCE_COUNT |
引用计数 |
cl_uint |
CL_QUEUE_PROPERTIES |
队列属性 |
cl_command_queue_properties |
实用代码示例
cpp
// 1. 创建命令队列
cl::CommandQueue queue(context, device, CL_QUEUE_PROFILING_ENABLE);
// 2. 执行内核并分析性能
cl::Event event;
queue.enqueueNDRangeKernel(kernel, cl::NullRange,
cl::NDRange(1024),
cl::NDRange(128),
nullptr, &event);
queue.finish();
// 3. 获取性能数据
if(queue.getInfo<CL_QUEUE_PROPERTIES>() & CL_QUEUE_PROFILING_ENABLE) {
cl_ulong start = event.getProfilingInfo<CL_PROFILING_COMMAND_START>();
cl_ulong end = event.getProfilingInfo<CL_PROFILING_COMMAND_END>();
double time_ms = (end - start) * 1e-6;
cout << "Kernel execution time: " << time_ms << " ms" << endl;
}
// 4. 乱序执行示例
cl::CommandQueue oooQueue(context, device,
CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE);
// 5. 多队列同步
cl::Event writeEvent;
queue.enqueueWriteBuffer(buffer, CL_FALSE, 0, size, data, nullptr, &writeEvent);
cl::Event kernelEvent;
vector<cl::Event> waitList = {writeEvent};
queue.enqueueNDRangeKernel(kernel, ..., waitList, &kernelEvent);
最佳实践建议
队列类型选择:
顺序队列(默认):命令按提交顺序执行
乱序队列:需要显式事件依赖管理
性能分析:
cpp
// 启用分析
cl::CommandQueue queue(context, device, CL_QUEUE_PROFILING_ENABLE);
// 获取时间戳
cl_ulong queued = event.getProfilingInfo<CL_PROFILING_COMMAND_QUEUED>();
cl_ulong submit = event.getProfilingInfo<CL_PROFILING_COMMAND_SUBMIT>();
cl_ulong start = event.getProfilingInfo<CL_PROFILING_COMMAND_START>();
cl_ulong end = event.getProfilingInfo<CL_PROFILING_COMMAND_END>();
多设备场景:
cpp
// 为每个设备创建独立队列
vector<cl::CommandQueue> queues;
for(auto& device : devices) {
queues.emplace_back(context, device);
}
错误处理:
cpp
try {
queue.enqueueNDRangeKernel(...);
} catch(cl::Error& e) {
cerr << "Error: " << e.what() << " (" << e.err() << ")" << endl;
}
Program属性与函数
Program 对象创建
| 对象/函数 |
描述 |
示例 |
cl::Program |
Program 对象 |
cl::Program(context, sources) |
cl::Program::Program(context, devices, binaries, binary_status, err) |
从二进制创建 |
|
cl::Program::Program(context, devices, kernel_names, err) |
从内置内核创建 |
|
Program 构建与编译
| 函数 |
描述 |
参数说明 |
cl::Program::build(devices, options, pfn_notify, user_data) |
构建 program |
devices: 目标设备 options: 构建选项 |
cl::Program::compile(devices, options, headers, header_include_names, pfn_notify, user_data) |
仅编译不链接 |
|
cl::Program::link(context, devices, options, programs, pfn_notify, user_data) |
链接多个 program |
|
Program 信息查询
| 查询函数 |
描述 |
返回类型 |
cl::Program::getBuildInfo<info_type>(device) |
获取构建信息 |
取决于参数 |
cl::Program::getInfo<info_type>() |
获取 program 信息 |
取决于参数 |
常用构建选项
| 选项 |
描述 |
示例 |
-D name=value |
定义宏 |
-D WORK_GROUP_SIZE=64 |
-I dir |
添加头文件路径 |
-I ./include |
-cl-std=CLx.y |
指定 OpenCL 版本 |
-cl-std=CL2.0 |
-cl-opt-disable |
禁用优化 |
|
-cl-single-precision-constant |
单精度常量 |
|
-cl-mad-enable |
允许乘加优化 |
|
Program 信息查询参数
| 查询参数 |
描述 |
返回类型 |
CL_PROGRAM_REFERENCE_COUNT |
引用计数 |
cl_uint |
CL_PROGRAM_CONTEXT |
关联上下文 |
cl::Context |
CL_PROGRAM_NUM_DEVICES |
关联设备数 |
cl_uint |
CL_PROGRAM_DEVICES |
关联设备列表 |
vector<cl::Device> |
CL_PROGRAM_SOURCE |
程序源代码 |
string |
CL_PROGRAM_BINARY_SIZES |
二进制大小 |
vector<size_t> |
CL_PROGRAM_BINARIES |
程序二进制 |
vector<char*> |
构建信息查询
| 查询参数 |
描述 |
返回类型 |
CL_PROGRAM_BUILD_STATUS |
构建状态 |
cl_build_status |
CL_PROGRAM_BUILD_OPTIONS |
构建选项 |
string |
CL_PROGRAM_BUILD_LOG |
构建日志 |
string |
CL_PROGRAM_BINARY_TYPE |
二进制类型 |
cl_program_binary_type |
Kernel 相关操作
| 函数 |
描述 |
示例 |
cl::Program::createKernels(kernels) |
创建所有 kernel |
|
cl::Kernel::Kernel(program, name, err) |
创建指定 kernel |
cl::Kernel(program, "vecAdd") |
实用代码示例
cpp
// 1. 从源代码创建 Program
std::string kernelCode = R"(
__kernel void vecAdd(__global const float* a,
__global const float* b,
__global float* c) {
int i = get_global_id(0);
c[i] = a[i] + b[i];
}
)";
cl::Program::Sources sources;
sources.push_back({kernelCode.c_str(), kernelCode.length()});
cl::Program program(context, sources);
// 2. 构建 Program
try {
program.build("-cl-std=CL1.2 -D BLOCK_SIZE=64");
} catch (cl::Error& e) {
// 获取构建日志
std::string log = program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device);
std::cerr << "Build error:
" << log << std::endl;
throw;
}
// 3. 创建 Kernel
cl::Kernel kernel(program, "vecAdd");
// 4. 获取二进制
vector<size_t> binarySizes = program.getInfo<CL_PROGRAM_BINARY_SIZES>();
vector<char*> binaries(binarySizes.size());
program.getInfo(CL_PROGRAM_BINARIES, &binaries);
// 5. 从二进制创建 Program
vector<vector<unsigned char>> binaryData;
cl::Program::Binaries binaries;
vector<cl_int> binaryStatus;
// ... 填充二进制数据 ...
cl::Program binaryProgram(context, {device}, binaries, &binaryStatus);
错误处理
| 错误码 |
描述 |
CL_INVALID_PROGRAM |
无效的 program |
CL_INVALID_VALUE |
无效的参数 |
CL_INVALID_BINARY |
无效的二进制 |
CL_INVALID_BUILD_OPTIONS |
无效的构建选项 |
CL_COMPILER_NOT_AVAILABLE |
编译器不可用 |
CL_BUILD_PROGRAM_FAILURE |
构建失败 |
最佳实践建议
构建选项优化:
cpp
// 常用优化选项组合
string options = "-cl-std=CL2.0 -cl-mad-enable -cl-no-signed-zeros";
if(device.getInfo<CL_DEVICE_VERSION>().find("2.0") != string::npos) {
options += " -D USE_SUBGROUPS";
}
program.build(options);
二进制缓存:
cpp
// 保存二进制到文件
ofstream binFile("kernel.bin", ios::binary);
binFile.write(binaries[0], binarySizes[0]);
// 从文件加载
ifstream binFile("kernel.bin", ios::binary);
vector<unsigned char> binary((istreambuf_iterator<char>(binFile)),
istreambuf_iterator<char>());
多设备构建:
cpp
// 为不同设备构建不同选项
map<cl::Device, string> deviceOptions;
for(auto& device : devices) {
if(device.getInfo<CL_DEVICE_TYPE>() == CL_DEVICE_TYPE_GPU) {
deviceOptions[device] = "-D GPU_DEVICE";
} else {
deviceOptions[device] = "-D CPU_DEVICE";
}
}
program.build(devices, "", nullptr, nullptr);
构建日志分析:
cpp
// 获取详细构建信息
for(auto& device : devices) {
auto status = program.getBuildInfo<CL_PROGRAM_BUILD_STATUS>(device);
auto options = program.getBuildInfo<CL_PROGRAM_BUILD_OPTIONS>(device);
auto log = program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device);
cout << "Device: " << device.getInfo<CL_DEVICE_NAME>() << endl
<< "Status: " << status << endl
<< "Options: " << options << endl
<< "Log: " << log << endl;
}
Kernel属性与函数
Kernel 对象创建
| 对象/函数 |
描述 |
示例 |
cl::Kernel |
Kernel 对象 |
cl::Kernel(program, "kernel_name") |
cl::Kernel::Kernel(program, name, err) |
带错误码的构造函数 |
|
cl::Program::createKernels(vector<Kernel>*) |
创建所有 kernel |
program.createKernels(&kernels) |
Kernel 参数设置
| 函数 |
描述 |
参数说明 |
cl::Kernel::setArg(index, value) |
设置内核参数 |
index: 参数索引 value: 参数值 |
cl::Kernel::setArg(index, size, ptr) |
设置本地内存参数 |
size: 本地内存大小 |
cl::Kernel::setSVMPointers(args) |
设置 SVM 指针(OpenCL 2.0+) |
|
Kernel 信息查询
| 查询函数 |
描述 |
返回类型 |
cl::Kernel::getInfo<info_type>() |
获取 kernel 信息 |
取决于参数 |
cl::Kernel::getWorkGroupInfo<info_type>(device) |
获取工作组信息 |
取决于参数 |
Kernel 执行函数
| 函数 |
描述 |
参数说明 |
cl::CommandQueue::enqueueNDRangeKernel(kernel, offset, global, local, events, event) |
执行内核 |
offset: 全局偏移 global: 全局工作项 local: 本地工作项 |
cl::CommandQueue::enqueueTask(kernel, events, event) |
执行任务内核 |
|
cl::KernelFunctor::operator()(args...) |
函数式内核调用 |
|
Kernel 信息查询参数
| 查询参数 |
描述 |
返回类型 |
CL_KERNEL_FUNCTION_NAME |
内核函数名 |
string |
CL_KERNEL_NUM_ARGS |
参数数量 |
cl_uint |
CL_KERNEL_REFERENCE_COUNT |
引用计数 |
cl_uint |
CL_KERNEL_CONTEXT |
关联上下文 |
cl::Context |
CL_KERNEL_PROGRAM |
关联程序 |
cl::Program |
CL_KERNEL_ATTRIBUTES |
内核属性 |
string |
Kernel 工作组信息查询
| 查询参数 |
描述 |
返回类型 |
CL_KERNEL_WORK_GROUP_SIZE |
最大工作组大小 |
size_t |
CL_KERNEL_COMPILE_WORK_GROUP_SIZE |
编译时指定工作组大小 |
array<size_t,3> |
CL_KERNEL_LOCAL_MEM_SIZE |
本地内存使用量 |
cl_ulong |
CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE |
优选工作组倍数 |
size_t |
CL_KERNEL_PRIVATE_MEM_SIZE |
私有内存使用量 |
cl_ulong |
实用代码示例
cpp
// 1. 创建 Kernel
cl::Kernel kernel(program, "matrixMul");
// 2. 设置内核参数
kernel.setArg(0, bufferA);
kernel.setArg(1, bufferB);
kernel.setArg(2, bufferC);
kernel.setArg(3, matrixSize);
// 3. 执行内核
cl::NDRange global(matrixSize, matrixSize);
cl::NDRange local(16, 16);
queue.enqueueNDRangeKernel(kernel, cl::NullRange, global, local);
// 4. 查询内核信息
string name = kernel.getInfo<CL_KERNEL_FUNCTION_NAME>();
size_t wgSize = kernel.getWorkGroupInfo<CL_KERNEL_WORK_GROUP_SIZE>(device);
// 5. 函数式调用(需要 cl.hpp)
auto matrixMul = cl::KernelFunctor<cl::Buffer, cl::Buffer, cl::Buffer, int>(program, "matrixMul");
matrixMul(cl::EnqueueArgs(queue, global, local), bufferA, bufferB, bufferC, matrixSize);
// 6. 设置本地内存参数
size_t localMemSize = 256 * sizeof(float);
kernel.setArg(4, localMemSize, nullptr);
错误处理
| 错误码 |
描述 |
CL_INVALID_KERNEL |
无效的 kernel |
CL_INVALID_KERNEL_ARGS |
无效的内核参数 |
CL_INVALID_WORK_GROUP_SIZE |
无效的工作组大小 |
CL_INVALID_WORK_ITEM_SIZE |
无效的工作项大小 |
最佳实践建议
参数设置优化:
cpp
// 批量设置参数
template<typename... Args>
void setKernelArgs(cl::Kernel& kernel, Args&&... args) {
int index = 0;
(..., kernel.setArg(index++, std::forward<Args>(args)));
}
setKernelArgs(kernel, bufferA, bufferB, bufferC, matrixSize);
动态工作组大小:
cpp
size_t maxWgSize = kernel.getWorkGroupInfo<CL_KERNEL_WORK_GROUP_SIZE>(device);
size_t optimalSize = std::min(maxWgSize, 256ul);
cl::NDRange local(optimalSize);
内核特性检查:
cpp
// 检查内核是否支持子组(OpenCL 2.1+)
string attributes = kernel.getInfo<CL_KERNEL_ATTRIBUTES>();
bool supportsSubgroups = attributes.find("sub_group_size") != string::npos;
性能分析:
cpp
cl::Event event;
queue.enqueueNDRangeKernel(kernel, ..., &event);
queue.finish();
cl_ulong start = event.getProfilingInfo<CL_PROFILING_COMMAND_START>();
cl_ulong end = event.getProfilingInfo<CL_PROFILING_COMMAND_END>();
double timeMs = (end - start) * 1e-6;
SVM 参数设置(OpenCL 2.0+):
cpp
void* svmPtr = clSVMAlloc(context(), CL_MEM_READ_WRITE, size, 0);
kernel.setSVMPointers({&svmPtr});
Buffer属性与函数
Buffer 对象创建
| 对象/函数 |
描述 |
示例 |
cl::Buffer |
Buffer 对象 |
cl::Buffer(context, flags, size) |
cl::Buffer::Buffer(context, flags, size, host_ptr, err) |
带主机指针的构造函数 |
|
cl::Buffer::Buffer(context, flags, vector<T>&) |
从 vector 创建 |
|
内存标志常量
| 标志 |
描述 |
值 |
CL_MEM_READ_ONLY |
只读内存 |
cl_mem_flags |
CL_MEM_WRITE_ONLY |
只写内存 |
cl_mem_flags |
CL_MEM_READ_WRITE |
读写内存 |
cl_mem_flags |
CL_MEM_USE_HOST_PTR |
使用主机指针 |
cl_mem_flags |
CL_MEM_ALLOC_HOST_PTR |
分配主机可访问内存 |
cl_mem_flags |
CL_MEM_COPY_HOST_PTR |
拷贝主机数据 |
cl_mem_flags |
CL_MEM_HOST_WRITE_ONLY |
主机只写 |
cl_mem_flags |
CL_MEM_HOST_READ_ONLY |
主机只读 |
cl_mem_flags |
CL_MEM_HOST_NO_ACCESS |
主机不可访问 |
cl_mem_flags |
Buffer 操作函数
数据传输
| 函数 |
描述 |
参数说明 |
cl::copy(queue, begin, end, buffer) |
主机到设备拷贝 |
STL 迭代器接口 |
cl::copy(queue, buffer, begin, end) |
设备到主机拷贝 |
|
cl::enqueueReadBuffer(queue, buffer, blocking, offset, size, ptr, events, event) |
读取缓冲区 |
|
cl::enqueueWriteBuffer(queue, buffer, blocking, offset, size, ptr, events, event) |
写入缓冲区 |
|
cl::enqueueFillBuffer(queue, buffer, pattern, pattern_size, offset, size, events, event) |
填充缓冲区 |
|
内存操作
| 函数 |
描述 |
cl::enqueueMapBuffer(queue, buffer, blocking, flags, offset, size, events, event, err) |
映射缓冲区到主机 |
cl::enqueueUnmapMemObject(queue, buffer, mapped_ptr, events, event) |
取消映射 |
缓冲区间操作
| 函数 |
描述 |
cl::enqueueCopyBuffer(queue, src, dst, src_offset, dst_offset, size, events, event) |
缓冲区间拷贝 |
cl::enqueueCopyBufferRect(queue, src, dst, src_origin, dst_origin, region, src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch, events, event) |
矩形区域拷贝 |
Buffer 信息查询
| 查询函数 |
描述 |
返回类型 |
cl::Buffer::getInfo<info_type>() |
获取 buffer 信息 |
取决于参数 |
Buffer 信息查询参数
| 查询参数 |
描述 |
返回类型 |
CL_MEM_TYPE |
内存类型 |
cl_mem_object_type |
CL_MEM_FLAGS |
内存标志 |
cl_mem_flags |
CL_MEM_SIZE |
内存大小 |
size_t |
CL_MEM_HOST_PTR |
主机指针 |
void* |
CL_MEM_MAP_COUNT |
映射计数 |
cl_uint |
CL_MEM_REFERENCE_COUNT |
引用计数 |
cl_uint |
CL_MEM_CONTEXT |
关联上下文 |
cl::Context |
实用代码示例
cpp
// 1. 创建缓冲区
cl::Buffer buffer(context, CL_MEM_READ_WRITE, 1024 * sizeof(float));
// 2. 数据传输
vector<float> hostData(1024, 1.0f);
queue.enqueueWriteBuffer(buffer, CL_TRUE, 0, 1024 * sizeof(float), hostData.data());
// 3. 使用STL风格拷贝
vector<float> srcData(1024, 2.0f);
cl::copy(queue, srcData.begin(), srcData.end(), buffer);
// 4. 映射缓冲区
float* ptr = (float*)queue.enqueueMapBuffer(buffer, CL_TRUE, CL_MAP_READ, 0, 1024 * sizeof(float));
// 使用映射指针...
queue.enqueueUnmapMemObject(buffer, ptr);
// 5. 填充缓冲区
cl_float pattern = 0.0f;
queue.enqueueFillBuffer(buffer, pattern, sizeof(cl_float), 0, 1024 * sizeof(float));
// 6. 缓冲区间拷贝
cl::Buffer srcBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, hostData.size() * sizeof(float), hostData.data());
cl::Buffer dstBuffer(context, CL_MEM_WRITE_ONLY, hostData.size() * sizeof(float));
queue.enqueueCopyBuffer(srcBuffer, dstBuffer, 0, 0, hostData.size() * sizeof(float));
// 7. 矩形区域拷贝
size_t region[] = {100, 100, 1}; // 宽度、高度、深度
size_t src_origin[] = {0, 0, 0};
size_t dst_origin[] = {50, 50, 0};
queue.enqueueCopyBufferRect(srcBuffer, dstBuffer, src_origin, dst_origin, region,
100*sizeof(float), 0, // src行间距/切片间距
100*sizeof(float), 0, // dst行间距/切片间距
nullptr, nullptr);
最佳实践建议
内存标志选择:
cpp
// 根据访问模式选择最佳标志
cl_mem_flags flags = CL_MEM_READ_WRITE;
if(access == "read-only") flags = CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY;
else if(access == "write-only") flags = CL_MEM_WRITE_ONLY | CL_MEM_HOST_READ_ONLY;
高效数据传输:
cpp
// 使用非阻塞写入+事件同步
cl::Event writeEvent;
queue.enqueueWriteBuffer(buffer, CL_FALSE, 0, size, data, nullptr, &writeEvent);
// ...其他操作...
writeEvent.wait();
缓冲区复用:
cpp
// 避免频繁创建/释放缓冲区
static cl::Buffer persistentBuffer(context, CL_MEM_READ_WRITE, MAX_SIZE);
对齐访问优化:
cpp
// 确保访问对齐(通常是128字节)
size_t alignment = device.getInfo<CL_DEVICE_MEM_BASE_ADDR_ALIGN>()/8;
size_t alignedSize = ((size + alignment - 1) / alignment) * alignment;
SVM缓冲区(OpenCL 2.0+):
cpp
// 共享虚拟内存缓冲区
void* svmPtr = clSVMAlloc(context(), CL_MEM_READ_WRITE, size, alignment);
cl::SVMBuffer svmBuffer(context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, svmPtr, size);
图像属性与函数
图像对象创建与管理
| 对象/函数 |
描述 |
示例 |
cl::Image1D |
一维图像对象 |
cl::Image1D(context, flags, format, width, host_ptr) |
cl::Image2D |
二维图像对象 |
cl::Image2D(context, flags, format, width, height, row_pitch, host_ptr) |
cl::Image3D |
三维图像对象 |
cl::Image3D(context, flags, format, width, height, depth, row_pitch, slice_pitch, host_ptr) |
cl::ImageFormat |
图像格式描述 |
cl::ImageFormat(order, type) |
cl::Image2DGL |
OpenGL共享2D图像 |
cl::Image2DGL(context, flags, target, miplevel, texture) |
图像格式相关
通道顺序 (Channel Order)
| 格式 |
描述 |
CL_R |
单通道 (红色) |
CL_RG |
双通道 (红-绿) |
CL_RGB |
三通道 (红-绿-蓝) |
CL_RGBA |
四通道 (红-绿-蓝-透明) |
CL_BGRA |
四通道 (蓝-绿-红-透明) |
CL_ARGB |
四通道 (透明-红-绿-蓝) |
通道数据类型 (Channel Type)
| 类型 |
描述 |
CL_SNORM_INT8 |
有符号8位归一化整数 |
CL_UNORM_INT8 |
无符号8位归一化整数 |
CL_SNORM_INT16 |
有符号16位归一化整数 |
CL_UNORM_INT16 |
无符号16位归一化整数 |
CL_FLOAT |
32位浮点数 |
CL_HALF_FLOAT |
16位浮点数 |
图像操作函数
图像读写
| 函数 |
描述 |
cl::enqueueReadImage(queue, image, blocking, origin, region, row_pitch, slice_pitch, ptr, events, event) |
从图像读取数据 |
cl::enqueueWriteImage(queue, image, blocking, origin, region, row_pitch, slice_pitch, ptr, events, event) |
向图像写入数据 |
cl::enqueueCopyImage(queue, src, dst, src_origin, dst_origin, region, events, event) |
图像间拷贝 |
cl::enqueueCopyImageToBuffer(queue, src, dst, src_origin, region, offset, events, event) |
图像到缓冲区拷贝 |
cl::enqueueCopyBufferToImage(queue, src, dst, offset, dst_origin, region, events, event) |
缓冲区到图像拷贝 |
图像映射
| 函数 |
描述 |
cl::enqueueMapImage(queue, image, blocking, flags, origin, region, row_pitch, slice_pitch, events, event, err) |
映射图像到主机内存 |
cl::enqueueUnmapMemObject(queue, image, mapped_ptr, events, event) |
取消映射图像 |
图像填充
| 函数 |
描述 |
cl::enqueueFillImage(queue, image, fill_color, origin, region, events, event) |
用指定颜色填充图像区域 |
图像采样器
| 对象/函数 |
描述 |
示例 |
cl::Sampler |
图像采样器对象 |
cl::Sampler(context, normalized_coords, addressing_mode, filter_mode) |
CL_ADDRESS_NONE |
边界处理: 不处理 |
|
CL_ADDRESS_CLAMP_TO_EDGE |
边界处理: 钳位到边缘 |
|
CL_ADDRESS_CLAMP |
边界处理: 钳位(已废弃) |
|
CL_ADDRESS_REPEAT |
边界处理: 重复 |
|
CL_ADDRESS_MIRRORED_REPEAT |
边界处理: 镜像重复 |
|
CL_FILTER_NEAREST |
过滤模式: 最近邻 |
|
CL_FILTER_LINEAR |
过滤模式: 线性插值 |
|
内核中的图像访问
图像访问限定符
| 限定符 |
描述 |
read_only |
只读图像 |
write_only |
只写图像 |
read_write |
读写图像 |
内置函数
| 函数 |
描述 |
read_imagef(image, sampler, coord) |
读取归一化坐标的浮点像素 |
read_imagei(image, sampler, coord) |
读取归一化坐标的整数像素 |
read_imageui(image, sampler, coord) |
读取归一化坐标的无符号整数像素 |
write_imagef(image, coord, color) |
写入浮点像素 |
write_imagei(image, coord, color) |
写入整数像素 |
write_imageui(image, coord, color) |
写入无符号整数像素 |
get_image_width(image) |
获取图像宽度 |
get_image_height(image) |
获取图像高度 |
get_image_depth(image) |
获取图像深度(3D) |
get_image_dim(image) |
获取图像维度 |
图像实用函数
| 函数 |
描述 |
cl::imageQuerySupportedFormats(context, flags, image_type, formats) |
查询支持的图像格式 |
clGetImageInfo(image, param_name, param_value_size, param_value, param_value_size_ret) |
获取图像信息 |
注意:图像操作需要设备支持相应的图像格式和功能,使用前应检查CL_DEVICE_IMAGE_SUPPORT属性。
Pipe属性与函数
管道(Pipe)是OpenCL 2.0引入的特性,主要用于生产者-消费者模式的数据传输,需要设备支持OpenCL 2.0或更高版本。
管道对象创建
| 对象/函数 |
描述 |
示例 |
cl::Pipe |
管道对象(OpenCL 2.0+) |
cl::Pipe(context, flags, packet_size, max_packets) |
cl::Pipe::Pipe(context, flags, packet_size, max_packets, err) |
带错误码的构造函数 |
|
管道内存标志
| 标志 |
描述 |
值 |
CL_MEM_READ_ONLY |
只读管道 |
cl_mem_flags |
CL_MEM_WRITE_ONLY |
只写管道 |
cl_mem_flags |
CL_MEM_HOST_NO_ACCESS |
主机不可访问 |
cl_mem_flags |
管道操作函数
管道读写
| 函数 |
描述 |
参数说明 |
cl::CommandQueue::enqueueReadPipe(queue, pipe, blocking, offset, size, ptr, events, event) |
从管道读取 |
OpenCL 2.0+ |
cl::CommandQueue::enqueueWritePipe(queue, pipe, blocking, offset, size, ptr, events, event) |
写入管道 |
OpenCL 2.0+ |
管道查询
| 函数 |
描述 |
cl::Pipe::getInfo<info_type>() |
获取管道信息 |
管道信息查询参数
| 查询参数 |
描述 |
返回类型 |
CL_PIPE_PACKET_SIZE |
数据包大小 |
cl_uint |
CL_PIPE_MAX_PACKETS |
最大数据包数量 |
cl_uint |
CL_PIPE_PROPERTIES |
管道属性 |
vector<cl_pipe_properties> |
内核中的管道函数
管道内置函数
| 函数 |
描述 |
内核语言示例 |
read_pipe |
从管道读取 |
read_pipe(pipe, &data) |
write_pipe |
写入管道 |
write_pipe(pipe, &data) |
reserve_read_pipe |
保留读取位置 |
reserve_id_t rid = reserve_read_pipe(pipe, num_packets) |
reserve_write_pipe |
保留写入位置 |
reserve_id_t wid = reserve_write_pipe(pipe, num_packets) |
commit_read_pipe |
提交读取 |
commit_read_pipe(pipe, rid) |
commit_write_pipe |
提交写入 |
commit_write_pipe(pipe, wid) |
管道实用代码示例
cpp
// 1. 创建管道
cl_uint packet_size = sizeof(float) * 4; // 每个数据包包含4个float
cl_uint max_packets = 16; // 管道容量16个数据包
cl::Pipe pipe(context, CL_MEM_READ_WRITE, packet_size, max_packets);
// 2. 内核中使用管道(示例内核代码)
const char* kernel_source = R"(
__kernel void pipe_example(__write_only pipe float4 *out_pipe,
__read_only pipe float4 *in_pipe) {
float4 data = read_pipe(in_pipe); // 从输入管道读取
// 处理数据...
write_pipe(out_pipe, &data); // 写入输出管道
}
)";
// 3. 主机端写入管道
std::vector<float> input_data(64, 1.0f); // 16个数据包×4个float
queue.enqueueWritePipe(pipe, CL_TRUE, 0,
input_data.size() * sizeof(float),
input_data.data());
// 4. 主机端读取管道
std::vector<float> output_data(64);
queue.enqueueReadPipe(pipe, CL_TRUE, 0,
output_data.size() * sizeof(float),
output_data.data());
// 5. 查询管道信息
cl_uint query_packet_size = pipe.getInfo<CL_PIPE_PACKET_SIZE>();
cl_uint query_max_packets = pipe.getInfo<CL_PIPE_MAX_PACKETS>();
管道保留/提交模式示例
cpp
// 内核代码示例(保留/提交模式)
const char* reserve_kernel = R"(
__kernel void pipe_reserve_example(__write_only pipe float4 *out_pipe) {
reserve_id_t wid = reserve_write_pipe(out_pipe, 2); // 保留2个数据包位置
if(is_valid_reserve_id(wid)) {
float4 data1 = (float4)(1.0f);
float4 data2 = (float4)(2.0f);
write_pipe(out_pipe, wid, 0, &data1); // 写入第一个保留位置
write_pipe(out_pipe, wid, 1, &data2); // 写入第二个保留位置
commit_write_pipe(out_pipe, wid); // 提交写入
}
}
)";
管道属性查询函数
| 函数 |
描述 |
cl::Pipe::getPacketSize() |
获取数据包大小 |
cl::Pipe::getMaxPackets() |
获取最大数据包数量 |
错误处理
| 错误码 |
描述 |
CL_INVALID_PIPE_SIZE |
无效的管道大小 |
CL_INVALID_PIPE_PROPERTIES |
无效的管道属性 |
CL_MEM_OBJECT_ALLOCATION_FAILURE |
管道分配失败 |
CL_OUT_OF_RESOURCES |
资源不足 |
最佳实践建议
大小选择:
cpp
// 根据数据特性选择合适的数据包大小和容量
size_t optimal_packet_size = cache_line_size; // 通常与缓存行对齐
size_t optimal_max_packets = work_group_size * 2; // 足够工作组使用
性能优化:
cpp
// 使用保留/提交模式提高并行效率
// 内核中:
reserve_id_t rid = reserve_read_pipe(pipe, work_group_size);
if(is_valid_reserve_id(rid)) {
for(int i=0; i<work_group_size; i++) {
read_pipe(pipe, rid, i, &data[i]);
}
commit_read_pipe(pipe, rid);
}
多管道设计:
cpp
// 创建输入输出管道对
cl::Pipe input_pipe(context, CL_MEM_READ_ONLY, packet_size, max_packets);
cl::Pipe output_pipe(context, CL_MEM_WRITE_ONLY, packet_size, max_packets);
错误检查:
cpp
try {
cl::Pipe pipe(context, CL_MEM_READ_WRITE, packet_size, max_packets);
} catch (cl::Error& e) {
if(e.err() == CL_INVALID_PIPE_SIZE) {
// 调整数据包大小
packet_size = align_up(packet_size, 4);
}
}
实用工具函数
| 函数 |
描述 |
cl::getErrorString(error_code) |
获取错误描述 |
cl::createProgramWithSource(context, sources) |
从源代码创建程序 |
cl::createKernelsInProgram(program, kernels) |
从程序创建所有内核 |
常用枚举与标志
内存标志
| 标志 |
描述 |
CL_MEM_READ_ONLY |
只读内存 |
CL_MEM_WRITE_ONLY |
只写内存 |
CL_MEM_READ_WRITE |
读写内存 |
CL_MEM_USE_HOST_PTR |
使用主机指针 |
CL_MEM_COPY_HOST_PTR |
拷贝主机指针数据 |
CL_MEM_ALLOC_HOST_PTR |
分配主机可访问内存 |
设备类型
| 类型 |
描述 |
CL_DEVICE_TYPE_CPU |
CPU设备 |
CL_DEVICE_TYPE_GPU |
GPU设备 |
CL_DEVICE_TYPE_ACCELERATOR |
加速器设备 |
CL_DEVICE_TYPE_DEFAULT |
默认设备 |
内核工作项维度
| 函数 |
描述 |
cl::NDRange(global) |
1D范围 |
cl::NDRange(globalX, globalY) |
2D范围 |
cl::NDRange(globalX, globalY, globalZ) |
3D范围 |
cl::NullRange |
空范围 |
暂无评论内容