2013-05-02 3 views
1

У меня есть код, который структурно похож на следующее в Matlab:Менее строгая альтернатива parfor в matlab?

bestConfiguration = 0; 
bestConfAwesomeness = 0; 

for i=1:X 
    % note that providing bestConfAwesomeness to the function helps it stop if it sees the current configuration is getting hopeless anyway 
    [configuration, awesomeness] = expensive_function(i, bestConfAwesomeness); 
    if awesomeness > bestConfAwesomeness 
     bestConfAwesomeness = awesomeness; 
     bestConfiguration = configuration; 
    end 
end 

Там есть немного больше, но основная структура является выше. X можно получить очень большой. Я пытаюсь запустить этот код параллельно, поскольку expensive_function() занимает много времени.

Проблема в том, что Matlab не позволит мне просто изменить for на parfor, потому что мне не нравится, что я обновляю лучшую конфигурацию в цикле.

До сих пор, что я сделал это:

[allConfigurations, allAwesomeness] = deal(cell(1, X)); 

parfor i=1:X 
    % note that this is not ideal because I am forced to use 0 as the best awesomeness in all cases 
    [allConfigurations{i}, allAwesomeness{i}] = expensive_function(i, 0); 
end 

for i=1:X 
    configuration = allConfigurations{i}; 
    awesomeness = allAwesomeness{i}; 
    if awesomeness > bestConfAwesomeness 
     bestConfAwesomeness = awesomeness; 
     bestConfiguration = configuration; 
    end 
endfor 

Это лучше с точки зрения времени, которое требуется для запуска; однако для больших входов требуется огромное количество памяти, потому что все конфигурации всегда сохраняются. Другая проблема заключается в том, что использование parfor заставляет меня всегда предоставлять 0 в качестве лучшей конфигурации, даже если лучшие могут быть известны.

Предоставляет ли Matlab лучший способ сделать это?

В принципе, если бы мне не пришлось использовать Matlab и я мог бы сам управлять потоками, у меня был бы один центральный поток, который давал рабочие места рабочим (т. Е. Заставлял их запускать expensive_function(i)), и как только рабочий вернется, посмотрите на данных, которые он создал, и сравнить их с лучшими, найденными до сих пор, и соответствующим образом обновить их. Не было бы необходимости сохранять все конфигурации, которые, по-видимому, являются единственным способом сделать работу parfor.

Есть ли способ сделать это в Matlab?

+0

Чтобы иметь возможность использовать ранее знание при вызове 'expensive_function', можно разделить диапазон' parfor' на более мелкие развертки (например, 'я = 1: пол (X/2) ', а затем' i = floor (X/2): X') и использовать наилучшие результаты первых разверток, чтобы выровнять следующие вызовы на 'дорогостоящие_функции'. Обратите внимание, что осуществимость этого решения зависит от компромисса между экономии времени выполнения из-за информированных звонков на «дорогая_функция» и экономии из-за наличия одного «парфора» по сравнению с несколькими последовательными 'parfor'. –

+0

@ H.Muster: Я думал об этом, но это не идеально, потому что «дорогая_функция» может занять много времени для некоторых входов, т. Е. Первая развертка может излишне ждать, пока небольшая часть ее завершится, когда она уже может выполняйте задания с другой стороны – houbysoft

+0

Как я уже сказал, это зависит от трауффа. В качестве обходного пути «дорогая_функция» могла сохранить некоторые результаты в файле. Затем, при каждом вызове, функция может проверить, доступны ли файлы результатов, и если да, используйте эти предварительные знания. –

ответ

1

Я не уверен, что контроль над вашими потоками возможен с помощью Matlab. Однако, поскольку X очень велико, это может быть стоит сделать следующее, что стоит вам еще одну итерацию expensiveFunction:

%# calculate awesomeness 
parfor i=1:X 
    [~,awesomeness(i)] = expensiveFunction(i); 
end 
%# find the most awesome i 
[mostAwesome,mostAwesomeIdx] = min(awesomeness); 
%# get the corresponding configuration 
bestConfiguration = expensiveFunction(mostAwesomeIdx); 
+0

Спасибо, правда, это может помочь снизить стоимость памяти. Причина, по которой я искал лучший вариант, заключалась в том, что мне также было бы полезно каким-то образом передать самую известную удивительность, найденную до сих пор, к дорогостоящей функции, которая возможна с помощью 'for', но не' parfor'. Теперь отредактированный вопрос, чтобы отразить это (я забыл упомянуть об этом ранее) – houbysoft

2

Использование bestConfAwesomeness каждый раз вокруг петли означает, что итерации вашего цикла не заказать -независимый, следовательно, почему PARFOR несчастлив. Один из подходов, который вы можете предпринять, - использовать SPMD, и каждый работник должен выполнить expensiveFunction параллельно, а затем сообщить об обновлении bestConfAwesomeness. Что-то вроде этого:

bestConfiguration = 0; 
bestConfAwesomeness = 0; 
spmd 
    for idx = 1:ceil(X/numlabs) 
    myIdx = labindex + ((idx-1) * numlabs); 
    % should really guard against myIdx > X here. 
    [thisConf, thisAwesome] = expensiveFunction(myIdx, bestConfAwesomeness); 
    % Now, we must communicate to see if who is best 
    [bestConfiguration, bestAwesomeness] = reduceAwesomeness(... 
     bestConfiguration, bestConfAwesomeness, thisConf, thisAwesome); 
    end 
end 

function [bestConf, bestConfAwesome] = reduceAwesomeness(... 
    bestConf, bestConfAwesome, thisConf, thisAwesome) 
% slightly lazy way of doing this, could be optimized 
% but probably not worth it if conf & awesome both scalars. 
allConfs = gcat(bestConf); 
allAwesome = gcat(thisAwesome); 
[maxThisTime, maxLoc] = max(allAwesome); 
if maxThisTime > bestConfAwesome 
    bestConfAwesome = maxThisTime; 
    bestConf = allConfs(maxLoc); 
end 
end 
Смежные вопросы