在不修改数组a地址的情况下,将数据从数组b复制到数组a的最快方法是什么。我需要这样做,因为外部库(PyFFTW)使用了指向无法更改的数组的指针。
例如:
a = numpy.empty(n, dtype=complex)
for i in xrange(a.size):
a[i] = b[i]
是否可以不循环地进行?
Answers:
我相信
a = numpy.empty_like (b)
a[:] = b
将快速制作出深层副本。正如Funsi所提到的,最新版本的numpy也具有该copyto
功能。
a = b
仅创建对的新引用b
。a[:] = b
表示“将所有元素设置为a
等于b
”。区别很重要,因为numpy数组是可变类型。
empty()
比大约快10%zeros()
。令人惊讶的empty_like()
是甚至更快。copyto(a,b)
比数组语法快a[:] = b
。参见gist.github.com/bhawkins/5095558
np.copyto(a, b)
以及何时a = b.astype(b.dtype)
提高速度的信息,请参见以下答案:stackoverflow.com/a/33672015/3703716
empty_like
是它的速度如此之快empty
,尤其是因为zeros_like
它的速度慢于zeros
。BTW我只是重新运行我的基准(现在更新),之间的差异copyto(a,b)
,并a[:] = b
似乎已经蒸发。gist.github.com/bhawkins/5095558
NumPy 1.7版具有执行所需numpy.copyto
功能的功能:
numpy.copyto(dst,src)
将值从一个数组复制到另一个数组,并根据需要进行广播。
请参阅:https: //docs.scipy.org/doc/numpy/reference/generated/numpy.copyto.html
AttributeError: 'module' object has no attribute 'copyto'
为了回答您的问题,我试用了一些变体并进行了介绍。
结论:要将数据从numpy数组复制到另一个,请使用内置的numpy函数之一,numpy.array(src)
或者numpy.copyto(dst, src)
在任何可能的地方。
(但如果dst
已分配的内存,请始终选择后者,以重用该内存。请参阅文章末尾的概要分析。)
分析设置
import timeit
import numpy as np
import pandas as pd
from IPython.display import display
def profile_this(methods, setup='', niter=10 ** 4, p_globals=None, **kwargs):
if p_globals is not None:
print('globals: {0}, tested {1:.0e} times'.format(p_globals, niter))
timings = np.array([timeit.timeit(method, setup=setup, number=niter,
globals=p_globals, **kwargs) for
method in methods])
ranking = np.argsort(timings)
timings = np.array(timings)[ranking]
methods = np.array(methods)[ranking]
speedups = np.amax(timings) / timings
pd.set_option('html', False)
data = {'time (s)': timings,
'speedup': ['{:.2f}x'.format(s) if 1 != s else '' for s in speedups],
'methods': methods}
data_frame = pd.DataFrame(data, columns=['time (s)', 'speedup', 'methods'])
display(data_frame)
print()
分析代码
setup = '''import numpy as np; x = np.random.random(n)'''
methods = (
'''y = np.zeros(n, dtype=x.dtype); y[:] = x''',
'''y = np.zeros_like(x); y[:] = x''',
'''y = np.empty(n, dtype=x.dtype); y[:] = x''',
'''y = np.empty_like(x); y[:] = x''',
'''y = np.copy(x)''',
'''y = x.astype(x.dtype)''',
'''y = 1*x''',
'''y = np.empty_like(x); np.copyto(y, x)''',
'''y = np.empty_like(x); np.copyto(y, x, casting='no')''',
'''y = np.empty(n)\nfor i in range(x.size):\n\ty[i] = x[i]'''
)
for n, it in ((2, 6), (3, 6), (3.8, 6), (4, 6), (5, 5), (6, 4.5)):
profile_this(methods[:-1:] if n > 2 else methods, setup,
niter=int(10 ** it), p_globals={'n': int(10 ** n)})
结果为Windows 7英特尔i7处理器,CPython的V3.5.0,numpy的v1.10.1。
另外,请参阅配置文件变体的结果,其中在值复制期间已经预先分配了目标内存,这y = np.empty_like(x)
是设置的一部分:
x.copy()
速度也非常快np.array(x)
,我更喜欢语法:$ python3 -m timeit -s "import numpy as np; x = np.random.random((100, 100))" "x.copy()"
- 100000 loops, best of 3: 4.7 usec per loop
。对于,我有类似的结果np.array(x)
。在Linux上使用i5-4210U和numpy 1.10.4进行了测试
np.copy
是更多的宽容:np.copy(False)
,np.copy(None)
还是工作,同时a = None; a.copy()
抛出AttributeError: 'NoneType' object has no attribute 'copy'
。同样,使用函数而不是方法语法来声明我们希望在此代码行中发生的事情更为精确。
np.copy(None)
没有抛出错误的事实确实是不可思议的。多使用一个理由a.copy()
:)
y[:] = x
现在的速度略快于copyto(y, x)
。gist.github.com/bhawkins/7cdbd5b9372cb798e34e21f92279d2dc上的
您可以轻松使用:
b = 1*a
这是最快的方法,但是也有一些问题。如果您不直接定义dtype
of a
,也没有检查dtype
of b
,则会遇到麻烦。例如:
a = np.arange(10) # dtype = int64
b = 1*a # dtype = int64
a = np.arange(10.) # dtype = float64
b = 1*a # dtype = float64
a = np.arange(10) # dtype = int64
b = 1. * a # dtype = float64
我希望我能阐明这一点。有时,您只需进行少量操作即可更改数据类型。
a = numpy.zeros(len(b))
或a = numpy.empty(n,dtype=complex)
还将创建一个新数组。
您可以执行许多不同的操作:
a=np.copy(b)
a=np.array(b) # Does exactly the same as np.copy
a[:]=b # a needs to be preallocated
a=b[np.arange(b.shape[0])]
a=copy.deepcopy(b)
无效的东西
a=b
a=b[:] # This have given my code bugs