Многие команды в Mathematica 8 ( Integrate
, Simplify
, и т. д.) похоже используют только одно ядро в моей системе. Есть ли способ изменить сродство так, чтобы оно использовало все ядра для вычислений?
решение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
и уменьшить 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!! *)
ОК, инициализируем пустой список для результатов интегрирования мономов
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]]