在 Cython 中填充 64 位 numpy 数组比 32 位数组慢
Filling 64 bit numpy array in Cython slower than 32 bit array
我想了解为什么填充 64 位数组比填充 32 位数组慢。
示例如下:
@cython.boundscheck(False)
@cython.wraparound(False)
def test32(long long int size):
cdef np.ndarray[np.int32_t,ndim=1] index = np.zeros(size, np.int32)
cdef Py_ssize_t i
for i in range(size):
index[i] = i
return indx
@cython.boundscheck(False)
@cython.wraparound(False)
def test64(long long int size):
cdef np.ndarray[np.int64_t,ndim=1] index = np.zeros(size, np.int64)
cdef Py_ssize_t i
for i in range(size):
index[i] = i
return indx
时间:
In [4]: %timeit test32(1000000)
1000 loops, best of 3: 1.13 ms over loop
In [5]: %timeit test64(1000000)
100 loops, best of 3: 2.04 ms per loop
我正在使用 64 位计算机和用于 Python (9.0) 编译器的 Visual C++。
编辑:
初始化 64 位数组和 32 位数组似乎花费相同的时间,这意味着时间差异是由于填充过程造成的。
In [8]: %timeit np.zeros(1000000,'int32')
100000 loops, best of 3: 2.49 μs per loop
In [9]: %timeit np.zeros(1000000,'int64')
100000 loops, best of 3: 2.49 μs per loop
编辑2:
正如 DavidW 指出的那样,可以使用 np.arange 复制此行为,这意味着这是预期的:
In [7]: %timeit np.arange(1000000,dtype='int32')
10 loops, best of 3: 1.22 ms per loop
In [8]: %timeit np.arange(1000000,dtype='int64')
10 loops, best of 3: 2.03 ms per loop
一组快速测量(我最初在评论中发布)表明您看到 np.full
、np.ones
和 np.ones
非常相似的行为(64 位占用的时间是 32 位的两倍) np.arange
,所有三个显示的时间彼此相似(arange
对我来说比其他两个慢 10%)。
我相信这表明这是预期的行为,只是填充内存所需的时间。 (64 位的内存显然是 32 位的两倍)。
那么有趣的问题是为什么 np.zeros
如此统一(和快速)——一个完整的答案可能在 this C-based question 中给出,但基本的总结是分配零(如 C function calloc
) 可以懒惰地完成 - 即它实际上不会分配或填充太多,直到你真正尝试写入内存。
我想了解为什么填充 64 位数组比填充 32 位数组慢。
示例如下:
@cython.boundscheck(False)
@cython.wraparound(False)
def test32(long long int size):
cdef np.ndarray[np.int32_t,ndim=1] index = np.zeros(size, np.int32)
cdef Py_ssize_t i
for i in range(size):
index[i] = i
return indx
@cython.boundscheck(False)
@cython.wraparound(False)
def test64(long long int size):
cdef np.ndarray[np.int64_t,ndim=1] index = np.zeros(size, np.int64)
cdef Py_ssize_t i
for i in range(size):
index[i] = i
return indx
时间:
In [4]: %timeit test32(1000000)
1000 loops, best of 3: 1.13 ms over loop
In [5]: %timeit test64(1000000)
100 loops, best of 3: 2.04 ms per loop
我正在使用 64 位计算机和用于 Python (9.0) 编译器的 Visual C++。
编辑:
初始化 64 位数组和 32 位数组似乎花费相同的时间,这意味着时间差异是由于填充过程造成的。
In [8]: %timeit np.zeros(1000000,'int32')
100000 loops, best of 3: 2.49 μs per loop
In [9]: %timeit np.zeros(1000000,'int64')
100000 loops, best of 3: 2.49 μs per loop
编辑2:
正如 DavidW 指出的那样,可以使用 np.arange 复制此行为,这意味着这是预期的:
In [7]: %timeit np.arange(1000000,dtype='int32')
10 loops, best of 3: 1.22 ms per loop
In [8]: %timeit np.arange(1000000,dtype='int64')
10 loops, best of 3: 2.03 ms per loop
一组快速测量(我最初在评论中发布)表明您看到 np.full
、np.ones
和 np.ones
非常相似的行为(64 位占用的时间是 32 位的两倍) np.arange
,所有三个显示的时间彼此相似(arange
对我来说比其他两个慢 10%)。
我相信这表明这是预期的行为,只是填充内存所需的时间。 (64 位的内存显然是 32 位的两倍)。
那么有趣的问题是为什么 np.zeros
如此统一(和快速)——一个完整的答案可能在 this C-based question 中给出,但基本的总结是分配零(如 C function calloc
) 可以懒惰地完成 - 即它实际上不会分配或填充太多,直到你真正尝试写入内存。