source: ThirdParty/mpqc_open/src/bin/mpqc/mpqcrun.in

Candidate_v1.6.1
Last change on this file was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100755
File size: 18.5 KB
Line 
1#!/usr/bin/env perl
2#eval 'exec perl $0 $*'
3# if 0;
4
5$prefix = '@prefix@';
6$exec_prefix = "@exec_prefix@";
7$bindir = "@bindir@";
8$scdatadir = "@scdatadir@";
9
10use POSIX;
11
12if ($prefix eq '@' . 'prefix@') {
13 $configurerun = 0;
14}
15else {
16 $configurerun = 1;
17}
18
19# The path to the MPQC executable
20if ($configurerun) {
21 $mpqc = "$bindir/mpqc";
22}
23else {
24 $mpqc = "mpqc";
25}
26
27# The path to the MPQC executable if it is to be run from the object
28# directory.
29if (!$configurerun) {
30 $mpqcobj = "mpqc";
31}
32else {
33 $mpqcobj = '@compiledir@/src/bin/mpqc/mpqc';
34}
35
36# The threadgrp specialization
37$threadgrp = "none";
38
39# The memorygrp specialization
40$memorygrp = "none";
41
42# The message specialization
43$messagegrp = "none";
44$always_use_mpi = '@ALWAYS_USE_MPI@';
45if ("$always_use_mpi" eq "yes") {
46 $messagegrp = "mpi";
47}
48
49# The integral specialization
50$integral = "none";
51
52# The mpi launch command
53$launch = '@LAUNCH@';
54
55# The number of tasks
56$ntask = 1;
57
58# A filename with a list of nodes.
59$nodefile = "";
60
61# A command line argument with a list of nodes.
62$nodes = "";
63
64# A format string to convert a node number to a node name
65$nodename = "%d";
66
67# The number of nodes each job will use.
68$nnodeperjob = "nnode";
69
70# The number of threads each process will use.
71$nthreadperproc = 1;
72
73# The number of processes to run on each node.
74$nprocpernode = 1;
75
76# The number of processes that each job should use.
77$nprocperjob = "all";
78
79# Files machining the given regex will be run sequentially,
80# in alphabetical order.
81$seq = "";
82
83# A regex for files to exclude from the runs
84$exclude = "";
85
86# If true, then mpqc with all inputs in the current directory.
87$readdir = "";
88
89# The directory where the input file is to be found.
90$inputprefix = "";
91
92# The directory where the output file is to be placed.
93$outputprefix = "";
94
95# If this is set to one, then a set of extra exclusions will be
96# included. This is only useful for the running test suite.
97$small = 0;
98
99# If true, then print out a list of files that would be run
100$printfiles = 0;
101
102# If true, then print out the number of files that would be run
103$count = 0;
104
105# If true, then print out help info and exit
106$help = 0;
107
108# If true, then don't actually run anything
109$debug = 0;
110
111# If true, then print out extra info.
112$verbose = 0;
113
114# If true, then overwrite output files that seem up-to-date
115$rerun = 0;
116
117# If true, then do not overwrite any output file.
118$onlynew = 0;
119
120# If true, then generate unique output file names.
121$uniqout = 0;
122
123# If true, then generate output file names.
124$autoout = 0;
125
126# If true, then do not append nproc, nthread, nnode info to filename.
127$simpout = 0;
128
129# If true, run mpqc from the object directory
130$objdir = 0;
131
132######################################################################
133
134use Getopt::Long;
135
136if (!GetOptions("small!" => \$small,
137 "launch=s" => \$launch,
138 "threadgrp=s" => \$threadgrp,
139 "memorygrp=s" => \$memorygrp,
140 "messagegrp=s" => \$messagegrp,
141 "integral=s" => \$integral,
142 "nnodeperjob=i" => \$nnodeperjob,
143 "nthreadperproc=i" => \$nthreadperproc,
144 "nprocpernode=i" => \$nprocpernode,
145 "nprocperjob=i" => \$nprocperjob,
146 "seq=s" => \$seq,
147 "mpqc=s" => \$mpqc,
148 "readdir=s" => \$readdir,
149 "outputprefix=s" => \$outputprefix,
150 "inputprefix=s" => \$inputprefix,
151 "nodefile=s" => \$nodefile,
152 "nodes=s" => \$nodes,
153 "nodename=s" => \$nodename,
154 "exclude=s" => \$exclude,
155 "help!" => \$help,
156 "printfiles!" => \$printfiles,
157 "rerun!" => \$rerun,
158 "onlynew!" => \$onlynew,
159 "uniqout!" => \$uniqout,
160 "autoout!" => \$autoout,
161 "simpout!" => \$simpout,
162 "objdir!" => \$objdir,
163 "count!" => \$count,
164 "debug!" => \$debug,
165 "verbose!" => \$verbose,
166 )) {
167 $help=1;
168}
169
170if ("$launch" eq '@' . 'LAUNCH@') {
171 if ("$messagegrp" eq "mpi") {
172 $launch = "mpirun [-hf %NODEFILE%] -n %NPROC% %MPQCRUNPROC% %MPQC% [-o %OUTPUT%] %INPUT%";
173 }
174 else {
175 $launch = "%MPQC% [-o %OUTPUT%] %INPUT%";
176 }
177}
178
179######################################################################
180
181if ($help) {
182 print "Usage: $ARGV[0] [options] [file1.in] [file2.in] ...\n";
183 print "Options:\n";
184 print " --mpqc path the mpqc executable to use (value: $mpqc)\n";
185 print " --objdir run the mpqc exec in the object dir (value: $objdir)\n";
186 print " --small skip big runs in verification suite (value: $small)\n";
187 print " --nnodeperjob n run with n nodes per job (value: $nnodeperjob)\n";
188 print " --nprocpernode n run with n procs per node (value: $nprocpernode)\n";
189 print " --nprocperjob n run with n procs in each job (value: $nprocperjob)\n";
190 print " --nthreadperproc n use n threads per process (value: $nthreadperproc)\n";
191 print " --threadgrp grp use the given threading layer (value: $threadgrp)\n";
192 print " none: uses MPQC's default\n";
193 print " proc: does a single threaded run\n";
194 print " posix: use POSIX threads\n";
195 print " --messagegrp grp use the given communication layer (value: $messagegrp)\n";
196 print " none: uses MPQC's default\n";
197 print " proc: does a single processor run\n";
198 print " mpi: use MPI\n";
199 print " --memorygrp grp use the given remote memory layer (value: $messagegrp)\n";
200 print " none: uses MPQC's default\n";
201 print " proc: does a single processor run\n";
202 print " mtmpi: use multi-threaded MPI\n";
203 print " armci: use ARMCI\n";
204 print " --integral intgl use the given integral package (value: $integral)\n";
205 print " none: uses MPQC's default\n";
206 print " intv3: this package is distributed with MPQC\n";
207 print " cints: the libint package (required for MP2-R12)\n";
208 printf " --launch cmd use the given cmd to launch jobs--see below (value: %s)\n",
209 (($launch eq "")?"<not set>":$launch);
210 printf " --nodefile file a file listing nodes to use (value: %s)\n",
211 (($nodefile eq "")?"<not set>":$nodefile);
212 printf " --nodes nodes a command line list of machines to use (value: %s)\n",
213 (($nodes eq "")?"<not set>":$nodes);
214 printf " groups can be given as 8-10,12,15-17 for example\n";
215 printf " --nodename fmt converts node num to name (value: %s)\n", $nodename;
216 printf " --seq regex run inputs matching reqex sequentially (value: %s)\n",
217 (("$seq" eq "")?"<not set>":"$seq");
218 printf " --exclude regex exclude files matching regex (value: %s)\n",
219 (("$exclude" eq "")?"<not set>":"$exclude");
220 printf " --readdir dir run mpqc on dir/*.in files (value: %s)\n",
221 (($readdir eq "")?"<not set>":$readdir);
222 print " --count print the number of input files that would be run\n";
223 print " --printfiles print the list of input files that would be run\n";
224 print " --rerun overwrite output file, even if up-to-date\n";
225 print " --onlynew do not overwrite output file, even if not up-to-date\n";
226 print " --uniqout generate unique output filenames\n";
227 print " --autoout generate output filenames\n";
228 print " --verbose print out what action is to be taken on each file\n";
229 print " --debug don't actually run mpqc\n";
230 print " --help print this help\n";
231 print "\n";
232 print "The launch command can contain special strings that will be substituted.\n";
233 print "These are:\n";
234 print " %MPQC% The MPQC program.\n";
235 print " %INPUT% The input filename.\n";
236 print " %OUTPUT% The output filename.\n";
237 print " %NPROC% The number of processes to start.\n";
238 print " %NODEFILE% The name of a file containing the node names.\n";
239 print " %NODELIST% A comma separated list of node names.\n";
240 print " For these last two, if they are contained within square brackets\n";
241 print " and a substitution is not available, then everything within the\n";
242 print " the brackets is removed.\n";
243 print "Examples of the launch argument:\n";
244 print " mpirun [-hf %NODEFILE%] -n %NPROC% %MPQC% [-o %OUTPUT%] %INPUT%\n";
245 print " mpirun [-H %NODELIST%] -n %NPROC% %MPQC% [-o %OUTPUT%] %INPUT%\n";
246 exit 0;
247}
248
249######################################################################
250
251if ($objdir) {
252 $mpqc = $mpqcobj;
253}
254
255######################################################################
256
257@nodelist = ();
258if ($nodes ne "") {
259 $nodes =~ s/-/../g;
260 foreach my $i (eval $nodes) {
261 $nodelist[$#nodelist + 1] = sprintf "$nodename", $i;
262 }
263}
264elsif ("$nodefile" eq "" && exists($ENV{"PBS_NODEFILE"})) {
265 $nodefile=$ENV{"PBS_NODEFILE"};
266}
267if ("$nodefile" ne "" && -f "$nodefile") {
268 my %nodesfound = {};
269 open(NODEFILE,"<$nodefile");
270 while(<NODEFILE>) {
271 if (/(\S+)/) {
272 my $nodename = $1;
273 if (!exists($nodesfound{$nodename})) {
274 $nodelist[$#nodelist + 1] = $nodename;
275 $nodesfound{$nodename} = 1;
276 }
277 }
278 }
279 close(NODEFILE);
280}
281
282if ($#nodelist == -1) {
283 $nnode = 1;
284}
285else {
286 $nnode = $#nodelist + 1;
287}
288
289if ($nnodeperjob eq "nnode") {
290 $nnodeperjob = $nnode;
291}
292
293if ($nprocperjob eq "all") {
294 $nprocperjob = $nnodeperjob * $nprocpernode;
295}
296
297if ($messagegrp eq "none" && $nprocperjob > 1) {
298 $messagegrp = "mpi";
299}
300
301if ($messagegrp eq "proc") {
302 $ENV{"MESSAGEGRP"} = "<ProcMessageGrp>:()";
303}
304elsif ($messagegrp eq "mpi") {
305 $ENV{"MESSAGEGRP"} = "<MPIMessageGrp>:()";
306}
307
308$nnodeperjob = POSIX::ceil($nprocperjob / $nprocpernode);
309
310@jobnodes = ();
311%jobnnodes = {};
312%nodelist = {};
313%nodefile = {};
314$maxjobs = 0;
315while (($maxjobs + 1) * $nnodeperjob <= $nnode) {
316 $jobnnodes[$maxjobs++] = $nnodeperjob;
317}
318
319if ($maxjobs == 0) {
320 die "requested $nnodeperjob nodes but have $nnode nodes";
321}
322
323$nodesbegin = 0;
324foreach my $i (0..$maxjobs-1) {
325 my $nodesend = $nodesbegin + $jobnnodes[$i];
326 my @slice = (@nodelist)[$nodesbegin..($nodesend-1)];
327 $jobnodes{$i} = \@slice;
328 $nodesbegin = $nodesend;
329 foreach my $j (@slice) {
330 if ($nodelist{$i} eq "") { $nodelist{$i} = $j; }
331 else { $nodelist{$i} = sprintf "%s,%s", $nodelist{$i}, $j; }
332 }
333 $nodefile{$i} = ".tmp.nodefile.$$.$i";
334 open(NODEFILE,">" . $nodefile{$i});
335 foreach my $proc (1..$nprocpernode) {
336 foreach my $j (@slice) {
337 printf NODEFILE "%s\n", $j;
338 }
339 }
340 close(NODEFILE);
341}
342
343######################################################################
344
345if ($threadgrp eq "none" && $nthreadperproc > 1) {
346 $threadgrp = "posix";
347}
348
349if ($threadgrp eq "proc") {
350 $ENV{"THREADGRP"} = "<ProcThreadGrp>:()";
351}
352elsif ($threadgrp eq "posix") {
353 $ENV{"THREADGRP"} = "<PthreadThreadGrp>:(num_threads=$nthreadperproc)";
354}
355
356######################################################################
357
358if ($memorygrp eq "proc") {
359 $ENV{"MEMORYGRP"} = "<ProcMemoryGrp>:()";
360}
361elsif ($memorygrp eq "mtmpi") {
362 $ENV{"MEMORYGRP"} = "<MTMPIMemoryGrp>:()";
363}
364elsif ($memorygrp eq "armci") {
365 $ENV{"MEMORYGRP"} = "<ARMCIMemoryGrp>:()";
366}
367
368######################################################################
369
370if ($integral eq "cints") {
371 $ENV{"INTEGRAL"} = "<IntegralCints>:()";
372}
373elsif ($integral eq "intv3") {
374 $ENV{"INTEGRAL"} = "<IntegralV3>:()";
375}
376
377######################################################################
378
379$usingthreads = 0;
380if ($maxjobs > 1) {
381 require threads;
382 require threads::shared;
383 $usingthreads = 1;
384}
385
386######################################################################
387
388# autoflush output
389$| = 1;
390
391@allfiles = reverse(get_file_list());
392
393my @seqfiles : shared = ();
394my @files : shared = ();
395foreach my $file (@allfiles) {
396 if ("$seq" ne "" && ($file =~ /$seq/)) {
397 $seqfiles[$#seqfiles+1] = $file;
398 }
399 else {
400 $files[$#files+1] = $file;
401 }
402}
403
404if ($count) {
405 printf "%d\n", $#allfiles + 1;
406 exit;
407}
408
409if ($printfiles) {
410 foreach my $i (@allfiles) {
411 printf "%s\n", "$i";
412 }
413 exit;
414}
415
416
417printf "Running a maximum of %d jobs at a time.\n", $maxjobs;
418printf "Running %d processes per job.\n", $nprocperjob;
419printf "Running %d threads per process.\n", $nthreadperproc;
420foreach my $i (0..$maxjobs-1) {
421 print "Nodes in slot $i:";
422 foreach my $j (@{$jobnodes{$i}}) {
423 printf " \"%s\"", $j;
424 }
425 print "\n";
426}
427printenvvar("MESSAGEGRP");
428printenvvar("THREADGRP");
429printenvvar("MEMORYGRP");
430printenvvar("SCLIBDIR");
431printenvvar("INTEGRAL");
432
433$thecount = 0;
434$n = 0;
435
436if ($usingthreads) {
437 @threads = ();
438
439 foreach my $jobnum (0..$maxjobs-1) {
440 my $thr = threads->new(\&jobrunner, $jobnum);
441 $threads[$#threads+1] = $thr;
442 }
443
444 foreach my $thr (@threads) {
445 $thr->join();
446 }
447
448 @threads = ();
449}
450else {
451 foreach my $jobnum (0..$maxjobs-1) {
452 jobrunner($jobnum);
453 }
454}
455
456foreach $i (values(%nodefile)) {
457 unlink "$i";
458}
459
460sub get_next_file {
461 my $jobnum = shift;
462 lock(@seqfiles) if ($usingthreads);
463 if ($#seqfiles >= 0 && $jobnum == 0) {
464 return pop(@seqfiles);
465 }
466 lock(@files) if ($usingthreads);
467 if ($#files >= 0) {
468 return pop(@files);
469 }
470 return "";
471}
472
473sub jobrunner {
474 my $jobslot = shift;
475
476 my $file;
477
478 while ( ($file = get_next_file($jobslot)) ne "") {
479 my $out = outfile("$file");
480 $out = "$outputprefix$out";
481 my $in = "$inputprefix$file";
482 my $cmd = "$launch";
483 $cmd =~ s/%MPQC%/$mpqc/;
484 $cmd =~ s/%NPROC%/$nprocperjob/;
485 $cmd =~ s/%INPUT%/$in/;
486
487 my $mpqcrunproc = "$scdatadir/mpqcrunproc $mpqc";
488 if (exists($ENV{MESSAGEGRP})) {
489 $mpqcrunproc = "$mpqcrunproc " . &isoencode("$ENV{MESSAGEGRP}");
490 }
491 else {
492 $mpqcrunproc = "$mpqcrunproc none";
493 }
494 if (exists($ENV{THREADGRP})) {
495 $mpqcrunproc = "$mpqcrunproc " . &isoencode("$ENV{THREADGRP}");
496 }
497 else {
498 $mpqcrunproc = "$mpqcrunproc none";
499 }
500 if (exists($ENV{MEMORYGRP})) {
501 $mpqcrunproc = "$mpqcrunproc " . &isoencode("$ENV{MEMORYGRP}");
502 }
503 else {
504 $mpqcrunproc = "$mpqcrunproc none";
505 }
506 if (exists($ENV{INTEGRAL})) {
507 $mpqcrunproc = "$mpqcrunproc " . &isoencode("$ENV{INTEGRAL}");
508 }
509 else {
510 $mpqcrunproc = "$mpqcrunproc none";
511 }
512 $cmd =~ s|%MPQCRUNPROC%|$mpqcrunproc|;
513
514 $cmd = substitute_optional_parameter($cmd, "%OUTPUT%", "$out");
515 $cmd = substitute_optional_parameter($cmd, "%NODELIST%", $nodelist{$jobslot});
516 $cmd = substitute_optional_parameter($cmd, "%NODEFILE%", $nodefile{$jobslot});
517
518 printf "starting in slot %d: %s\n", $jobslot, "$cmd";
519 $cmd = "true" if ($debug);
520 $pid = fork();
521 if ($pid == 0) {
522 exec("$cmd");
523 die "exec returned";
524 }
525 waitpid($pid,'');
526 }
527}
528
529sub get_file_list {
530 my @dirfiles;
531 my @argfiles;
532
533 if ($readdir ne "") {
534 opendir(DIR,"$readdir");
535 @tdirfiles = sort(readdir(DIR));
536 foreach my $j (@tdirfiles) {
537 if ($j =~ /\.in$/) {
538 $dirfiles[$#dirfiles+1] = $j;
539 }
540 }
541 closedir(DIR);
542 }
543
544 @argfiles = sort(@ARGV);
545
546 my @allfiles = (@dirfiles, @argfiles);
547
548 my @files;
549
550 foreach my $infile (@allfiles) {
551 my $out = outfile("$infile");
552 $out = "$outputprefix$out";
553 $in = "$inputprefix$infile";
554 $issmall = (!($in =~ /ccpc?v[dtq5]z/));
555 if ($in =~ /^(cl|hsos|u)scf_.*6311gss/) {
556 $issmall = 0;
557 }
558 if ($in =~ /^basis2_/) {
559 $issmall = 0;
560 }
561 if ($in =~ /^orthog_.*(hfs|zapt2|mp2)/) {
562 $issmall = 0;
563 }
564 if ($in =~ /^dft_/) {
565 $issmall = 0;
566 }
567 if ($in =~ /^symm1_cub/) {
568 $issmall = 0;
569 }
570 if ($in =~ /^methods_/) {
571 $issmall = 0;
572 }
573 if ($in =~ /^basis[12]_.*pc[234]/) {
574 $issmall = 0;
575 }
576 if ($in =~ /^mbpt_mp2r12_c6h6_multipass/) {
577 $issmall = 0;
578 }
579 if ($exclude ne "" && $in =~ /$exclude/) {
580 if ($verbose) {
581 print "$in: excluded by --exclude option\n";
582 }
583 }
584 if (!$rerun
585 && (-f "$out")
586 && ($onlynew
587 || (-M "$out" < -M "$in" && (! -f "$mpqc" || -M "$out" < -M "$mpqc")))) {
588 if ($verbose) {
589 print "$in: skipping: $out up-to-date\n";
590 }
591 }
592 elsif ($small && ! $issmall) {
593 if ($verbose) {
594 print "$in: skipping due to --small option\n";
595 }
596 }
597 else {
598 if ($verbose) {
599 print "$in: will be run\n";
600 }
601 $files[$#files+1] = "$infile";
602 }
603 }
604
605 return @files;
606}
607
608sub outfile {
609 my $in = shift;
610
611 my $outbase = "$in";
612 $outbase =~ s/\.[^.]*$//;
613 if ($simpout) {
614 $outbase = sprintf "%s.out", "$outbase";
615 }
616 else {
617 $outbase = sprintf "%s.out.%03d.%02d.%02d", "$outbase",
618 $nnodeperjob, $nprocpernode, $nthreadperproc;
619 }
620
621 my $out;
622 if ($uniqout) {
623 $out = "$outbase";
624 my $outversion = 1;
625 while (-f "$out") {
626 $outversion++;
627 $out = sprintf "%s.%02d", "$outbase", $outversion;
628 }
629 }
630 elsif ($autoout) {
631 $out = "$outbase";
632 }
633 else {
634 $out = "";
635 }
636
637 return "$out";
638}
639
640sub printenvvar {
641 my $envvar = shift;
642 if (exists($ENV{$envvar})) {
643 printf "Using %s = \"%s\"\n", $envvar, $ENV{$envvar};
644 }
645}
646
647sub substitute_optional_parameter {
648 my $str = shift;
649 my $name = shift;
650 my $value = shift;
651 if ($value ne "") {
652 $str =~ s/\[([^[]*$name[^[]*)\]/$1/;
653 $str =~ s/$name/$value/;
654 }
655 else {
656 $str =~ s/\[([^[]*$name[^[]*)\]//;
657 }
658 return $str;
659}
660
661sub isoencode {
662 my $str = shift;
663 $str =~ s/ /%20/g;
664 $str =~ s/\</%3c/g;
665 $str =~ s/\>/%3e/g;
666 $str =~ s/\[/%5b/g;
667 $str =~ s/\]/%5d/g;
668 $str =~ s/\$/%24/g;
669 $str =~ s/:/%38/g;
670 $str =~ s/\(/%28/g;
671 $str =~ s/\)/%29/g;
672 return $str;
673}
Note: See TracBrowser for help on using the repository browser.