#opencl #gpu #gpgpu

opencl3

A Rust implementation of the Khronos OpenCL 3.0 API

4 releases

0.1.3 Jan 16, 2021
0.1.2 Jan 12, 2021
0.1.1 Jan 4, 2021
0.1.0 Dec 31, 2020

#203 in Asynchronous

Apache-2.0

175KB
3.5K SLoC

opencl3

crates.io docs.io OpenCL 3.0 License Rust

A Rust implementation of the Khronos OpenCL API.

Description

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,

Design

See the crate documentation.

Use

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:

[dependencies]
opencl3 = "0.1"

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:

[dependencies.opencl3]
version = "0.1"
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.

Tests

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.:

cargo test -- --test-threads=1 --show-output

The integration tests are marked ignore so use the following command to run them:

cargo test -- --test-threads=1 --show-output --ignored

Examples

The tests provide examples of how the crate may be used, e.g. see: platform, device, context, integration_test and opencl2_kernel_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.:

// Create OpenCL context from the OpenCL 2 device
// and an OpenCL command queue for the device
let mut context = Context::from_device(device).unwrap();
context.create_command_queues_with_properties(0, 0).unwrap();

// Build the OpenCL 2.0 program source and create the kernels.
let src = CString::new(PROGRAM_SOURCE).unwrap();
let options = CString::new(PROGRAM_BUILD_OPTIONS).unwrap();
context.build_program_from_source(&src, &options).unwrap();

// Get the svm capability of all the devices in the context.
let svm_capability = context.get_svm_mem_capability();

// The input data
const ARRAY_SIZE: usize = 8;
let value_array: [cl_int; ARRAY_SIZE] = [3, 2, 5, 9, 7, 1, 4, 2];

// Copy input data into an OpenCL SVM vector
let mut test_values = SvmVec::<cl_int>::with_capacity(&context, svm_capability, ARRAY_SIZE);
for &val in value_array.iter() {
    test_values.push(val);
}

// The output data, an OpenCL SVM vector
let mut results =
    SvmVec::<cl_int>::with_capacity_zeroed(&context, svm_capability, ARRAY_SIZE);
unsafe { results.set_len(ARRAY_SIZE) };

// Get the command queue for the device
let queue = context.default_queue();

// Run the inclusive scan kernel on the input data
let inclusive_scan_kernel_name = CString::new(INCLUSIVE_SCAN_KERNEL_NAME).unwrap();
if let Some(inclusive_scan_kernel) = context.get_kernel(&inclusive_scan_kernel_name) {
    // No need to write or map the data before enqueueing the kernel
    let kernel_event = ExecuteKernel::new(inclusive_scan_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)
        .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);
}

License

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.

Dependencies

~675KB