我有时间计算以下语句需要多长时间(其中V [x]是一个耗时的函数调用):
Alice = Table[V[i],{i,1,300},{1000}]; Bob = Table[Table[V[i],{i,1,300}],{1000}]^tr; Chris_pre = Table[V[i],{i,1,300}]; Chris = Table[Chris_pre,{1000}]^tr;
爱丽丝,鲍勃和克里斯是相同的基质,计算3种略有不同的方式.我发现Chris的计算速度比Alice和Bob快1000倍.
Alice计算速度慢1000倍并不奇怪,因为天真地,函数V必须比计算Chris时多被调用1000次.但令人非常惊讶的是,Bob的速度非常慢,因为除了Chris存储中间步骤Chris_pre之外,他的计算方式与Chris完全相同.
鲍勃为什么评价这么慢?
第二个问题
假设我想在表单的Mathematica中编译一个函数
f(x)=x+y
其中“y”是在编译时固定的常量(但我不希望在代码中直接替换它的数字,因为我希望能够轻松地更改它).如果y的实际值是y = 7.3,我定义
f1=Compile[{x},x+y] f2=Compile[{x},x+7.3]
然后f1比f2慢50%.当编译f1时,如何使Mathematica将“y”替换为“7.3”,以便f1以f2的速度运行?
编辑:
我找到了第二个问题的一个丑陋的解决方法:
f1=ReleaseHold[Hold[Compile[{x},x+z]]/.{z->y}]
肯定有更好的办法…
您可能应该将这些问题作为单独的问题发布,但不用担心!问题一
Alice的问题当然是你的期望. Bob的问题是每次外部表的迭代都会评估内部表一次. Trace清晰可见:
Trace[Table[Table[i, {i, 1, 3}], {3}]] { Table[Table[i,{i,1,2}],{2}], {Table[i,{i,1,2}],{i,1},{i,2},{1,2}},{Table[i,{i,1,2}],{i,1},{i,2},{1,2}}, {{1,2},{1,2}} }
添加了换行符以强调,是的,Trace on Table的输出有点奇怪,但你可以看到它.很明显,Mathematica可以更好地优化它,因为知道外部表没有迭代器,但无论出于何种原因,它都没有考虑到这一点.只有克里斯做你想要的,尽管你可以修改鲍勃:
Transpose[Table[Evaluate[Table[V[i],{i,1,300}]],{1000}]]
这看起来实际上比Chris大约两倍左右,因为它不必存储中间结果.
问题二
使用Evaluate有一个更简单的解决方案,但我希望它不适用于所有可能编译的函数(即真正应该被保存的函数):
f1 = Compile[{x}, Evaluate[x + y]];
您还可以使用With:
With[{y=7.3}, f1 = Compile[{x}, x + y]; ]
或者,如果y在其他地方定义,请使用临时:
y = 7.3; With[{z = y}, f1 = Compile[{x}, x + z]; ]
我不是Mathematica的范围和评估机制的专家,所以可以很容易地有一个更好的方法,但希望其中一个为你做到!