Look here để tìm câu trả lời.
Ý tưởng cơ bản là bạn muốn cpython.array.array
và cpython.array.clone
(khôngcython.array.*
):
from cpython.array cimport array, clone
# This type is what you want and can be cast to things of
# the "double[:]" syntax, so no problems there
cdef array[double] armv, templatemv
templatemv = array('d')
# This is fast
armv = clone(templatemv, L, False)
EDIT
Nó chỉ ra rằng các tiêu chuẩn trong chủ đề đó là rác. Dưới đây là bộ của tôi, với timings của tôi:
# cython: language_level=3
# cython: boundscheck=False
# cython: wraparound=False
import time
import sys
from cpython.array cimport array, clone
from cython.view cimport array as cvarray
from libc.stdlib cimport malloc, free
import numpy as numpy
cimport numpy as numpy
cdef int loops
def timefunc(name):
def timedecorator(f):
cdef int L, i
print("Running", name)
for L in [1, 10, 100, 1000, 10000, 100000, 1000000]:
start = time.clock()
f(L)
end = time.clock()
print(format((end-start)/loops * 1e6, "2f"), end=" ")
sys.stdout.flush()
print("μs")
return timedecorator
print()
print("INITIALISATIONS")
loops = 100000
@timefunc("cpython.array buffer")
def _(int L):
cdef int i
cdef array[double] arr, template = array('d')
for i in range(loops):
arr = clone(template, L, False)
# Prevents dead code elimination
str(arr[0])
@timefunc("cpython.array memoryview")
def _(int L):
cdef int i
cdef double[::1] arr
cdef array template = array('d')
for i in range(loops):
arr = clone(template, L, False)
# Prevents dead code elimination
str(arr[0])
@timefunc("cpython.array raw C type")
def _(int L):
cdef int i
cdef array arr, template = array('d')
for i in range(loops):
arr = clone(template, L, False)
# Prevents dead code elimination
str(arr[0])
@timefunc("numpy.empty_like memoryview")
def _(int L):
cdef int i
cdef double[::1] arr
template = numpy.empty((L,), dtype='double')
for i in range(loops):
arr = numpy.empty_like(template)
# Prevents dead code elimination
str(arr[0])
@timefunc("malloc")
def _(int L):
cdef int i
cdef double* arrptr
for i in range(loops):
arrptr = <double*> malloc(sizeof(double) * L)
free(arrptr)
# Prevents dead code elimination
str(arrptr[0])
@timefunc("malloc memoryview")
def _(int L):
cdef int i
cdef double* arrptr
cdef double[::1] arr
for i in range(loops):
arrptr = <double*> malloc(sizeof(double) * L)
arr = <double[:L]>arrptr
free(arrptr)
# Prevents dead code elimination
str(arr[0])
@timefunc("cvarray memoryview")
def _(int L):
cdef int i
cdef double[::1] arr
for i in range(loops):
arr = cvarray((L,),sizeof(double),'d')
# Prevents dead code elimination
str(arr[0])
print()
print("ITERATING")
loops = 1000
@timefunc("cpython.array buffer")
def _(int L):
cdef int i
cdef array[double] arr = clone(array('d'), L, False)
cdef double d
for i in range(loops):
for i in range(L):
d = arr[i]
# Prevents dead-code elimination
str(d)
@timefunc("cpython.array memoryview")
def _(int L):
cdef int i
cdef double[::1] arr = clone(array('d'), L, False)
cdef double d
for i in range(loops):
for i in range(L):
d = arr[i]
# Prevents dead-code elimination
str(d)
@timefunc("cpython.array raw C type")
def _(int L):
cdef int i
cdef array arr = clone(array('d'), L, False)
cdef double d
for i in range(loops):
for i in range(L):
d = arr[i]
# Prevents dead-code elimination
str(d)
@timefunc("numpy.empty_like memoryview")
def _(int L):
cdef int i
cdef double[::1] arr = numpy.empty((L,), dtype='double')
cdef double d
for i in range(loops):
for i in range(L):
d = arr[i]
# Prevents dead-code elimination
str(d)
@timefunc("malloc")
def _(int L):
cdef int i
cdef double* arrptr = <double*> malloc(sizeof(double) * L)
cdef double d
for i in range(loops):
for i in range(L):
d = arrptr[i]
free(arrptr)
# Prevents dead-code elimination
str(d)
@timefunc("malloc memoryview")
def _(int L):
cdef int i
cdef double* arrptr = <double*> malloc(sizeof(double) * L)
cdef double[::1] arr = <double[:L]>arrptr
cdef double d
for i in range(loops):
for i in range(L):
d = arr[i]
free(arrptr)
# Prevents dead-code elimination
str(d)
@timefunc("cvarray memoryview")
def _(int L):
cdef int i
cdef double[::1] arr = cvarray((L,),sizeof(double),'d')
cdef double d
for i in range(loops):
for i in range(L):
d = arr[i]
# Prevents dead-code elimination
str(d)
Output:
INITIALISATIONS
Running cpython.array buffer
0.100040 0.097140 0.133110 0.121820 0.131630 0.108420 0.112160 μs
Running cpython.array memoryview
0.339480 0.333240 0.378790 0.445720 0.449800 0.414280 0.414060 μs
Running cpython.array raw C type
0.048270 0.049250 0.069770 0.074140 0.076300 0.060980 0.060270 μs
Running numpy.empty_like memoryview
1.006200 1.012160 1.128540 1.212350 1.250270 1.235710 1.241050 μs
Running malloc
0.021850 0.022430 0.037240 0.046260 0.039570 0.043690 0.030720 μs
Running malloc memoryview
1.640200 1.648000 1.681310 1.769610 1.755540 1.804950 1.758150 μs
Running cvarray memoryview
1.332330 1.353910 1.358160 1.481150 1.517690 1.485600 1.490790 μs
ITERATING
Running cpython.array buffer
0.010000 0.027000 0.091000 0.669000 6.314000 64.389000 635.171000 μs
Running cpython.array memoryview
0.013000 0.015000 0.058000 0.354000 3.186000 33.062000 338.300000 μs
Running cpython.array raw C type
0.014000 0.146000 0.979000 9.501000 94.160000 916.073000 9287.079000 μs
Running numpy.empty_like memoryview
0.042000 0.020000 0.057000 0.352000 3.193000 34.474000 333.089000 μs
Running malloc
0.002000 0.004000 0.064000 0.367000 3.599000 32.712000 323.858000 μs
Running malloc memoryview
0.019000 0.032000 0.070000 0.356000 3.194000 32.100000 327.929000 μs
Running cvarray memoryview
0.014000 0.026000 0.063000 0.351000 3.209000 32.013000 327.890000 μs
(. Lý do cho sự "lặp lại" điểm chuẩn là một số phương pháp có những đặc điểm đáng ngạc nhiên khác nhau trong lĩnh vực này)
Để tốc độ khởi tạo:
malloc
: Đây là một thế giới khắc nghiệt, nhưng nó rất nhanh.Nếu bạn cần phân bổ nhiều thứ và có hiệu suất lập lại và lập chỉ mục không bị cản trở, điều này phải là nó. Nhưng thông thường, bạn là một cá cược tốt cho ...
cpython.array raw C type
: Thật đáng buồn, nó rất nhanh. Và nó an toàn. Thật không may nó đi qua Python để truy cập vào các trường dữ liệu của nó. Bạn có thể tránh điều đó bằng cách sử dụng một mẹo tuyệt vời:
arr.data.as_doubles[i]
mang đến tốc độ tiêu chuẩn trong khi tháo an toàn! Điều này làm cho việc thay thế tuyệt vời này là cho malloc
, về cơ bản là phiên bản được tính tham khảo khá!
cpython.array buffer
: Chỉ đến ba lần bốn lần thời gian thiết lập là malloc
, đây có vẻ là một cược tuyệt vời. Thật không may nó có chi phí đáng kể (mặc dù nhỏ so với các chỉ thị boundscheck
và wraparound
). Điều đó có nghĩa là nó chỉ thực sự cạnh tranh với các biến thể an toàn đầy đủ, nhưng nó là là là nhanh nhất trong số đó để khởi tạo. Lựa chọn của bạn.
cpython.array memoryview
: Đây là mức độ chậm hơn malloc
để khởi tạo. Đó là một sự xấu hổ, nhưng nó lặp lại nhanh như vậy. Đây là giải pháp tiêu chuẩn mà tôi sẽ đề xuất trừ khi boundscheck
hoặc wraparound
được bật (trong trường hợp này cpython.array buffer
có thể là một sự cân bằng hấp dẫn hơn).
Phần còn lại. Người duy nhất đáng giá bất cứ thứ gì là numpy
, do nhiều phương pháp thú vị gắn liền với các vật thể. Đó là nó, mặc dù.
Câu hỏi hay, tôi tự hỏi về điều gì đó tương tự. – AlexE
Điểm chuẩn của bạn là câu trả lời hay nhất mà tôi biết. Để trả lời câu hỏi tiếp theo, bạn chỉ có thể khai báo mảng NumPy của bạn theo cách thông thường (bạn thậm chí không cần phải sử dụng giao diện kiểu cũ) và sau đó làm một cái gì đó như 'cdef int [:] arrview = arr' để có được một xem cùng một bộ nhớ được sử dụng cho mảng NumPy. Bạn có thể sử dụng khung nhìn để lập chỉ mục nhanh và chuyển các lát giữa các hàm Cython trong khi vẫn có quyền truy cập vào các hàm NumPy thông qua mảng NumPy. Khi bạn hoàn tất, bạn có thể trả về mảng NumPy. – IanH
có [câu hỏi liên quan tốt ở đây ...] (http://stackoverflow.com/q/18410342/832621) nơi bạn có thể thấy rằng np.empty có thể chậm ... –