0

我正在尝试对 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 语句之前和之后打印第 i 列。i 是一个从 1 到 40 的向量。我可以从 Scilab 控制台看到前 10 个打印件,然后从终端看到最后 30 个打印件(我的机器有四个内核,我认为这与此有关)。然后我在并行运行完成其工作后打印整个弹出矩阵。从这个 pop 的最终版本中,我意识到只有我在 Scilab 控制台上观察到的变化才会生效,而我在终端上观察到的变化都没有。

原始代码的完整版本位于http://www1.icsi.berkeley.edu/~storn/code.html#scil

我认为这些损失是我得到糟糕结果的原因。有没有人知道可能发生的事情?谢谢。

4

1 回答 1

0

回答有点匆忙,但您应该通过结果变量导出结果。如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

希望这对您有所帮助。

于 2015-04-09T17:32:55.923 回答