【发布时间】:2016-10-22 07:17:48
【问题描述】:
将某些 Cython 变量从 int 类型更改为 size_t 类型可以显着减少某些函数时间 (~30%),但我不明白为什么。
例如:
cimport numpy as cnp
import numpy as np
def sum_int(cnp.int64_t[::1] A):
cdef unsigned long s = 0
cdef int k
for k in xrange(A.shape[0]):
s += A[k]
return s
def sum_size_t(cnp.int64_t[::1] A):
cdef unsigned long s = 0
cdef size_t k
for k in xrange(A.shape[0]):
s += A[k]
return s
a = np.array(range(1000000))
以及计时结果:
In [17]: %timeit sum_int(a)
1000 loops, best of 3: 652 µs per loop
In [18]: %timeit sum_size_t(a)
1000 loops, best of 3: 427 µs per loop
我是 Cython 的新手,并且比 C 更了解 Fortran。请帮帮我。导致这种性能差异的这两种变量类型之间的重要区别是什么? Cython 有什么我不理解的?
【问题讨论】:
-
你检查生成的程序集了吗?
-
@KarolyHorvath 我试图查看生成的 C 代码,但几乎失明了。我确信它已经过高度优化,但由于我更喜欢 Fortran,因此自动生成的 C 语言很难阅读。
-
您正在获取
int64_t的数组。为什么不将int64_t用于您的累加器? -
@user2357112 哈哈。好吧,我想我认为添加一百万个数字可能会溢出 64 位整数。邋遢。但是,它不会改变结果。两个示例之间的累加器类型没有变化。
-
size_t不是隐含无符号的吗?当您在循环中使用变量k时,我猜如果您使用 size_t 或 unsigned int 作为 cython doc 报告,则它是优化的 "range() 在 cdef 声明索引值时是 C 优化的,对于示例”。因此,众所周知,您稍后用作A的索引器的无符号值永远不会为负(它应该允许您将wraparound和boundscheck参数转换为False,因为您正在安全循环在您的数组范围内,并且可能具有更高的性能)?
标签: python performance types cython