A Rust implementation of the Khronos OpenCL API.
This crate provides a relatively simple, object based model of the OpenCL 3.0
API.
It is built upon the cl3 crate, which
provides a functional interface to the OpenCL API.
OpenCL (Open Computing Language) is framework for general purpose parallel programming across heterogeneous devices including: CPUs, GPUs, DSPs, FPGAs and other processors or hardware accelerators.
It is often considered as an open-source alternative to Nvidia's proprietary Compute Unified Device Architecture CUDA for performing General-purpose computing on GPUs, see GPGPU.
The OpenCL Specification has evolved over time and not all device vendors support all OpenCL features.
OpenCL 3.0
is a unified specification that adds little new functionality to previous OpenCL versions.
It specifies that all OpenCL 1.2 features are mandatory, while all
OpenCL 2.x and 3.0 features are now optional.
OpenCL 2.x and 3.0 optional features include: * Shared Virtual Memory (SVM), * nested parallelism, * pipes * atomics * and a generic address space,
The tests provide examples of how the crate may be used, e.g. see: platform, device, context, integrationtest and opencl2kernel_test.
The library is designed to support events and OpenCL 2 features such as Shared Virtual Memory (SVM) and kernel built-in work-group functions, e.g.:
```rust no-run const PROGRAMSOURCE: &str = r#" kernel void inclusivescanint (global int* output, global int const* values) { int sum = 0; sizet lid = getlocalid(0); sizet lsize = getlocal_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 KERNELNAME: &str = "inclusivescan_int";
// Create a Context on an OpenCL device let context = Context::fromdevice(&device).expect("Context::fromdevice failed");
// Build the OpenCL program source and create the kernel. let program = Program::createandbuildfromsource(&context, PROGRAMSOURCE, CLSTD20) .expect("Program::createandbuildfromsource failed"); let kernel = Kernel::create(&program, KERNEL_NAME).expect("Kernel::create failed");
// Create a commandqueue on the Context's device let queue = CommandQueue::createwithproperties( &context, context.defaultdevice(), CLQUEUEPROFILINGENABLE, 0, ) .expect("CommandQueue::createwith_properties failed");
// The input data const ARRAYSIZE: usize = 8; let valuearray: [clint; ARRAYSIZE] = [3, 2, 5, 9, 7, 1, 4, 2];
// Copy input data into an OpenCL SVM vector
let mut testvalues = SvmVec::
// The output data, an OpenCL SVM vector
let mut results =
SvmVec::
// Run the kernel on the input data let kernelevent = ExecuteKernel::new(kernel) .setargsvm(results.asmutptr()) .setargsvm(testvalues.asptr()) .setglobalworksize(ARRAYSIZE) .enqueuend_range(&queue) .unwrap();
// Wait for the kernel to complete execution on the device kernel_event.wait().unwrap();
// Can access OpenCL SVM directly, no need to map or read the results println!("sum results: {:?}", results); ```
Ensure that an OpenCL Installable Client Driver (ICD) and the appropriate OpenCL hardware driver(s) are installed, see OpenCL Installation.
opencl3
supports OpenCL 1.2 and 2.0 ICD loaders by default. If you have an
OpenCL 2.0 ICD loader then add the following to your project's Cargo.toml
:
toml
[dependencies]
opencl3 = "0.4"
If your OpenCL ICD loader supports higher versions of OpenCL then add the
appropriate features to opencl3, e.g. for an OpenCL 2.2 ICD loader add the
following to your project's Cargo.toml
instead:
toml
[dependencies.opencl3]
version = "0.4"
features = ["CL_VERSION_2_1", "CL_VERSION_2_2"]
For examples on how to use the library see the integration tests in integration_test.rs
See OpenCL Description for background on using OpenCL.
The API has changed considerably since version 0.1
of the library, with the
aim of making the library more consistent and easier to use.
The most recent change is to features, to enable running on older OpenCL ICDs that don't even support OpenCL 1.2, see issue #30.
The biggest change is that Context no longer contains:
Programs, Kernels and Command Queues.
They must now be built separately, as shown in the example above.
Note; it is now recommended to call the Program::create_and_build_from_*
methods
to build programs since they will return the build log if there is a build failure.
The OpenCL function calls now return an error type with a Display trait that shows the name of the OpenCL error, not just its number.
The Event
API now returns CommandExecutionStatus
and EventCommandType
which also use the Display trait to display their names.
The API for memory
structs: Buffer
, Image
and Pipe
have been unified
using the ClMem
trait object.
Nearly all the structs implement the Drop
trait to release their corresponding
OpenCL objects, see the crate documentation.
The crate contains unit, documentation and integration tests.
The tests run the platform and device info functions (among others) so they
can provide useful information about OpenCL capabilities of the system.
It is recommended to run the tests in single-threaded mode, since some of them can interfere with each other when run multi-threaded, e.g.:
shell
cargo test -- --test-threads=1 --show-output
The integration tests are marked ignore
so use the following command to
run them:
shell
cargo test -- --test-threads=1 --show-output --ignored
Licensed under the Apache License, Version 2.0, as per Khronos Group OpenCL.
You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
OpenCL and the OpenCL logo are trademarks of Apple Inc. used under license by Khronos.