배열 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
보다 훨씬 빠릅니다 . BTW 난 그냥 (지금 업데이트) 내 벤치 마크를-실행 다시, 그리고 사이의 차이 와는 증발 것 같습니다. gist.github.com/bhawkins/5095558empty
zeros_like
zeros
copyto(a,b)
a[:] = b
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)})
Intel 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)
있습니다. i5-4210U 및 numpy 1.10.4로 Linux에서 테스트 됨
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