2016-07-28 6 views
2

Problem: Ich brauche einen sehr schnellen Weg in Python3, um viele (in tausend) Funktionen am gleichen Argument zu bewerten. In gewisser Weise brauche ich das Gegenteil von NumPy's Broadcasting, das ermöglicht, schnell zu bewerten eine Funktion bei mehrere Punkte.Schnelle Auswertung vieler Funktionen an einem Punkt in Python

Meine Lösung: Im Moment speichere ich einfach meine Funktionen in einer Liste und iteriere dann über die Liste mit einer klassischen for-Schleife, um alle Funktionen einzeln auszuwerten. Dies ist jedoch viel zu langsam.

Beispiele, Ideen und Links zu Paketen sind sehr willkommen.

Bearbeiten: Die Leute haben gefragt, wie die Funktionen aussehen: 1. Sie sind rechnerischer Natur. Keine I/O. 2. Sie beinhalten nur die üblichen algebraischen Operationen wie +, -, *,/und ** sowie eine Indikatorfunktion. Also keine trigonometrischen Funktionen oder andere spezielle Funktionen.

+0

Haben Sie versucht mit Threads? Und PyPy? –

+0

Können Sie ein Beispiel Ihrer Liste veröffentlichen? –

+2

hast du ein Listenverständnis versucht? '[func (arg) für func in list_of_func]' – Kasramvd

Antwort

3

Wenn Ihre Funktionen werden IO gebunden (das heißt, sie den größten Teil ihrer Zeit damit verbringen, für einige IO-Betrieb warten zu vervollständigen), dann mehrere Threads verwendet, kann eine faire Lösung sein.

Wenn Ihre Funktionen CPU-gebunden sind (was bedeutet, dass sie die meiste Zeit mit der eigentlichen Rechenarbeit verbringen), dann helfen Ihnen mehrere Threads nicht, es sei denn, Sie verwenden eine Python-Implementierung, die keine global interpreter lock hat.

Was Sie hier tun können, ist die Verwendung mehrerer Python-Prozesse. Die einfachste Lösung ist multiprocessing Modul. Hier ein Beispiel:

#!/usr/bin/env python3 
from multiprocessing import Pool 
from functools import reduce 

def a(x): 
     return reduce(lambda memo, i: memo + i, x) 
def b(x): 
     return reduce(lambda memo, i: memo - i, x) 
def c(x): 
     return reduce(lambda memo, i: memo + i**2, x) 

my_funcs = [a, b, c] 

#create a process pool of 4 worker processes 
pool = Pool(4) 

async_results = [] 
for f in my_funcs: 
     #seconds parameter to apply_async should be a tuple of parameters to pass to the function 
     async_results.append(pool.apply_async(f, (range(1, 1000000),))) 
results = list(map(lambda async_result: async_result.get(), async_results)) 
print(results) 

Mit dieser Methode können Sie alle Ihre CPU-Leistung parallel nutzen: nur eine Pool-Größe auswählen, die die Anzahl der CPUs in Ihrer Umgebung entspricht. Die Einschränkung dieses Ansatzes besteht darin, dass alle Ihre Funktionen pickleable sein müssen.

0

Bewerten Sie sie mithilfe von Threads, indem Sie sie in mehreren Threads ausführen, solange sie keine Ressourcenkonflikte haben.

http://www.tutorialspoint.com/python/python_multithreading.htm

+3

Multithreading wird nichts beschleunigen. Es ist an einen Kern gebunden. In der Tat wird es wahrscheinlich erheblich * langsamer * sein, da der Interpreter nun zwischen den Threads hin und her wechseln muss. 'Multiprocessing' verwendet mehrere Kerne. – MisterMiyagi

+0

@MisterMiyagi Es vermeidet zumindest Dinge in Reihenfolge, nicht wahr? Threading lässt Dinge parallel laufen. Aber wie Sie gesagt haben, Multiprocessing ist der beste Weg, um es mit der besten Leistung zu erreichen –

+0

Threading tut ** nicht ** Dinge parallel laufen! Es führt sie gleichzeitig aus. Grundsätzlich bedeutet dies, dass eine Aufgabe * pausiert * werden kann, eine andere durchgeführt wird, dann die erste * wieder aufgenommen * wird. Wenn es eine feste Liste von auszuführenden Operationen gibt und diese nicht durch externe Ressourcen (I/O) gebunden sind, kann das Pausieren, Wechseln und Wiederaufnehmen beträchtlichen Zeitaufwand bedeuten. Multithreaded-Code läuft möglicherweise auf vielen Prozessoren langsamer (http://www.dabeaz.com/GIL/). – MisterMiyagi

Verwandte Themen