Параллельный цикл в методе класса, вызывающий другой метод класса - PullRequest
0 голосов
/ 01 июня 2019

Этот вопрос относится к этим другим сообщениям на SO, однако предлагаемые там решения, похоже, не работают для моего случая. Вкратце, моя проблема может быть проиллюстрирована на следующем примере. У меня есть класс Algebra, где с помощью метода triPower я стремлюсь вычислить мощность тринома, то есть (a+b+c)**n для многих n значений с фиксированным a, b, c. Для этого я подумал о создании метода _triPower(a,b,c,n) и передаче его в мою pool.map() функцию с помощью functools.partial(_triPower,...), где я фиксирую a, b, c и оставляю n в качестве единственного параметра, так как я работаю в Python 2.7 и map из модуля multiprocessing требуется только одна функция аргумента (см. В противном случае этот пост ). Код следующий:

from __future__ import division
import numpy as np
import functools as fntls
import multiprocessing as mp
import multiprocessing.pool as mppl

# A couple of classes introduced to allow multiple processes to have their own daemons (parallelization)
class NoDaemonProcess(mp.Process):
   # make 'daemon' attribute always return False
   def _get_daemon(self):
      return False
   def _set_daemon(self, value):
      pass
   daemon = property(_get_daemon, _set_daemon)

# We sub-class multiprocessing.pool.Pool instead of multiprocessing.Pool
# because the latter is only a wrapper function, not a proper class.
class MyPool(mppl.Pool):
    Process = NoDaemonProcess

# Sample class where I want a method to run a parallel loop
class Algebra(object):
    def __init__(self,offset):
        self.offset = offset

    def trinomial(self,a,b,c):
        return a+b+c

    def _triPower(self,a,b,c,n):
    """This is the method that I want to run in parallel from the next method"""
        return self.offset + self.trinomial(a,b,c)**n

    def triPower(self,n):
        pls = MyPool(4)
        vals = pls.map(fntls.partial(self._triPower,a=1.,b=0.,c=1.),n)
        print vals

# Testing
if __name__ == "__main__":
    A = Algebra(0.)
    A.triPower(np.arange(0.,10.,0.01))

Выше не работает и выдает (как и ожидалось от этот пост ) ошибку:

cPickle.PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed

Следовательно, следуя тому же посту, я попытался определить _triPower как глобальную функцию, т.е.

def _triPower(alg,a,b,c,n):
"""This is the method that I want to run in parallel from the next method"""
    return alg.trinomial(a,b,c)**n 

и затем редактирование Algebra.triPower(...) в соответствии с:

    def triPower(self,n):
    pls = MyPool(4)
    vals = pls.map(fntls.partial(_triPower, alg=self, a=1., b=0., c=1.), n)
    print vals 

и этот последний вместо этого выдает странную ошибку TypeError, такую ​​как:

TypeError: _triPower() got multiple values for keyword argument 'alg' 

С другой стороны, предложение попытаться сделать методы сериализуемыми с помощью VeryPicklableObject , как в , этот другой пост , кажется, также не работает, и этот пакет кажется мертвым (на момент 05/2019). Так что я делаю не так и как я могу заставить мои вычисления выполняться параллельно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...