31个版本
0.9.5 | 2023年12月22日 |
---|---|
0.9.4 | 2023年11月5日 |
0.9.3 | 2023年5月11日 |
0.9.2 | 2022年12月30日 |
0.1.0 | 2020年12月31日 |
#22 in 图形API
1,293 每月下载量
在30 个工具包中使用 (5 直接)
315KB
6K SLoC
opencl3
Khronos OpenCL API的Rust实现。
描述
OpenCL 3.0 API的相对简单、基于对象的模型。
它建立在cl3工具包之上,该工具包为OpenCL C API提供了功能接口。
OpenCL (开放计算语言)是一个用于跨异构设备(包括:CPU、GPU、DSP、FPGA和其他处理器或硬件加速器)进行通用并行编程的框架。它通常被视为Nvidia专有计算统一设备架构CUDA的开源替代品,用于在GPU上进行通用计算,请参阅GPGPU。
OpenCL 3.0是一个统一规范,在之前的OpenCL版本中添加了很少的新功能。
它规定所有OpenCL 1.2功能都是强制性的,而所有OpenCL 2.x和3.0功能现在是可选的。
特性
这个库具有以下特性:
- 简单的API,使大多数OpenCL对象可以通过单个函数调用来创建。
- 使用Drop特性自动管理OpenCL资源,以实现RAII。
- 支持使用事件等待列表执行有向无环图 OpenCL控制流。
- 支持使用可序列化和反序列化的 SvmVec 对象的共享虚拟内存(SVM)。
- 支持 OpenCL 扩展,详见 OpenCL 扩展。
- 支持使用 Send 和 Sync 特性进行多线程。
设计
该库基于对象,大多数 OpenCL 对象都由 Rust 结构体表示。例如,OpenCL 的 cl_device_id
由 Device 结构体表示,它提供获取设备信息的方法,而不是使用带有相关 cl_device_info
值的 clGetDeviceInfo
调用。
OpenCL 上下文类图
结构体方法比在 cl3 中的独立函数更易使用,因为它们将 InfoType
枚举转换为由 clGetDeviceInfo
调用返回的 cl_device_info
值的正确基础类型。
几乎所有结构体都实现了 Drop
特性以释放其对应的 OpenCL 对象。例外是 Platform
和 Device
,它们不需要释放。请参阅 文档。
OpenCL 版本和扩展的 API 由 Rust 功能(如 "CL_VERSION_2_0" 和 "cl_khr_gl_sharing")控制。要启用 OpenCL 版本,必须启用该版本的特性和 所有 之前的 OpenCL 版本的特性,例如对于 "CL_VERSION_2_0";还必须启用 "CL_VERSION_1_1" 和 "CL_VERSION_1_2"。
默认特性为 "CL_VERSION_1_1","CL_VERSION_1_2" 和 "CL_VERSION_2_0"。
对于由启用的 OpenCL 版本弃用的 OpenCL API 函数(例如,当 "CL_VERSION_2_0" 启用时,clCreateCommandQueue
被弃用),Rust 将给出弃用警告。
使用
确保已安装 OpenCL 可安装客户端驱动程序(ICD)和相应的 OpenCL 硬件驱动程序,详见 OpenCL 安装。
opencl3
默认支持 OpenCL 1.2 和 2.0 ICD 加载器。如果您有 OpenCL 2.0 ICD 加载器,则只需将以下内容添加到项目 Cargo.toml
文件中:
[dependencies]
opencl3 = "0.9"
如果您的 OpenCL ICD 加载器支持更高版本的 OpenCL,则将相应的功能添加到 opencl3 中,例如对于 OpenCL 3.0 ICD 加载器,将以下内容添加到项目 Cargo.toml
文件中:
[dependencies.opencl3]
version = "0.9"
features = ["CL_VERSION_2_1", "CL_VERSION_2_2", "CL_VERSION_3_0"]
也可以通过添加其功能来启用 OpenCL 扩展和 serde
支持,例如:
[dependencies.opencl3]
version = "0.9"
features = ["cl_khr_gl_sharing", "cl_khr_dx9_media_sharing", "serde"]
有关使用 OpenCL 的背景信息,请参阅 OpenCL 指南 和 OpenCL 描述。
示例
在 示例 目录中有示例。测试还提供了如何使用该库的示例,例如:请参阅 platform、device、context、integration_test 和 opencl2_kernel_test。
该库旨在支持事件和 OpenCL 2 功能,例如共享虚拟内存(SVM)和内置工作组函数。它还提供了可选的 serde
支持。
const PROGRAM_SOURCE: &str = r#"
kernel void inclusive_scan_int (global int* output,
global int const* values)
{
int sum = 0;
size_t lid = get_local_id(0);
size_t lsize = get_local_size(0);
size_t num_groups = get_num_groups(0);
for (size_t i = 0u; i < num_groups; ++i)
{
size_t lidx = i * lsize + lid;
int value = work_group_scan_inclusive_add(values[lidx]);
output[lidx] = sum + value;
sum += work_group_broadcast(value, lsize - 1);
}
}"#;
const KERNEL_NAME: &str = "inclusive_scan_int";
// Create a Context on an OpenCL device
let context = Context::from_device(&device).expect("Context::from_device failed");
// Build the OpenCL program source and create the kernel.
let program = Program::create_and_build_from_source(&context, PROGRAM_SOURCE, CL_STD_2_0)
.expect("Program::create_and_build_from_source failed");
let kernel = Kernel::create(&program, KERNEL_NAME).expect("Kernel::create failed");
// Create a command_queue on the Context's device
let queue = CommandQueue::create_default_with_properties(
&context,
CL_QUEUE_PROFILING_ENABLE,
0,
)
.expect("CommandQueue::create_default_with_properties failed");
// The input data
const ARRAY_SIZE: usize = 8;
const VALUE_ARRAY: &str = "[3,2,5,9,7,1,4,2]";
// Create an OpenCL SVM vector
let mut test_values = SvmVec::<cl_int>::new(&context);
// Handle test_values if device only supports CL_DEVICE_SVM_COARSE_GRAIN_BUFFER
if !test_values.is_fine_grained() {
// SVM_COARSE_GRAIN_BUFFER needs to know the size of the data to allocate the SVM
test_values = SvmVec::<cl_int>::allocate(&context, ARRAY_SIZE).expect("SVM allocation failed");
// Map the SVM for a SVM_COARSE_GRAIN_BUFFER
unsafe { queue.enqueue_svm_map(CL_BLOCKING, CL_MAP_WRITE, &mut test_values, &[])? };
// Clear the SVM for the deserializer
test_values.clear();
}
ExtendSvmVec(&mut test_values)
.deserialize(&mut deserializer)
.expect("Error deserializing the VALUE_ARRAY JSON string.");
// Make test_values immutable
let test_values = test_values;
// Unmap test_values if not a CL_MEM_SVM_FINE_GRAIN_BUFFER
if !test_values.is_fine_grained() {
let unmap_test_values_event = unsafe { queue.enqueue_svm_unmap(&test_values, &[])? };
unmap_test_values_event.wait()?;
}
// The output data, an OpenCL SVM vector
let mut results =
SvmVec::<cl_int>::allocate(&context, ARRAY_SIZE).expect("SVM allocation failed");
// Run the kernel on the input data
let sum_kernel_event = unsafe {
ExecuteKernel::new(&kernel)
.set_arg_svm(results.as_mut_ptr())
.set_arg_svm(test_values.as_ptr())
.set_global_work_size(ARRAY_SIZE)
.enqueue_nd_range(&queue)?
};
// Wait for the kernel to complete execution on the device
kernel_event.wait()?;
// Map results if not a CL_MEM_SVM_FINE_GRAIN_BUFFER
if !results.is_fine_grained() {
unsafe { queue.enqueue_svm_map(CL_BLOCKING, CL_MAP_READ, &mut results, &[])? };
}
// Convert SVM results to json
let json_results = serde_json::to_string(&results).unwrap();
println!("json results: {}", json_results);
// Unmap results if not a CL_MEM_SVM_FINE_GRAIN_BUFFER
if !results.is_fine_grained() {
let unmap_results_event = unsafe { queue.enqueue_svm_unmap(&results, &[])? };
unmap_results_event.wait()?;
}
上述示例取自:opencl2serde.rs。
测试
该软件包包含单元测试、文档测试和集成测试。
测试会运行平台和设备信息函数(等等),以便提供关于系统OpenCL功能的有用信息。
建议以单线程模式运行测试,因为当多线程运行时,其中一些可能会相互干扰,例如。
cargo test -- --test-threads=1 --show-output
集成测试被标记为ignore
,因此请使用以下命令来运行它们
cargo test -- --test-threads=1 --show-output --ignored
近期更改
自库的0.1
版本以来,API已经发生了相当大的变化,目的是使库更一致且易于使用。
SvmVec最近已更改以支持serde
反序列化。它还在版本0.5.0中更改,以更好地支持粗粒度缓冲区共享虚拟内存,因为Nvidia现在支持它,请参阅Nvidia OpenCL。
在版本0.6.0中,从底层的cl3软件包和该软件包中删除了Info枚举,以便将来可以使用当前未定义的新值从OpenCL设备读取数据。
在版本0.8.0中,对于被启用的OpenCL版本废弃的OpenCL API函数给出弃用警告,例如,当启用"CL_VERSION_2_0"时,clCreateCommandQueue
已被废弃。
在版本0.9.0中,许多OpenCL API函数被声明为unsafe
,因为如果调用不当可能会引起未定义的行为。
有关其他更改的信息,请参阅版本。
贡献
如果您想通过代码或文档进行贡献,贡献指南是开始的最佳位置。如果您有任何问题,请随时提问。但请遵守我们的行为准则。
许可证
根据Khronos Group OpenCL,许可协议为Apache License,版本2.0。
您可以在以下位置获得许可证的副本:https://apache.ac.cn/licenses/LICENSE-2.0
您故意提交给包含在作品中的任何贡献,均应按照上述Apache-2.0许可证中的定义进行许可,除非您明确表示否则,无需任何额外条款或条件。
OpenCL和OpenCL标志是Apple Inc.的商标,由Khronos Group许可使用。
依赖项
~1–1.6MB
~35K SLoC