Оптимизация не сходится с функцией parallel_run в Scilab
Я пытаюсь выполнить оптимизацию в Scilab, и я хочу запустить дифференциальный эволюционный код параллельно, используя функцию parallel_run.
Оригинальная версия кода включает цикл for для части, которую я хочу распараллелить, и она прекрасно работает. Когда я изменяю код с помощью функции parallel_run и запускаю его на компьютере с Windows, он снова работает, но, насколько я знаю, эта функция не для Windows, и она работает только на одном ядре. Наконец, я попытался запустить модифицированный код на машине Linux без ошибок снова, однако оптимизация не сходилась и дала мне гораздо худший конечный результат.
Пытаясь выяснить проблему, я понял, что часть вещей, которые печатает код, была на консоли Scilab, а другая часть была на терминале. И хотя в терминале были проведены некоторые вычисления, процесс оптимизации не смог получить данные оттуда.
Это цикл for из исходной версии кода:
//-----Select which vectors are allowed to enter the new population------------
for i=1:NP
tempval = fct(ui(:,i),y); // check cost of competitor
nfeval = nfeval + 1;
if (tempval <= val(i)) // if competitor is better than value in "cost array"
pop(:,i) = ui(:,i); // replace old vector with new one (for new iteration)
val(i) = tempval; // save value in "cost array"
//----we update optval only in case of success to save time-----------
if (tempval < optval) // if competitor better than the best one ever
optval = tempval; // new best value
optarg = ui(:,i); // new best parameter vector ever
end;
end;
end; //---end for imember=1:NP
А вот вложенная функция, которую я использую для замены цикла и пытаюсь заставить его работать параллельно:
function gpar(i);
disp("called on "+string(i));
global nfeval
global val
global pop
global optval
global optarg
tempval = fct(ui(:,i),y); // check cost of competitor
nfeval = nfeval + i;
disp("tempval "+string(tempval));
disp("val(i) "+string(val(i)));
disp("optval "+string(optval));
disp("bef_pop(i) "+string(pop(:,i)));
if (tempval <= val(i)) // if competitor is better than value in "cost array"
pop(:,i) = ui(:,i); // replace old vector with new one (for new iteration)
val(i) = tempval; // save value in "cost array"
//----we update optval only in case of success to save time-----------
if (tempval < optval) // if competitor better than the best one ever
optval = tempval; // new best value
optarg = ui(:,i); // new best parameter vector ever
end;
end;
disp("aft_pop(i) "+string(pop(:,i)));
endfunction; //---end for imember=1:NP
parallel_run(1:NP, "gpar"); //calling function gpar in parallel
disp("popThisGen "+string(pop)); //display the population after changes
Здесь i-й столбец поп-матрицы изменяется, если выполняется какое-либо условие. И я печатаю этот столбец до и после операторов if. я - вектор, который работает от 1 до 40. Я могу видеть первые 10 таких отпечатков с консоли Scilab, и последние 30 с терминала (моя машина имеет четыре ядра, я думаю, что это как-то связано с этим). Затем я печатаю всю поп-матрицу после того, как параллельный запуск завершает свою работу. Из этой окончательной версии pop я понял, что вступили в силу только те изменения, которые я наблюдал на консоли Scilab, и никаких изменений, которые я наблюдал на терминале.
Полная версия исходного кода находится по адресу http://www1.icsi.berkeley.edu/~storn/code.html
Я думаю, что эти потери являются причиной плохих результатов, которые я получаю. Кто-нибудь имеет представление о том, что может происходить? Благодарю.
1 ответ
Отвечая как бы спешно, но вы должны экспортировать результат через переменные результата. Как указано в документах parallel_run:
Кроме того, в Scilab нет блокирующих примитивов для одновременного доступа к общим переменным. По этой причине одновременное выполнение макросов Scilab не может быть безопасным в среде с общей памятью, и каждое параллельное выполнение должно выполняться в отдельном пространстве памяти. В результате не следует полагаться на побочные эффекты, такие как изменение переменных из внешней области: только данные, сохраненные в результирующих переменных, будут скопированы обратно в вызывающую среду.
Также убедитесь, что все параллельные вычисления полностью независимы. Получить во всех входах через параметры.
Глядя на ваш код, все вещи, объявленные глобальными, будут распределены между всеми процессами. Поэтому поместите их все в список аргументов. Вы не должны предполагать какой-либо порядок выполнения отдельных расчетов.
Примеры в документах Scilab на самом деле довольно хороши для объяснения возвращаемых значений. Например, следующий пример.
function [r_min, r_med, r_max]=min_med_max(a, b, c)
r_min=min(a,b,c); r_med=median([a,b,c]); r_max=max(a,b,c);
endfunction
N=10;
A=rand(1:N);B=rand(1:N);C=rand(1:N);
[Min,Med,Max]=parallel_run(A,B,C,"min_med_max");
Помимо использования результатов, SciLab очень строг в том, как они определены, только векторы столбцов и т. Д.
Также ознакомьтесь с Scilab Wiki о параллельных вычислениях.
Надеюсь, это поможет вам.