2017-01-17 1 views
0

У меня довольно длинный цикл parfor (скажем, 100 000 итераций, где каждая итерация занимает около минуты), что я работаю с 36 ядрами. Я заметил, что в конце работы большое количество ядер простаивает, а некоторые заканчивают то, что, по моему мнению, должно быть несколькими итерациями на одного работника. Это приводит к большому количеству потраченного впустую вычислительного времени, ожидая, пока один работник закончит несколько заданий, в то время как остальные сидят без дела.Почему графический планировщик Matlab оставляет рабочих бездействующим?

Следующий сценарий показывает проблему (с помощью файла обмена утилита Par.m):

% Set up parallel pool 
nLoop = 480; 
p1 = gcp; 

% Run a loop 
pclock = Par(nLoop); 
parfor iLoop = 1:nLoop 
    Par.tic; 
    pause(0.1); 
    pclock(iLoop) = Par.toc; 
end 
stop(pclock); 
plot(pclock); 

% Process the timing info: 
runs = [[pclock.Worker]' [pclock.ItStart]' [pclock.ItStop]']; 
nRuns = arrayfun(@(x) sum(runs(:,1) == x), 1:max(runs)); 
starts = nan(max(nRuns), p1.NumWorkers); 
ends = nan(max(nRuns), p1.NumWorkers); 
for iS = 1:p1.NumWorkers 
    starts(1:nRuns(iS), iS) = sort(runs(runs(:, 1) == iS, 2)); 
    ends(1:nRuns(iS), iS) = sort(runs(runs(:, 1) == iS, 3)); 
end 

firstWorkerStops = min(max(ends)); 
badRuns = starts > firstWorkerStops; 
nBadRuns = sum(sum(badRuns)) - (p1.NumWorkers-1); 

fprintf('At least %d (%3.1f%%) iterations run inefficiently.\n', ... 
    nBadRuns, nBadRuns/nLoop * 100); 

Путь я смотрю на него, каждый работник должен быть занят до тех пор, пока очередь не пуста, после чего все рабочие сидеть без дела. Но здесь похоже, что этого не происходит - с 480 итерациями я получаю между 6-20 итерациями, которые начинаются с рабочего, после того, как другой рабочий сидел без дела для полного цикла. Это число, по-видимому, масштабируется линейно, число итераций цикла составляет около 2% от общего числа. При ограниченном тестировании это, по-видимому, согласуется с Matlab 2016b и 2014b.

Есть ли причина, по которой это ожидаемое поведение, или это просто плохо написанный планировщик в реализации parfor? Если да, то как я могу структурировать это, так что я не сижу с простаивающими рабочими так долго?

ответ

0

Планировщик parfor пытается загрузить баланс для циклов, где итерации не принимают равномерного количества времени. К сожалению, как вы заметили, это может привести к тому, что рабочие перестанут работать в конце цикла. С parfor у вас нет контроля над разделением работы; но вы можете использовать parfeval, чтобы разделить вашу работу на четные куски - это может дать вам лучшее использование. Или вы могли бы использовать spmd в сочетании с петлей for-drange.

+0

Как бы вы выполняли явное планирование с помощью 'spmd'? Я думаю, что я написал пример, но, похоже, он сталкивается с той же проблемой, что и «parfor». –

+0

Конструкция 'for-drange' просто делит итерации цикла на куски одинакового размера, вот что я имел в виду. Это нормально, если каждая итерация занимает столько же времени. – Edric

1

Я думаю, что это объясняет, что вы наблюдаете.

Если количество итераций больше, чем работников, некоторые работники выполняют более одной итерации цикла; в этом случае рабочий может сразу получать несколько итераций, чтобы сократить время связи. (От «When to Use parfor») »)

В конце цикла два рабочих могут завершить свои итерации примерно в одно и то же время. Если есть только одна группа итераций, которые нужно назначить, тогда один работник получит их все, а другой останется бездействующим. Похоже, что это ожидаемое поведение, и, вероятно, потому, что базовая реализация пытается уменьшить стоимость связи, связанную с пулом работников. Я просмотрел веб-страницы и настройки Matlab, и, похоже, нет способа настроить коммуникационную стратегию.