2015-05-21 3 views
7

Я пытаюсь выполнить некоторую параллельную оптимизацию с помощью PyOpt. Сложная часть заключается в том, что в рамках моей целевой функции я хочу запустить код C++, используя mpi.Python со встроенным вызовом mpirun

Мой питон скрипт выглядит следующим образом:

#!/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) 

Я бегу этот код с помощью:

mpirun -np 20 python Script.py 

Однако, я получаю следующее сообщение об ошибке:

[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 *** 

я сообразить, что 2 разных вызова mpirun (тот, который вызывает скрипт python и тот, который находится внутри сценарий) противоречат друг другу. Любые выводы о том, как это решить?

спасибо !!

+0

ли вы обмен данными между процессами питона с помощью МПИ связи или вы просто используете 'mpi4py' для запуска нескольких изолированных экземпляров. Если это так, вы можете использовать модуль 'subprocess' в python для создания нескольких потоков, каждый из которых может вызывать экземпляр' mpirun' (используя 'subprocess.Popen'). Я делаю это часто и не испытываю никаких проблем. Если вы используете 'Script.py' на нескольких машинах, это может быть невозможно ... –

ответ

1

См. Calling mpi binary in serial as subprocess of mpi application: самым безопасным способом является использование MPI_Comm_spawn(). Посмотрите, например, на this manager-worker example.

Быстрое исправление должно заключаться в использовании subprocess.Popen, как указано в @EdSmith. Однако обратите внимание, что поведение по умолчанию subprocess.Popen использует среду родителя. Я предполагаю, что это то же самое для os.system(). К сожалению, некоторые переменные среды добавляются mpirun, в зависимости от реализации MPI, например OMPI_COMM_WORLD_RANK или OMPI_MCA_orte_ess_num_procs. Чтобы увидеть эти переменные среды, введите import os ; print os.environ в коде mpi4py и в базовой оболочке python. Эти переменные среды могут привести к сбою подпроцесса. Таким образом, я должен был добавить строку, чтобы избавиться от них ... что довольно грязно ... Она сводится к тому:

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 

Полный тестовый код, побежал 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]) 

Basic работник, составленный 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; 

} 
Смежные вопросы