X-Git-Url: https://git.donarmstrong.com/?p=uiuc_igb_scripts.git;a=blobdiff_plain;f=dqsub;h=571bc281cd88c45827ae35fa7672844b66a98875;hp=27b8b39c5b43e97a0da442b65e241fd9aa247438;hb=9d5820c033136980f80cccad98a499ba58c0cde5;hpb=e6e19e0274ff4ce9fe45ae9debfd5eebd40a5d69 diff --git a/dqsub b/dqsub index 27b8b39..571bc28 100755 --- a/dqsub +++ b/dqsub @@ -31,6 +31,8 @@ dqsub [options] --ppn processors per node to use --mem memory to request --dir Directory to run the script in (default current directory) + --account, -A Account name to use + --join, -J join error and output streams (default) --name, -N Name of the job --debug, -d debugging level (Default 0) --help, -h display this help @@ -60,6 +62,20 @@ command run in the current directory. File to read array arguments from. If not provided, and B<--array> is given, arguments will be read from STDIN. +=item B<--account, -A> + +Account name to use + +=item B<--join, J> + +Whether to join STDOUT and STDERR. On by default; disable with +C<--nojoin>. + +=item B<--batch> + +Which batch system to use. If sbatch exists, assume it's slurm, +otherwise, PBS. + =item B<--debug, -d> Debug verbosity. (Default 0) @@ -94,10 +110,12 @@ my %options = (nodes => 1, man => 0, interactive => 0, array_per_job => 1, + join => 1, ); GetOptions(\%options, 'queue|q=s', + 'batch=s', 'interactive|I!', 'nodes=i', 'array=s', @@ -105,7 +123,9 @@ GetOptions(\%options, 'array_per_job|array-per-job=i', 'array_slot_limit|array-slot-limit=i', 'array_all_in_one_job|array-all-in-one-job!', - 'ppn|processors-per-node=i', + 'ppn|cpus|processors-per-node=i', + 'account|A=s', + 'join|J!', 'mem|memory=s', 'time|walltime=s','cputime|cput=s','host=s', 'pmem|process_mem|process-mem=s', @@ -135,15 +155,44 @@ if ($options{interactive} and @ARGV) { push @USAGE_ERRORS,"Don't provide commands when you're asking for an interactive shell"; } +if (not defined $options{batch}) { + qx/which sbatch/; + if ($?) { + $options{batch} = 'slurm' + } else { + $options{batch} = 'pbs' + } +} + +if ($options{batch} !~ /^pbs|slurm$/) { + push @USAGE_ERRORS,"Unsupported batch system '$options{batch}'; ". + "supported systems are pbs or slurm"; +} + # pod2usage(join("\n",@USAGE_ERRORS)) if @USAGE_ERRORS; -print STDERR join("\n",@USAGE_ERRORS) and exit 1 if @USAGE_ERRORS; +if (@USAGE_ERRORS) { + print STDERR map {"$_\n"} @USAGE_ERRORS; + exit 1; +} + +my $JOB_SUBMITTER = 'qsub'; # OK. Generate the options to qsub which we'll be using -my @qsub_options = generate_qsub_options(\%options,\@ARGV); +my @qsub_options; +if ($options{batch} eq 'pbs') { + @qsub_options = generate_qsub_options(\%options,\@ARGV); + $JOB_SUBMITTER = 'qsub'; +} elsif ($options{batch} eq 'slurm') { + @qsub_options = generate_slurm_options(\%options,\@ARGV); + $JOB_SUBMITTER = 'sbatch'; +} else { + die "Unsupported batch system '$options{batch}'"; +} + if ($options{interactive}) { print STDERR 'running: qsub '.join(' ',@qsub_options) if $DEBUG; - exec('qsub',@qsub_options); + exec($JOB_SUBMITTER,@qsub_options); } else { my @array = (); if ($options{array}) { @@ -158,6 +207,9 @@ if ($options{interactive}) { } } } + if ($options{batch} eq 'pbs') { + push @qsub_options,'-'; + } call_qsub(\@qsub_options,write_qsub_script(\%options,\@ARGV,\@array)); } @@ -167,17 +219,15 @@ sub generate_qsub_options{ if (defined $options->{queue} and length $options->{queue}) { push @qo,'-q',$options->{queue}; } - if (defined $options->{dir}) { - push @qo,'-d',abs_path($options->{dir}); - } else { - push @qo,'-d',getcwd; - } ## handle the -l options my @l; push @l, 'nodes='.$options->{nodes}; if (defined $options->{ppn}) { $l[$#l] .= ':ppn='.$options->{ppn}; } + if (defined $options->{account}) { + push @qo,'-A',$options->{account}; + } my %l_options = (mem => 'vmem', time => 'walltime', @@ -199,7 +249,58 @@ sub generate_qsub_options{ if ($options->{name}) { push @qo,'-N',$options->{name}; } else { - push @qo,'-N',join('_',@{$args}[0..min($#{$args},2)]); + push @qo,'-N',join('_', + map {my $a = $_; $a =~ s/[^a-zA-Z0-9]*//g; $a;} + @{$args}[0..min($#{$args},2)]); + } + # join error and output streams + if ($options->{join}) { + push @qo,'-j','oe'; + } + return @qo; +} + +sub generate_slurm_options{ + my ($options,$args) = @_; + my @qo; + if (defined $options->{queue} and length $options->{queue}) { + push @qo,'-p',$options->{queue}; + } + ## handle the -l options + if (defined $options->{account}) { + push @qo,'-A',$options->{account}; + } + my %options_map = + (mem => 'mem', + ppn => 'cpus-per-task', + time => 'time', + cputime => 'cput', + host => 'host', + pmem => 'pmem', + pvmem => 'pvmem', + max_file => 'file', + ); + for my $k (keys %options_map) { + if ($options->{$k}) { + push @qo,'--'.$options_map{$k}.'=',$options{$k}; + } + } + if ($options{mem}) { + push @qo,'--mem=',$options{mem}; + } + if ($options->{interactive}) { + push @qo,'-I'; + } + if ($options->{name}) { + push @qo,'-J',$options->{name}; + } else { + push @qo,'-J',join('_', + map {my $a = $_; $a =~ s/[^a-zA-Z0-9]*//g; $a;} + @{$args}[0..min($#{$args},2)]); + } + # join error and output streams + if ($options->{join}) { + push @qo,'-j','oe'; } return @qo; } @@ -222,27 +323,43 @@ sub read_array_options{ sub call_qsub { my ($qsub_options,$script) = @_; my $qsub_fh; - open $qsub_fh,'|-','qsub',@{$qsub_options},'-' or - die "Unable to start qsub: $!"; + open $qsub_fh,'|-',$JOB_SUBMITTER,@{$qsub_options} or + die "Unable to start $JOB_SUBMITTER: $!"; print {$qsub_fh} $script or - die "Unable to print to qsub: $!"; + die "Unable to print to $JOB_SUBMITTER: $!"; close($qsub_fh) or - die "Unable to close qsub filehandle: $!"; + die "Unable to close $JOB_SUBMITTER filehandle: $!"; } sub write_qsub_script { my ($opt,$arg,$array) = @_; my $script = "#!/bin/bash\n"; - my $command = join(' ',map {qq('$_')} @{$arg}); + my $command = join(' ',map {$_ =~ /\s/?qq('$_'):$_} @{$arg}); $script .= <{dir}) { + $directory = abs_path($opt->{dir}); + } + # we really should be quoting this instead + $script .=<{array}) { my @subshell = ('',''); my $array_opt = join("\n",@{$array}); my $max_array = scalar @{$array}; my $apjm1 = $opt->{array_per_job} - 1; + $script .= <{array_per_job} > 1) { # we will use subshells if there are more than one array # items per job @@ -250,13 +367,13 @@ EOF $script .= <{array_per_job}); do # in some cases, the jobs aren't going to come out evenly. Handle that. -JOBNUM=\$(( \${PBS_ARRAYID:=1} * $opt->{array_per_job} + \$i - $opt->{array_per_job} )) +JOBNUM=\$(( \${MYARRAYID:=1} * $opt->{array_per_job} + \$i - $opt->{array_per_job} )) if [ \$JOBNUM -le $max_array ]; then OPT=\$(sed -n -e "\$JOBNUM p"<<'_HERE_DOC_END_' EOF } else { $script .= <