has
'submit_command'
=> (
is
=>
'rw'
,
isa
=>
'Str'
,
default
=>
'qsub'
,
);
has
'template_file'
=> (
is
=>
'rw'
,
isa
=>
'Str'
,
default
=>
sub
{
my
$self
=
shift
;
my
(
$fh
,
$filename
) = tempfile();
my
$tt
=
<<EOF;
#!/usr/bin/env bash
#
#PBS -N [% JOBNAME %]
[% IF job.has_queue %]
#PBS -q [% job.queue %]
[% END %]
#PBS -l nodes=[% job.nodes_count %]:ppn=[% job.cpus_per_task %]
[% IF job.has_walltime %]
#PBS -l walltime=[% job.walltime %]
[% END %]
#PBS -j oe
#PBS -o localhost:[% OUT %]
[% IF job.has_mem %]
#PBS -l mem=[% job.mem %]
[% END %]
[% IF ARRAY_STR %]
[% PERL %]
my \$stash = \$context->stash;
my \$array_str=\$stash->get('ARRAY_STR');
my \@array = split(':', \$array_str);
my \$step = \$array[1];
\@array = split('-', \$array[0]);
if(\$step == 1){
print PERLOUT "\n#PBS -J=".\$array[0]."-".\$array[1];
}
else{
my \@new_array = ();
for(my \$x=\$array[0]; \$x <= \$array[1]; \$x = \$x + \$step){
push(\@new_array, \$x);
}
print PERLOUT "\n#PBS -J=".join(',', \@new_array);
}
[% END %]
[% END %]
EOF
if
(
$self
->use_batches ) {
$tt
.=
<<EOF;
[% IF AFTEROK %]
#PBS -W depend=afterok:[% AFTEROK %]
[% END %]
EOF
}
else
{
$tt
.=
<<EOF;
[% IF AFTEROK %]
[% PERL %]
my \$stash = \$context->stash;
my \$afterok=\$stash->get('AFTEROK');
my \@array = split(':', \$afterok);
foreach my \$a (\@array){
\$a = \$a."[]";
}
my \$newafterok = join(':', \@array);
print PERLOUT "\n#PBS -W depend=afterokarray:\$newafterok"
[% END %]
[% END %]
EOF
}
$tt
.=
<<EOF;
[% IF MODULES %]
module load [% MODULES %]
[% END %]
[% IF job.has_conda_env %]
source activate [% job.conda_env %]
[% END %]
[% COMMAND %]
EOF
print
$fh
$tt
;
return
$filename
;
},
predicate
=>
'has_template_file'
,
clearer
=>
'clear_template_file'
,
documentation
=>
q{Path to Slurm template file if you do not wish to use the default}
);
has
'log'
=> (
is
=>
'rw'
,
default
=>
sub
{
my
$log_conf
=
q(
log4perl.rootLogger = DEBUG, Screen
log4perl.appender.Screen = \
Log::Log4perl::Appender::ScreenColoredLevels
log4perl.appender.Screen.layout = \
Log::Log4perl::Layout::PatternLayout
log4perl.appender.Screen.layout.ConversionPattern = \
[%d] %m %n
)
;
Log::Log4perl::init( \
$log_conf
);
return
Log::Log4perl->get_logger();
}
);
sub
submit_jobs {
my
$self
=
shift
;
my
(
$exitcode
,
$stdout
,
$stderr
) =
$self
->submit_to_scheduler(
$self
->submit_command .
" "
.
$self
->slurmfile );
sleep
(5);
if
(
$exitcode
!= 0 ) {
$self
->
log
->fatal(
"Job was not submitted successfully"
);
$self
->
log
->
warn
(
"STDERR: "
.
$stderr
)
if
$stderr
;
$self
->
log
->
warn
(
"STDOUT: "
.
$stdout
)
if
$stdout
;
}
my
$jobid
=
$stdout
;
if
( !
$jobid
) {
$self
->job_failure;
}
else
{
$self
->
log
->debug(
"Submited job "
.
$self
->slurmfile .
"\n\tWith PBS jobid $jobid"
);
}
return
$jobid
;
}
sub
update_job_deps {
my
$self
=
shift
;
return
unless
$self
->has_array_deps;
$self
->
log
->
warn
(
'Task dependencies in PBS is still very experimental!'
);
$self
->
log
->
warn
(
'Please raise any problems as an issue at github.'
.
"\n"
while
(
my
(
$current_task
,
$v
) =
each
%{
$self
->array_deps } ) {
my
$cmd
;
if
(
$self
->use_batches ) {
my
$dep_tasks
=
join
(
':'
,
@$v
);
$cmd
=
"qalter $current_task -W depend=afterok:$dep_tasks"
;
}
else
{
foreach
my
$tv
( @{
$v
} ) {
$tv
=~ s/\n//;
my
@tmp
=
split
(
'_'
,
$tv
);
my
$dep_scheduler_id
=
$self
->parse_pbs_scheduler_id(
$tmp
[0],
$tmp
[1] );
$tv
=
$dep_scheduler_id
;
}
my
@tmp
=
split
(
'_'
,
$current_task
);
my
$current_scheduler_id
=
$self
->parse_pbs_scheduler_id(
$tmp
[0],
$tmp
[1] );
my
$dep_tasks
=
join
(
':'
,
@$v
);
$dep_tasks
=
'"'
.
$dep_tasks
.
'"'
;
$cmd
=
"qalter \"$current_scheduler_id\" -W depend=afterokarray:$dep_tasks"
;
}
$self
->submit_to_scheduler(
$cmd
);
}
}
sub
parse_pbs_scheduler_id {
my
$self
=
shift
;
my
$pbs_scheduler_id
=
shift
;
my
$task
=
shift
;
my
@split_host
=
split
(
'\.'
,
$pbs_scheduler_id
);
my
$scheduler_id
=
shift
@split_host
;
$scheduler_id
=~ s/\[\]//;
my
$host
=
join
(
'.'
,
@split_host
);
my
$current_scheduler_id
=
$scheduler_id
.
'['
.
$task
.
'].'
.
$host
;
return
$current_scheduler_id
;
}
1;