Многопроцессорность несовместима с NumPy

Я пытаюсь выполнить простой тест с использованием многопроцессорности. Тест работает хорошо, пока я не импортирую numpy (даже если он не используется в программе). Вот код:

from multiprocessing import Pool
import time
import numpy as np #this is the problematic line


def CostlyFunc(N):
    """"""
    tstart = time.time()
    x = 0
    for i in xrange(N):
        for j in xrange(N):
            if i % 2: x += 2
            else: x -= 2       
    print "CostlyFunc : elapsed time %f s" % (time.time() - tstart)
    return x

#serial application
ResultList0 = []
StartTime = time.time()
for i in xrange(3):
    ResultList0.append(CostlyFunc(5000))
print "Elapsed time (serial) : ", time.time() - StartTime


#multiprocessing application
StartTime = time.time()
pool = Pool()
asyncResult = pool.map_async(CostlyFunc, [5000, 5000, 5000])
ResultList1 = asyncResult.get()
print "Elapsed time (multiporcessing) : ", time.time() - StartTime

Если я не импортирую numpy, результат будет следующим:

CostlyFunc : elapsed time 2.866265 s
CostlyFunc : elapsed time 2.793213 s
CostlyFunc : elapsed time 2.794936 s
Elapsed time (serial) :  8.45455098152
CostlyFunc : elapsed time 2.889815 s
CostlyFunc : elapsed time 2.891556 s
CostlyFunc : elapsed time 2.898898 s
Elapsed time (multiporcessing) :  2.91595196724

Общее прошедшее время аналогично времени, требуемому для 1 процесса, что означает, что вычисление было распараллелено. Если я импортирую numpy, результат будет выглядеть следующим образом:

CostlyFunc : elapsed time 2.877116 s
CostlyFunc : elapsed time 2.866778 s
CostlyFunc : elapsed time 2.860894 s
Elapsed time (serial) :  8.60492110252
CostlyFunc : elapsed time 8.450145 s
CostlyFunc : elapsed time 8.473006 s
CostlyFunc : elapsed time 8.506402 s
Elapsed time (multiporcessing) :  8.55398178101

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

В настоящее время я использую Python2.7, NumPy 1.6.2 и многопроцессорную обработку 0.70a1 на linux

Ответ 1

(Первое сообщение извините, если оно плохо сформулировано или присвоено)

Вы можете остановить Numpy для использования многопоточности, установив MKL_NUM_THREADS в 1

Под debian я использовал:

export MKL_NUM_THREADS=1

Источник из связанного сообщения stackoverflow: Python: как вы останавливаете numpy из многопоточности?

Результат:

[email protected]:~/tmp$ python multi.py
CostlyFunc : elapsed time 3.847009 s
CostlyFunc : elapsed time 3.253226 s
CostlyFunc : elapsed time 3.415734 s
Elapsed time (serial) :  10.5163660049
CostlyFunc : elapsed time 4.218424 s
CostlyFunc : elapsed time 5.252429 s
CostlyFunc : elapsed time 4.862513 s
Elapsed time (multiporcessing) :  9.11713695526

[email protected]:~/tmp$ export MKL_NUM_THREADS=1

[email protected]:~/tmp$ python multi.py
CostlyFunc : elapsed time 3.014677 s
CostlyFunc : elapsed time 3.102548 s
CostlyFunc : elapsed time 3.060915 s
Elapsed time (serial) :  9.17840886116
CostlyFunc : elapsed time 3.720322 s
CostlyFunc : elapsed time 3.950583 s
CostlyFunc : elapsed time 3.656165 s
Elapsed time (multiporcessing) :  7.399310112

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

Ответ 2

Из комментариев по вашему вопросу, посмотрите на эту ссылку @Ophion нет, но я отметил это как дубликат Почему многопроцессорность использует только одно ядро ​​после импорта numpy? - ali_m 22 августа в 9:06

Я бы посмотрел, использует ли вы оптимизированную версию BLAS. Я обнаружил, что некоторые родовые установки numpy не доставляют и не оптимизируют версию этой библиотеки. Из моей установки вы можете заметить, что это указывает на libf77blas.so, libcblas.so, libatlas.so.

Вот инструкции по созданию оптимизированной версии BLAS: http://docs.scipy.org/doc/numpy/user/install.html

От с помощью в python:

  

import numpy.core._dotblas

  
>>> numpy.core._dotblas.__file__

## output:

'PYTHONHOME/lib/python2.7/site-packages/numpy/core/_dotblas.so'

С вашего терминала:

$ ldd 'PYTHONHOME/lib/python2.7/site-packages/numpy/core/_dotblas.so'
linux-vdso.so.1 =>  (0x00007fff241ff000)
libf77blas.so => /opt/arch/intel/lib/libf77blas.so (0x00007f6050647000)
libcblas.so => /opt/arch/intel/lib/libcblas.so (0x00007f6050429000)
libatlas.so => /opt/arch/intel/lib/libatlas.so (0x00007f604fbf1000)
libpython2.7.so.1.0 => 'PYTHONHOME/lib/libpython2.7.so.1.0 (0x00007f604f817000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f604f5f9000)
libc.so.6 => /lib64/libc.so.6 (0x00007f604f266000)
libgfortran.so.3 => /usr/lib64/libgfortran.so.3 (0x00007f604ef74000)
libm.so.6 => /lib64/libm.so.6 (0x00007f604ecef000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f604eaeb000)
libutil.so.1 => /lib64/libutil.so.1 (0x00007f604e8e8000)

/lib64/ld-linux-x86-64.so.2 (0x0000003c75e00000)