Подтвердить что ты не робот

Мониторинг хода параллельного вычисления в 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 и суммировало их с интервалами? Возможно, какой-то способ определить, какие элементы таблицы уже обработаны ядрами?

4b9b3361

Ответ 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.