考虑以下简单示例:
基本上是将两个二维数组沿着特定的轴求和,并找到另一个轴上的最大索引。
使用gcc -O3编译并使用参数(1, 2000, 2000)调用时,添加boundscheck=True会导致执行速度比boundscheck=False快两倍。
为什么会出现这种情况的任何提示?(嗯,我可以猜测这可能再次与GCC自动向量化有关...)
#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]
基本上是将两个二维数组沿着特定的轴求和,并找到另一个轴上的最大索引。
使用gcc -O3编译并使用参数(1, 2000, 2000)调用时,添加boundscheck=True会导致执行速度比boundscheck=False快两倍。
为什么会出现这种情况的任何提示?(嗯,我可以猜测这可能再次与GCC自动向量化有关...)
with cython.boundscheck(True)
的版本大约慢了3倍。我认为由于malloc
的原因,a
、b
、best
的内存都未初始化。我将其更改为等效的calloc
调用。此外,当t == nt - 1
时,行best[t + 1, j, y]
似乎正在索引无效的内存。 - Alok--setup.py
具有extra_compile_args=["-O3"]
,我正在使用gcc 5.1.0。 - antony