Python multiprocesamiento dentro de mpi

Tengo un script de Python que escribí usando el módulo de multiprocesamiento, para una ejecución más rápida. El cálculo es vergonzosamente paralelo, por lo que la eficiencia aumenta con el número de procesadores. Ahora, me gustaría usar esto dentro de un programa MPI, que gestiona un cálculo MCMC en varias computadoras. Este código tiene una llamada a system () que invoca el script python. Sin embargo, descubro que cuando se llama de esta manera, la ganancia de eficiencia del uso del multiprocesamiento de Python desaparece.

¿Cómo puedo hacer que mi script de Python retenga las ganancias de velocidad del multiprocesamiento cuando se llama desde MPI?

Aquí hay un ejemplo simple, que es análogo a los códigos mucho más complicados que quiero usar, pero muestra el mismo comportamiento general. Escribo un script ejecutable de Python llamado junk.py.

#!/usr/bin/python
import multiprocessing
import numpy as np

nproc = 3
nlen = 100000


def f(x):
    print x
    v = np.arange(nlen)
    result = 0.
    for i, y in enumerate(v):
        result += (x+v[i:]).sum()
    return result


def foo():
    pool = multiprocessing.Pool(processes=nproc)
    xlist = range(2,2+nproc)
    print xlist
    result = pool.map(f, xlist)
    print result

if __name__ == '__main__':
    foo()

Cuando ejecuto esto desde el shell por sí mismo, usando "top" puedo ver tres procesos de python que toman cada uno el 100% de la CPU en mi máquina de 16 núcleos.

node094:mpi[ 206 ] /usr/bin/time junk.py
[2, 3, 4]
2
3
4
[333343333400000.0, 333348333450000.0, 333353333500000.0]
62.68user 0.04system 0:21.11elapsed 297%CPU (0avgtext+0avgdata 16516maxresident)k
0inputs+0outputs (0major+11092minor)pagefaults 0swaps

Sin embargo, si invoco esto con mpirun, cada proceso de Python toma el 33% de la CPU y, en general, tarda aproximadamente tres veces más en ejecutarse. Llamar con -np 2 o más da como resultado más procesos, pero no acelera el cálculo.

node094:mpi[ 208 ] /usr/bin/time mpirun -np 1 junk.py
[2, 3, 4]
2
3
4
[333343333400000.0, 333348333450000.0, 333353333500000.0]
61.63user 0.07system 1:01.91elapsed 99%CPU (0avgtext+0avgdata 16520maxresident)k
0inputs+8outputs (0major+13715minor)pagefaults 0swaps

(Notas adicionales: Esto es mpirun 1.8.1, python 2.7.3 en Linux Debian versión wheezy. He oído que system () no siempre está permitido en los programas MPI, pero me ha funcionado durante los últimos cinco años en esta computadora. Por ejemplo, he llamado un código paralelo basado en pthread desde system () dentro de un programa MPI, y se utiliza el 100% de la CPU para cada hilo, según lo deseado. Además, en caso de que sugiera ejecutar el script de Python en serie y simplemente llamando a más nodos ... el cálculo de MCMC implica un número fijo de cadenas que necesitan moverse de forma sincronizada, por lo que desafortunadamente el cálculo no se puede reorganizar de esa manera).

Respuestas a la pregunta(1)

Su respuesta a la pregunta