2015-05-21 10 views
7

Sto cercando di eseguire un'ottimizzazione parallela usando PyOpt. La parte difficile è che all'interno della mia funzione obiettivo, voglio eseguire un codice C++ usando anche mpi.Python con chiamata integrata a mpirun

Il mio script python è la seguente:

#!/usr/bin/env python  
# Standard Python modules 
import os, sys, time, math 
import subprocess 


# External Python modules 
try: 
    from mpi4py import MPI 
    comm = MPI.COMM_WORLD 
    myrank = comm.Get_rank() 
except: 
    raise ImportError('mpi4py is required for parallelization') 

# Extension modules 
from pyOpt import Optimization 
from pyOpt import ALPSO 

# Predefine the BashCommand 
RunCprogram = "mpirun -np 2 CProgram" # Parallel C++ program 


######################### 
def objfunc(x): 

    f = -(((math.sin(2*math.pi*x[0])**3)*math.sin(2*math.pi*x[1]))/((x[0]**3)*(x[0]+x[1]))) 

    # Run CProgram 
    os.system(RunCprogram) #where the mpirun call occurs 

    g = [0.0]*2 
    g[0] = x[0]**2 - x[1] + 1 
    g[1] = 1 - x[0] + (x[1]-4)**2 

    time.sleep(0.01) 
    fail = 0 
    return f,g, fail 

# Instantiate Optimization Problem 
opt_prob = Optimization('Thermal Conductivity Optimization',objfunc) 
opt_prob.addVar('x1','c',lower=5.0,upper=1e-6,value=10.0) 
opt_prob.addVar('x2','c',lower=5.0,upper=1e-6,value=10.0) 
opt_prob.addObj('f') 
opt_prob.addCon('g1','i') 
opt_prob.addCon('g2','i') 

# Solve Problem (DPM-Parallelization) 
alpso_dpm = ALPSO(pll_type='DPM') 
alpso_dpm.setOption('fileout',0) 
alpso_dpm(opt_prob) 
print opt_prob.solution(0) 

corro che il codice utilizzando:

mpirun -np 20 python Script.py 

Tuttavia, sto ottenendo il seguente errore:

[user:28323] *** Process received signal *** 
[user:28323] Signal: Segmentation fault (11) 
[user:28323] Signal code: Address not mapped (1) 
[user:28323] Failing at address: (nil) 
[user:28323] [ 0] /lib64/libpthread.so.0() [0x3ccfc0f500] 
[user:28323] *** End of error message *** 

Ho capito che, le 2 diverse chiamate mpirun (quella che chiama lo script python e quella all'interno del script) sono in conflitto tra loro. Qualche vantaggio su come risolverlo?

Grazie !!

+0

ti scambio di dati tra i processi di pitone utilizzando comunicazioni MPI o sei solo utilizzando 'mpi4py' di eseguire più istanze isolate. Se questo è il caso, puoi prendere in considerazione l'uso del modulo 'subprocess' in python per generare thread multipli, ognuno dei quali può chiamare un'istanza' mpirun' (usando 'subprocess.Popen'). Lo faccio spesso e non ho avuto problemi. Se stai eseguendo 'Script.py' su più macchine questo potrebbe non essere possibile ... –

risposta

1

Vedere Calling mpi binary in serial as subprocess of mpi application: il modo più sicuro è utilizzare MPI_Comm_spawn(). Dai un'occhiata allo this manager-worker example per esempio.

Una soluzione rapida sarebbe utilizzare subprocess.Popen come segnalato da @EdSmith. Tuttavia, si noti che il comportamento predefinito di subprocess.Popen utilizza l'ambiente del genitore. La mia ipotesi è che sia lo stesso per os.system(). Sfortunatamente, mpirun aggiunge alcune variabili di ambiente, a seconda dell'implementazione di MPI, come ad esempio OMPI_COMM_WORLD_RANK o OMPI_MCA_orte_ess_num_procs. Per visualizzare queste variabili di ambiente, digitare import os ; print os.environ in un codice mpi4py e in una shell python di base. Queste variabili di ambiente possono portare a un fallimento del sottoprocesso. Così ho dovuto aggiungere una linea di sbarazzarsi di loro ... che è piuttosto sporca ... Si riduce a:

args = shlex.split(RunCprogram) 
    env=os.environ 
    # to remove all environment variables with "MPI" in it...rather dirty... 
    new_env = {k: v for k, v in env.iteritems() if "MPI" not in k} 

    #print new_env 
    # shell=True : watch for security issues... 
    p = subprocess.Popen(RunCprogram,shell=True, env=new_env,stdout=subprocess.PIPE, stdin=subprocess.PIPE) 
    p.wait() 
    result="process myrank "+str(myrank)+" got "+p.stdout.read() 
    print result 

codice di prova completa, imbattuto da mpirun -np 2 python opti.py:

#!/usr/bin/env python  
# Standard Python modules 
import os, sys, time, math 
import subprocess 
import shlex 


# External Python modules 
try: 
    from mpi4py import MPI 
    comm = MPI.COMM_WORLD 
    myrank = comm.Get_rank() 
except: 
    raise ImportError('mpi4py is required for parallelization') 

# Predefine the BashCommand 
RunCprogram = "mpirun -np 2 main" # Parallel C++ program 


######################### 
def objfunc(x): 

    f = -(((math.sin(2*math.pi*x[0])**3)*math.sin(2*math.pi*x[1]))/((x[0]**3)*(x[0]+x[1]))) 

    # Run CProgram 
    #os.system(RunCprogram) #where the mpirun call occurs 
    args = shlex.split(RunCprogram) 
    env=os.environ 
    new_env = {k: v for k, v in env.iteritems() if "MPI" not in k} 

    #print new_env 
    p = subprocess.Popen(RunCprogram,shell=True, env=new_env,stdout=subprocess.PIPE, stdin=subprocess.PIPE) 
    p.wait() 
    result="process myrank "+str(myrank)+" got "+p.stdout.read() 
    print result 



    g = [0.0]*2 
    g[0] = x[0]**2 - x[1] + 1 
    g[1] = 1 - x[0] + (x[1]-4)**2 

    time.sleep(0.01) 
    fail = 0 
    return f,g, fail 

print objfunc([1.0,0.0]) 

di base lavoratore, compilato da mpiCC main.cpp -o main:

#include "mpi.h" 

int main(int argc, char* argv[]) { 
    int rank, size; 

    MPI_Init (&argc, &argv);  
    MPI_Comm_rank (MPI_COMM_WORLD, &rank); 
    MPI_Comm_size (MPI_COMM_WORLD, &size); 

    if(rank==0){ 
     std::cout<<" size "<<size<<std::endl; 
    } 
    MPI_Finalize(); 

    return 0; 

} 
Problemi correlati