#!/usr/bin/perl # # 2011/11/03 gabriel use strict; use Getopt::Long(); use Pod::Usage; use Coro; use Coro::Signal; use Coro::Semaphore; my $task = 0; my $overload = 1.1; my $file = ''; my $verbose; my $help; Getopt::Long::GetOptions( 'task=i' => \$task, 'overload=f' => \$overload, 'file=s' => \$file, 'verbose' => \$verbose, 'help' => \$help, ) || pod2usage(-verbose => 0); pod2usage(-verbose => 2) if $help; if ($task == 0) { open(NODE_FILE, '<', "$ENV{OAR_NODE_FILE}") or die "can't open ENV{OAR_NODE_FILE}: $!"; $task++ while ; close NODE_FILE; } my @job = (); open (JOB_LIST, '<', "$file") or die "can't open $file: $!"; while () { chomp; next if m/^#/; push @job, $_ if m/^\s*oarsub/; } close JOB_LIST; my $container_id=$ENV{OAR_JOB_ID}; my $insert_oar_option = "-t inner=$container_id"; # interactive job if (not $container_id > 1) { $insert_oar_option = ''; $overload = 1; } my $finished = new Coro::Signal; my $job_active = new Coro::Semaphore 0; my $job_todo = new Coro::Semaphore 0; $job_todo->up for (@job); my %scheduled = (); async { for my $job (@job) { while ($job_active->count >= $task*$overload) { cede; } $job =~ s/^\s*oarsub//; print "oarsub $insert_oar_option $job" if $verbose; my $job_id = `oarsub $insert_oar_option $job|grep ^OAR_JOB_ID|cut -f 2 -d '='`; chomp $job_id; if ($job_id > 1) { $scheduled{$job_id}++; $job_active->up; } cede; } } async { while () { for my $job_id (keys %scheduled) { my $is_finish = `oarstat -s -j $job_id`; chomp $is_finish; if ($is_finish =~ m/Terminated/) { delete $scheduled{$job_id}; $job_active->down; $job_todo->down; } cede; } $finished->send if $job_todo->count == 0; cede; } } cede; $finished->wait; __END__ =head1 NAME oar-dispatch - dispatch lot of small oar job =head1 SYNOPSIS oar-dispatch [--core integer] [--overload real] --file filepath [--verbose] oar-dispatch --help =head1 OPTIONS --task number of task to do in parallel. default to line number of file OAR_NODE_FILE. --overload number of OAR job to create / number of task. Some job are create in advance to start whenever it's possible. 1.1 by default. --file file name which content OAR job list --verbose --help Input job file name content can have - empty line - comment line begin with # - oarsub command without -t option C will add C<-t inner=container_id> in this command line, just after C. Example where F<$HOME/test/subjob.txt> is a list of OAR script job (and can be executable but not need here). oarsub -n test -l /core=1,walltime=00:05:00 $HOME/test/subjob1.oar oarsub -n test -l /core=1,walltime=00:05:00 $HOME/test/subjob2.oar oarsub -n test -l /core=1,walltime=00:05:00 $HOME/test/subjob3.oar oarsub -n test -l /core=1,walltime=00:05:00 $HOME/test/subjob4.oar ... oarsub -n test -l /core=1,walltime=00:05:00 $HOME/test/subjob38.oar oarsub -n test -l /core=1,walltime=00:05:00 $HOME/test/subjob39.oar oarsub -n test -l /core=1,walltime=00:05:00 $HOME/test/subjob40.oar These jobs could be launch with oarsub -t container -n test-container -l /core=6,walltime=00:35:00 "oar-dispatch -f ./subjob.list.txt" Total C is defined by the formula: total_walltime = subjob_walltime * total_subjob / core + global_delay In practise, C take few second and each subjob run in less than it's walltime so total_walltime < subjob_walltime * total_subjob / core If launch in interactif, C parameter is equal to 1, C must be define and no inner container is add to the C command line. =head1 SEE ALSO oar-parexec, mpilauncher =head1 AUTHORS Written by Gabriel Moreau, Grenoble - France =head1 LICENSE AND COPYRIGHT GPL version 2 or later and Perl equivalent Copyright (C) 2011 Gabriel Moreau / LEGI - CNRS UMR 5519 - France