1010"""
1111Interop with other python packages.
1212
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
1418
15- 1. numpy
16- 2. pycuda
17- 3. pyopencl
1819"""
1920
2021from .array import *
2122from .device import *
2223
24+
25+ def _fc_to_af_array (in_ptr , in_shape , in_dtype , is_device = False , copy = True ):
26+ """
27+ Fortran Contiguous to af array
28+ """
29+ res = Array (in_ptr , in_shape , in_dtype , is_device = is_device )
30+
31+ if is_device :
32+ lock_array (res )
33+ pass
34+
35+ return res .copy () if copy else res
36+
37+ def _cc_to_af_array (in_ptr , ndim , in_shape , in_dtype , is_device = False , copy = True ):
38+ """
39+ C Contiguous to af array
40+ """
41+ if ndim == 1 :
42+ return _fc_to_af_array (in_ptr , in_shape , in_dtype , is_device , copy )
43+ elif ndim == 2 :
44+ shape = (in_shape [1 ], in_shape [0 ])
45+ res = Array (in_ptr , shape , in_dtype , is_device = is_device )
46+ if is_device : lock_array (res )
47+ return reorder (res , 1 , 0 )
48+ elif ndim == 3 :
49+ shape = (in_shape [2 ], in_shape [1 ], in_shape [0 ])
50+ res = Array (in_ptr , shape , in_dtype , is_device = is_device )
51+ if is_device : lock_array (res )
52+ return reorder (res , 2 , 1 , 0 )
53+ elif ndim == 4 :
54+ shape = (in_shape [3 ], in_shape [2 ], in_shape [1 ], in_shape [0 ])
55+ res = Array (in_ptr , shape , in_dtype , is_device = is_device )
56+ if is_device : lock_array (res )
57+ return reorder (res , 3 , 2 , 1 , 0 )
58+ else :
59+ raise RuntimeError ("Unsupported ndim" )
60+
2361try :
2462 import numpy as np
2563 from numpy import ndarray as NumpyArray
4078 'f8' : Dtype .f64 ,
4179 'c16' : Dtype .c64 }
4280
43- def np_to_af_array (np_arr ):
81+ def np_to_af_array (np_arr , copy = True ):
4482 """
4583 Convert numpy.ndarray to arrayfire.Array.
4684
4785 Parameters
4886 ----------
4987 np_arr : numpy.ndarray()
5088
89+ copy : Bool specifying if array is to be copied.
90+ Default is true.
91+ Can only be False if array is fortran contiguous.
92+
5193 Returns
5294 ---------
5395 af_arr : arrayfire.Array()
@@ -57,27 +99,15 @@ def np_to_af_array(np_arr):
5799 in_ptr = np_arr .ctypes .data_as (c_void_ptr_t )
58100 in_dtype = _nptype_to_aftype [np_arr .dtype .str [1 :]]
59101
102+ if not copy :
103+ raise RuntimeError ("Copy can not be False for numpy arrays" )
104+
60105 if (np_arr .flags ['F_CONTIGUOUS' ]):
61- return Array (in_ptr , in_shape , in_dtype )
106+ return _fc_to_af_array (in_ptr , in_shape , in_dtype )
62107 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" )
108+ return _cc_to_af_array (in_ptr , np_arr .ndim , in_shape , in_dtype )
79109 else :
80- return np_to_af_array (np . asfortranarray ( np_arr ))
110+ return np_to_af_array (np_arr . copy ( ))
81111
82112 from_ndarray = np_to_af_array
83113except :
@@ -88,14 +118,18 @@ def np_to_af_array(np_arr):
88118 from pycuda .gpuarray import GPUArray as CudaArray
89119 AF_PYCUDA_FOUND = True
90120
91- def pycuda_to_af_array (pycu_arr ):
121+ def pycuda_to_af_array (pycu_arr , copy = True ):
92122 """
93123 Convert pycuda.gpuarray to arrayfire.Array
94124
95125 Parameters
96126 -----------
97127 pycu_arr : pycuda.GPUArray()
98128
129+ copy : Bool specifying if array is to be copied.
130+ Default is true.
131+ Can only be False if array is fortran contiguous.
132+
99133 Returns
100134 ----------
101135 af_arr : arrayfire.Array()
@@ -109,31 +143,13 @@ def pycuda_to_af_array(pycu_arr):
109143 in_shape = pycu_arr .shape
110144 in_dtype = pycu_arr .dtype .char
111145
146+ if not copy and not pycu_arr .flags .f_contiguous :
147+ raise RuntimeError ("Copy can only be False when arr.flags.f_contiguous is True" )
148+
112149 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
150+ return _fc_to_af_array (in_ptr , in_shape , in_dtype , True , copy )
117151 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" )
152+ return _cc_to_af_array (in_ptr , pycu_arr .ndim , in_shape , in_dtype , True , copy )
137153 else :
138154 return pycuda_to_af_array (pycu_arr .copy ())
139155except :
@@ -147,14 +163,18 @@ def pycuda_to_af_array(pycu_arr):
147163 from .opencl import get_context as _get_context
148164 AF_PYOPENCL_FOUND = True
149165
150- def pyopencl_to_af_array (pycl_arr ):
166+ def pyopencl_to_af_array (pycl_arr , copy = True ):
151167 """
152168 Convert pyopencl.gpuarray to arrayfire.Array
153169
154170 Parameters
155171 -----------
156172 pycl_arr : pyopencl.Array()
157173
174+ copy : Bool specifying if array is to be copied.
175+ Default is true.
176+ Can only be False if array is fortran contiguous.
177+
158178 Returns
159179 ----------
160180 af_arr : arrayfire.Array()
@@ -179,44 +199,31 @@ def pyopencl_to_af_array(pycl_arr):
179199
180200 if (dev_idx == None or ctx_idx == None or
181201 dev_idx != dev or ctx_idx != ctx ):
202+ print ("Adding context and queue" )
182203 _add_device_context (dev , ctx , que )
183204 _set_device_context (dev , ctx )
184205
206+ info ()
185207 in_ptr = pycl_arr .base_data .int_ptr
186208 in_shape = pycl_arr .shape
187209 in_dtype = pycl_arr .dtype .char
188210
211+ if not copy and not pycl_arr .flags .f_contiguous :
212+ raise RuntimeError ("Copy can only be False when arr.flags.f_contiguous is True" )
213+
214+ print ("Copying array" )
215+ print (pycl_arr .base_data .int_ptr )
189216 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
217+ return _fc_to_af_array (in_ptr , in_shape , in_dtype , True , copy )
193218 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" )
219+ return _cc_to_af_array (in_ptr , pycl_arr .ndim , in_shape , in_dtype , True , copy )
213220 else :
214221 return pyopencl_to_af_array (pycl_arr .copy ())
215222except :
216223 AF_PYOPENCL_FOUND = False
217224
218225
219- def to_array (in_array ):
226+ def to_array (in_array , copy = True ):
220227 """
221228 Helper function to convert input from a different module to af.Array
222229
@@ -226,16 +233,19 @@ def to_array(in_array):
226233 in_array : array like object
227234 Can be one of numpy.ndarray, pycuda.GPUArray, pyopencl.Array, array.array, list
228235
236+ copy : Bool specifying if array is to be copied.
237+ Default is true.
238+ Can only be False if array is fortran contiguous.
239+
229240 Returns
230241 --------------
231242 af.Array of same dimensions as input after copying the data from the input
232243
233-
234244 """
235245 if AF_NUMPY_FOUND and isinstance (in_array , NumpyArray ):
236- return np_to_af_array (in_array )
246+ return np_to_af_array (in_array , copy )
237247 if AF_PYCUDA_FOUND and isinstance (in_array , CudaArray ):
238- return pycuda_to_af_array (in_array )
248+ return pycuda_to_af_array (in_array , copy )
239249 if AF_PYOPENCL_FOUND and isinstance (in_array , OpenclArray ):
240- return pyopencl_to_af_array (in_array )
250+ return pyopencl_to_af_array (in_array , copy )
241251 return Array (src = in_array )
0 commit comments