xem xét ví dụ tối thiểu sau đây:cython boundscheck = True nhanh hơn boundscheck = False
#cython: language_level=3, boundscheck=False, wraparound=False, initializedcheck=False, cdivision=True
cimport cython
from libc.stdlib cimport malloc
def main(size_t ni, size_t nt, size_t nx):
cdef:
size_t i, j, t, x, y
double[:, :, ::1] a = <double[:ni, :ni, :nx]>malloc(ni * ni * nx * sizeof(double))
double[:, :, ::1] b = <double[:nt, :ni, :nx]>malloc(nt * ni * nx * sizeof(double))
size_t[:, :, ::1] best = <size_t[:nt, :ni, :nx]>malloc(nt * ni * nx * sizeof(size_t))
size_t mxi
double s, mxs
for t in range(nt):
for j in range(ni):
for y in range(nx): # this loops does nothing but is needed for the effect below.
mxs = -1e300
for i in range(ni):
for x in range(nx):
with cython.boundscheck(False): # Faster!?!?
s = b[t, i, x] + a[i, j, x]
if s >= mxs:
mxs = s
mxi = i
best[t + 1, j, y] = mxi
return best[0, 0, 0]
cơ bản tổng hợp hai mảng 2D cùng một số trục cụ thể và tìm ra các chỉ số tối đa hóa dọc theo trục khác.
Khi được biên dịch bằng gcc -O3 và được gọi với các đối số (1, 2000, 2000), hãy thêm boundscheck = Kết quả thực trong thực thi nhanh hơn gấp hai lần khi boundscheck = False.
Bất kỳ gợi ý nào về lý do này sẽ xảy ra? (Ừm, tôi có thể đoán điều này một lần nữa để làm với tự động hóa GCC ...)
Xin cảm ơn trước.
(cross-đăng từ cython-users)
Trong các thử nghiệm của tôi, các phiên bản với 'với cython.boundscheck (True)' là chậm hơn khoảng 3 lần. Tôi nghĩ rằng bộ nhớ cho 'a',' b', 'best' là tất cả uninitialized vì' malloc'. Tôi đã thay đổi điều đó thành một cuộc gọi 'calloc' tương đương. Ngoài ra, dòng 'tốt nhất [t + 1, j, y]' dường như đang lập chỉ mục bộ nhớ không hợp lệ khi 't == nt - 1'. –
Thay đổi mallocs thành callocs và thay thế 't + 1' bằng' t' không (chất lượng) thay đổi kết quả cho tôi. 'Setup.py' của tôi có' extra_compile_args = ["- O3"] 'và tôi đang sử dụng gcc 5.1.0. – antony
OK, tôi đã thử với -O3 và tôi nhận được cùng một tốc độ với cả hai phiên bản. Tôi đang sử dụng gcc 4.9.1. Nhìn vào mã C được tạo ra, tôi nghĩ có thể gcc đủ thông minh để biết rằng các kiểm tra giới hạn bổ sung sẽ không bao giờ được kích hoạt (vì điều kiện vòng lặp). Tôi không biết tại sao bạn nhận được tốc độ khác nhau như vậy mặc dù. –