Como fazer comandos no Mathematica 8 usar todos os núcleos?

5

Muitos comandos do Mathematica 8 ( Integrate , Simplify , etc.) parecem estar usando apenas um único núcleo no meu sistema. Existe alguma maneira que eu possa mudar a afinidade para que ele utilize todos os núcleos para cálculos?

    
por derdack 26.07.2011 / 18:02

2 respostas

3

Como mencionado em outras perguntas e comentários, coisas como Integrate e Simplify seriam realmente difíceis de paralelizar, então o Mathematica retorna a mensagem Parallelize::nopar1 e prossegue "com avaliação sequencial".

(Apesar de refletir, talvez FullSimplify possa ser paralelizado, já que basicamente funciona tentando várias regras diferentes e fazendo contagens nelas ...)

Se você tem muitas integrações ou simplificações para fazer, então você pode usar ParallelTable ou ParallelMap etc ...

Como um exemplo trivial, se você tem os integrandos

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}

Você pode usar 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}

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

Obviamente, para pequenas listas de integrais como as descritas acima, a sobrecarga de paralelização é provavelmente maior que o benefício. Mas se você tem listas realmente grandes e integrais complexas, provavelmente vale a pena.

Editar em resposta a comentários

Dada a integração realmente confusa com a qual o OP está interessado (nota: você deve realmente simplificar seus resultados à medida que avança!), aqui está um código que divide a integral em uma soma de monômios e executa as integrais usando ParallelDo .

Primeiro, importamos a integral do pastebin

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

extraia o domínio de integração

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

e o integrando, que vem como a soma de 21 termos monstruosos

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

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

Precisamos quebrar a bagunça horrível em pedaços menores. Primeiro nós extraímos todas as diferentes funções da integral

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

Encontramos os coeficientes (não-expansivos) de 13849 de monômios construídos a partir de fns

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

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

Verifique se todos os coeficientes estão livres de quaisquer variáveis de integração

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

Note que podemos realmente limpar os coeficientes usando Factor ou Simplify e diminuir o ByteSize em cerca de 5 vezes ... Mas como as integrais da maioria dos monômios são zero, poderíamos deixar simplificações até o final.

É assim que você reconstrói um monômio, integra-o e recombina com seu coeficiente, por exemplo, o monomial 40 dá uma integral não-evanescente:

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

Por enquanto, vou reduzir o número de termos, pois levaria uma eternidade para fazer todas as integrais no meu laptop de dois núcleos. Exclua ou comente a seguinte linha quando quiser avaliar todo o conjunto de integrais

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

OK, inicialize uma lista vazia para os resultados da integração monomial

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

À medida que executamos as integrais, nós Print out num: {timing, resultado} para cada monomial integrado. O CellLabel de cada célula impressa informa qual núcleo fez a integral. A impressão pode ficar irritante - se isso te incomoda, em seguida, substitua Print por PrintTempory ou ##& . Você também pode monitorar o cálculo usando uma variável dinâmica de algum tipo: por exemplo, uma barra de progresso .

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

Combine com seus coeficientes

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

E (espero) é isso!

    
por 27.07.2011 / 02:24
4

No Paralelizar a doação , em Exemplos > Problemas possíveis:

Expressions that cannot be parallelized are evaluated normally:

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

enter image description here

    
por 26.07.2011 / 18:21