Wolfram mathematica 计算匹配谓词的元素的最快方法
今天早些时候,我问Mathematica中是否有函数,因为我关心的是性能 我对给定谓词Wolfram mathematica 计算匹配谓词的元素的最快方法,wolfram-mathematica,Wolfram Mathematica,今天早些时候,我问Mathematica中是否有函数,因为我关心的是性能 我对给定谓词pred的初始方法如下: PredCount1[lst_, pred_] := Length@Select[lst, pred]; 我得到了一个建议,可以用 PredCount2[lst_, pred_] := Count[lst, x_/;pred@x]; 我开始分析这些函数,使用不同的lst大小和pred函数,并添加了另外两个定义: PredCount3[lst_, pred_] := Count[Th
pred
的初始方法如下:
PredCount1[lst_, pred_] := Length@Select[lst, pred];
我得到了一个建议,可以用
PredCount2[lst_, pred_] := Count[lst, x_/;pred@x];
我开始分析这些函数,使用不同的lst
大小和pred
函数,并添加了另外两个定义:
PredCount3[lst_, pred_] := Count[Thread@pred@lst, True];
PredCount4[lst_, pred_] := Total[If[pred@#, 1, 0] & /@ lst];
我的数据样本范围在100万到1000万个元素之间,我的测试函数是
EvenQ
,#,您可以看到自动编译的结果
首先,对于Listable
函数,例如EvenQ
和PrimeQ
不需要使用Thread
:
EvenQ[{1, 2, 3}]
这也解释了为什么PredCount3
在这些函数上表现良好。(它们经过内部优化,可在列表上执行线程操作。)
现在让我们看看时间安排
dat = RandomInteger[1*^6, 1*^6];
test = # < 5 &;
First@Timing[#[dat, test]] & /@ {PredCount1, PredCount2, PredCount3, PredCount4}
如果我们更改系统选项以防止在Map
中自动编译并再次运行测试:
SetSystemOptions["CompileOptions" -> {"MapCompileLength" -> Infinity}]
First@Timing[#[dat, test]] & /@ {PredCount1, PredCount2, PredCount3, PredCount4}
您可以清楚地看到,没有编译,PredCount4
的速度要慢得多。简而言之,如果您的测试函数可以由Mathematica编译,这是一个很好的选择
列表中整数的性质会对可实现的计时产生重大影响。如果整数的范围受到限制,则使用计数
可以提高性能
(* Count items in the list matching predicate, pred *)
PredCountID[lst_, pred_] :=
Select[Tally@lst, pred@First@# &]\[Transpose] // Last // Total
(* Define the values over which to check timings *)
ranges = {100, 1000, 10000, 100000, 1000000};
sizes = {100, 1000, 10000, 100000, 1000000, 10000000,100000000};
对于PrimeQ,此函数提供以下计时:
表明即使在一个10^8大小的列表中,如果素数来自{0,…,100000}的整数集合,并且如果它们在一个小范围内(如1到100),则小于计时的分辨率,则可以在不到十分之一秒的时间内计数素数
由于谓词只需应用于计数
值集,因此这种方法对精确的谓词函数相对不敏感。您使用的是计时[]还是绝对时间[]?请发布你的计时功能!您想对列表中包含的元素类型进行计数,实数/整数可能会有不同的执行方式。我使用//计时,列表是用Range@num,并包含整数。谢谢,这很有意义;我希望有一个简单的通用方法来做这件事,因为我肯定你同意PredCount4不是很直观。
SetSystemOptions["CompileOptions" -> {"MapCompileLength" -> Infinity}]
First@Timing[#[dat, test]] & /@ {PredCount1, PredCount2, PredCount3, PredCount4}
{0.343, 0.452, 0.234, 0.765}
(* Count items in the list matching predicate, pred *)
PredCountID[lst_, pred_] :=
Select[Tally@lst, pred@First@# &]\[Transpose] // Last // Total
(* Define the values over which to check timings *)
ranges = {100, 1000, 10000, 100000, 1000000};
sizes = {100, 1000, 10000, 100000, 1000000, 10000000,100000000};