Não tenho certeza se isso conta mais como um problema do sistema operacional, mas pensei em perguntar aqui, caso alguém tenha alguma ideia do final das coisas em Python.
Eu tenho tentado paralelizar um for
loop pesado de CPU usando joblib
, mas acho que, em vez de cada processo de trabalho ser atribuído a um núcleo diferente, acabo com todos eles sendo atribuídos ao mesmo núcleo e sem ganho de desempenho.
Aqui está um exemplo muito 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()
... e aqui está o que vejo htop
enquanto este script está sendo executado:
Estou executando o Ubuntu 12.10 (3.5.0-26) em um laptop com 4 núcleos. Claramente joblib.Parallel
está gerando processos separados para os diferentes trabalhadores, mas existe alguma maneira de eu fazer esses processos serem executados em núcleos diferentes?
Respostas:
Depois de pesquisar um pouco mais, encontrei a resposta aqui .
Acontece que certos módulos Python (
numpy
,scipy
,tables
,pandas
,skimage
...) mexer com afinidade núcleo na importação. Até onde eu sei, esse problema parece ser causado especificamente por eles vincularem-se a bibliotecas OpenBLAS multithread.Uma solução alternativa é redefinir a afinidade da tarefa usando
Com esta linha colada após a importação do módulo, meu exemplo agora é executado em todos os núcleos:
Minha experiência até agora tem sido que isso não parece ter nenhum efeito negativo no
numpy
desempenho da empresa, embora provavelmente seja específico da máquina e da tarefa.Atualizar:
Existem também duas maneiras de desativar o comportamento de redefinição de afinidade da CPU do próprio OpenBLAS. No tempo de execução, você pode usar a variável de ambiente
OPENBLAS_MAIN_FREE
(ouGOTOBLAS_MAIN_FREE
), por exemploOu, alternativamente, se você estiver compilando o OpenBLAS a partir da fonte, poderá desativá-lo permanentemente no momento da construção, editando o
Makefile.rule
para conter a linhafonte
psutil
.O Python 3 agora expõe os métodos para definir diretamente a afinidade
fonte
Este parece ser um problema comum com o Python no Ubuntu e não é específico para
joblib
:Eu sugeriria experimentar a afinidade da CPU (
taskset
).fonte
Python on Ubuntu
Isso implica que ele está funcionando sem problemas no Windows e em outro sistema operacional. É isso?