Параллельный Python: как мне предоставить аргументы для «отправки»? - PullRequest
6 голосов
/ 10 октября 2009

Это только второй вопрос с тегом Parallels-Python. После просмотра документации и поиска по этой теме, я пришел сюда, потому что именно там мне повезло с ответами и предложениями.

Ниже приведен API (я думаю, он называется), который передает всю необходимую информацию на стр.

    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()
    """

Вот мое утверждение с его аргументами:

job_server.submit(reify, (pop1, pop2, 1000), 
                  depfuncs = (key_seq, Chromosome, Params, Node, Tree), 
                  modules = ("math",), 
                  callback = sum.add, globals = globals())

Все заглавные имена в depfuncs являются именами классов. Я не был уверен, куда поместить классы или даже если мне нужно будет включить их, как они есть в словаре globals(). Но когда я запускаю его с пустым depfuncs(), возникает ошибка, например "Tree not defined".

Теперь, key_seq - это генератор, поэтому мне нужно работать с его экземпляром, чтобы иметь возможность использовать .next():

def key_seq():
    a = 0
    while True:
        yield a
        a = a + 1
ks = key_seq()

ks определяется в globals(). Когда я больше нигде не включал его, я получал сообщение «ks is not defined». Когда я включаю ks в depfuncs, это ошибка:

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

Я почти уверен, что arg имеет в виду ks. Итак, где я могу рассказать .submit() о ks? Я не понимаю, что должно идти куда. Спасибо.

Ответы [ 2 ]

5 голосов
/ 10 октября 2009

интересно - вы занимаетесь генетическим моделированием? Я спрашиваю, потому что вижу там «Хромосому», и однажды я разработал симуляцию популяционной генетики с использованием параллельного питона.

Ваш подход выглядит действительно сложным. В моей параллельной программе на Python я использовал следующий вызов:

job = jobServer.submit( doRun, (param,))

как мне это сошло с рук? хитрость в том, что функция doRun не работает в том же контексте, что и контекст, в котором вы вызываете sumbit. Например (надуманный пример):

import os, pp

def doRun(param):
    print "your name is %s!" % os.getlogin()

jobServer = pp.Server()
jobServer.submit( doRun, (param,))

этот код не удастся. это потому, что модуль os не существует в doRun - doRun не работает в том же контексте, что и submit. конечно, вы можете передать os в module параметре submit, но не проще ли просто вызвать import os в doRun?

Параллельный Python пытается избежать GIL Python, запустив вашу функцию в совершенно отдельный процесс. он пытается упростить это, позволяя вам цитировать- «передавать» параметры и пространства имен в вашу функцию, но делает это с помощью хаков. например, ваши классы будут сериализованы с использованием некоторого варианта pickle, а затем не сериализованы в новом процессе.

Но вместо того, чтобы полагаться на хаки submit, просто примите реальность того, что вашей функции понадобится выполнить всю работу по настройке контекста выполнения. у вас действительно есть две main функции - одна, которая устанавливает вызов на submit, и одна, которую вы вызываете с помощью submit, которая фактически устанавливает работу, которую вам нужно сделать.

если вам нужно, чтобы следующее значение из вашего генератора было доступно для запуска pp, также передайте его как параметр! это исключает лямбда-функции и ссылки на генераторы и оставляет вам возможность передавать простую переменную!

мой код больше не поддерживается, но если вам интересно, проверьте его здесь: http://pps -spud.uchicago.edu / ViewVC / FPS / багажник / питон / fps.py? Вид = Разметка

0 голосов
/ 10 октября 2009

Я думаю, что вы должны передавать лямбду: ks.next () вместо простого старого ks

...