Мониторинг хода параллельного вычисления в Mathematica
Я создаю большой ParallelTable
и хотел бы иметь некоторое представление о том, как происходит вычисление. Для непараллельной таблицы следующий код выполняет отличную работу:
counter = 1;
Timing[
Monitor[
Table[
counter++
, {n, 10^6}];
, ProgressIndicator[counter, {0, 10^6}]
]
]
с результатом {0.943512, Null}
. Однако для параллельного случая необходимо, чтобы counter
делился между ядрами:
counter = 1;
SetSharedVariable[counter];
Timing[
Monitor[
ParallelTable[
counter++
, {n, 10^4}];
, ProgressIndicator[counter, {0, 10^4}]
]
]
с результатом {6.33388, Null}
. Поскольку значение counter
должно передаваться между ядрами при каждом обновлении, удар производительности не является серьезным. Любые идеи о том, как получить представление о том, как происходит вычисление? Возможно, чтобы каждое ядро имело собственное значение для counter
и суммировало их с интервалами? Возможно, какой-то способ определить, какие элементы таблицы уже обработаны ядрами?
Ответы
Ответ 1
Вы почти ответили сами, когда сказали: "Возможно, чтобы каждое ядро имело свое значение для счетчика и суммировало их с интервалом?".
Попробуйте что-то вроде этого:
counter = 1;
SetSharedVariable[counter];
ParallelEvaluate[last = AbsoluteTime[]; localcounter = 1;]
Timing[Monitor[
ParallelTable[localcounter++;
If[AbsoluteTime[] - last > 1, last = AbsoluteTime[];
counter += localcounter; localcounter = 0;], {n, 10^6}];,
ProgressIndicator[counter, {0, 10^6}]]]
Обратите внимание, что это занимает больше времени, чем ваш первый случай с одним процессором, только потому, что он действительно что-то делает в цикле.
Вы можете изменить тест AbsoluteTime [] - last > 1 на нечто более частое, например AbsoluteTime [] - last > 0.1.
Ответ 2
Это трудно решить. Из руководства :
Если вы не используете общие переменные, выполняются параллельные оценки полностью независимы и не могут влиять друг на друга. Кроме того, любые побочные эффекты, такие как присвоения переменных, произойдет, поскольку часть оценок будет потеряна. Единственный эффект параллельная оценка заключается в том, что ее результат возвращается в конце.
Тем не менее, приблизительный индикатор прогресса может быть получен с использованием старого оператора Print
:
![enter image description here]()
Ответ 3
Другой подход заключается в том, чтобы поместить трассировку на LinkWrite и LinkRead и изменить их трассировочные сообщения, чтобы сделать некоторый полезный учет.
Сначала запустите несколько параллельных ядер:
LaunchKernels[]
Это создаст объекты ссылок для параллельных ядер.
Затем определите функцию init для счетчиков чтения и записи ссылок:
init[] := Map[(LinkWriteCounter[#] = 0; LinkReadCounter[#] = 0) &, Links[]]
Затем вы хотите увеличить эти счетчики, когда их ссылки читаются или записываются на:
Unprotect[Message];
Message[LinkWrite::trace, x_, y_] := LinkWriteCounter[x[[1, 1]]] += 1;
Message[LinkRead::trace, x_, y_] := LinkReadCounter[x[[1, 1]]] += 1;
Protect[Message];
Здесь x[[1,1]]
является объектом LinkObject.
Теперь включите трассировку на LinkWrite и LinkRead:
On[LinkWrite];
On[LinkRead];
Чтобы отформатировать индикатор выполнения, сначала немного сократите отображение LinkObject, так как они довольно подробные:
Format[LinkObject[k_, a_, b_]] := Kernel[a, b]
И это способ отображения динамических чтений и записи для ссылок на подъязык:
init[];
Dynamic[Grid[Join[
{{"Kernel", "Writes", "Reads"}},
Map[{#, LinkWriteCounter[#]/2, LinkReadCounter[#]/2} &,
Select[Links[], StringMatchQ[First[#], "*subkernel*"] &
]]], Frame -> All]]
(я деля счеты на два, потому что каждое чтение и запись ссылок прослеживается дважды).
И, наконец, протестируйте его с помощью таблицы из 10000 элементов:
init[];
ParallelTable[i, {i, 10^4}, Method -> "FinestGrained"];
Если все сработало, вы должны увидеть окончательное отображение прогресса с примерно 5000 чтением и записью для каждого ядра:
![Screen shot of the kernel session]()
Для этого есть средняя производительность: 10,73 с без монитора и 13,69 с монитором. И, конечно, использование опции "FinestGrained" - это не самый оптимальный метод для использования в этом конкретном параллельном вычислении.
Ответ 4
Вы можете получить некоторые идеи из пакета Spin`System`LoopControl`
, разработанного Юрием Кандрашкиным:
![screenshot from Spin Algebra home]()
Анонс пакета Spin`
:
Hi group,
I have prepared the package Spin` that consists of several applications
which are designed for research in the area of magnetic resonance and
spin chemistry and physics.
The applications Unit` and LoopControl` can be useful to a broader
audience.
The package and short outline is available at:
http://sites.google.com/site/spinalgebra/.
Sincerely,
Yuri Kandrashkin.