比较python factorial的性能(math与scipy)
为什么math.factorial比scipy.special.factorial快得多比较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:获取类型列表时需要一个整数
我使用的是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代码。这很公平。我想这是一场关于标量的毫无意义的辩论。