OpenCL C++ 常见属性与函数

核心对象与属性

对象/属性 描述 示例
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 空范围
© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容