配列aのアドレスを変更せずに、配列bから配列aにデータをコピーする最速の方法は何ですか。外部ライブラリ(PyFFTW)が変更できない配列へのポインタを使用するため、これが必要です。
例えば:
a = numpy.empty(n, dtype=complex)
for i in xrange(a.size):
a[i] = b[i]
ループなしでそれを行うことは可能ですか?
配列aのアドレスを変更せずに、配列bから配列aにデータをコピーする最速の方法は何ですか。外部ライブラリ(PyFFTW)が変更できない配列へのポインタを使用するため、これが必要です。
例えば:
a = numpy.empty(n, dtype=complex)
for i in xrange(a.size):
a[i] = b[i]
ループなしでそれを行うことは可能ですか?
回答:
私は信じている
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
です。ところで、ベンチマークを再実行したところ(現在は更新されています)、との違いは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'
a = numpy.array(b)
numpy v1.6までの推奨ソリューションよりもさらに高速で、アレイのコピーも作成します。ただし、numpyの最新バージョンがないため、copyto(a、b)に対してテストできませんでした。
あなたの質問に答えるために、私はいくつかの変種で遊んで、それらをプロファイリングしました。
結論: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)})
結果インテルi7のCPU、CPythonとのv3.5.0、numpyのv1.10.1上のWindows 7用。
また、これはセットアップの一部であるため、値のコピー中に宛先のメモリがすでに事前に割り当てられているプロファイリングのバリアントの結果を参照してください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とnumpy1.10.4を使用してテスト
np.copy
はより寛容であることに注意してください:np.copy(False)
、スローしnp.copy(None)
ながら、まだ動作します。また、メソッド構文の代わりに関数を使用して、このコード行で何を実行したいかをより正確に宣言します。a = None; a.copy()
AttributeError: 'NoneType' object has no attribute 'copy'
np.copy(None)
はエラーをスローしませんが、本当に非Pythonです。使用するもう1つの理由a.copy()
:)
y[:] = x
現在はcopyto(y, x)
。よりもわずかに高速であることがわかりました。gist.github.com/bhawkins/7cdbd5b9372cb798e34e21f92279d2dcの
あなたは簡単に使うことができます:
b = 1*a
これが最速の方法ですが、いくつかの問題もあります。dtype
ofa
を直接定義せず、ofもチェックしないと、問題が発生する可能性がdtype
あり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
要点を明確にできればと思います。たった1回の小さな操作でデータ型を変更できる場合があります。
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