为什么Mathematica中这些例程的相对效率?

时间:2011-10-14 19:00:19

标签: performance algorithm math optimization wolfram-mathematica

Daniel Lichtblau pointed out以两种方式得出素因子数(PrimeOmega)与不同素因子数({{1}之间的差异的时间差异让我感到惊讶一个整数,n。所以我决定再深入研究一下。

以下函数PrimeNug1是使用ones丹尼尔以及其他三个的略微变化。它们都返回从1到n的无平方整数的数量。但差异相当大。任何人都可以解释差异背后的原因。特别是,为什么g2 Sum提供了这样的速度优势?

g5

比较:

g1[n_] := Count[PrimeOmega[Range[n]] - PrimeNu[Range[n]], 0]

g2[n_] := Count[With[{fax = FactorInteger[#]}, 
 Total[fax[[All, 2]]] - Length[fax]] & /@ Range[n], 0]

g3[n_] := Count[SquareFreeQ/@ Range[n], True]

(* g3[n_] := Count[SquareFreeQ[#] & /@ Range[n], True] Mr.Wizard's suggestion
   incorporated above. Better written but no significant increase in speed. *) 

g4[n_] := n - Count[MoebiusMu[Range[n]], 0]

g5[n_] := Sum[MoebiusMu[d]*Floor[(n - 1)/d^2], {d, 1, Sqrt[n - 1]}]  

结果:

n = 2^20;
Timing[g1[n]]
Timing[g2[n]]
Timing[g3[n]]
Timing[g4[n]]
Timing[g5[n]]

修改

Mysticial提出了后一种惯例正在获得订单收益的可能性 - 一些缓存可能一直在进行。

所以让我们按相反的顺序运行比较:

{44.5867, 637461}
{11.4228, 637461}
{4.43416, 637461}
{1.00392, 637461}
{0.004478, 637461}

反向比较的结果:

n = 2^20;
Timing[g5[n]]
Timing[g4[n]]
Timing[g3[n]]
Timing[g2[n]]
Timing[g1[n]]

结论:合理的猜测,但数据不支持。

1 个答案:

答案 0 :(得分:8)

ModebiusMu对于小数字有一些专用的快速筛分代码,实际上是快捷方式实际分解,只是在找到因子时计算。它不会添加像PrimeOmega这样的指数,因此它确实没有任务。每当它检测到具有多重性的素因子时,它也会短路。

我认为截止时间恰好在2 ^ 20左右。没有时间进行测试,但确实可能会慢一些。

g4的答案。显然g5正在使用程序员的聪明才智(当然没有错),因此速度提升。

至于g3,它实质上是在实现代码方面对g4的调用。在这种情况下,瓶颈是预处理开销,因为它是用mathematica而不是C代码实现的。我怀疑如果使用更大的输入,这将不太明显,因为在这种情况下,花费更多的时间来完成实际工作而不是Mathematica解释器开销。我再次测试过这个。