如何讓 Mathematica 8 中的指令使用所有核心?

如何讓 Mathematica 8 中的指令使用所有核心?

Mathematica 8 中的許多指令(IntegrateSimplify等)似乎只在我的系統上使用單一核心。有什麼方法可以改變親和力,以便它利用所有核心進行計算?

答案1

正如其他問題和評論中提到的,類似Integrate和的事情Simplify確實很難並行化,因此 Mathematica 返回訊息Parallelize::nopar1並繼續「進行順序評估」。

(儘管經過反思,也許FullSimplify可以並行化,因為它基本上通過嘗試許多不同的規則並對它們進行葉子計數來工作...)

如果你有很多積分或簡化要做,那麼你可以使用ParallelTableParallelMap等等...

舉一個簡單的例子,如果你有被積函數

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}

您可以使用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}

或者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}

顯然,對於像上面這樣的小積分列表,並行化開銷可能大於收益。但如果你有非常大的列表和複雜的積分,那麼它可能是值得的。


編輯回應評論

考慮到OP感興趣的真正混亂的被積函數(注意:你應該真正簡化你的結果!),這裡有一些程式碼將積分分解為單項式和並使用執行積分ParallelDo

首先我們從pastebin導入積分

In[1]:= import = Import["http://pastebin.com/raw.php?i=JZ0CXewJ", "Text"];

提取積分域

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}}

以及被積函數,它是 21 個龐大項的總和

In[4]:= integrand = First@(2 Pi^5 ToExpression[StringReplace[import, "Integrate" -> "Hold"]]);
        Length[integrand]
        LeafCount[integrand]

Out[5]= 21
Out[6]= 48111

我們需要將可怕的混亂分解成一口大小的塊。首先,我們從積分中提取所有不同的函數

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]}}

我們發現單項式的(13849 個非零)係數由fns

In[8]:= coef = CoefficientRules[integrand, fns]; // Timing
         Length@coef

Out[8]= {35.63, Null}
Out[9]= 13849

檢查所有係數是否不含任何積分變數

In[10]:= FreeQ[coef[[All, 2]], Alternatives@@vars]
Out[10]= True

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))

現在我將減少項數,因為在我的雙核心筆記型電腦上完成所有積分將花費很長時間。當您想要計算整組積分時,刪除或註解掉以下行

In[15]:= coef = RandomChoice[coef, 100];  (* Delete me!! *)

OK,為單項積分結果初始化一個空列表

In[16]:= SetSharedVariable[ints]
         ints = ConstantArray[Null, Length@coef];

當我們執行積分時,我們Print得到 num: {時間,結果} 對於每個單項式積分。每個CellLabel列印單元的 都會告訴您哪個核心進行了積分。列印可能會很煩人 - 如果它確實讓您煩惱,請替換PrintPrintTempory##&。您也可以使用某種動態變數來監視計算:例如進度條

ParallelDo[Print[c, ": ", Timing[
            ints[[c]] = Integrate[Times@@(fns^coef[[c,1]]), Sequence@@intLimits]]], 
           {c, Length@coef}]

結合它們的係數

1/(2 Pi^5) Simplify[ints.coef[[All, 2]]]

(希望)就是這樣!

答案2

來自並行化文檔,在範例 > 可能的問題下:

無法並行化的表達式會正常計算:

Parallelize[Integrate[1/(x - 1), x]]

在此輸入影像描述

相關內容