Mathematica 8 のコマンドですべてのコアを使用するにはどうすればよいでしょうか?

Mathematica 8 のコマンドですべてのコアを使用するにはどうすればよいでしょうか?

Mathematica 8 の多くのコマンド ( IntegrateSimplifyなど) は、システム上で 1 つのコアしか使用していないようです。計算にすべてのコアが使用されるようにアフィニティを変更する方法はありますか?

答え1

他の質問やコメントで述べたように、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}

使用できます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またはを使用して係数をクリーンアップしSimplify、 を約 5 倍減らすことができることに注意してくださいByteSize...ただし、ほとんどの単項式の積分はゼロなので、単純化は最後まで残しておいたほうがよいでしょう。

これは、単項式を再構築し、積分してその係数と再結合する方法です。たとえば、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数値: {タイミング、結果} 積分された各単項式について。CellLabel各印刷されたセルの は、どのコアが積分を行ったかを示します。印刷が煩わしい場合は、またはPrintに置き換えてください。また、何らかの動的変数を使用して計算を監視することもできます。たとえば、PrintTempory##&プログレスバー

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

ここに画像の説明を入力してください

関連情報