Почему многопроцессорность использует только одно ядро ​​после импорта numpy?

129

Я не уверен, считается ли это проблемой ОС, но я подумал, что спрошу здесь, если у кого-то есть какое-то представление о вещах, связанных с Python.

Я пытался распараллелить forцикл joblib, нагружающий ЦП , но обнаружил, что вместо того, чтобы каждый рабочий процесс был назначен другому ядру, я получаю, что все они назначаются одному ядру без увеличения производительности.

Вот очень банальный пример ...

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()

... и вот что я вижу во htopвремя выполнения этого скрипта:

HTOP

Я запускаю Ubuntu 12.10 (3.5.0-26) на ноутбуке с 4 ядрами. Очевидно, что joblib.Parallelдля разных рабочих процессов создаются отдельные процессы, но есть ли способ заставить эти процессы выполняться на разных ядрах?

ali_m
источник
1
stackoverflow.com/questions/15168014/… - Боюсь, здесь нет ответов, но это похоже на ту же проблему.
NPE
Это все еще проблема? Я пытаюсь воссоздать это с помощью Python 3.7 и импортирую numpy с помощью multiprocessing.Pool (), и он использует все потоки (как и должно). Просто хочу убедиться, что это было исправлено.
Джаред Нильсен

Ответы:

149

После еще нескольких поисков в Google я нашел здесь ответ .

Оказывается, что некоторые модули Python ( numpy, scipy, tables, pandas, skimage...) связывайтесь с основным сродством по импорту. Насколько я могу судить, эта проблема, похоже, вызвана именно тем, что они связаны с многопоточными библиотеками OpenBLAS.

Обходной путь - сбросить привязку задачи с помощью

os.system("taskset -p 0xff %d" % os.getpid())

С этой строкой, вставленной после импорта модуля, мой пример теперь работает на всех ядрах:

htop_workaround

По моему опыту, это не оказывает никакого отрицательного влияния на numpyпроизводительность, хотя это, вероятно, зависит от машины и задачи.

Обновить:

Есть также два способа отключить поведение OpenBLAS по сбросу привязки ЦП. Во время выполнения вы можете использовать переменную среды OPENBLAS_MAIN_FREE(или GOTOBLAS_MAIN_FREE), например

OPENBLAS_MAIN_FREE=1 python myscript.py

Или, в качестве альтернативы, если вы компилируете OpenBLAS из исходного кода, вы можете навсегда отключить его во время сборки, отредактировав, Makefile.ruleчтобы он содержал строку

NO_AFFINITY=1
ali_m
источник
Спасибо, ваше решение решило проблему. Один вопрос: у меня один и тот же код, но на разных машинах он работает по-разному. Обе машины - Ubuntu 12.04 LTS, python 2.7, но только у одной есть эта проблема. Вы знаете почему?
iampat
Обе машины имеют OpenBLAS (сборка с OpenMPI).
iampat 08
2
Старый поток, но в случае, если кто-то еще обнаружит эту проблему, у меня была точная проблема, и она действительно была связана с библиотеками OpenBLAS. См. Здесь два возможных обходных пути и некоторые связанные обсуждения.
Габриэль
2
Другой способ установить привязку процессора - использоватьpsutil .
Иоаннис Филиппидис
2
@JHG Это проблема с OpenBLAS, а не с Python, поэтому я не вижу причин, по которым версия Python будет иметь значение
ali_m
27

Python 3 теперь предоставляет методы для прямой установки сродства

>>> 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}
WOJ
источник
1
Ошибка> AttributeError: модуль 'os' не имеет атрибута 'sched_getaffinity', Python 3.6
Пэдди,
4
@Paddy Из связанной документации: они доступны только на некоторых платформах Unix.
BlackJack
2
У меня такая же проблема, но я интегрировал эту же строку в верхнюю часть os.system ("taskset -p 0xff% d"% os.getpid ()), но она не использует все процессоры
rajeshcis
12

Похоже, это обычная проблема Python в Ubuntu, и она не относится к joblib:

Я предлагаю поэкспериментировать с CPU affinity ( taskset).

NPE
источник
Python on UbuntuЭто означает, что он работает без проблем в Windows и других ОС. Это?
Mast