Skip to content

Commit 18e5208

Browse files
committed
Support to let users create Array from raw device pointers
The example show cases the usage using CUDA API, but it should be similar to OpenCL or CPU. In the case of OpenCL backend, the pointer would be cl_mem
1 parent f6af4c1 commit 18e5208

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

src/array.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ extern "C" {
2323
aftype: c_uint,
2424
) -> c_int;
2525

26+
fn af_device_array(
27+
out: MutAfArray,
28+
data: *const c_void,
29+
ndims: c_uint,
30+
dims: *const DimT,
31+
aftype: c_uint,
32+
) -> c_int;
33+
2634
fn af_create_handle(out: MutAfArray, ndims: c_uint, dims: *const DimT, aftype: c_uint)
2735
-> c_int;
2836

@@ -253,6 +261,86 @@ where
253261
}
254262
}
255263

264+
/// Constructs a new Array object from device pointer
265+
///
266+
/// The example show cases the usage using CUDA API, but usage of this function will
267+
/// be similar in CPU and OpenCL backends also. In the case of OpenCL backend, the pointer
268+
/// would be cl_mem.
269+
///
270+
/// # Examples
271+
///
272+
/// An example of creating an Array device pointer using
273+
/// [rustacuda](https://github.com/bheisler/RustaCUDA) crate. The
274+
/// example has to be copied to a `bin` crate with following contents in Cargo.toml
275+
/// to run successfully. Note that, all required setup for rustacuda and arrayfire crate
276+
/// have to completed first.
277+
/// ```text
278+
/// [package]
279+
/// ....
280+
/// [dependencies]
281+
/// rustacuda = "0.1"
282+
/// rustacuda_derive = "0.1"
283+
/// rustacuda_core = "0.1"
284+
/// arrayfire = "3.7.*"
285+
/// ```
286+
///
287+
/// ```rust,ignore
288+
///use arrayfire::*;
289+
///use rustacuda::*;
290+
///use rustacuda::prelude::*;
291+
///
292+
///fn main() {
293+
/// let v: Vec<_> = (0u8 .. 100).map(f32::from).collect();
294+
///
295+
/// rustacuda::init(CudaFlags::empty());
296+
/// let device = Device::get_device(0).unwrap();
297+
/// let context = Context::create_and_push(ContextFlags::MAP_HOST | ContextFlags::SCHED_AUTO,
298+
/// device).unwrap();
299+
/// // Approach 1
300+
/// {
301+
/// let mut buffer = memory::DeviceBuffer::from_slice(&v).unwrap();
302+
///
303+
/// let array_dptr = Array::new_from_device_ptr(
304+
/// buffer.as_device_ptr().as_raw_mut(), dim4!(10, 10));
305+
///
306+
/// af_print!("array_dptr", &array_dptr);
307+
///
308+
/// array_dptr.lock(); // Needed to avoid free as arrayfire takes ownership
309+
/// }
310+
///
311+
/// // Approach 2
312+
/// {
313+
/// let mut dptr: *mut f32 = std::ptr::null_mut();
314+
/// unsafe {
315+
/// dptr = memory::cuda_malloc::<f32>(10*10).unwrap().as_raw_mut();
316+
/// }
317+
/// let array_dptr = Array::new_from_device_ptr(dptr, dim4!(10, 10));
318+
/// // note that values might be garbage in the memory pointed out by dptr
319+
/// // in this example as it is allocated but not initialized prior to passing
320+
/// // along to arrayfire::Array::new*
321+
///
322+
/// // After ArrayFire takes over ownership of the pointer, you can use other
323+
/// // arrayfire functions as usual.
324+
/// af_print!("array_dptr", &array_dptr);
325+
/// }
326+
///}
327+
/// ```
328+
pub fn new_from_device_ptr(dev_ptr: *mut T, dims: Dim4) -> Self {
329+
let aftype = T::get_af_dtype();
330+
let mut temp: i64 = 0;
331+
unsafe {
332+
let err_val = af_device_array(
333+
&mut temp as MutAfArray,
334+
dev_ptr as *mut c_void,
335+
dims.ndims() as c_uint,
336+
dims.get().as_ptr() as *const c_longlong,
337+
aftype as c_uint,
338+
);
339+
HANDLE_ERROR(AfError::from(err_val));
340+
}
341+
temp.into()
342+
}
343+
256344
/// Returns the backend of the Array
257345
///
258346
/// # Return Values

0 commit comments

Comments
 (0)