Betrachten Sie das folgende Beispiel minimal:cython boundscheck = True schneller als 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]
im Wesentlichen zwei entlang einiger spezifischen Achsen 2D-Arrays Summieren und den maximier Index entlang einer anderen Achse zu finden.
Wenn mit gcc -O3 kompiliert und mit den Argumenten (1, 2000, 2000) aufgerufen wird, führt das Hinzufügen von boundscheck = True zu einer doppelt schnelleren Ausführung als bei boundscheck = False.
Irgendein Hinweis, warum das der Fall wäre? (Nun, ich kann wahrscheinlich vermuten, dass dies wieder mit der Autokorrektur des GCC zu tun hat ...)
Vielen Dank im Voraus.
(Cross-Gepostet von cython-Benutzer)
In meinen Tests, die Version mit 'mit cython.boundscheck (True)' ist etwa 3 mal langsamer. Ich denke, die Erinnerung an 'a',' b', 'best' ist wegen' malloc' nicht initialisiert. Ich änderte das zu einem äquivalenten Call-Call. Auch scheint die Zeile 'best [t + 1, j, y]' ungültigen Speicher zu indizieren, wenn 't == nt - 1'. –
Das Ändern von mallocs in Callocs und Ersetzen von "t + 1" durch "t" ändert (qualitativ) die Ergebnisse für mich nicht. Mein 'setup.py' hat' extra_compile_args = ["- O3"] 'und ich benutze gcc 5.1.0. – antony
OK, ich habe es mit -O3 versucht, und ich bekomme die gleiche Geschwindigkeit mit beiden Versionen. Ich benutze gcc 4.9.1. Wenn ich mir den generierten C-Code anschaue, denke ich, dass gcc intelligent genug ist, um zu wissen, dass die Extra-Grenzen-Checks nie ausgelöst werden (wegen der Bedingung für die Schleife). Ich weiß nicht, warum Sie so unterschiedliche Geschwindigkeiten bekommen. –