python - multiplicar - numpy functions
¿Por qué el multiprocesamiento usa solo un núcleo después de importar numpy? (3)
No estoy seguro de si esto cuenta más como un problema de sistema operativo, pero pensé que podría preguntar aquí en caso de que alguien tenga alguna idea del final de Python.
He estado intentando paralelizar un ciclo pesado for
CPU con joblib
, pero encuentro que en lugar de que cada proceso de trabajo se asigne a un núcleo diferente, termino con todos ellos asignados al mismo núcleo y sin ganancia de rendimiento.
Aquí hay un ejemplo muy trivial ...
from joblib import Parallel,delayed
import numpy as np
def testfunc(data):
# some very boneheaded CPU work
for nn in xrange(1000):
for ii in data[0,:]:
for jj in data[1,:]:
ii*jj
def run(niter=10):
data = (np.random.randn(2,100) for ii in xrange(niter))
pool = Parallel(n_jobs=-1,verbose=1,pre_dispatch=''all'')
results = pool(delayed(testfunc)(dd) for dd in data)
if __name__ == ''__main__'':
run()
... y esto es lo que veo en htop
mientras se ejecuta este script:
Estoy ejecutando Ubuntu 12.10 (3.5.0-26) en una computadora portátil con 4 núcleos. Claramente, joblib.Parallel
está generando procesos separados para los diferentes trabajadores, pero ¿hay alguna forma en que pueda hacer que estos procesos se ejecuten en diferentes núcleos?
Después de buscar en Google, encontré la respuesta aquí .
Resulta que ciertos módulos de Python ( numpy
, scipy
, tables
, pandas
, skimage
...) se skimage
con la afinidad central en la importación. Por lo que puedo decir, este problema parece ser específicamente causado por su vinculación con bibliotecas multiproceso OpenBLAS.
Una solución alternativa es restablecer la afinidad de la tarea usando
os.system("taskset -p 0xff %d" % os.getpid())
Con esta línea pegada después de que el módulo importa, mi ejemplo ahora se ejecuta en todos los núcleos:
Mi experiencia hasta ahora ha sido que esto no parece tener ningún efecto negativo en el numpy
de numpy
, aunque esto probablemente sea específico de la máquina y de la tarea.
Actualizar:
También hay dos formas de desactivar el comportamiento de reinicio de afinidad de la CPU de OpenBLAS. En tiempo de ejecución, puede usar la variable de entorno OPENBLAS_MAIN_FREE
(o GOTOBLAS_MAIN_FREE
), por ejemplo
OPENBLAS_MAIN_FREE=1 python myscript.py
O, como alternativa, si está compilando OpenBLAS desde el origen, puede desactivarlo permanentemente en el momento de la compilación editando el Makefile.rule
para que contenga la línea.
NO_AFFINITY=1
Esto parece ser un problema común con Python en Ubuntu, y no es específico de joblib
:
- Tanto multiprocessing.map como joblib usan solo 1 CPU después de la actualización de Ubuntu 10.10 a 12.04
- El multiprocesamiento de Python utiliza solo un núcleo
- multiprocesamiento. Procesos de la piscina bloqueados en un único núcleo
Sugeriría experimentar con la afinidad de la CPU (conjunto de taskset
).
Python 3 ahora expone los métodos para establecer directamente la afinidad
>>> import os
>>> os.sched_getaffinity(0)
{0, 1, 2, 3}
>>> os.sched_setaffinity(0, {1, 3})
>>> os.sched_getaffinity(0)
{1, 3}
>>> x = {i for i in range(10)}
>>> x
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> os.sched_setaffinity(0, x)
>>> os.sched_getaffinity(0)
{0, 1, 2, 3}