2010-07-22 20 views
10

Ho una funzione (modello di rete neurale) che produce figure. Desidero testare diversi parametri, metodi e input diversi (ovvero centinaia di esecuzioni della funzione) da python usando PBS su un cluster standard con Torque.programmazione "imbarazzantemente parallela" usando python e PBS su un cluster

Nota: ho provato parallelpython, ipython e simili e non sono mai stato completamente soddisfatto, poiché desidero qualcosa di più semplice. Il cluster è in una data configurazione che non posso cambiare e una tale soluzione che integra python + qsub sarà sicuramente di beneficio per la comunità.

Per semplificare le cose, ho una semplice funzione come:

import myModule 
def model(input, a= 1., N=100): 
    do_lots_number_crunching(input, a,N) 
    pylab.savefig('figure_' + input.name + '_' + str(a) + '_' + str(N) + '.png') 

dove input è un oggetto che rappresenta l'ingresso, input.name è una stringa, e do_lots_number_crunching può durare ore.

La mia domanda è: esiste un modo corretto per trasformare qualcosa di simile a una scansione di parametri quali

for a in pylab.linspace(0., 1., 100): 
    model(input, a) 

in "qualcosa" che avrebbe lanciato uno script PBS per ogni chiamata alla funzione model?

#PBS -l ncpus=1 
#PBS -l mem=i1000mb 
#PBS -l cput=24:00:00 
#PBS -V 
cd /data/work/ 
python experiment_model.py 

Stavo pensando a una funzione che dovrebbe includere il modello PBS e chiamarlo dallo script python, ma non poteva ancora capirlo (decoratore?).

risposta

4

pbs_python [1] potrebbe funzionare per questo. Se experiment_model.py 'a' come argomento si potrebbe fare

import pbs, os 

server_name = pbs.pbs_default() 
c = pbs.pbs_connect(server_name) 

attopl = pbs.new_attropl(4) 
attropl[0].name = pbs.ATTR_l 
attropl[0].resource = 'ncpus' 
attropl[0].value = '1' 

attropl[1].name = pbs.ATTR_l 
attropl[1].resource = 'mem' 
attropl[1].value = 'i1000mb' 

attropl[2].name = pbs.ATTR_l 
attropl[2].resource = 'cput' 
attropl[2].value = '24:00:00' 

attrop1[3].name = pbs.ATTR_V 

script=''' 
cd /data/work/ 
python experiment_model.py %f 
''' 

jobs = [] 

for a in pylab.linspace(0.,1.,100): 
    script_name = 'experiment_model.job' + str(a) 
    with open(script_name,'w') as scriptf: 
     scriptf.write(script % a) 
    job_id = pbs.pbs_submit(c, attropl, script_name, 'NULL', 'NULL') 
    jobs.append(job_id) 
    os.remove(script_name) 

print jobs 
[1]

: https://oss.trac.surfsara.nl/pbs_python/wiki/TorqueUsage pbs_python

3

Lo si può fare facilmente usando jug (che ho sviluppato per una configurazione simile).

devi scrivere in un file (ad esempio, model.py):

@TaskGenerator 
def model(param1, param2): 
    res = complex_computation(param1, param2) 
    pyplot.coolgraph(res) 


for param1 in np.linspace(0, 1.,100): 
    for param2 in xrange(2000): 
     model(param1, param2) 

E questo è tutto!

Ora è possibile avviare "job jug" sulla coda: jug execute model.py e questo verrà automaticamente parallelo. Quello che succede è che ogni lavoro sarà in, un loop, fare qualcosa di simile:

while not all_done(): 
    for t in tasks in tasks_that_i_can_run(): 
     if t.lock_for_me(): t.run() 

(In realtà è più complicato di così, ma si ottiene il punto).

Utilizza il filesystem per il blocco (se si è su un sistema NFS) o un server redis se si preferisce. Può anche gestire le dipendenze tra le attività.

Questo non è esattamente quello che hai chiesto, ma credo che sia un'architettura più pulita per separare questo dal sistema di messa in coda del lavoro.

2

Sembra che io sia un po 'in ritardo per la festa, ma ho anche avuto la stessa domanda su come mappare problemi imbarazzanti paralleli su un cluster in Python alcuni anni fa e ho scritto la mia soluzione.Recentemente ho caricato su GitHub qui: https://github.com/plediii/pbs_util

per scrivere il programma con pbs_util, desidero innanzitutto creare un pbs_util.ini nella directory di lavoro contenente

[PBSUTIL] 
numnodes=1 
numprocs=1 
mem=i1000mb 
walltime=24:00:00 

Poi uno script python come questo

import pbs_util.pbs_map as ppm 

import pylab 
import myModule 

class ModelWorker(ppm.Worker): 

    def __init__(self, input, N): 
     self.input = input 
     self.N = N 

    def __call__(self, a): 
     myModule.do_lots_number_crunching(self.input, a, self.N) 
     pylab.savefig('figure_' + self.input.name + '_' + str(a) + '_' + str(self.N) + '.png') 



# You need "main" protection like this since pbs_map will import this file on the  compute nodes 
if __name__ == "__main__": 
    input, N = something, picklable 
    # Use list to force the iterator 
    list(ppm.pbs_map(ModelWorker, pylab.linspace(0., 1., 100), 
        startup_args=(input, N), 
        num_clients=100)) 

E lo farebbe.

0

Ho appena iniziato a lavorare con i cluster e le applicazioni EP. Il mio obiettivo (sono con la biblioteca) è di imparare abbastanza da aiutare altri ricercatori nel campus ad accedere a HPC con applicazioni EP ... specialmente i ricercatori al di fuori di STEM. Sono ancora molto nuovo, ma ho pensato che potrebbe aiutare questa domanda a sottolineare l'uso di GNU Parallel in uno script PBS per lanciare script Python di base con vari argomenti. Nel file .pbs, ci sono due linee di segnalo:

module load gnu-parallel # this is required on my environment 

parallel -j 4 --env PBS_O_WORKDIR --sshloginfile $PBS_NODEFILE \ 
--workdir $NODE_LOCAL_DIR --transfer --return 'output.{#}' --clean \ 
`pwd`/simple.py '{#}' '{}' ::: $INPUT_DIR/input.* 

# `-j 4` is the number of processors to use per node, will be cluster-specific 
# {#} will substitute the process number into the string 
# `pwd`/simple.py `{#}` `{}` this is the command that will be run multiple times 
# ::: $INPUT_DIR/input.* all of the files in $INPUT_DIR/ that start with 'input.' 
#  will be substituted into the python call as the second(3rd) argument where the 
#  `{}` resides. These can be simple text files that you use in your 'simple.py' 
#  script to pass the parameter sets, filenames, etc. 

Come newby al PE supercalcolo, anche se non capisco ancora tutte le altre opzioni in "parallelo", questo comando mi ha permesso di lanciare script Python in parallelo con diversi parametri. Ciò funzionerebbe bene se si riuscisse a generare un gran numero di file di parametri in anticipo che parallelizzeranno il problema. Ad esempio, eseguendo simulazioni attraverso uno spazio parametrico. O elaborando molti file con lo stesso codice.