{{#include interop_excerpts.md:1:4}}
ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. As such, most of the interoperability functions focus on reducing potential synchronization conflicts between ArrayFire and OpenCL.
{{#include interop_excerpts.md:6:7}}
Function | Purpose |
---|---|
Array::new_from_device_ptr | Construct an ArrayFire Array from cl_mem |
Array::device_ptr | Obtain a pointer to the device memory (implies lock ) |
Array::lock | Removes ArrayFire's control of a device memory pointer |
Array::unlock | Restores ArrayFire's control over a device memory pointer |
get_platform | Get ArrayFire's current cl_platform |
get_device | Gets the current ArrayFire device ID |
get_device_id | Get ArrayFire's current cl_device_id |
set_device_id | Set ArrayFire's device from a cl_device_id |
set_device | Switches ArrayFire to the specified device |
get_context | Get ArrayFire's current cl_context |
get_queue | Get ArrayFire's current cl_command_queue |
get_device_type | Get the current DeviceType |
Note that the pointer returned by Array::device_ptr should be cast to cl_mem
before using
it with OpenCL opaque types. The pointer is a cl_mem
internally that is force casted to pointer
type by ArrayFire before returning the value to caller.
Additionally, the OpenCL backend permits the programmer to add and remove custom devices from the ArrayFire device manager. These permit you to attach ArrayFire directly to the OpenCL queue used by other portions of your application.
Function | Purpose |
---|---|
add_device_context | Add a new device to ArrayFire's device manager |
set_device_context | Set ArrayFire's device from cl_device_id & cl_context |
delete_device_context | Remove a device from ArrayFire's device manager |
Below we provide two worked examples on how ArrayFire can be integrated into new and existing projects.
By default, ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. Thus there is some bookkeeping that needs to be done to integrate your custom OpenCL kernel.
If your kernels can share operate in the same queue as ArrayFire, you should:
- Obtain the OpenCL context, device, and queue used by ArrayFire
- Obtain cl_mem references to Array objects
- Load, build, and use your kernels
- Return control of Array memory to ArrayFire
Note, ArrayFire uses an in-order queue, thus when ArrayFire and your kernels are operating in the same queue, there is no need to perform any synchronization operations.
This process is best illustrated with a fully worked example:
{{#include ../../opencl-interop/examples/custom_kernel.rs}}
If your kernels needs to operate in their own OpenCL queue, the process is essentially identical,
except you need to instruct ArrayFire to complete its computations using the sync function
prior to launching your own kernel and ensure your kernels are complete using clFinish
(or similar) commands prior to returning control of the memory to ArrayFire:
- Obtain the OpenCL context, device, and queue used by ArrayFire
- Obtain cl_mem references to Array objects
- Instruct ArrayFire to finish operations using sync
- Load, build, and use your kernels
- Instruct OpenCL to finish operations using clFinish() or similar commands.
- Return control of Array memory to ArrayFire
{{#include interop_excerpts.md:9:15}}
- Instruct OpenCL to complete its operations using clFinish (or similar)
- Instruct ArrayFire to use the user-created OpenCL Context
- Create ArrayFire arrays from OpenCL memory objects
- Perform ArrayFire operations on the Arrays
- Instruct ArrayFire to finish operations using sync
- Obtain cl_mem references for important memory
- Continue your OpenCL application
ArrayFire's memory manager automatically assumes responsibility for any memory provided to it. If you are creating an array from another RAII style object, you should retain it to ensure your memory is not deallocated if your RAII object were to go out of scope.
If you do not wish for ArrayFire to manage your memory, you may call the Array::unlock function and manage the memory yourself; however, if you do so, please be cautious not to call
clReleaseMemObj
on acl_mem
when ArrayFire might be using it!
Given below is a fully working example:
{{#include ../../opencl-interop/examples/ocl_af_app.rs}}