Итак, друг заметил кое-что любопытное в numpy .Вот минимальный пример, который запускает один и тот же сценарий первым последовательно, а затем два экземпляра, параллельные каждому в своем собственном процессе:
#!/bin/bash
# This is runner.sh
fl=/tmp/$(mktemp test_XXXXX.py)
trap "rm -fv '$fl'" EXIT
cat - > "$fl" <<-'EndOfHereDoc'
#!/usr/bin/env python
import numpy as np
import sys
if __name__ == '__main__':
if len(sys.argv)>1: print(sys.argv[1] +' start: '+ str(datetime.datetime.now()))
cube_size=100
cube=np.zeros((cube_size,cube_size,cube_size))
cube_ones=np.ones((cube_size,cube_size,cube_size))
for x in range(10000):
np.add(cube_ones,cube,out=cube)
if len(sys.argv)>1: print(sys.argv[1] +' start: '+ str(datetime.datetime.now()))
EndOfHereDoc
echo "Serial"
time python "$fl" 0
echo
echo "Parallel"
time python "$fl" 1&
time python3 "$fl" 2&
wait
rm -fv "$fl"
trap '' EXIT
Вывод которого:
$ runner.sh
Serial
0 start: 2018-09-19 15:46:52.540881
0 end: 2018-09-19 15:47:04.592280
real 0m12,105s
user 0m12,084s
sys 0m0,020s
Parallel
1 start: 2018-09-19 15:47:04.665260
2 start: 2018-09-19 15:47:04.780635
2 end: 2018-09-19 15:47:27.053261
real 0m22,480s
user 0m22,448s
sys 0m0,128s
1 end: 2018-09-19 15:47:27.097312
real 0m22,505s
user 0m22,409s
sys 0m0,040s
removed '/tmp/test_zWN0V.py'
Без ускорения.Это как если бы процессы выполнялись один за другим.Я предполагаю, что numpy использует ресурс исключительно, а другой процесс ожидает освобождения этого ресурса. Но что именно здесь происходит? GIL должен быть проблемой только с многопоточностью, а не с несколькими процессами, верно?Я нахожу это особенно странным, что p2 не просто ждет окончания p1.Вместо этого ОБА процессы заканчиваются ~ 22 с.Я ожидаю, что один получит ресурс и финиширует в два раза быстрее.В то время как другой ждет, пока первый выпустит его, и потребует дополнительных ~ 12 с.
Обратите внимание, что это также происходит при запуске кода Python с собственным модулем multiprocessing
в Pool
.Это, однако, не происходит, если вы делаете что-то, что не связано с какими-то конкретными функциями, такими как:
cube_size=25
cube=[0 for i in range(cube_size**3)]
for x in range(10000):
cube = [ value + 1 for value in cube]
Редактировать:
У меня есть настоящий 4-основной процессор.Я запомнил это, это не проблема.Во время одной части процесса один процессор находится на 100%, остальные бездействуют.Во время двухпроцессной части две находятся на 100%, остальная часть простаивает (согласно htop
).Я понимаю, что numpy запускает библиотеки ATLAS, LAPACK и BLAS в фоновом режиме, которые не являются Python (на самом деле это чистый C или Fortran).Они могут использовать параллельные методы.Мой вопрос здесь, почему это не проявляется в загрузке процессора?