从 Python 调用 MATLAB 必然会降低性能,我可以通过用 Python 重写(大量)代码来避免这种情况。然而,这对我来说不是一个现实的选择,但让我恼火的是,效率的巨大损失在于从 numpy 数组到 MATLAB double 的简单转换。
我说的是以下从 data1 到 data1m 的转换,其中
data1 = np.random.uniform(low = 0.0, high = 30000.0, size = (1000000,))
data1m = matlab.double(list(data1))
这里的 matlab.double 来自 Mathworks 自己的 MATLAB 包/引擎。第二行代码在我的系统上花费了 20 秒,这对于一个除了使数字对于 MATLAB 来说“可食用”之外没有真正做任何事情的转换来说似乎太多了。
所以基本上我正在寻找与给出的技巧相反的技巧 here用于将 MATLAB 输出转换回 Python。
最佳答案
高效传递 numpy 数组
查看文件夹 PYTHONPATH\Lib\site-packages\matlab\_internal
中的文件 mlarray_sequence.py
。在那里您会找到 MATLAB 数组对象的构造。性能问题来自于在 generic_flattening
函数中使用循环复制数据。
为了避免这种行为,我们将稍微编辑一下文件。此修复应该适用于复杂和非复杂数据类型。
备份原始文件以防出现问题。
将
import numpy as np
添加到文件开头的其他导入在第 38 行你应该找到:
init_dims = _get_size(initializer)
将其替换为:
try: init_dims=initializer.shape except: init_dims = _get_size(initializer)
在第 48 行你应该找到:
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)
将其替换为:
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)
现在您可以将 numpy 数组直接传递给 MATLAB 数组创建方法。
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)
MATLAB 数组创建的性能提高了 15 倍,界面现在更易于使用。
关于python - 提高将 numpy 数组转换为 MATLAB double 的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45284124/