我正在尝试获取 cython 和 numpy 的 FLOPS 基准。为此我在 cython 中编写了一个程序。这是:
cimport numpy as np
import numpy as np
import time
cimport cython
@cython.boundscheck(False)
@cython.wraparound(False)
def numpybenchmark():
cdef np.ndarray[np.float64_t, ndim=2] m1 = np.random.rand(3,3)
cdef np.ndarray[np.float64_t, ndim=1] m2 = np.random.rand(3)
cdef np.ndarray[np.float64_t, ndim=1] res
cdef int niters = 10000000
cdef int x
t1 = time.time()
for x in range(niters):
res = np.dot(m1, m2)
t2 = time.time()
cdef double numopsperloop = 9. + 6.
cdef double totalops = numopsperloop * float(niters)
cdef double mflops = totalops / (t2-t1) / 1024. / 1024.
print 'Computed MFLops is: ' + str(mflops)
在我的机器上,我测量“计算的 MFLops 为:7.42390102416”。我的机器配备 Intel Core i7-6700HQ CPU @ 2.6 GHz,运行 Windows 10。
如果您想在您的计算机上运行它,请将代码保存在名为“benchmark.pyx”的文件中。然后创建一个名为“setup.py”的文件,其中包含以下内容:
from distutils.core import setup
from Cython.Build import cythonize
import numpy
setup(
ext_modules = cythonize("benchmark.pyx"),
include_dirs=[numpy.get_include()]
)
然后你应该能够使用“python setup.py build_ext --inplace”来编译它。在 Windows 上,这可能会有点困难,因为我遇到了可怕的“无法找到 vcvarsall.bat”错误,并且不得不花费大量精力来解决该问题。
这个性能对我来说似乎很差。我想知道是否有人可以在他们的平台上运行它并告诉我你会得到什么?或者指出我的代码中出现的任何对性能产生不利影响的明显错误?
谢谢!
最佳答案
Cython 实际上并没有消除 np.dot
上的任何 Python 调用开销。这涉及(请注意,该列表并不详尽,并且在某些地方可能略有错误,但它给出了要点):
找到要调用的
np.dot
:- 在全局命名空间中查找
np
- 在
np
的命名空间中查找dot
的字典。 (请注意,通过在函数内执行dot = np.dot
,然后调用dot
可以消除上述所有内容) - 在
dot
上查找__call__
。 (如果 dot 是 C/Fortran 编译函数,则可以通过更快的机制来完成)
- 在全局命名空间中查找
打包为
np.dot
准备参数:- 创建一个元组,其中包含传递给
np.dot
的两个参数 - 增加每个参数的引用计数。
- 创建一个元组,其中包含传递给
np.dot
然后处理参数...- 解压元组
- 检查 numpy 数组中的每个参数。
- 检查每个 numpy 数组的
dtype
是否相同,并根据dtype
选择要调用的 BLAS 函数。 - 检查数组维度并确保它们匹配。
...为输出参数分配空间...
- 分配一个新的
np.ndarray
对象 - 增加该引用计数
- 为
ndarray
中的物理数组分配空间
- 分配一个新的
...调用 BLAS 运算,为您提供浮点运算...
...并减少所传递的输入参数的引用计数(检查是否应该释放任何参数,尽管不会)
您的调用函数必须:
- 检查
np.dot
是否引发异常 - 接收输出数组(这里可能有一些引用计数杂耍)
- 减少
res 之前内容的引用计数
- 释放
res
之前的内容,请记住,这至少是一个 2 步过程,因为该数组与ndarray
持有者分开保存。
- 检查
如果您想让其中的大部分内容(可能除了分配)与矩阵向量乘法相比变得微不足道,那么您需要在更大的数组上进行测量。您可以使用 np.dot
中的 out
可选参数来取消分配。如果您想让这一切消失,那么您可以使用 scipy Cython BLAS interface直接调用BLAS函数。
关于python - Cython 性能基准,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35347466/