Apa cara tercepat untuk menyalin data dari larik b ke larik a, tanpa mengubah alamat larik a. Saya memerlukan ini karena perpustakaan eksternal (PyFFTW) menggunakan penunjuk ke array saya yang tidak dapat berubah.
Sebagai contoh:
a = numpy.empty(n, dtype=complex)
for i in xrange(a.size):
a[i] = b[i]
Apakah mungkin untuk melakukannya tanpa loop?
a = b
hanya membuat referensi baru keb
.a[:] = b
berarti "mengatur semua elemena
sama dengan yang adab
". Perbedaannya penting karena array numpy adalah tipe yang bisa berubah.empty()
sekitar 10% lebih cepat daripadazeros()
. Ternyataempty_like()
lebih cepat.copyto(a,b)
lebih cepat dari sintaks arraya[:] = b
. Lihat gist.github.com/bhawkins/5095558np.copyto(a, b)
dan kapana = b.astype(b.dtype)
untuk peningkatan kecepatan, lihat jawaban di bawah ini: stackoverflow.com/a/33672015/3703716empty_like
jauh lebih cepat daripadaempty
, terutama karenazeros_like
lebih lambat darizeros
. BTW Saya baru saja menjalankan kembali benchmark saya (sekarang diperbarui), dan perbedaan antaracopyto(a,b)
dana[:] = b
tampaknya telah menguap. gist.github.com/bhawkins/5095558NumPy versi 1.7 memiliki
numpy.copyto
fungsi yang melakukan apa yang Anda cari:Lihat: https://docs.scipy.org/doc/numpy/reference/generated/numpy.copyto.html
sumber
AttributeError: 'module' object has no attribute 'copyto'
bahkan lebih cepat daripada solusi yang disarankan hingga numpy v1.6 dan juga membuat salinan larik. Namun saya tidak dapat mengujinya dengan copyto (a, b), karena saya tidak memiliki versi terbaru dari numpy.
sumber
Untuk menjawab pertanyaan Anda, saya bermain dengan beberapa varian dan membuat profilnya.
Kesimpulan: untuk menyalin data dari array numpy ke yang lain gunakan salah satu fungsi numpy bawaan
numpy.array(src)
ataunumpy.copyto(dst, src)
jika memungkinkan.(Tapi selalu pilih nanti jika
dst
memori sudah dialokasikan, untuk menggunakan kembali memori. Lihat profil di akhir posting.)pengaturan profil
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()
kode profil
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)})
hasil untuk Windows 7 pada Intel i7 CPU, CPython v3.5.0, numpy v1.10.1.
Tampilkan cuplikan kode
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
Selain itu, lihat hasil untuk varian pembuatan profil di mana memori tujuan sudah dialokasikan sebelumnya selama penyalinan nilai, karena
y = np.empty_like(x)
merupakan bagian dari penyiapan:Tampilkan cuplikan kode
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')
sumber
x.copy()
secepatnp.array(x)
dan saya lebih suka sintaksnya:$ 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
. Saya memiliki hasil yang serupa untuknp.array(x)
. Diuji di Linux dengan i5-4210U dan numpy 1.10.4np.copy
lebih memaafkan:np.copy(False)
,np.copy(None)
masih kerja, sementaraa = None; a.copy()
melemparAttributeError: 'NoneType' object has no attribute 'copy'
. Juga, kami lebih tepat dalam mendeklarasikan apa yang kami inginkan terjadi di baris kode ini menggunakan fungsi daripada sintaks metode.np.copy(None)
tidak melempar kesalahan itu benar-benar unpythonic. Satu alasan lagi untuk menggunakana.copy()
:)y[:] = x
sekarang sedikit lebih cepat daricopyto(y, x)
. Kode dan keluaran di gist.github.com/bhawkins/7cdbd5b9372cb798e34e21f92279d2dcAnda dapat dengan mudah menggunakan:
b = 1*a
ini adalah cara tercepat, tetapi juga memiliki beberapa masalah. Jika Anda tidak menentukan secara langsung
dtype
daria
dan juga tidak memeriksadtype
darib
Anda bisa mendapat masalah. Sebagai contoh: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
Saya harap, saya bisa menjelaskan maksudnya. Terkadang Anda akan mengalami perubahan tipe data hanya dengan satu operasi kecil.
sumber
a = numpy.zeros(len(b))
ataua = numpy.empty(n,dtype=complex)
juga akan membuat array baru.Ada banyak hal berbeda yang dapat Anda lakukan:
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)
Hal-hal yang tidak berhasil
a=b a=b[:] # This have given my code bugs
sumber
Mengapa tidak digunakan
a = 0 + b
Menurut saya ini mirip dengan perkalian sebelumnya tetapi mungkin lebih sederhana.
sumber