GNU/Linux >> Znalost Linux >  >> Linux

Jak zajistit, aby příkazy v Mathematice 8 využívaly všechna jádra?

Z dokumentace Parallelize v části Příklady> Možné problémy:

Výrazy, které nelze paralelizovat, jsou vyhodnoceny normálně:

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


Jak bylo zmíněno v ostatních otázkách a komentářích, věci jako Integrate a Simplify by bylo opravdu obtížné paralelizovat, takže Mathematica vrací zprávu Parallelize::nopar1 a pokračuje "se sekvenčním vyhodnocením."

(Ačkoli při zamyšlení, možná FullSimplify lze paralelizovat, protože v zásadě funguje tak, že zkouší spoustu různých pravidel a provádí na nich počty listů...)

Pokud musíte udělat mnoho integrálů nebo zjednodušení, můžete použít ParallelTable nebo ParallelMap atd...

Jako triviální příklad, pokud máte integrandy

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}

Můžete použít 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}

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

Je zřejmé, že pro malé seznamy integrálů, jako jsou výše uvedené, je režie paralelizace pravděpodobně větší než přínos. Ale pokud máte opravdu velké seznamy a komplexní integrály, pak to pravděpodobně stojí za to.

Upravit v reakci na komentáře

Vzhledem k opravdu chaotickému integrandu, o který se OP zajímá (poznámka:své výsledky byste měli skutečně zjednodušit za pochodu!), zde je nějaký kód, který rozdělí integrál na součet monočlenů a provede integrály pomocí ParallelDo .

Nejprve importujeme integrál z pastebin

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

extrahovat integrační doménu

In[2]:= intLimits = [email protected](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}}

a integrand, který je součtem 21 monstrózních výrazů

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

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

Musíme ten strašný nepořádek rozdělit na malé kousky. Nejprve z integrálu extrahujeme všechny různé funkce

In[7]:= (fns=Union[vars, Cases[integrand, (Cos|Sin|Tan|Sec|Csc|Cot)[x_]/;!FreeQ[x,[email protected]@vars],Infinity]])//Timing
Out[7]= {0.1,{\[Theta]1, <snip> ,Tan[\[CurlyPhi]2]}}

Najdeme (13849 nemizejících) koeficientů monočlenů sestrojených z fns

In[8]:= coef = CoefficientRules[integrand, fns]; // Timing
         [email protected]

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

Zkontrolujte, zda všechny koeficienty neobsahují žádné integrační proměnné

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

Všimněte si, že můžeme skutečně vyčistit koeficienty pomocí Factor nebo Simplify a snižte ByteSize asi 5krát...Ale protože integrály většiny monočlenů jsou nulové, můžeme si zjednodušení nechat až na úplný konec.

Takto rekonstruujete monočlen, integrujete jej a rekombinujete s jeho koeficientem, například 40. monočlen dává neústupný integrál:

In[11]:= monomialNum=40;
         [email protected]@(fns^coef[[monomialNum,1]])
         Integrate[%, [email protected]@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))

Prozatím snížím počet členů, protože provedení všech integrálů na mém dvoujádrovém notebooku by trvalo věčnost. Pokud chcete vyhodnotit celou sadu integrálů, smažte nebo zakomentujte následující řádek

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

OK, inicializujte prázdný seznam pro výsledky monomiální integrace

In[16]:= SetSharedVariable[ints]
         ints = ConstantArray[Null, [email protected]];

Při provádění integrálů jsme Print outnum:{časování, výsledek} pro každý integrovaný jednočlen. CellLabel každé vytištěné buňky vám řekne, které jádro provedlo integraci. Tisk může být otravný – pokud vás obtěžuje, nahraďte Print s PrintTempory nebo ##& .Výpočet můžete také sledovat pomocí nějaké dynamické proměnné:např. ukazatel průběhu.

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

Kombinujte s jejich koeficienty

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

A (doufejme) to je ono!


Linux
  1. Jak používat příkazy historie Bash

  2. Jak používat manuální stránky, abyste se naučili používat příkazy?

  3. Jak zajistit, aby Skype používal Notify-osd?

  1. Jak přimět Startx používat alternativní Xinitrc?

  2. Jak používat příkazy Grep na Linuxu nebo FreeBSD

  3. Jak auditovat všechny příkazy spuštěné na OEL 5,6 pomocí auditd

  1. Jak používat příkazy a možnosti SFTP

  2. Jak používat příkaz mkdir k vytvoření nebo vytvoření adresáře Linux

  3. Jak používat příkazy strace a ltrace v Linuxu