Как многопоточность с getattr, один поток на свойство? - PullRequest
0 голосов
/ 11 декабря 2018

Предположим, у меня есть следующий объект с несколькими дорогими свойствами, например:

class Object:

  def __init__(self, num):
    self.num = num

  @property 
  def expensive_property(self):
    return expensive_calculation

  @property 
  def expensive_property1(self):
    return expensive_calculation

  @property 
  def expensive_property2(self):
    return expensive_calculation

Примечание. Число дорогих свойств может со временем увеличиваться.Учитывая список Objects, как я могу вычислить каждое дорогостоящее свойство для потока, для всех объектов в списке.Мне трудно понять, как мне устроить свой бассейн.

Это то, чего я пытаюсь достичь:

from multithreading.dummy import Pool
from multithreading.dummy import Queue

object_list = [Object(i) for i in range(20)]
properties = [expensive_property2, expensive_propert5, expensive_property9, expensive_property3]


def get(obj, expensive_property):
  return [getattr(expensive_property, o) for o in obj]

tasks = Queue()
for p in properties :
  tasks.put((get, o, p))

results = []

with Pool(len(properties )) as pool:
   while True:
      task = tasks.get()
      if task is None:
        break
      func, *args = task
      result = pool.apply_async(func, args)
      results.append(result)

1 Ответ

0 голосов
/ 11 декабря 2018

Это немного безумно, потому что apply_async имеет внутреннюю очередь для распределения задач по пулу.Я могу представить себе причины иметь очередную очередь вокруг наблюдаемости или противодавления.Ваш пример - ваша полная программа?или вы ставите в очередь работу из другого процесса / потока?

Если ваши вычисления связаны с ЦП, одним из вариантов может быть удаление очереди, чтобы сделать ее немного проще:

def wait_all(async_results, timeout_seconds_per_task=1):
   for r in async_results:
      r.get(timeout_seconds)

wait_all(
  [pool.apply_async(get, (o, p)) for p in properties],
  timeout_seconds_per_task=1,
)

Как и в приведенном выше примере, это позволяет распределять вычисления по доступному процессору.(пул даже по умолчанию равен числу процессоров на вашем компьютере ).Если ваша работа связана с вводом-выводом (предложено вашим сном), процессы могут иметь убывающую отдачу

Вы должны были бы провести тестирование, но для привязки к вводу-выводу вы могли бы создать пул потоков, используя тот же шаблон https://stackoverflow.com/a/3034000/594589

Другими вариантами может быть использование неблокирующего ввода-вывода с циклом событий, таким как gevent,или asyncio.Оба позволят вам моделировать один и тот же шаблон на основе пула!

...