der*_*ack 6 linux multi-core mathematica
Mathematica 8 中的许多命令(Integrate
、Simplify
等)似乎只在我的系统上使用单个内核。有什么方法可以改变亲和力,以便它利用所有核心进行计算?
正如其他问题和评论中提到的,类似Integrate
和 的事情Simplify
确实很难并行化,因此 Mathematica 返回消息Parallelize::nopar1
并继续“进行顺序评估”。
(尽管经过反思,也许FullSimplify
可以并行化,因为它基本上是通过尝试许多不同的规则并对它们进行叶计数来工作的......)
如果你有很多积分或简化要做,那么你可以使用ParallelTable
或ParallelMap
等等......
举一个简单的例子,如果你有被积函数
In[1]:= ints = Table[x^n, {n, 1, 10}]
Out[1]= {x, x^2, x^3, x^4, x^5, x^6, x^7, x^8, x^9, x^10}
Run Code Online (Sandbox Code Playgroud)
您可以使用ParallelTable
In[2]:= ParallelTable[Integrate[int, x], {int, ints}]
Out[2]= {x^2/2, x^3/3, x^4/4, x^5/5, x^6/6, x^7/7, x^8/8,\
x^9/9, x^10/10, x^11/11}
Run Code Online (Sandbox Code Playgroud)
或者ParallelMap
In[3]:= ParallelMap[Integrate[#, x] &, ints]
Out[3]= {x^2/2, x^3/3, x^4/4, x^5/5, x^6/6, x^7/7, x^8/8,\
x^9/9, x^10/10, x^11/11}
Run Code Online (Sandbox Code Playgroud)
显然,对于像上面这样的小积分列表,并行化开销可能大于收益。但如果你有非常大的列表和复杂的积分,那么它可能是值得的。
考虑到OP感兴趣的真正混乱的被积函数(注意:你应该真正简化你的结果!),这里有一些代码将积分分解为单项式和并使用执行积分ParallelDo
。
首先我们从pastebin导入积分
In[1]:= import = Import["http://pastebin.com/raw.php?i=JZ0CXewJ", "Text"];
Run Code Online (Sandbox Code Playgroud)
提取积分域
In[2]:= intLimits = Rest@(2 Pi^5 ToExpression[StringReplace[import, "Integrate" -> "List"]])
vars = intLimits[[All, 1]];
Out[2]= {{\[Theta]3, 0, 2*Pi}, {\[Theta]2, 0, 2*Pi},
{\[Theta]1, 0, 2*Pi}, {\[CurlyPhi]2, 0, Pi/2}, {\[CurlyPhi]1, 0, Pi/2}}
Run Code Online (Sandbox Code Playgroud)
以及被积函数,它是 21 个庞大项的总和
In[4]:= integrand = First@(2 Pi^5 ToExpression[StringReplace[import, "Integrate" -> "Hold"]]);
Length[integrand]
LeafCount[integrand]
Out[5]= 21
Out[6]= 48111
Run Code Online (Sandbox Code Playgroud)
我们需要将可怕的混乱分解成一口大小的块。首先,我们从积分中提取所有不同的函数
In[7]:= (fns=Union[vars, Cases[integrand, (Cos|Sin|Tan|Sec|Csc|Cot)[x_]/;!FreeQ[x,Alternatives@@vars],Infinity]])//Timing
Out[7]= {0.1,{\[Theta]1, <snip> ,Tan[\[CurlyPhi]2]}}
Run Code Online (Sandbox Code Playgroud)
我们发现单项式的(13849 个非零)系数由fns
In[8]:= coef = CoefficientRules[integrand, fns]; // Timing
Length@coef
Out[8]= {35.63, Null}
Out[9]= 13849
Run Code Online (Sandbox Code Playgroud)
检查所有系数是否不含任何积分变量
In[10]:= FreeQ[coef[[All, 2]], Alternatives@@vars]
Out[10]= True
Run Code Online (Sandbox Code Playgroud)
Factor
请注意,我们实际上可以使用or清理系数Simplify
并将 减少ByteSize
约 5 倍...但是由于大多数单项式的积分为零,我们不妨将简化留到最后。
这就是重建单项式、对其进行积分并与其系数重新组合的方法,例如,第 40 个单项式给出一个非零积分:
In[11]:= monomialNum=40;
Times@@(fns^coef[[monomialNum,1]])
Integrate[%, Sequence@@intLimits]
coef[[monomialNum,2]] %//Factor
Out[12]= \[Theta]1 Cos[\[Theta]1]^2 Cos[\[CurlyPhi]1]^4 Cos[4 \[CurlyPhi]1] Cos[\[CurlyPhi]2]^4 Cos[2 \[CurlyPhi]2] Sin[\[Theta]1]^2
Out[13]= \[Pi]^6/256
Out[14]= -((k1^2 (k1-k2) (k1+k2) (-2+p) p^3 \[Pi]^6 \[Sigma]^4)/(131072 \[Omega]1))
Run Code Online (Sandbox Code Playgroud)
现在我将减少项数,因为在我的双核笔记本电脑上完成所有积分将花费很长时间。当您想要计算整组积分时,删除或注释掉以下行
In[15]:= coef = RandomChoice[coef, 100]; (* Delete me!! *)
Run Code Online (Sandbox Code Playgroud)
OK,为单项积分结果初始化一个空列表
In[16]:= SetSharedVariable[ints]
ints = ConstantArray[Null, Length@coef];
Run Code Online (Sandbox Code Playgroud)
当我们执行积分时,我们会
为每个单项式积分Print
得出
num: {timing, result} 。每个打印单元的都会CellLabel
告诉您哪个核心进行了积分。打印可能会很烦人 - 如果它确实让您烦恼,请替换Print
为PrintTempory
或##&
。您还可以使用某种动态变量来监视计算:例如进度条。
ParallelDo[Print[c, ": ", Timing[
ints[[c]] = Integrate[Times@@(fns^coef[[c,1]]), Sequence@@intLimits]]],
{c, Length@coef}]
Run Code Online (Sandbox Code Playgroud)
结合它们的系数
1/(2 Pi^5) Simplify[ints.coef[[All, 2]]]
Run Code Online (Sandbox Code Playgroud)
(希望)就是这样!
归档时间: |
|
查看次数: |
9702 次 |
最近记录: |