В этом примере показано, как профилировать параллельный код с помощью параллельного профилировщика на рабочих в параллельном пуле.
Создайте параллельный пул.
numberOfWorkers = 3; pool = parpool(numberOfWorkers);
Starting parallel pool (parpool) using the 'local' profile ... Connected to the parallel pool (number of workers: 3).
Соберите параллельные данные о профиле путем включения mpiprofile.
mpiprofile on
Запустите свой параллельный код. В целях этого примера используйте простой parfor
цикл, который выполняет итерации по серии значений.
values = [5 12 13 1 12 5]; tic; parfor idx = 1:numel(values) u = rand(values(idx)*3e4,1); out(idx) = max(conv(u,u)); end toc
Elapsed time is 31.228931 seconds.
После того, как код завершается, просмотрите результаты параллельного профилировщика путем вызова mpiprofile viewer
. Это действие также останавливает сбор данных профиля.
mpiprofile viewer
Отчет показывает информацию о времени выполнения для каждой функции, которая работает на рабочих. Можно исследовать, какие функции занимают большую часть времени в каждом рабочем.
Обычно сравнение рабочих с минимальными и максимальными общими временами выполнения полезно. Для этого нажмите Compare (макс. по сравнению с min TotalTime) в отчете. В этом примере наблюдайте тот conv
выполняется многократно и берет значительно дольше в одном рабочем, чем в другом. Это наблюдение предполагает, что загрузка не может быть распределена равномерно на рабочих.
Если вы не знаете рабочую нагрузку каждой итерации, то хорошая практика должна рандомизировать итерации, такой как в следующем примере кода.
values = values(randperm(numel(values)));
Если вы действительно знаете рабочую нагрузку каждой итерации в вашем parfor
цикл, затем можно использовать parforOptions
управлять разделением итераций в подобласти значений для рабочих. Для получения дополнительной информации смотрите parforOptions
.
В этом примере, большем values(idx)
более в вычислительном отношении интенсивен, итерация. Каждая последовательная пара значений в values
балансы низкая и высокая вычислительная интенсивность. Чтобы распределить рабочую нагрузку лучше, создайте набор parfor
опции, чтобы разделить parfor
итерации в подобласти значений размера 2
.
opts = parforOptions(pool,"RangePartitionMethod","fixed","SubrangeSize",2);
Включите параллельному профилировщику.
mpiprofile on
Запустите тот же код как прежде. Использовать parfor
опции, передайте их второму входному параметру parfor
.
values = [5 12 13 1 12 5]; tic; parfor (idx = 1:numel(values),opts) u = rand(values(idx)*3e4,1); out(idx) = max(conv(u,u)); end toc
Elapsed time is 21.077027 seconds.
Визуализируйте параллельные результаты профилировщика.
mpiprofile viewer
В отчете выберите Compare (макс. по сравнению с min TotalTime), чтобы сравнить рабочих с минимальными и максимальными общими временами выполнения. Заметьте что на этот раз, несколько выполнения conv
займите подобное количество времени во всех рабочих. Рабочая нагрузка теперь лучше распределяется.