What is the fastest way to copy data from array b to array a, without modifying the address of array a. I need this because an external library (PyFFTW) uses a pointer to my array that cannot change.
将数据从数组b复制到数组a的最快方法是什么,而不修改数组a的地址。我需要这个,因为外部库(PyFFTW)使用指向我的数组的指针,该指针无法更改。
For example:
例如:
a = numpy.empty(n, dtype=complex)
for i in xrange(a.size):
a[i] = b[i]
It is possible to do it without a loop?
有没有循环可以做到这一点?
7 个解决方案
#1
71
I believe
我相信
a = numpy.empty_like (b)
a[:] = b
will make a deep copy quickly. As Funsi mentions, recent versions of numpy also have the copyto
function.
将快速复制。正如Funsi所提到的,numpy的最新版本也具有copyto功能。
#2
25
numpy version 1.7 has the numpy.copyto function that does what you are looking for:
numpy版本1.7有numpy.copyto函数,可以满足您的需求:
numpy.copyto(dst, src)
numpy.copyto(dst,src)
Copies values from one array to another,> broadcasting as necessary.
将值从一个数组复制到另一个数组,>根据需要进行广播。
See: http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.copyto.html
请参阅:http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.copyto.html
#3
13
a = numpy.array(b)
is even faster than the suggested solutions up to numpy v1.6 and makes a copy of the array as well. I could however not test it against copyto(a,b), since I don't have the most recent version of numpy.
甚至比numpy v1.6的建议解决方案更快,并且也制作了数组的副本。然而,我可以不对copyto(a,b)进行测试,因为我没有numpy的最新版本。
#4
9
you can easy use:
你可以轻松使用:
b = 1*a
this is the fastest way, but also have some problems. If you don't define directly the dtype
of a
and also doesn't check the dtype
of b
you can get into trouble. For example:
这是最快的方法,但也有一些问题。如果你没有直接定义a的dtype而且也没有检查b的dtype你可能会遇到麻烦。例如:
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
I hope, I could make the point clear. Sometimes you will have a data type change with just one little operation.
我希望,我能说清楚。有时您只需要一个小操作即可更改数据类型。
#5
9
To answer your question, I played with some variants and profiled them.
为了回答你的问题,我玩了一些变种并对它们进行了描述。
Conclusion: to copy data from a numpy array to another use one of the built-in numpy functions numpy.array(src)
or numpy.copyto(dst, src)
wherever possible.
结论:将数据从numpy数组复制到另一个数组时尽可能使用内置的numpy函数numpy.array(src)或numpy.copyto(dst,src)。
(But always choose the later if dst
's memory is already allocated, to reuse the memory. See profiling at the end of the post.)
(但是如果已经分配了dst的内存,则总是选择后者,以重用内存。请参阅帖子末尾的分析。)
profiling setup
分析设置
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.max(timings) / timings
pd.set_option('html', False)
data = {'time (s)': timings, 'speedup': ['{0:0.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()
profiling code
分析代码
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, int(10**it), {'n': int(10**n)})
results for Windows 7 on Intel i7 CPU, CPython v3.5.0, numpy v1.10.1.
Windows 7在Intel i7 CPU,CPython v3.5.0,numpy v1.10.1上的结果。
globals: {'n': 100}, tested 1e+06 times
time (s) speedup methods
0 0.386908 33.76x y = np.array(x)
1 0.496475 26.31x y = x.astype(x.dtype)
2 0.567027 23.03x y = np.empty_like(x); np.copyto(y, x)
3 0.666129 19.61x y = np.empty_like(x); y[:] = x
4 0.967086 13.51x y = 1*x
5 1.067240 12.24x y = np.empty_like(x); np.copyto(y, x, casting=...
6 1.235198 10.57x y = np.copy(x)
7 1.624535 8.04x y = np.zeros(n, dtype=x.dtype); y[:] = x
8 1.626120 8.03x y = np.empty(n, dtype=x.dtype); y[:] = x
9 3.569372 3.66x y = np.zeros_like(x); y[:] = x
10 13.061154 y = np.empty(n)\nfor i in range(x.size):\n\ty[...
globals: {'n': 1000}, tested 1e+06 times
time (s) speedup methods
0 0.666237 6.10x y = x.astype(x.dtype)
1 0.740594 5.49x y = np.empty_like(x); np.copyto(y, x)
2 0.755246 5.39x y = np.array(x)
3 1.043631 3.90x y = np.empty_like(x); y[:] = x
4 1.398793 2.91x y = 1*x
5 1.434299 2.84x y = np.empty_like(x); np.copyto(y, x, casting=...
6 1.544769 2.63x y = np.copy(x)
7 1.873119 2.17x y = np.empty(n, dtype=x.dtype); y[:] = x
8 2.355593 1.73x y = np.zeros(n, dtype=x.dtype); y[:] = x
9 4.067133 y = np.zeros_like(x); y[:] = x
globals: {'n': 6309}, tested 1e+06 times
time (s) speedup methods
0 2.338428 3.05x y = np.array(x)
1 2.466636 2.89x y = x.astype(x.dtype)
2 2.561535 2.78x y = np.empty_like(x); np.copyto(y, x)
3 2.603601 2.74x y = np.empty_like(x); y[:] = x
4 3.005610 2.37x y = np.empty_like(x); np.copyto(y, x, casting=...
5 3.215863 2.22x y = np.copy(x)
6 3.249763 2.19x y = 1*x
7 3.661599 1.95x y = np.empty(n, dtype=x.dtype); y[:] = x
8 6.344077 1.12x y = np.zeros(n, dtype=x.dtype); y[:] = x
9 7.133050 y = np.zeros_like(x); y[:] = x
globals: {'n': 10000}, tested 1e+06 times
time (s) speedup methods
0 3.421806 2.82x y = np.array(x)
1 3.569501 2.71x y = x.astype(x.dtype)
2 3.618747 2.67x y = np.empty_like(x); np.copyto(y, x)
3 3.708604 2.61x y = np.empty_like(x); y[:] = x
4 4.150505 2.33x y = np.empty_like(x); np.copyto(y, x, casting=...
5 4.402126 2.19x y = np.copy(x)
6 4.917966 1.96x y = np.empty(n, dtype=x.dtype); y[:] = x
7 4.941269 1.96x y = 1*x
8 8.925884 1.08x y = np.zeros(n, dtype=x.dtype); y[:] = x
9 9.661437 y = np.zeros_like(x); y[:] = x
globals: {'n': 100000}, tested 1e+05 times
time (s) speedup methods
0 3.858588 2.63x y = x.astype(x.dtype)
1 3.873989 2.62x y = np.array(x)
2 3.896584 2.60x y = np.empty_like(x); np.copyto(y, x)
3 3.919729 2.58x y = np.empty_like(x); np.copyto(y, x, casting=...
4 3.948563 2.57x y = np.empty_like(x); y[:] = x
5 4.000521 2.53x y = np.copy(x)
6 4.087255 2.48x y = np.empty(n, dtype=x.dtype); y[:] = x
7 4.803606 2.11x y = 1*x
8 6.723291 1.51x y = np.zeros_like(x); y[:] = x
9 10.131983 y = np.zeros(n, dtype=x.dtype); y[:] = x
globals: {'n': 1000000}, tested 3e+04 times
time (s) speedup methods
0 85.625484 1.24x y = np.empty_like(x); y[:] = x
1 85.693316 1.24x y = np.empty_like(x); np.copyto(y, x)
2 85.790064 1.24x y = np.empty_like(x); np.copyto(y, x, casting=...
3 86.342230 1.23x y = np.empty(n, dtype=x.dtype); y[:] = x
4 86.954862 1.22x y = np.zeros(n, dtype=x.dtype); y[:] = x
5 89.503368 1.18x y = np.array(x)
6 91.986177 1.15x y = 1*x
7 95.216021 1.11x y = np.copy(x)
8 100.524358 1.05x y = x.astype(x.dtype)
9 106.045746 y = np.zeros_like(x); y[:] = x
Also, see results for a variant of the profiling where the destination's memory is already pre-allocated during value copying, since y = np.empty_like(x)
is part of the setup:
此外,请参阅结果的变体,其中目标的内存已在值复制期间预先分配,因为y = np.empty_like(x)是设置的一部分:
globals: {'n': 100}, tested 1e+06 times
time (s) speedup methods
0 0.328492 2.33x np.copyto(y, x)
1 0.384043 1.99x y = np.array(x)
2 0.405529 1.89x y[:] = x
3 0.764625 np.copyto(y, x, casting='no')
globals: {'n': 1000}, tested 1e+06 times
time (s) speedup methods
0 0.453094 1.95x np.copyto(y, x)
1 0.537594 1.64x y[:] = x
2 0.770695 1.15x y = np.array(x)
3 0.884261 np.copyto(y, x, casting='no')
globals: {'n': 6309}, tested 1e+06 times
time (s) speedup methods
0 2.125426 1.20x np.copyto(y, x)
1 2.182111 1.17x y[:] = x
2 2.364018 1.08x y = np.array(x)
3 2.553323 np.copyto(y, x, casting='no')
globals: {'n': 10000}, tested 1e+06 times
time (s) speedup methods
0 3.196402 1.13x np.copyto(y, x)
1 3.523396 1.02x y[:] = x
2 3.531007 1.02x y = np.array(x)
3 3.597598 np.copyto(y, x, casting='no')
globals: {'n': 100000}, tested 1e+05 times
time (s) speedup methods
0 3.862123 1.01x np.copyto(y, x)
1 3.863693 1.01x y = np.array(x)
2 3.873194 1.01x y[:] = x
3 3.909018 np.copyto(y, x, casting='no')
#6
1
There are many different things you can do:
你可以做很多不同的事情:
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)
Things that don't work
事情不起作用
a=b
a=b[:] # This have given my code bugs
#7
1
Why not to use
为什么不使用
a = 0 + b
I think it is similar to previous multiplication but might be simpler.
我认为它类似于之前的乘法,但可能更简单。
#1
71
I believe
我相信
a = numpy.empty_like (b)
a[:] = b
will make a deep copy quickly. As Funsi mentions, recent versions of numpy also have the copyto
function.
将快速复制。正如Funsi所提到的,numpy的最新版本也具有copyto功能。
#2
25
numpy version 1.7 has the numpy.copyto function that does what you are looking for:
numpy版本1.7有numpy.copyto函数,可以满足您的需求:
numpy.copyto(dst, src)
numpy.copyto(dst,src)
Copies values from one array to another,> broadcasting as necessary.
将值从一个数组复制到另一个数组,>根据需要进行广播。
See: http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.copyto.html
请参阅:http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.copyto.html
#3
13
a = numpy.array(b)
is even faster than the suggested solutions up to numpy v1.6 and makes a copy of the array as well. I could however not test it against copyto(a,b), since I don't have the most recent version of numpy.
甚至比numpy v1.6的建议解决方案更快,并且也制作了数组的副本。然而,我可以不对copyto(a,b)进行测试,因为我没有numpy的最新版本。
#4
9
you can easy use:
你可以轻松使用:
b = 1*a
this is the fastest way, but also have some problems. If you don't define directly the dtype
of a
and also doesn't check the dtype
of b
you can get into trouble. For example:
这是最快的方法,但也有一些问题。如果你没有直接定义a的dtype而且也没有检查b的dtype你可能会遇到麻烦。例如:
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
I hope, I could make the point clear. Sometimes you will have a data type change with just one little operation.
我希望,我能说清楚。有时您只需要一个小操作即可更改数据类型。
#5
9
To answer your question, I played with some variants and profiled them.
为了回答你的问题,我玩了一些变种并对它们进行了描述。
Conclusion: to copy data from a numpy array to another use one of the built-in numpy functions numpy.array(src)
or numpy.copyto(dst, src)
wherever possible.
结论:将数据从numpy数组复制到另一个数组时尽可能使用内置的numpy函数numpy.array(src)或numpy.copyto(dst,src)。
(But always choose the later if dst
's memory is already allocated, to reuse the memory. See profiling at the end of the post.)
(但是如果已经分配了dst的内存,则总是选择后者,以重用内存。请参阅帖子末尾的分析。)
profiling setup
分析设置
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.max(timings) / timings
pd.set_option('html', False)
data = {'time (s)': timings, 'speedup': ['{0:0.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()
profiling code
分析代码
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, int(10**it), {'n': int(10**n)})
results for Windows 7 on Intel i7 CPU, CPython v3.5.0, numpy v1.10.1.
Windows 7在Intel i7 CPU,CPython v3.5.0,numpy v1.10.1上的结果。
globals: {'n': 100}, tested 1e+06 times
time (s) speedup methods
0 0.386908 33.76x y = np.array(x)
1 0.496475 26.31x y = x.astype(x.dtype)
2 0.567027 23.03x y = np.empty_like(x); np.copyto(y, x)
3 0.666129 19.61x y = np.empty_like(x); y[:] = x
4 0.967086 13.51x y = 1*x
5 1.067240 12.24x y = np.empty_like(x); np.copyto(y, x, casting=...
6 1.235198 10.57x y = np.copy(x)
7 1.624535 8.04x y = np.zeros(n, dtype=x.dtype); y[:] = x
8 1.626120 8.03x y = np.empty(n, dtype=x.dtype); y[:] = x
9 3.569372 3.66x y = np.zeros_like(x); y[:] = x
10 13.061154 y = np.empty(n)\nfor i in range(x.size):\n\ty[...
globals: {'n': 1000}, tested 1e+06 times
time (s) speedup methods
0 0.666237 6.10x y = x.astype(x.dtype)
1 0.740594 5.49x y = np.empty_like(x); np.copyto(y, x)
2 0.755246 5.39x y = np.array(x)
3 1.043631 3.90x y = np.empty_like(x); y[:] = x
4 1.398793 2.91x y = 1*x
5 1.434299 2.84x y = np.empty_like(x); np.copyto(y, x, casting=...
6 1.544769 2.63x y = np.copy(x)
7 1.873119 2.17x y = np.empty(n, dtype=x.dtype); y[:] = x
8 2.355593 1.73x y = np.zeros(n, dtype=x.dtype); y[:] = x
9 4.067133 y = np.zeros_like(x); y[:] = x
globals: {'n': 6309}, tested 1e+06 times
time (s) speedup methods
0 2.338428 3.05x y = np.array(x)
1 2.466636 2.89x y = x.astype(x.dtype)
2 2.561535 2.78x y = np.empty_like(x); np.copyto(y, x)
3 2.603601 2.74x y = np.empty_like(x); y[:] = x
4 3.005610 2.37x y = np.empty_like(x); np.copyto(y, x, casting=...
5 3.215863 2.22x y = np.copy(x)
6 3.249763 2.19x y = 1*x
7 3.661599 1.95x y = np.empty(n, dtype=x.dtype); y[:] = x
8 6.344077 1.12x y = np.zeros(n, dtype=x.dtype); y[:] = x
9 7.133050 y = np.zeros_like(x); y[:] = x
globals: {'n': 10000}, tested 1e+06 times
time (s) speedup methods
0 3.421806 2.82x y = np.array(x)
1 3.569501 2.71x y = x.astype(x.dtype)
2 3.618747 2.67x y = np.empty_like(x); np.copyto(y, x)
3 3.708604 2.61x y = np.empty_like(x); y[:] = x
4 4.150505 2.33x y = np.empty_like(x); np.copyto(y, x, casting=...
5 4.402126 2.19x y = np.copy(x)
6 4.917966 1.96x y = np.empty(n, dtype=x.dtype); y[:] = x
7 4.941269 1.96x y = 1*x
8 8.925884 1.08x y = np.zeros(n, dtype=x.dtype); y[:] = x
9 9.661437 y = np.zeros_like(x); y[:] = x
globals: {'n': 100000}, tested 1e+05 times
time (s) speedup methods
0 3.858588 2.63x y = x.astype(x.dtype)
1 3.873989 2.62x y = np.array(x)
2 3.896584 2.60x y = np.empty_like(x); np.copyto(y, x)
3 3.919729 2.58x y = np.empty_like(x); np.copyto(y, x, casting=...
4 3.948563 2.57x y = np.empty_like(x); y[:] = x
5 4.000521 2.53x y = np.copy(x)
6 4.087255 2.48x y = np.empty(n, dtype=x.dtype); y[:] = x
7 4.803606 2.11x y = 1*x
8 6.723291 1.51x y = np.zeros_like(x); y[:] = x
9 10.131983 y = np.zeros(n, dtype=x.dtype); y[:] = x
globals: {'n': 1000000}, tested 3e+04 times
time (s) speedup methods
0 85.625484 1.24x y = np.empty_like(x); y[:] = x
1 85.693316 1.24x y = np.empty_like(x); np.copyto(y, x)
2 85.790064 1.24x y = np.empty_like(x); np.copyto(y, x, casting=...
3 86.342230 1.23x y = np.empty(n, dtype=x.dtype); y[:] = x
4 86.954862 1.22x y = np.zeros(n, dtype=x.dtype); y[:] = x
5 89.503368 1.18x y = np.array(x)
6 91.986177 1.15x y = 1*x
7 95.216021 1.11x y = np.copy(x)
8 100.524358 1.05x y = x.astype(x.dtype)
9 106.045746 y = np.zeros_like(x); y[:] = x
Also, see results for a variant of the profiling where the destination's memory is already pre-allocated during value copying, since y = np.empty_like(x)
is part of the setup:
此外,请参阅结果的变体,其中目标的内存已在值复制期间预先分配,因为y = np.empty_like(x)是设置的一部分:
globals: {'n': 100}, tested 1e+06 times
time (s) speedup methods
0 0.328492 2.33x np.copyto(y, x)
1 0.384043 1.99x y = np.array(x)
2 0.405529 1.89x y[:] = x
3 0.764625 np.copyto(y, x, casting='no')
globals: {'n': 1000}, tested 1e+06 times
time (s) speedup methods
0 0.453094 1.95x np.copyto(y, x)
1 0.537594 1.64x y[:] = x
2 0.770695 1.15x y = np.array(x)
3 0.884261 np.copyto(y, x, casting='no')
globals: {'n': 6309}, tested 1e+06 times
time (s) speedup methods
0 2.125426 1.20x np.copyto(y, x)
1 2.182111 1.17x y[:] = x
2 2.364018 1.08x y = np.array(x)
3 2.553323 np.copyto(y, x, casting='no')
globals: {'n': 10000}, tested 1e+06 times
time (s) speedup methods
0 3.196402 1.13x np.copyto(y, x)
1 3.523396 1.02x y[:] = x
2 3.531007 1.02x y = np.array(x)
3 3.597598 np.copyto(y, x, casting='no')
globals: {'n': 100000}, tested 1e+05 times
time (s) speedup methods
0 3.862123 1.01x np.copyto(y, x)
1 3.863693 1.01x y = np.array(x)
2 3.873194 1.01x y[:] = x
3 3.909018 np.copyto(y, x, casting='no')
#6
1
There are many different things you can do:
你可以做很多不同的事情:
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)
Things that don't work
事情不起作用
a=b
a=b[:] # This have given my code bugs
#7
1
Why not to use
为什么不使用
a = 0 + b
I think it is similar to previous multiplication but might be simpler.
我认为它类似于之前的乘法,但可能更简单。