Date: Tue, 16 Feb 2010 09:47:57 +0100
From: Luca Favatella <slacky...@gmail.com>
Subject:

On 08/02/2010, Luca Favatella <slacky...@gmail.com> wrote:
> On 08/02/2010, Muthiah Annamalai <muthusp...@gmail.com> wrote:
[...]
> Great! Thanks for your interest and contribution.
> I'd prefer to keep ga package Matlab compatible, so I locally started
> to implement handling of "UseParallel" [0] and "Vectorized" [1]
> options. Below you can read the description I'm adding for them. I
> hope to commit this code by this week. Then we will be able to decide
> if it is possible to add your ideas (or other ideas in this email
> thread) in a Matlab-compatible way.

| (Sorry for the delay.)
|
| Now modifying one line in __ga_scores__.m it is possible to integrate
| parallel evaluation (I marked that line with TODO).
| You can commit you changes yourself, or please provide me a patch.
|
| Cheers,
| Luca Favatella

Hello there,

Thanks for modify the toolbox to allow for the vectorized solver support.

I found it necessary to add option Ncore to the GA optimset default functions,
as default_options.Ncores = 1; .

The patch uses essentially the same mechanism of separate processess,
( despite the excellent suggestions to use MPI and parcellfun()  ) as I found
them to have some advantages which only MPI could give for large data sets.
Jaroslav & Riccardo Corradini for your suggestions.

The patch touches the following files:
1. gaoptimset.m
2. __gaoptimset_default_options__.m
3. __ga_scores__.m

and introduces two new files,

4. __ga_multicore_scores__.m
5. __ga_multicore_helper__.m

I hope they are acceptable changes.
Let me know what you think.

Best,
-Muthu
Index: __gaoptimset_default_options__.m
===================================================================
--- __gaoptimset_default_options__.m	(revision 6922)
+++ __gaoptimset_default_options__.m	(working copy)
@@ -50,4 +50,6 @@
                                 #default_options.TolFun = 1e-6;
   default_options.UseParallel = "never";
   default_options.Vectorized = "off";
-endfunction
\ No newline at end of file
+  default_options.Ncores = 1;
+endfunction
+
Index: __ga_scores__.m
===================================================================
--- __ga_scores__.m	(revision 6922)
+++ __ga_scores__.m	(working copy)
@@ -22,7 +22,16 @@
       warning ("'Vectorized' option is 'on': ignoring 'UseParallel' \
           option, even if it is 'always'");
     endif
-    Scores = problem.fitnessfcn (Population);
+    ## use multicore score evaluator
+    ## fitnessfcn has to be a string or m-file name converted from a handle.
+    ## accessible from another process that does not share memory-space.
+    if ( strcmp(class(problem.fitnessfcn),"function_handle") )
+      fitness_fcn_name = func2str( problem.fitnessfcn );
+    else
+      fitness_fcn_name = problem.fitnessfcn;
+    end
+    Scores = __ga_multicore_score__(fitness_fcn_name,population,problem.options.ncores);
+    return
   else ## not using vectorized evaluation
     if (! strcmp (problem.options.Vectorized, "off"))
       error ("'Vectorized' option must be 'on' or 'off'");
@@ -42,4 +51,4 @@
       Scores = tmp(1:nrP, 1);
     endif
   endif
-endfunction
\ No newline at end of file
+endfunction
Index: gaoptimset.m
===================================================================
--- gaoptimset.m	(revision 6922)
+++ gaoptimset.m	(working copy)
@@ -54,6 +54,8 @@
 ##       "always" | "never" (default) . Parallel evaluation of objective function. TODO: parallel evaluation of nonlinear constraints
 ## @item Vectorized
 ##       "on" | "off" (default) . Vectorized evaluation of objective function. TODO: vectorized evaluation of nonlinear constraints
+## @item Ncores
+##        n | 1 ( default ) . Specify non-zero integer, the number of cores to use for evaluating the Vectorized GA on multicore machines.
 ## @end table
 ##
 ## @seealso{ga}
@@ -92,4 +94,4 @@
 %! options = gaoptimset ("EliteCount", 1, "FitnessLimit", 1e-7, "Generations", 1000, "PopInitRange", [-5; 5], "PopulationSize", 200);
 %!
 %! ## "CrossoverFraction" is not specified, so gaoptimset should put the default value: testing this too
-%! assert ([(getfield (options, "CrossoverFraction")); (getfield (options, "EliteCount")); (getfield (options, "FitnessLimit")); (getfield (options, "Generations")); (getfield (options, "PopInitRange")); (getfield (options, "PopulationSize"))], [0.8; 1; 1e-7; 1000; [-5; 5]; 200])
\ No newline at end of file
+%! assert ([(getfield (options, "CrossoverFraction")); (getfield (options, "EliteCount")); (getfield (options, "FitnessLimit")); (getfield (options, "Generations")); (getfield (options, "PopInitRange")); (getfield (options, "PopulationSize"))], [0.8; 1; 1e-7; 1000; [-5; 5]; 200])
## Copyright (C) 2010 Muthiah Annamalai <gnumu...@users.sf.net>
## Copyright (C) 2008 Luca Favatella <slacky...@gmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; If not, see <http://www.gnu.org/licenses/>.

## Author: Luca Favatella <slacky...@gmail.com>
## Version: 5.3.1
## 
## Modified for use with Multicore CPU to utilize data-parallel
## nature of GA fitness functions, which we cannot do with limited
## License software. Go Octave!
## 
## Assumptions, Fitness functions have to be a m-file, since we 
## donot share memory with the child process.
## [ncores] has to be the number of cores to be used in the GA
## fitness evaluation, obtained as struct element of GA problem,
## and passed down to us.
## 

function Scores = __ga_multicore_scores__ (fitnessfcn, Population, ncores)
  if ( nargin < 2 )
       error('__ga_multicore_scores__ : internal function, wrong invocation');      
  elseif ( nargin < 3 )
       ncores = 2;
  end

  [nrPopulation ncPopulation] = size (Population);
  Scores = zeros(nrPopulation,1);
  
  probstr = sprintf('GA-%d-Pop-%dx%d-',round(rand()*1e6),nrPopulation,ncPopulation);
  datestr = strrep(ctime(time),':','-');
  matfileprefix = sprintf('%s-%s',probstr,datestr);
  matfileprefix = strrep(matfileprefix,' ','-');
  
  index = 1;
  while ( index  <= nrPopulation )
    matfilename = {};
    
    ## save ncore data elements to file
    idx = index;
    while ( idx <= nrPopulation && idx < index + ncores )
          matfile = sprintf('%s-%d.mat',matfileprefix(1:end-1),idx);
	  matfilename{idx-index + 1} = matfile;
	  data = Population(index, 1:ncPopulation);
	  save('-mat',matfile,'data');
          idx = idx + 1;
    end
    nprocs = idx-index; ## number of processess to be started.
    
    ## start the processess with the marshaller function
    idx = index; pid_child = zeros( nprocs, 1 );
    while ( idx <= nrPopulation && idx < index + ncores )
	  matfile = matfilename{idx-index + 1};
          pid_child( idx - index + 1 ) = system(sprintf('octave -q __ga_multicore_helper__.m "%s" "%s" ',fitnessfcn, matfile),'','async');
          idx = idx + 1;
    end

    ## wait for the processess to finish
    for idx = 1:nprocs
	waitpid( pid_child(idx), 0 );
        ## fprintf('GA multicore: Terminated Child %d\n',pid_child(idx));
    end
    ## matfilename; nprocs
    
    ## load results from the processed cousins
    for idx = 1:nprocs
        matfile = matfilename{idx}
        procfile = sprintf('proc-%s',matfile);
        load(procfile); ## has variable fitnessval.
        Scores(index+idx-1,1) = fitnessval;
        unlink(matfile);
        unlink(procfile);
    end    
    index = index + ncores;
  end
  
  Scores(1:nrPopulation, 1) = Scores;
endfunction

## Copyright (C) 2010 Muthiah Annamalai <gnumu...@users.sf.net>
## 
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; If not, see <http://www.gnu.org/licenses/>.
## 

## usage: octave -q __ga_multicore_helper__.m fitnessfcn matfile
## and save the result in proc-$matfile in the variable fitnessval.
## load(procfile); ## has variable fitnessval.
## 
more off
parameters = argv();
## fprintf('__ga_multicore_helper__.m : Child process %d: command line received :\n',getpid());
## parameters

fitnessfcn = parameters{1}; matfile = parameters{2};
load(matfile);

fitnessval = feval( fitnessfcn, data(:) );
## fitnessval

save('-mat',sprintf('proc-%s',matfile),'fitnessval');
------------------------------------------------------------------------------
Download Intel&reg; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs 
proactively, and fine-tune applications for parallel performance. 
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
Octave-dev mailing list
Octave-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/octave-dev

Reply via email to