Ich benutze Python Multiprocessing-Lib, um etwas Code zu beschleunigen (Kleinste Quadrate passend zu scipy).Python Multiprocessing-Modul: seltsames Verhalten und Prozessorlast bei Verwendung von Pool
Es funktioniert gut auf 3 verschiedenen Maschinen, aber es zeigt ein seltsames Verhalten auf einer 4. Maschine.
Der Code:
import numpy as np
from scipy.optimize import least_squares
import time
import parmap
from multiprocessing import Pool
p0 = [1., 1., 0.5]
def f(p, xx):
return p[0]*np.exp(-xx ** 2/p[1] ** 2) + p[2]
def errorfunc(p, xx, yy):
return f(p, xx) - yy
def do_fit(yy, xx):
return least_squares(errorfunc, p0[:], args=(xx, yy))
if __name__ == '__main__':
# create data
x = np.linspace(-10, 10, 1000)
y = []
np.random.seed(42)
for i in range(1000):
y.append(f([np.random.rand(1) * 10, np.random.rand(1), 0.], x) + np.random.rand(len(x)))
# fit without multiprocessing
t1 = time.time()
for y_data in y:
p1 = least_squares(errorfunc, p0[:], args=(x, y_data))
t2 = time.time()
print t2 - t1
# fit with multiprocessing lib
times = []
for p in range(1,13):
my_pool = Pool(p)
t3 = time.time()
results = parmap.map(do_fit, y, x, pool=my_pool)
t4 = time.time()
times.append(t4-t3)
my_pool.close()
print times
Für die 3 Maschinen, bei denen es funktioniert, beschleunigt es etwa in der erwarteten Art und Weise nach oben. Z.B. es gibt auf meinem i7 Laptop:
[4.92650294303894, 2.5883090496063232, 1.7945551872253418, 1.629533052444458,
1.4896039962768555, 1.3550388813018799, 1.1796400547027588, 1.1852478981018066,
1.1404039859771729, 1.2239141464233398, 1.1676840782165527, 1.1416618824005127]
Ich bin mit Ubuntu 14.10, Python 2.7.6, numpy 1.11.0 und 0.17.0 scipy. Ich testete es auf einem anderen Ubuntu-Rechner, einem Dell PowerEdge R210 mit ähnlichen Ergebnissen und auf einem MacBook Pro Retina (hier mit Python 2.7.11 und den gleichen numpy und scipy Versionen).
Der Computer, der Probleme verursacht, ist ein PowerEdge R710 (zwei Hexcores) mit Ubuntu 15.10, Python 2.7.11 und derselben numpy und scipy Version wie oben. Allerdings beobachte ich keine Beschleunigung. Die Zeiten liegen bei 6 Sekunden, egal welche Poolgröße ich verwende. In der Tat ist es für eine Poolgröße von 2 etwas besser und wird für mehr Prozesse schlechter.
htop
zeigt, dass irgendwie mehr Prozesse hervorgebracht werden, als ich erwarten würde.
z. auf meinem Laptop htop
zeigt einen Eintrag pro Prozess (der die Poolgröße entspricht) und schließlich zeigt jeder Prozess 100% CPU-Auslastung.
Auf dem PowerEdge R710 sehe ich etwa 8 Python-Prozesse für eine Poolgröße von 1 und etwa 20 Prozesse für eine Poolgröße von 2 usw., von denen jede 100% CPU-Last anzeigt.
Ich überprüft BIOS-Einstellungen des R710 und ich konnte nichts ungewöhnliches finden. Was soll ich suchen?
EDIT: Als ich auf den Kommentar antwortete, benutzte ich ein anderes einfaches Skript. Überraschenderweise scheint dies ein zu ‚Arbeit‘ für alle Maschinen:
from multiprocessing import Pool
import time
import math
import numpy as np
def f_np(x):
return x**np.sin(x)+np.fabs(np.cos(x))**np.arctan(x)
def f(x):
return x**math.sin(x)+math.fabs(math.cos(x))**math.atan(x)
if __name__ == '__main__':
print "#pool", ", numpy", ", pure python"
for p in range(1,9):
pool = Pool(processes=p)
np.random.seed(42)
a = np.random.rand(1000,1000)
t1 = time.time()
for i in range(5):
pool.map(f_np, a)
t2 = time.time()
for i in range(5):
pool.map(f, range(1000000))
print p, t2-t1, time.time()-t2
pool.close()
gibt:
#pool , numpy , pure python
1 1.34186911583 5.87641906738
2 0.697530984879 3.16030216217
3 0.470160961151 2.20742988586
4 0.35701417923 1.73128080368
5 0.308979988098 1.47339701653
6 0.286448001862 1.37223601341
7 0.274246931076 1.27663207054
8 0.245123147964 1.24748778343
auf der Maschine, die die Probleme verursacht. Es gibt keine weiteren Threads (oder Prozesse?), Als ich erwartet hätte.
Es sieht aus wie numpy ist nicht das Problem, aber sobald ich scipy.optimize.least_squares
verwenden, tritt das Problem auf.
Verwendung auf htop
auf die Prozesse zeigt viel sched_yield()
Anrufe, die ich, wenn ich scipy.optimize.least_squares
und die ich auch auf meinem Laptop nicht sehen, auch nicht verwenden nicht sehen, wenn least_squares
verwenden.
Da Sie 'htop' verwenden, wählen Sie jeden der 8 Python-Prozesse auf dem fehlerhaften Rechner und drücken Sie' s' für 'strace'. Sehen Sie, was jeder Prozess mit dieser 100% CPU-Zeit macht. Versuchen Sie auch ein einfacheres Testprogramm, das Numpy überhaupt nicht verwendet. –
Ich habe meinen ursprünglichen Beitrag bearbeitet. Ich habe das komplexere Beispiel zuerst verwendet, weil es meinem letzten Problem näher kommt. –
Versuchen wir herauszufinden, wo diese Prozesse entstehen, sollen wir? Sie können Ihr Programm unter einem Debugger, z. 'gdb --arg python yescript.py' ... dann' break fork' um zu stoppen, wenn ein neuer Prozess erstellt wird, dann schaue, was die Forking macht. Es könnte die zugrundeliegenden C- oder Fortran-Routinen in Scipy sein. Siehe https://sourceware.org/gdb/onlinedocs/gdb/Forks.html –