作品なんで貼っとく-Parallel Simulation Script-

WindowsでEmbrassingly parallelでシミュレータを回すためのスクリプト

Windowsでやるには、プロセスの数数えるのと、forkのエミュレーション用のモジュールのインポートがめんどくさい。Unix系だったら、もうちょっと簡単。

やってることは、
・ParameterList.csvからパラメータのリストを読み込む。
・Simulation用のパラメータを読み込んでは子供に渡す
・子供はシミュレータを回すコマンドを生成し、コマンドプロンプトに投げ、終わったら死ぬ。
・親は子供の数を数え、子供が15人以下なら新しく作る。(コア数が16個のマシンだから
・出力ファイルの処理。(ここは見るべきところなし)

Windowsでfork(親プロセスから子供を生成)するのは、デフォでは対応してないので、3行目の

use POSIX

Unixをエミュレートしてる。。。らしい。

プロセスのカウントはUnixなら

ps -e | grep "process name" | wc

とかで一発なんだが、うまいやり方が思いつかなかったので、一旦ファイルに書きだしてからPerlで数えてる。

Windows,Perl,fork」とかで検索して来た人はmainルーチンと、process_countルーチン以外は読む価値なしだから。


use strict;
use warnings;
use POSIX ":sys_wait_h";#for fork emulation

#main routine
#need 2 commandline parameter.
if( @ARGV != 2 ){
die "How to use...\n$0 ModelFile.ind ParameterList.csv\n";# $0 is program name
}

my $model_file = $ARGV[0];#*.ind
my $parameter_list_file=$ARGV[1]; chomp($parameter_list_file);#parameter list

my $prefix_master =$` if($model_file =~ /.ind/);
my $exe_name="fullwave.exe";
my $process_limit=15;
my $parameter_name_string = "Ratio,Period,fdtd_stop_time,fdtd_stop_time";

open (LIST,"<$parameter_list_file");
while(my $line=<LIST>){
chomp($line);
my $parameter_list_string = $line;
my $generate_success=0;
while (!$generate_success){
if (&process_count($exe_name) < $process_limit){
my $pid = fork;
if (!defined $pid){
die "fork failed\n";#Never comes here
}elsif($pid){ # Parent process
print "generating child\n";
}elsif(!$pid){ #Child process
&run_simulater($parameter_name_string,$parameter_list_string);
print "$$ exit\n";
exit; #Kill child
}
$generate_success=1;
} else {
$generate_success=0;
sleep 10;
}
}
}
close(LIST);

&file_transaction();

# simulation command routine (forked children)
sub run_simulater {
(my $parameter_name_string ,my $parameter_list_string) = @_;
my @parameter_name = split(/,/,$parameter_name_string);
my @parameter_list = split(/,/,$parameter_list_string);
my $parameter_number = @parameter_name;
my $prefix =sprintf("%s%s%.1f%s%.1f",$prefix_master,"_$parameter_name[0]",$parameter_list[0],"_$parameter_name[1]",$parameter_list[1]);
my $symbols ="wait=0 prefix=$prefix";
for (my $i=0 ; $i < $parameter_number - 2 ;$i++){
$symbols .= " scan_variable=$parameter_name[$i] $parameter_name[$i]=$parameter_list[$i] ";
}
my $stop_time1 = " scan_variable=$parameter_name[2] $parameter_name[2]=$parameter_list[2] ";
my $stop_time2 = " scan_variable=$parameter_name[3] $parameter_name[3]=$parameter_list[3] ";
print "$symbols $stop_time1\n";
`start /min fullwave $model_file $symbols $stop_time1`;
print "$symbols $stop_time2\n";
`start /min fullwave $model_file $symbols $stop_time2`;
my $log_file_name ='Log' . $$ . '.txt';
open (LOG, ">$log_file_name");
print LOG "I'm a child. My pid is $$ \n";
print LOG "$parameter_name_string";
print LOG "$parameter_list_string";
close(LOG);
}

#counting thread routine
sub process_count{
(my $exe_name) = @_;
`tasklist > process.txt`;
open (PS, "process.txt");
my $process_number=0;
while (my $line = <PS>) {
$process_number++ if ($line =~ /$exe_name/);
}
close (PS);
return "$process_number\n";
}

sub file_transactio{
open(DIR,'.');
my @file_list = readdir(DIR);
foreach my $file_name(@file_list){
if ($file_name=~ /_m([0-9]+)_t[0-9]+_e[xyz]\.dat$/){
my $postfix=$&;
my $prefix=$`;
$postfix=~ s/\.dat/\.tmp/;
open(DAT,$file_name) or die "can't open file\n";
open(TMP,">>$prefix$postfix");
for (my $i=1;!eof(DAT);$i++){
my $line=<DAT>;
if ($i > 4){
$line =~ s/^ //;
$line =~ s/ / /g;
$line =~ s/ $//;
}
print TMP $line;
}
close(TMP);
close(DAT);
unlink $file_name;
rename "$prefix$postfix" , "$file_name";
unlink "$prefix\.fst";
unlink "$prefix\.dataindex";
}
}
}