Parallel Python: Wie liefere ich Argumente, um zu "einreichen"?
-
20-09-2019 - |
Frage
Dies ist nur die zweite Frage mit dem Parallel-Python-Tag. Nachdem ich die Dokumentation und das Googeln nach dem Thema durchgesehen hatte, bin ich hierher gekommen, da ich dort das beste Glück mit Antworten und Vorschlägen hatte.
Das Folgende ist die API (ich denke, sie heißt genannt), die alle relevanten Informationen an PP unterbreitet.
def submit(self, func, args=(), depfuncs=(), modules=(),
callback=None, callbackargs=(), group='default', globals=None):
"""Submits function to the execution queue
func - function to be executed
args - tuple with arguments of the 'func'
depfuncs - tuple with functions which might be called from 'func'
modules - tuple with module names to import
callback - callback function which will be called with argument
list equal to callbackargs+(result,)
as soon as calculation is done
callbackargs - additional arguments for callback function
group - job group, is used when wait(group) is called to wait for
jobs in a given group to finish
globals - dictionary from which all modules, functions and classes
will be imported, for instance: globals=globals()
"""
Hier ist meine Einreichungserklärung mit seinen Argumenten:
job_server.submit(reify, (pop1, pop2, 1000),
depfuncs = (key_seq, Chromosome, Params, Node, Tree),
modules = ("math",),
callback = sum.add, globals = globals())
Alle kapitalisierten Namen in depfuncs
sind die Namen von Klassen. Ich war mir nicht sicher, wo ich die Klassen einfügen sollte oder ob ich sie so einbeziehen müsste, wie sie in der globals()
Wörterbuch. Aber als ich es mit dem leitete depfuncs()
Leer, es würde einen Fehler aufwerfen, wie z. "Tree not defined
" (zum Beispiel).
Jetzt, key_seq
ist ein Generator, also muss ich mit einer Instanz arbeiten, um verwenden zu können .next()
:
def key_seq():
a = 0
while True:
yield a
a = a + 1
ks = key_seq()
ks
ist definiert in globals()
. Als ich es nirgendwo anders angemeldet habe, bekam ich einen Fehler, der sagte: 'ks is not defined
'. Wenn ich eingehört habe ks
in depfuncs
, Dies ist der Fehler:
Traceback (most recent call last):
File "C:\Python26\Code\gppp.py", line 459, in <module>
job_server.submit(reify, (pop1, pop2, 1000), depfuncs = (key_seq, ks, Chromosome, Params, Node, Tree), modules = ("math",), callback = sum.add, globals = globals())
File "C:\Python26\lib\site-packages\pp.py", line 449, in submit
sfunc = self.__dumpsfunc((func, ) + depfuncs, modules)
File "C:\Python26\lib\site-packages\pp.py", line 634, in __dumpsfunc
sources = [self.__get_source(func) for func in funcs]
File "C:\Python26\lib\site-packages\pp.py", line 713, in __get_source
sourcelines = inspect.getsourcelines(func)[0]
File "C:\Python26\lib\inspect.py", line 678, in getsourcelines
lines, lnum = findsource(object)
File "C:\Python26\lib\inspect.py", line 519, in findsource
file = getsourcefile(object) or getfile(object)
File "C:\Python26\lib\inspect.py", line 441, in getsourcefile
filename = getfile(object)
File "C:\Python26\lib\inspect.py", line 418, in getfile
raise TypeError('arg is not a module, class, method, '
TypeError: arg is not a module, class, method, function, traceback, frame, or code object
Ich bin ziemlich sicher arg
bezieht sich auf ks
. Also, wo sage ich .submit()
um ks
? Ich verstehe nicht, was wohin gehen soll. Vielen Dank.
Lösung
Interessant - machen Sie Genetiksimulationen? Ich frage, weil ich dort 'Chromosom' sehe, und ich habe einmal eine Populationsgenetiksimulation mit parallelem Python entwickelt.
Ihr Ansatz sieht wirklich kompliziert aus. In meinem parallelen Python -Programm habe ich den folgenden Anruf verwendet:
job = jobServer.submit( doRun, (param,))
Wie bin ich damit davongekommen? Der Trick ist, dass die Dorun -Funktion nicht im gleichen Kontext wie der Kontext ausgeführt wird, in dem Sie Sumbit nennen. Zum Beispiel (erfundenes Beispiel):
import os, pp
def doRun(param):
print "your name is %s!" % os.getlogin()
jobServer = pp.Server()
jobServer.submit( doRun, (param,))
Dieser Code fällt fehl. Dies liegt daran, dass das Betriebssystemmodul in Dorun nicht existiert - Dorun läuft nicht im selben Kontext wie Subjekt. Sicher, Sie können passieren os
in dem module
Parameter von submit
, aber ist es nicht einfacher, nur anzurufen import os
in Dorun?
Parallel Python versucht, Pythons Gil zu vermeiden, indem Sie Ihre Funktion in einem völlig separaten Prozess ausführen. Es wird versucht, dies einfacher zu schlucken, indem Sie Parameter und Namespaces "übergeben" können, um Ihre Funktion zu erhalten, aber es wird mit Hacks verwendet. Zum Beispiel werden Ihre Klassen unter Verwendung einer Variante von serialisiert pickle
und dann im neuen Prozess unverzweigt.
Aber anstatt sich darauf zu verlassen submit
Hacks, akzeptieren Sie einfach die Realität, dass Ihre Funktion die gesamte Arbeit des Einrichtens des Run -Kontexts erledigen muss. Sie haben wirklich zwei main
Funktionen - eine, die den Anruf einsetzt submit
, und eine, über die Sie nennen submit
, was tatsächlich die Arbeit einstellt, die Sie erledigen müssen.
Wenn Sie den nächsten Wert von Ihrem Generator benötigen, um für einen PP -Lauf verfügbar zu sein, geben Sie ihn auch als Parameter weiter! Dies vermeidet Lambda -Funktionen und Generatorreferenzen und lässt Sie mit einer einfachen Variablen vorbei!
Mein Code wird nicht mehr gepflegt, aber wenn Sie neugierig sind, schauen Sie ihn hier aus:http://pps-spud.uchicago.edu/viewvc/fps/trunk/python/fps.py?view=markup
Andere Tipps
Ich denke, Sie sollten in Lambda vorbeikommen: ks.next () anstelle von einfachen alten ks