比较python factorial的性能(math与scipy)

比较python factorial的性能(math与scipy),python,factorial,Python,Factorial,为什么math.factorial比scipy.special.factorial快得多 我使用的是Python 3.7 scipy版本是1.1.0这是一个常见的错误,类似于期望np.exp之类的东西比数学模块工作得更快。这不是这些职能的目的。科学堆栈NumPy、Pandas、SciPy和其他人关注的是跨数组的矢量化方法,而不是单个值 from math import factorial factorial([20, 20, 20]) 这将给出TypeError:获取类型列表时需要一个整数

为什么math.factorial比scipy.special.factorial快得多


我使用的是Python 3.7 scipy版本是1.1.0这是一个常见的错误,类似于期望np.exp之类的东西比数学模块工作得更快。这不是这些职能的目的。科学堆栈NumPy、Pandas、SciPy和其他人关注的是跨数组的矢量化方法,而不是单个值

from math import factorial

factorial([20, 20, 20])
这将给出TypeError:获取类型列表时需要一个整数

但是:

将计算整个列表的阶乘,给出:

array([2.43290201e+18, 2.43290201e+18, 2.43290201e+18])

如果您将math.factorial计算放入for循环以覆盖列表中的多个项目,它将很快在计时方面落后于矢量化方法,如果您首先提供NumPy数组而不是列表,则矢量化方法会更快这是一个常见错误,类似于期望像np.exp这样的东西比数学模块工作得更快。这不是这些职能的目的。科学堆栈NumPy、Pandas、SciPy和其他人关注的是跨数组的矢量化方法,而不是单个值

from math import factorial

factorial([20, 20, 20])
这将给出TypeError:获取类型列表时需要一个整数

但是:

将计算整个列表的阶乘,给出:

array([2.43290201e+18, 2.43290201e+18, 2.43290201e+18])
如果将math.factorial计算放入for循环以覆盖列表中的多个项,与矢量化方法相比,它在计时方面会很快落后,如果您首先提供一个NumPy数组而不是一个列表,那么矢量化方法会更快

当exact=True时,scipy函数实际上只是充当math.factorial的包装器,请参见…因此我猜额外的时间只是参数检查的开销逻辑和额外的函数调用

当exact=False或未指定时,您使用的是近似值,这将比n的小值的精确计算慢。

当exact=True时,scipy函数实际上只是充当数学的包装器。factorial请参见……因此我猜额外的时间只是参数检查逻辑和额外函数调用的开销

当exact=False或未指定时,您使用的是近似值,这将比精确计算小值n要慢。

math.factorial是python内置函数,它不会编译为python字节码,实际上是在执行c代码

您可以在其他函数中看到类似的行为,例如numpy cos/sin等。

math.factorial是一个python内置函数,它不会编译为python字节码,实际上是在执行c代码


您可以在其他函数中看到类似的行为,如numpy cos/sin等。

除了前面提到的有关scipy目标向量化输入的事实之外,您在这里使用了一个非常小的测试用例-如果您扩展它,它将不那么清楚:

import timeit

for z in range(20,100000,10000):
    t1 = timeit.timeit(f"from math import factorial; factorial({z})",number=10)
    t2 = timeit.timeit(f"from scipy.special import factorial; factorial({z})",number=10)
    t3 = timeit.timeit(f"from scipy.special import factorial; factorial({z}, exact=True)",number=10)
    print(f"{z}  : {t1:<20}  {t2:<20}  {t3:<20}")
通过使用更大范围的输入,您可以看到它并不总是更快

如果做计时,总是考虑少量和大量的数据与正常量


*返回z>170的inf-因此没有认真计算它,而且计时也有偏差

除了已经提到的关于scipy目标向量化输入的事实之外-您在这里使用了一个非常小的测试用例-如果您扩大它,它将不那么清楚:

import timeit

for z in range(20,100000,10000):
    t1 = timeit.timeit(f"from math import factorial; factorial({z})",number=10)
    t2 = timeit.timeit(f"from scipy.special import factorial; factorial({z})",number=10)
    t3 = timeit.timeit(f"from scipy.special import factorial; factorial({z}, exact=True)",number=10)
    print(f"{z}  : {t1:<20}  {t2:<20}  {t3:<20}")
通过使用更大范围的输入,您可以看到它并不总是更快

如果做计时,总是考虑少量和大量的数据与正常量


*返回z>170的inf-因此不认真计算它,并且计时有偏差

这没有意义。OP观察到math.factorial的工作速度比SciPy等价物快。这正是应该发生的事情,而SciPy等价物编译成字节码并执行得更慢,math.factorial只调用c函数,速度更快。不,SciPy将把计算降到编译的c代码中。问题是这样做会有一些开销。这个函数从来就不应该在scalars上调用。我不知道你在争论什么,我们说的是同一件事。SciPy调用有开销,它编译成python字节码并执行。factorial math.factorial没有任何开销,甚至没有将其编译成字节码,并立即执行c代码。我想这是一场关于标量的毫无意义的辩论。这毫无意义。OP观察到math.factorial的工作速度比SciPy等价物快。这正是应该发生的事情,而SciPy等价物编译成字节码并执行得更慢,math.factorial只调用c函数,速度更快。不,SciPy将把计算降到编译的c代码中。问题是这样做会有一些开销。这个函数从来就不应该在scalars上调用。我不知道你在争论什么,我们说的是同一件事。SciPy调用有开销,它编译成python字节码并执行。并且比ma有更多的功能
factorial math.factorial完全没有开销,甚至不需要将其编译成字节码,并立即执行c代码。这很公平。我想这是一场关于标量的毫无意义的辩论。