@@ -23,6 +23,14 @@ extern "C" {
23
23
aftype : c_uint ,
24
24
) -> c_int ;
25
25
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
+
26
34
fn af_create_handle ( out : MutAfArray , ndims : c_uint , dims : * const DimT , aftype : c_uint )
27
35
-> c_int ;
28
36
@@ -253,6 +261,86 @@ where
253
261
}
254
262
}
255
263
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
+
256
344
/// Returns the backend of the Array
257
345
///
258
346
/// # Return Values
0 commit comments