Phi*_*hil 23 arrays wolfram-mathematica
我在mathematica中主要是一个Table函数用户.但是我注意到在几个使用Array而不是Table来表示相同结果的例子中,它运行速度明显更快,尤其是随着表的维度变大.
所以我的问题是:当执行速度是主要问题时,何时最适合使用表?
是什么解释了这种差异
我的猜测是因为Arrays假设列表中的项目之间存在功能关系,它会更有效地存储它们,因此使用更少的内存,从而便于存储和后续处理?
它是怎么回事?
Sas*_*sha 12
Array没有性能优势Table.它们之间存在差异,这使得一个优先于另一个.
Table多维阵列的速度较慢.所有这些都使用变量来保存表大小.Table具有HoldAll属性并且仅自动评估最外层的交互绑定.因为内部迭代器仍未被评估,所以表的元素无法编译.With在自动编译中使用显式数字或结果:
In[2]:= With[{b = 10^4, c = 10^4},
{Timing@(#[[1, 1]] &[ar = Array[(# + #2) &, {b, c}]]) ,
Timing@(#[[1, 1]] &[ta = Table[(i + j), {i, b}, {j, c}]])}
]
Out[2]= {{4.93, 2}, {4.742, 2}}
In[3]:= Attributes[Table]
Out[3]= {HoldAll, Protected}
Run Code Online (Sandbox Code Playgroud)
Array让你丝毫不亚于构建函数值的数组Table.他们采取不同的论点.Array采取功能:
In[34]:= Array[Function[{i, j}, a[i, j]], {3, 3}]
Out[34]= {{a[1, 1], a[1, 2], a[1, 3]}, {a[2, 1], a[2, 2],
a[2, 3]}, {a[3, 1], a[3, 2], a[3, 3]}}
Run Code Online (Sandbox Code Playgroud)
而表采用明确的形式:
In[35]:= Table[a[i, j], {i, 3}, {j, 3}]
Out[35]= {{a[1, 1], a[1, 2], a[1, 3]}, {a[2, 1], a[2, 2],
a[2, 3]}, {a[3, 1], a[3, 2], a[3, 3]}}
Run Code Online (Sandbox Code Playgroud)
Array只能遍历常规数组,同时Table可以对列表进行任意迭代:
In[36]:= Table[a[i, j], {i, {2, 3, 5, 7, 11}}, {j, {13, 17, 19}}]
Out[36]= {{a[2, 13], a[2, 17], a[2, 19]}, {a[3, 13], a[3, 17],
a[3, 19]}, {a[5, 13], a[5, 17], a[5, 19]}, {a[7, 13], a[7, 17],
a[7, 19]}, {a[11, 13], a[11, 17], a[11, 19]}}
Run Code Online (Sandbox Code Playgroud)
有时Array可以更简洁.比较乘法表:
In[37]:= Array[Times, {5, 5}]
Out[37]= {{1, 2, 3, 4, 5}, {2, 4, 6, 8, 10}, {3, 6, 9, 12, 15}, {4, 8,
12, 16, 20}, {5, 10, 15, 20, 25}}
Run Code Online (Sandbox Code Playgroud)
与
In[38]:= Table[i j, {i, 5}, {j, 5}]
Out[38]= {{1, 2, 3, 4, 5}, {2, 4, 6, 8, 10}, {3, 6, 9, 12, 15}, {4, 8,
12, 16, 20}, {5, 10, 15, 20, 25}}
Run Code Online (Sandbox Code Playgroud)
Array 允许一个人用任何头部构建表达式,而不仅仅是列表:
In[39]:= Array[a, {3, 3}, {1, 1}, h]
Out[39]= h[h[a[1, 1], a[1, 2], a[1, 3]], h[a[2, 1], a[2, 2], a[2, 3]],
h[a[3, 1], a[3, 2], a[3, 3]]]
Run Code Online (Sandbox Code Playgroud)
默认情况下,h选择头部会List导致创建常规数组.表没有这种灵活性.
迈克尔·特洛特在编程(第707 - 710)地址之间的差异问题Array和Table并认为作为Table具有属性HoldAll就计算它的每一个调用的参数,而Array"尽可能"才刚刚开始计算它的参数.这可能会导致行为和速度的差异.
Attributes[Table]
Run Code Online (Sandbox Code Playgroud)
{HoldAll,Protected}
Attributes[Array]
Run Code Online (Sandbox Code Playgroud)
{}保护
Michael Trott使用以下示例来说明速度和行为的差异.我从他的书(光盘)中逐字逐句地接受它们.我希望我这样做不违反任何规则.
Remove[a, i, j];
a = 0;
Table[a = a + 1; ToExpression[StringJoin["a" <> ToString[a]]][i, j],
{i, 3}, {j, 3}]
Run Code Online (Sandbox Code Playgroud)
{{a1 [1,1],a2 [1,2],a3 [1,3]},{a4 [2,1],a5 [2,2],a6 [2,3]},{a7 [ 3,1],a8 [3,2],a9 [3,3]}}
a = 0;
Array[a = a + 1;
ToExpression[StringJoin["a" <> ToString[a]]], {3, 3}]
Run Code Online (Sandbox Code Playgroud)
{{a1 [1,1],a1 [1,2],a1 [1,3]},{a1 [2,1],a1 [2,2],a1 [2,3]},{a1 [ 3,1],a1 [3,2],a1 [3,3]}}
(注意行为上的差异)
为了说明预计算第一个参数的效果,他使用了以下示例(再次逐字,第709页).
o[a = 0;
Table[a = a + 1;
ToExpression[StringJoin["a" <> ToString[a]]][i, j],
{i, 3}, {j, 3}], {2000}] // Timing
Do[a = 0;
Array[a = a + 1; ToExpression[ StringJoin["a" <> ToString[a]]],
{3, 3}], {2000}] // Timing
Run Code Online (Sandbox Code Playgroud)
{0.700173,Null}
{0.102587,Null}
(我在Mac上使用mma7.我的编程副本使用v5.1.可能有更新)
当然,这不是编程中讨论Array和Table讨论的唯一区别.
我看到其他答案,我有兴趣了解其他人对这一点的看法.
一个原因Array可能更快,因为它经常更好地编译其第一个参数.
在Mathematica 7中:
In[1]:= SystemOptions[CompileOptions -> ArrayCompileLength]
Out[1]= {"CompileOptions" -> {"ArrayCompileLength" -> 250}}
Run Code Online (Sandbox Code Playgroud)
和
In[2]:= SystemOptions[CompileOptions -> TableCompileLength]
Out[2]= {"CompileOptions" -> {"TableCompileLength" -> 250}}
Run Code Online (Sandbox Code Playgroud)
所以可以推断出Array并且Table应该在同一点编译.
但是,让我们试一试.我将利用Timo的timeAvg功能:
n = 15;
Array[Mod[#^2, 5]*(1 + #2) &, {n, n}] // timeAvg
Table[Mod[i^2, 5]*(1 + j), {i, n}, {j, n}] // timeAvg
(* Out = 0.00034496 *)
(* Out = 0.00030016 *)
n = 16;
Array[Mod[#^2, 5]*(1 + #2) &, {n, n}] // timeAvg
Table[Mod[i^2, 5]*(1 + j), {i, n}, {j, n}] // timeAvg
(* Out = 0.000060032 *)
(* Out = 0.0005008 *)
Run Code Online (Sandbox Code Playgroud)
我们看到的是Array能够编译Mod[#^2, 5]*(1 + #2) &而Table无法编译Mod[i^2, 5]*(1 + j),因此Array在达到CompileLength时变得更快.许多功能都不那么有利.如果你只是在函数中将乘法更改为除法,这会导致有理而不是整数结果,那么这种自动编译不会发生,并且Table更快:
n = 15;
Array[Mod[#^2, 5]/(1 + #2) &, {n, n}] // timeAvg
Table[Mod[i^2, 5]/(1 + j), {i, n}, {j, n}] // timeAvg
(* Out = 0.000576 *)
(* Out = 0.00042496 *)
n = 16;
Array[Mod[#^2, 5]/(1 + #2) &, {n, n}] // timeAvg
Table[Mod[i^2, 5]/(1 + j), {i, n}, {j, n}] // timeAvg
(* Out = 0.0005744 *)
(* Out = 0.0004352 *)
Run Code Online (Sandbox Code Playgroud)
但是,如果我们也可以编译呢?如果我们使用浮点数,通过开始1.,我们得到Real输出,可以编译:
n = 15;
Array[Mod[#^2, 5]/(1 + #2) &, {n, n}, 1.] // timeAvg
Table[Mod[i^2, 5]/(1 + j), {i, 1., n}, {j, 1., n}] // timeAvg
(* Out = 0.0006256 *)
(* Out = 0.00047488 *)
n = 16;
Array[Mod[#^2, 5]/(1 + #2) &, {n, n}, 1.] // timeAvg
Table[Mod[i^2, 5]/(1 + j), {i, 1., n}, {j, 1., n}] // timeAvg
(* Out = 0.00010528 *)
(* Out = 0.00053472 *)
Run Code Online (Sandbox Code Playgroud)
再次,Array在更大尺寸的阵列上更快.
| 归档时间: |
|
| 查看次数: |
10073 次 |
| 最近记录: |