10
10
"""
11
11
Interop with other python packages.
12
12
13
- This module provides interoperability with the following python packages.
13
+ This module provides helper functions to copy data to arrayfire from the following modules:
14
+
15
+ 1. numpy - numpy.ndarray
16
+ 2. pycuda - pycuda.gpuarray
17
+ 3. pyopencl - pyopencl.array
18
+ 4. numba - numba.cuda.cudadrv.devicearray.DeviceNDArray
14
19
15
- 1. numpy
16
- 2. pycuda
17
- 3. pyopencl
18
20
"""
19
21
20
22
from .array import *
21
23
from .device import *
22
24
25
+
26
+ def _fc_to_af_array (in_ptr , in_shape , in_dtype , is_device = False , copy = True ):
27
+ """
28
+ Fortran Contiguous to af array
29
+ """
30
+ res = Array (in_ptr , in_shape , in_dtype , is_device = is_device )
31
+
32
+ if is_device :
33
+ lock_array (res )
34
+ pass
35
+
36
+ return res .copy () if copy else res
37
+
38
+ def _cc_to_af_array (in_ptr , ndim , in_shape , in_dtype , is_device = False , copy = True ):
39
+ """
40
+ C Contiguous to af array
41
+ """
42
+ if ndim == 1 :
43
+ return _fc_to_af_array (in_ptr , in_shape , in_dtype , is_device , copy )
44
+ elif ndim == 2 :
45
+ shape = (in_shape [1 ], in_shape [0 ])
46
+ res = Array (in_ptr , shape , in_dtype , is_device = is_device )
47
+ if is_device : lock_array (res )
48
+ return reorder (res , 1 , 0 )
49
+ elif ndim == 3 :
50
+ shape = (in_shape [2 ], in_shape [1 ], in_shape [0 ])
51
+ res = Array (in_ptr , shape , in_dtype , is_device = is_device )
52
+ if is_device : lock_array (res )
53
+ return reorder (res , 2 , 1 , 0 )
54
+ elif ndim == 4 :
55
+ shape = (in_shape [3 ], in_shape [2 ], in_shape [1 ], in_shape [0 ])
56
+ res = Array (in_ptr , shape , in_dtype , is_device = is_device )
57
+ if is_device : lock_array (res )
58
+ return reorder (res , 3 , 2 , 1 , 0 )
59
+ else :
60
+ raise RuntimeError ("Unsupported ndim" )
61
+
62
+
63
+ _nptype_to_aftype = {'b1' : Dtype .b8 ,
64
+ 'u1' : Dtype .u8 ,
65
+ 'u2' : Dtype .u16 ,
66
+ 'i2' : Dtype .s16 ,
67
+ 's4' : Dtype .u32 ,
68
+ 'i4' : Dtype .s32 ,
69
+ 'f4' : Dtype .f32 ,
70
+ 'c8' : Dtype .c32 ,
71
+ 's8' : Dtype .u64 ,
72
+ 'i8' : Dtype .s64 ,
73
+ 'f8' : Dtype .f64 ,
74
+ 'c16' : Dtype .c64 }
75
+
23
76
try :
24
77
import numpy as np
25
78
from numpy import ndarray as NumpyArray
26
79
from .data import reorder
27
80
28
81
AF_NUMPY_FOUND = True
29
82
30
- _nptype_to_aftype = {'b1' : Dtype .b8 ,
31
- 'u1' : Dtype .u8 ,
32
- 'u2' : Dtype .u16 ,
33
- 'i2' : Dtype .s16 ,
34
- 's4' : Dtype .u32 ,
35
- 'i4' : Dtype .s32 ,
36
- 'f4' : Dtype .f32 ,
37
- 'c8' : Dtype .c32 ,
38
- 's8' : Dtype .u64 ,
39
- 'i8' : Dtype .s64 ,
40
- 'f8' : Dtype .f64 ,
41
- 'c16' : Dtype .c64 }
42
-
43
- def np_to_af_array (np_arr ):
83
+ def np_to_af_array (np_arr , copy = True ):
44
84
"""
45
85
Convert numpy.ndarray to arrayfire.Array.
46
86
47
87
Parameters
48
88
----------
49
89
np_arr : numpy.ndarray()
50
90
91
+ copy : Bool specifying if array is to be copied.
92
+ Default is true.
93
+ Can only be False if array is fortran contiguous.
94
+
51
95
Returns
52
96
---------
53
97
af_arr : arrayfire.Array()
@@ -57,27 +101,15 @@ def np_to_af_array(np_arr):
57
101
in_ptr = np_arr .ctypes .data_as (c_void_ptr_t )
58
102
in_dtype = _nptype_to_aftype [np_arr .dtype .str [1 :]]
59
103
104
+ if not copy :
105
+ raise RuntimeError ("Copy can not be False for numpy arrays" )
106
+
60
107
if (np_arr .flags ['F_CONTIGUOUS' ]):
61
- return Array (in_ptr , in_shape , in_dtype )
108
+ return _fc_to_af_array (in_ptr , in_shape , in_dtype )
62
109
elif (np_arr .flags ['C_CONTIGUOUS' ]):
63
- if np_arr .ndim == 1 :
64
- return Array (in_ptr , in_shape , in_dtype )
65
- elif np_arr .ndim == 2 :
66
- shape = (in_shape [1 ], in_shape [0 ])
67
- res = Array (in_ptr , shape , in_dtype )
68
- return reorder (res , 1 , 0 )
69
- elif np_arr .ndim == 3 :
70
- shape = (in_shape [2 ], in_shape [1 ], in_shape [0 ])
71
- res = Array (in_ptr , shape , in_dtype )
72
- return reorder (res , 2 , 1 , 0 )
73
- elif np_arr .ndim == 4 :
74
- shape = (in_shape [3 ], in_shape [2 ], in_shape [1 ], in_shape [0 ])
75
- res = Array (in_ptr , shape , in_dtype )
76
- return reorder (res , 3 , 2 , 1 , 0 )
77
- else :
78
- raise RuntimeError ("Unsupported ndim" )
110
+ return _cc_to_af_array (in_ptr , np_arr .ndim , in_shape , in_dtype )
79
111
else :
80
- return np_to_af_array (np . asfortranarray ( np_arr ))
112
+ return np_to_af_array (np_arr . copy ( ))
81
113
82
114
from_ndarray = np_to_af_array
83
115
except :
@@ -88,14 +120,18 @@ def np_to_af_array(np_arr):
88
120
from pycuda .gpuarray import GPUArray as CudaArray
89
121
AF_PYCUDA_FOUND = True
90
122
91
- def pycuda_to_af_array (pycu_arr ):
123
+ def pycuda_to_af_array (pycu_arr , copy = True ):
92
124
"""
93
125
Convert pycuda.gpuarray to arrayfire.Array
94
126
95
127
Parameters
96
128
-----------
97
129
pycu_arr : pycuda.GPUArray()
98
130
131
+ copy : Bool specifying if array is to be copied.
132
+ Default is true.
133
+ Can only be False if array is fortran contiguous.
134
+
99
135
Returns
100
136
----------
101
137
af_arr : arrayfire.Array()
@@ -109,31 +145,13 @@ def pycuda_to_af_array(pycu_arr):
109
145
in_shape = pycu_arr .shape
110
146
in_dtype = pycu_arr .dtype .char
111
147
148
+ if not copy and not pycu_arr .flags .f_contiguous :
149
+ raise RuntimeError ("Copy can only be False when arr.flags.f_contiguous is True" )
150
+
112
151
if (pycu_arr .flags .f_contiguous ):
113
- res = Array (in_ptr , in_shape , in_dtype , is_device = True )
114
- lock_array (res )
115
- res = res .copy ()
116
- return res
152
+ return _fc_to_af_array (in_ptr , in_shape , in_dtype , True , copy )
117
153
elif (pycu_arr .flags .c_contiguous ):
118
- if pycu_arr .ndim == 1 :
119
- return Array (in_ptr , in_shape , in_dtype , is_device = True )
120
- elif pycu_arr .ndim == 2 :
121
- shape = (in_shape [1 ], in_shape [0 ])
122
- res = Array (in_ptr , shape , in_dtype , is_device = True )
123
- lock_array (res )
124
- return reorder (res , 1 , 0 )
125
- elif pycu_arr .ndim == 3 :
126
- shape = (in_shape [2 ], in_shape [1 ], in_shape [0 ])
127
- res = Array (in_ptr , shape , in_dtype , is_device = True )
128
- lock_array (res )
129
- return reorder (res , 2 , 1 , 0 )
130
- elif pycu_arr .ndim == 4 :
131
- shape = (in_shape [3 ], in_shape [2 ], in_shape [1 ], in_shape [0 ])
132
- res = Array (in_ptr , shape , in_dtype , is_device = True )
133
- lock_array (res )
134
- return reorder (res , 3 , 2 , 1 , 0 )
135
- else :
136
- raise RuntimeError ("Unsupported ndim" )
154
+ return _cc_to_af_array (in_ptr , pycu_arr .ndim , in_shape , in_dtype , True , copy )
137
155
else :
138
156
return pycuda_to_af_array (pycu_arr .copy ())
139
157
except :
@@ -147,14 +165,18 @@ def pycuda_to_af_array(pycu_arr):
147
165
from .opencl import get_context as _get_context
148
166
AF_PYOPENCL_FOUND = True
149
167
150
- def pyopencl_to_af_array (pycl_arr ):
168
+ def pyopencl_to_af_array (pycl_arr , copy = True ):
151
169
"""
152
170
Convert pyopencl.gpuarray to arrayfire.Array
153
171
154
172
Parameters
155
173
-----------
156
174
pycl_arr : pyopencl.Array()
157
175
176
+ copy : Bool specifying if array is to be copied.
177
+ Default is true.
178
+ Can only be False if array is fortran contiguous.
179
+
158
180
Returns
159
181
----------
160
182
af_arr : arrayfire.Array()
@@ -179,63 +201,102 @@ def pyopencl_to_af_array(pycl_arr):
179
201
180
202
if (dev_idx == None or ctx_idx == None or
181
203
dev_idx != dev or ctx_idx != ctx ):
204
+ print ("Adding context and queue" )
182
205
_add_device_context (dev , ctx , que )
183
206
_set_device_context (dev , ctx )
184
207
208
+ info ()
185
209
in_ptr = pycl_arr .base_data .int_ptr
186
210
in_shape = pycl_arr .shape
187
211
in_dtype = pycl_arr .dtype .char
188
212
213
+ if not copy and not pycl_arr .flags .f_contiguous :
214
+ raise RuntimeError ("Copy can only be False when arr.flags.f_contiguous is True" )
215
+
216
+ print ("Copying array" )
217
+ print (pycl_arr .base_data .int_ptr )
189
218
if (pycl_arr .flags .f_contiguous ):
190
- res = Array (in_ptr , in_shape , in_dtype , is_device = True )
191
- lock_array (res )
192
- return res
219
+ return _fc_to_af_array (in_ptr , in_shape , in_dtype , True , copy )
193
220
elif (pycl_arr .flags .c_contiguous ):
194
- if pycl_arr .ndim == 1 :
195
- return Array (in_ptr , in_shape , in_dtype , is_device = True )
196
- elif pycl_arr .ndim == 2 :
197
- shape = (in_shape [1 ], in_shape [0 ])
198
- res = Array (in_ptr , shape , in_dtype , is_device = True )
199
- lock_array (res )
200
- return reorder (res , 1 , 0 )
201
- elif pycl_arr .ndim == 3 :
202
- shape = (in_shape [2 ], in_shape [1 ], in_shape [0 ])
203
- res = Array (in_ptr , shape , in_dtype , is_device = True )
204
- lock_array (res )
205
- return reorder (res , 2 , 1 , 0 )
206
- elif pycl_arr .ndim == 4 :
207
- shape = (in_shape [3 ], in_shape [2 ], in_shape [1 ], in_shape [0 ])
208
- res = Array (in_ptr , shape , in_dtype , is_device = True )
209
- lock_array (res )
210
- return reorder (res , 3 , 2 , 1 , 0 )
211
- else :
212
- raise RuntimeError ("Unsupported ndim" )
221
+ return _cc_to_af_array (in_ptr , pycl_arr .ndim , in_shape , in_dtype , True , copy )
213
222
else :
214
223
return pyopencl_to_af_array (pycl_arr .copy ())
215
224
except :
216
225
AF_PYOPENCL_FOUND = False
217
226
227
+ try :
228
+ import numba
229
+ from numba import cuda
230
+ NumbaCudaArray = cuda .cudadrv .devicearray .DeviceNDArray
231
+ AF_NUMBA_FOUND = True
232
+
233
+ def numba_to_af_array (nb_arr , copy = True ):
234
+ """
235
+ Convert numba.gpuarray to arrayfire.Array
236
+
237
+ Parameters
238
+ -----------
239
+ nb_arr : numba.cuda.cudadrv.devicearray.DeviceNDArray()
240
+
241
+ copy : Bool specifying if array is to be copied.
242
+ Default is true.
243
+ Can only be False if array is fortran contiguous.
244
+
245
+ Returns
246
+ ----------
247
+ af_arr : arrayfire.Array()
218
248
219
- def to_array (in_array ):
249
+ Note
250
+ ----------
251
+ The input array is copied to af.Array
252
+ """
253
+
254
+ in_ptr = nb_arr .device_ctypes_pointer .value
255
+ in_shape = nb_arr .shape
256
+ in_dtype = _nptype_to_aftype [nb_arr .dtype .str [1 :]]
257
+
258
+ if not copy and not nb_arr .flags .f_contiguous :
259
+ raise RuntimeError ("Copy can only be False when arr.flags.f_contiguous is True" )
260
+
261
+ if (nb_arr .is_f_contiguous ()):
262
+ return _fc_to_af_array (in_ptr , in_shape , in_dtype , True , copy )
263
+ elif (nb_arr .is_c_contiguous ()):
264
+ return _cc_to_af_array (in_ptr , nb_arr .ndim , in_shape , in_dtype , True , copy )
265
+ else :
266
+ return numba_to_af_array (nb_arr .copy ())
267
+ except :
268
+ AF_NUMBA_FOUND = False
269
+
270
+ def to_array (in_array , copy = True ):
220
271
"""
221
272
Helper function to convert input from a different module to af.Array
222
273
223
274
Parameters
224
275
-------------
225
276
226
277
in_array : array like object
227
- Can be one of numpy.ndarray, pycuda.GPUArray, pyopencl.Array, array.array, list
278
+ Can be one of the following:
279
+ - numpy.ndarray
280
+ - pycuda.GPUArray
281
+ - pyopencl.Array
282
+ - numba.cuda.cudadrv.devicearray.DeviceNDArray
283
+ - array.array
284
+ - list
285
+ copy : Bool specifying if array is to be copied.
286
+ Default is true.
287
+ Can only be False if array is fortran contiguous.
228
288
229
289
Returns
230
290
--------------
231
291
af.Array of same dimensions as input after copying the data from the input
232
292
233
-
234
293
"""
235
294
if AF_NUMPY_FOUND and isinstance (in_array , NumpyArray ):
236
- return np_to_af_array (in_array )
295
+ return np_to_af_array (in_array , copy )
237
296
if AF_PYCUDA_FOUND and isinstance (in_array , CudaArray ):
238
- return pycuda_to_af_array (in_array )
297
+ return pycuda_to_af_array (in_array , copy )
239
298
if AF_PYOPENCL_FOUND and isinstance (in_array , OpenclArray ):
240
- return pyopencl_to_af_array (in_array )
299
+ return pyopencl_to_af_array (in_array , copy )
300
+ if AF_NUMBA_FOUND and isinstance (in_array , NumbaCudaArray ):
301
+ return numba_to_af_array (in_array , copy )
241
302
return Array (src = in_array )
0 commit comments