Passing numpy arrays efficiently
Take a look at the file mlarray_sequence.py
in the folder PYTHONPATH\Lib\site-packages\matlab\_internal
. There you will find the construction of the MATLAB array object. The performance problem comes from copying data with loops within the generic_flattening
function.
To avoid this behavior we will edit the file a bit. This fix should work on complex and non-complex datatypes.
-
Make a backup of the original file in case something goes wrong.
-
Add
import numpy as np
to the other imports at the beginning of the file -
In line 38 you should find:
init_dims = _get_size(initializer)
replace this with:
try: init_dims=initializer.shape except: init_dims = _get_size(initializer)
-
In line 48 you should find:
if is_complex: complex_array = flat(self, initializer, init_dims, typecode) self._real = complex_array['real'] self._imag = complex_array['imag'] else: self._data = flat(self, initializer, init_dims, typecode)
Replace this with:
if is_complex: try: self._real = array.array(typecode,np.ravel(initializer, order="F").real) self._imag = array.array(typecode,np.ravel(initializer, order="F").imag) except: complex_array = flat(self, initializer,init_dims, typecode) self._real = complex_array['real'] self._imag = complex_array['imag'] else: try: self._data = array.array(typecode,np.ravel(initializer, order="F")) except: self._data = flat(self, initializer, init_dims, typecode)
Now you can pass a numpy array directly to the MATLAB array creation method.
data1 = np.random.uniform(low = 0.0, high = 30000.0, size = (1000000,))
#faster
data1m = matlab.double(data1)
#or slower method
data1m = matlab.double(data1.tolist())
data2 = np.random.uniform(low = 0.0, high = 30000.0, size = (1000000,)).astype(np.complex128)
#faster
data1m = matlab.double(data2,is_complex=True)
#or slower method
data1m = matlab.double(data2.tolist(),is_complex=True)
The performance in MATLAB array creation increases by a factor of 15 and the interface is easier to use now.