最快的 Cython 实现取决于计算机?
Fastest Cython implementation depends on computer?
我正在将 python 脚本转换为 cython 并对其进行优化以提高速度。现在我有两个版本,在我的台式机上,V2 的速度是 V1 的两倍,不幸的是,在我的笔记本电脑上,V1 的速度是 V2 的两倍,我无法找出为什么会有如此大的差异。
两台电脑都使用:
- Ubuntu 16.04
- Python 2.7.12
- Cython 0.25.2
- 麻木 1.12.1
桌面:
- 英特尔® 酷睿™ i3-4370 CPU @ 3.80GHz × 4 64 位。 16GB 内存
笔记本电脑:
- 英特尔® 酷睿™ i5-3210 CPU @ 2.5GHz × 2 64 位。 8GB 内存
V1 - 您可以找到完整代码 here。所做的唯一更改是将 go.py
、preprocessing.py
重命名为 go.pyx
、preprocessing.pyx
并使用
import pyximport; pyximport.install()
编译它们。你可以 运行 test.py
。此版本使用 2d numpy 数组 board
在 go.pyx
中存储数据,并在 preprocessing.pyx
中的 get_board
函数中使用列表理解来处理数据。在测试期间,没有从 go.py
调用任何函数,仅使用了 numpy 数组 board
V2 - 您可以找到完整代码 here。相当多的东西发生了变化,您可以在下面找到一个列表,其中包含影响此测试用例的所有内容。请注意,所有函数和变量声明都必须在 go.pxd
中。您可以 运行 test.py
使用此命令:python test.py build_ext --inplace
二维 numpy 数组替换为:
cdef char board[ 362 ]
和 go.pyx
中的函数 get_board_feature
替换了 numpy 列表理解:
cdef char get_board_feature( self, short location ):
# return correct board feature value
# 0 active player stone
# 1 opponent stone
# 2 empty location
cdef char value = self.board[ location ]
if value == EMPTY:
return 2
if value == self.player_current:
return 0
return 1
preprocessing.pyx
中的 get_board
函数替换为循环遍历数组并为每个位置 go.pyx
调用 get_board_feature
的函数
@cython.boundscheck(False)
@cython.wraparound(False)
cdef int get_board(self, GameState state, np.ndarray[double, ndim=2] tensor, int offSet ):
"""A feature encoding WHITE BLACK and EMPTY on separate planes, but plane 0
always refers to the current player and plane 1 to the opponent
"""
cdef short location
for location in range( 0, state.size * state.size ):
tensor[ offSet + state.get_board_feature( location ), location ] = 1
return offSet + 3
如果我应该包括任何其他信息或运行某些测试,请告诉我。
cmp, diff 测试
V2 go.c
和 preprocessing.c
文件是相同的。
V1 不生成 .c
文件来比较
更新比较 .so
个文件
V2 go.so
文件不同:
goD.so goL.so differ: byte 473, line 1
preprocessing.so
文件是相同的,不知道该怎么想..
它们是两台不同的机器,行为也不同。处理器评论使用大型基准套件是有原因的。可以说桌面 CPU 的平均性能更好,但是两个小但重要的代码片段之间的执行时间并不 'have' 有利于桌面 CPU。而且执行时间的差异绝对不必遵循任何线性关系。性能始终取决于大量因素。可能的解释包括但不限于台式机上较小的 L1 和 L2 缓存以及 Ivy Bridge 笔记本电脑和 Haswell 台式机之间向量指令集从 AVX 到 AVX2 的变化。
通常,在优化性能时集中精力使用好的算法并识别和消除瓶颈是个好主意。试图盯着不同机器之间的基准测试可能只会让人头疼。
我正在将 python 脚本转换为 cython 并对其进行优化以提高速度。现在我有两个版本,在我的台式机上,V2 的速度是 V1 的两倍,不幸的是,在我的笔记本电脑上,V1 的速度是 V2 的两倍,我无法找出为什么会有如此大的差异。
两台电脑都使用:
- Ubuntu 16.04
- Python 2.7.12
- Cython 0.25.2
- 麻木 1.12.1
桌面:
- 英特尔® 酷睿™ i3-4370 CPU @ 3.80GHz × 4 64 位。 16GB 内存
笔记本电脑:
- 英特尔® 酷睿™ i5-3210 CPU @ 2.5GHz × 2 64 位。 8GB 内存
V1 - 您可以找到完整代码 here。所做的唯一更改是将 go.py
、preprocessing.py
重命名为 go.pyx
、preprocessing.pyx
并使用
import pyximport; pyximport.install()
编译它们。你可以 运行 test.py
。此版本使用 2d numpy 数组 board
在 go.pyx
中存储数据,并在 preprocessing.pyx
中的 get_board
函数中使用列表理解来处理数据。在测试期间,没有从 go.py
调用任何函数,仅使用了 numpy 数组 board
V2 - 您可以找到完整代码 here。相当多的东西发生了变化,您可以在下面找到一个列表,其中包含影响此测试用例的所有内容。请注意,所有函数和变量声明都必须在 go.pxd
中。您可以 运行 test.py
使用此命令:python test.py build_ext --inplace
二维 numpy 数组替换为:
cdef char board[ 362 ]
和 go.pyx
中的函数 get_board_feature
替换了 numpy 列表理解:
cdef char get_board_feature( self, short location ):
# return correct board feature value
# 0 active player stone
# 1 opponent stone
# 2 empty location
cdef char value = self.board[ location ]
if value == EMPTY:
return 2
if value == self.player_current:
return 0
return 1
preprocessing.pyx
中的 get_board
函数替换为循环遍历数组并为每个位置 go.pyx
调用 get_board_feature
的函数
@cython.boundscheck(False)
@cython.wraparound(False)
cdef int get_board(self, GameState state, np.ndarray[double, ndim=2] tensor, int offSet ):
"""A feature encoding WHITE BLACK and EMPTY on separate planes, but plane 0
always refers to the current player and plane 1 to the opponent
"""
cdef short location
for location in range( 0, state.size * state.size ):
tensor[ offSet + state.get_board_feature( location ), location ] = 1
return offSet + 3
如果我应该包括任何其他信息或运行某些测试,请告诉我。
cmp, diff 测试
V2 go.c
和 preprocessing.c
文件是相同的。
V1 不生成 .c
文件来比较
更新比较 .so
个文件
V2 go.so
文件不同:
goD.so goL.so differ: byte 473, line 1
preprocessing.so
文件是相同的,不知道该怎么想..
它们是两台不同的机器,行为也不同。处理器评论使用大型基准套件是有原因的。可以说桌面 CPU 的平均性能更好,但是两个小但重要的代码片段之间的执行时间并不 'have' 有利于桌面 CPU。而且执行时间的差异绝对不必遵循任何线性关系。性能始终取决于大量因素。可能的解释包括但不限于台式机上较小的 L1 和 L2 缓存以及 Ivy Bridge 笔记本电脑和 Haswell 台式机之间向量指令集从 AVX 到 AVX2 的变化。
通常,在优化性能时集中精力使用好的算法并识别和消除瓶颈是个好主意。试图盯着不同机器之间的基准测试可能只会让人头疼。