В этом примере показано, как профилировать параллельный код с помощью параллельного профилировщика для работников в параллельном пуле.
Создайте параллельный пул.
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
Отчет показывает информацию о времени выполнения для каждой функции, которая запускается работниками. Можно исследовать, какие функции занимают больше всего времени у каждого работника.
Как правило, сравнение работников с минимальными и максимальными общими временами выполнения полезно. Для этого в отчете щелкните Сравнить (max vs. 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
В отчете выберите Сравнить (max vs. min TotalTime), чтобы сравнить работников с минимальными и максимальными общими временами выполнения. Заметьте, что на этот раз, множества потоков выполнения conv
взять аналогичное количество времени у всех работников. Теперь рабочая нагрузка распределена лучше.