Python paralelo: Como forneço argumentos para 'submeter'?
-
20-09-2019 - |
Pergunta
Esta é apenas a segunda pergunta com a tag paralela-python. Depois de examinar a documentação e pesquisar no assunto, cheguei aqui, pois é onde tive a melhor sorte com respostas e sugestões.
A seguir, a API (acho que é chamada) que envia todas as informações pertinentes ao PP.
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()
"""
Aqui está minha declaração de envio com seus argumentos:
job_server.submit(reify, (pop1, pop2, 1000),
depfuncs = (key_seq, Chromosome, Params, Node, Tree),
modules = ("math",),
callback = sum.add, globals = globals())
Todos os nomes capitalizados em depfuncs
são os nomes das classes. Eu não tinha certeza de onde colocar as aulas ou mesmo se eu precisará incluí -las como elas estão no globals()
dicionário. Mas quando eu o corri com o depfuncs()
vazio, levantaria um erro como "Tree not defined
" (por exemplo).
Agora, key_seq
é um gerador, então tenho que trabalhar com uma instância para poder usar .next()
:
def key_seq():
a = 0
while True:
yield a
a = a + 1
ks = key_seq()
ks
é definido em globals()
. Quando não o incluí em nenhum outro lugar, recebi um erro dizendo 'ks is not defined
'. Quando eu incluo ks
dentro depfuncs
, este é o erro:
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
Eu tenho certeza arg
está se referindo a ks
. Então, onde eu digo .submit()
cerca de ks
? Não entendo o que deveria ir para onde. Obrigado.
Solução
Interessante - você está fazendo simulações de genética? Pergunto porque vejo 'cromossomo' lá e uma vez desenvolvi uma simulação de genética populacional usando python paralelo.
Sua abordagem parece realmente complicada. No meu programa Python paralelo, usei a seguinte chamada:
job = jobServer.submit( doRun, (param,))
Como eu fui com isso? O truque é que a função dorun não é executada no mesmo contexto que o contexto em que você chama Sumbit. Por exemplo (exemplo artificial):
import os, pp
def doRun(param):
print "your name is %s!" % os.getlogin()
jobServer = pp.Server()
jobServer.submit( doRun, (param,))
Este código falhará. Isso ocorre porque o módulo OS não existe em Dorun - Dorun não está em execução no mesmo contexto que o envio. Claro, você pode passar os
no module
parâmetro de submit
, mas não é mais fácil apenas ligar import os
em Dorun?
O Python paralelo tenta evitar o GIL do Python, executando sua função em um processo totalmente separado. Ele tenta facilitar isso, permitindo que você cite os parâmetros e os espaços para nomes de "passe" para sua função, mas faz isso usando hacks. por exemplo, suas aulas serão serializadas usando alguma variante de pickle
e depois não érializado no novo processo.
Mas em vez de confiar submit
Os hacks, apenas aceitam a realidade de que sua função precisará fazer todo o trabalho de configurar seu contexto de execução. você realmente tem dois main
funções - uma que configura a chamada para submit
, e um, que você chama via submit
, que realmente configura o trabalho que você precisa fazer.
Se você precisar do próximo valor do seu gerador para estar disponível para uma execução de PP, passe -o também como um parâmetro! Isso evita funções lambda e referências ao gerador e deixa você passando uma variável simples!
Meu código não é mais mantido, mas se você estiver curioso, confira aqui:http://pps-spud.uchicago.edu/viewvc/fps/trunk/python/fps.py?view=markup
Outras dicas
Eu acho que você deveria estar passando em lambda: ks.next () em vez de ks antigo e simples