<?xml version="1.0" encoding="utf-8"?><!DOCTYPE article  PUBLIC '-//OASIS//DTD DocBook XML V4.4//EN'  'http://www.docbook.org/xml/4.4/docbookx.dtd'><article><articleinfo><title>InfolabClusterComputeHowtoJobArray</title><revhistory><revision><revnumber>3</revnumber><date>2012-10-17 04:13:36</date><authorinitials>akrevl</authorinitials></revision><revision><revnumber>2</revnumber><date>2012-10-17 04:11:24</date><authorinitials>akrevl</authorinitials></revision><revision><revnumber>1</revnumber><date>2012-10-17 04:00:16</date><authorinitials>akrevl</authorinitials></revision></revhistory></articleinfo><para>Here is a hypothetical... you have one program that is not multi-threaded nor aware of multiple cores. You have to run that program about a thousand times with different input parameters and different input data. And luckily... the results of a single run are independent of all the other results. This HOWTO describes how one might run such a scenario on the <ulink url="http://snap.stanford.edu/moin/InfolabClusterComputeHowtoJobArray/moin/InfolabClusterCompute#">Infolab Compute Cluster</ulink>.  </para><para>We presume that you know your <emphasis>qsub</emphasis> basics. If that is not the case, please see <ulink url="http://snap.stanford.edu/moin/InfolabClusterComputeHowtoJobArray/moin/InfolabClusterComputeHowtoSingle#">InfolabClusterComputeHowtoSingle</ulink> and <ulink url="http://snap.stanford.edu/moin/InfolabClusterComputeHowtoJobArray/moin/InfolabClusterComputeHowtoVariables#">InfolabClusterComputeHowtoVariables</ulink> first.  </para><section><title>The submission script</title><para>We'll tackle this one the other way around. So let's create our submission script first. You can download the script here: <ulink url="http://snap.stanford.edu/moin/InfolabClusterComputeHowtoJobArray/moin/InfolabClusterComputeHowtoJobArray?action=AttachFile&amp;do=get&amp;target=JobArray.qsub.sh">JobArray.qsub.sh</ulink> </para><programlisting format="linespecific" language="highlight" linenumbering="numbered" startinglinenumber="1"><lineannotation><![CDATA[#!/bin/bash]]></lineannotation>
<lineannotation></lineannotation><lineannotation><![CDATA[#PBS -N JobArray]]></lineannotation>
<lineannotation></lineannotation><lineannotation><![CDATA[#PBS -l nodes=1:ppn=1]]></lineannotation>
<lineannotation></lineannotation><lineannotation><![CDATA[#PBS -l walltime=00:01:00]]></lineannotation>
<lineannotation></lineannotation>
<![CDATA[/usr/bin/python2.7 ]]><methodname><![CDATA[$HOME]]></methodname><![CDATA[/tutorial/JobArray/JobArray.py ]]><methodname><![CDATA[$PBS_ARRAYID]]></methodname><![CDATA[ ]]>
</programlisting><para>The only special thing here is that we'll be passing the array id (so the number of the job in the array) to our Python script. </para></section><section><title>The program</title><para>Again we are using the same simple Python script that sleeps for a while and outputs some time and the arguments that it was called with. You can download the script here: <ulink url="http://snap.stanford.edu/moin/InfolabClusterComputeHowtoJobArray/moin/InfolabClusterComputeHowtoJobArray?action=AttachFile&amp;do=get&amp;target=JobArray.py">JobArray.py</ulink> </para><programlisting format="linespecific" language="highlight" linenumbering="numbered" startinglinenumber="1"><lineannotation><![CDATA[#!/usr/bin/python2.7]]></lineannotation>

<token><![CDATA[import]]></token><![CDATA[ ]]><methodname><![CDATA[socket]]></methodname><![CDATA[, ]]><methodname><![CDATA[datetime]]></methodname><![CDATA[, ]]><methodname><![CDATA[time]]></methodname><![CDATA[, ]]><methodname><![CDATA[getpass]]></methodname><![CDATA[, ]]><methodname><![CDATA[sys]]></methodname>

<methodname><![CDATA[arrayid]]></methodname><![CDATA[ = ]]><methodname><![CDATA[sys]]></methodname><![CDATA[.]]><methodname><![CDATA[argv]]></methodname><![CDATA[[1]]]>

<lineannotation><![CDATA[# We're using just using a simple list here but you can]]></lineannotation>
<lineannotation><![CDATA[# easily imagine this getting read from a file or sth ...]]></lineannotation>
<methodname><![CDATA[arguments]]></methodname><![CDATA[ = []]>
<![CDATA[  [ ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[myarg1-0]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[, ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[myarg2-0]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[, ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[myarg3-0]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[ ],]]>
<![CDATA[  [ ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[myarg1-1]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[, ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[myarg2-1]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[, ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[myarg3-1]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[ ],]]>
<![CDATA[  [ ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[myarg1-2]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[, ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[myarg2-2]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[, ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[myarg3-2]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[ ],]]>
<![CDATA[  [ ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[myarg1-3]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[, ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[myarg2-3]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[, ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[myarg3-3]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[ ]]]>
<![CDATA[]]]>

<methodname><![CDATA[start]]></methodname><![CDATA[ = ]]><methodname><![CDATA[datetime]]></methodname><![CDATA[.]]><methodname><![CDATA[datetime]]></methodname><![CDATA[.]]><methodname><![CDATA[now]]></methodname><![CDATA[()]]>
<methodname><![CDATA[hostname]]></methodname><![CDATA[ = ]]><methodname><![CDATA[socket]]></methodname><![CDATA[.]]><methodname><![CDATA[gethostname]]></methodname><![CDATA[().]]><methodname><![CDATA[split]]></methodname><![CDATA[(]]><phrase><![CDATA[']]></phrase><phrase><![CDATA[.]]></phrase><phrase><![CDATA[']]></phrase><![CDATA[)[0]]]>
<methodname><![CDATA[username]]></methodname><![CDATA[ = ]]><methodname><![CDATA[getpass]]></methodname><![CDATA[.]]><methodname><![CDATA[getuser]]></methodname><![CDATA[()]]>
<methodname><![CDATA[time]]></methodname><![CDATA[.]]><methodname><![CDATA[sleep]]></methodname><![CDATA[(10)]]>
<methodname><![CDATA[end]]></methodname><![CDATA[ = ]]><methodname><![CDATA[datetime]]></methodname><![CDATA[.]]><methodname><![CDATA[datetime]]></methodname><![CDATA[.]]><methodname><![CDATA[now]]></methodname><![CDATA[()]]>

<methodname><![CDATA[dfmt]]></methodname><![CDATA[ = ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[%]]></phrase><phrase><![CDATA[Y-]]></phrase><phrase><![CDATA[%]]></phrase><phrase><![CDATA[m-]]></phrase><phrase><![CDATA[%d]]></phrase><phrase><![CDATA[ ]]></phrase><phrase><![CDATA[%]]></phrase><phrase><![CDATA[H:]]></phrase><phrase><![CDATA[%]]></phrase><phrase><![CDATA[M:]]></phrase><phrase><![CDATA[%]]></phrase><phrase><![CDATA[S]]></phrase><phrase><![CDATA["]]></phrase>
<token><![CDATA[print]]></token><![CDATA[ ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[Started: ]]></phrase><phrase><![CDATA[%s]]></phrase><phrase><![CDATA[ Finished: ]]></phrase><phrase><![CDATA[%s]]></phrase><phrase><![CDATA[ Host: ]]></phrase><phrase><![CDATA[%s]]></phrase><phrase><![CDATA[ User: ]]></phrase><phrase><![CDATA[%s]]></phrase><phrase><![CDATA["]]></phrase><![CDATA[ % (]]><methodname><![CDATA[start]]></methodname><![CDATA[.]]><methodname><![CDATA[strftime]]></methodname><![CDATA[(]]><methodname><![CDATA[dfmt]]></methodname><![CDATA[), ]]><methodname><![CDATA[end]]></methodname><![CDATA[.]]><methodname><![CDATA[strftime]]></methodname><![CDATA[(]]><methodname><![CDATA[dfmt]]></methodname><![CDATA[), ]]><methodname><![CDATA[hostname]]></methodname><![CDATA[, ]]><methodname><![CDATA[username]]></methodname><![CDATA[)]]>
<token><![CDATA[print]]></token><![CDATA[ ]]><phrase><![CDATA["]]></phrase><phrase><![CDATA[My arguments:]]></phrase><phrase><![CDATA["]]></phrase>
<token><![CDATA[print]]></token><![CDATA[ ]]><methodname><![CDATA[arguments]]></methodname><![CDATA[ []]><token><![CDATA[int]]></token><![CDATA[(]]><methodname><![CDATA[arrayid]]></methodname><![CDATA[)]]]>
</programlisting><para>The only twist is, that we are reading the actual arguments from the list provided in the script itself. This could be easily replaced by reading from a cvs file or some other, neater argument storage. </para></section><section><title>Submit the job</title><para>Nothing left to do but submit the job to the cluster with <emphasis>qsub</emphasis>: </para><screen><![CDATA[qsub -V -t 0-3 $HOME/tutorial/JobArray/JobArray.qsub.sh]]></screen><para>There is a few things to note about the <emphasis>-t</emphasis> argument. This argument specifies that we the job should be run as a job array. In addition to that it also specifies the array ids that our instabces will get. When we run the command above we'll get instances 0, 1, 2, 3 respectively. We could also specify those as a comma delimited list. The following command does the same thing as the previous one: </para><screen><![CDATA[qsub -V -t 0,1,2,3 $HOME/tutorial/JobArray/JobArray.qsub.sh]]></screen><para>We could also make up our own non-sequential ids: </para><screen><![CDATA[qsub -V -t 111,211,311,411 $HOME/tutorial/JobArray/JobArray.qsub.sh]]></screen><para>Anyhow, if our jobs ran successfully, we should be able to see the results in the output files. In our case: </para><screen><![CDATA[~/ $ cat *.o*
Started: 2012-10-16 21:01:12 Finished: 2012-10-16 21:01:22 Host: iln28 User: akrevl
My arguments:
['myarg1-0', 'myarg2-0', 'myarg3-0']
Started: 2012-10-16 21:01:12 Finished: 2012-10-16 21:01:22 Host: iln28 User: akrevl
My arguments:
['myarg1-1', 'myarg2-1', 'myarg3-1']
Started: 2012-10-16 21:01:12 Finished: 2012-10-16 21:01:22 Host: iln28 User: akrevl
My arguments:
['myarg1-2', 'myarg2-2', 'myarg3-2']
Started: 2012-10-16 21:01:13 Finished: 2012-10-16 21:01:23 Host: iln28 User: akrevl
My arguments:
['myarg1-3', 'myarg2-3', 'myarg3-3']]]></screen><para>So we successfully ran four instances of our script with 4 different sets of arguments. Of course this is only one way of doing things... but it seems to work... </para></section></article>