@@ -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