Как go распараллелить мою обработку, используя tbb ::rallel_for и tbb :: dataflow? - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть источник файлов, которые мне нужно обработать. Из каждого файла мой код генерирует переменное число объектов данных, назовем его N. У меня есть K числа объектов обработки, которые можно использовать для обработки N объектов данных.

Я думаю сделать с помощью Tbb: dataflow:

  1. Создайте function_node с параллелизмом K и поместите объекты обработки my K в concurrent_queue.
  2. Используйте input_node для чтения файла, создания N объектов данных и try_put каждый в function_node.
  3. Тело function_node снимает с обработки объект обработки, использует его для обработки объекта данных, а затем возвращает объект обработки обратно в concurrent_queue после завершения.

Другой Я могу думать так:

  1. Создать function_node с последовательным параллелизмом.
  2. Использовать input_node, чтобы прочитать файл, сгенерировать N объектов данных, поместить объекты данных в сбор и отправка в function_node.
  3. В function_node разделите N объектов на K диапазонов и мы e каждый из K обрабатывает объекты для одновременной обработки каждого диапазона - не уверен, что для этой цели можно настроить параллелизу.

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

Как вы думаете, что является наилучшим способом go для распараллеливания этой обработки?

1 Ответ

0 голосов
/ 11 апреля 2020

Да, вы правы в том, что первый метод имеет то преимущество, что он не ждет, пока все объекты данных начнут свою обработку. Тем не менее, он также имеет преимущество в том, что не ожидает завершения обработки всех объектов данных, переданных в parallel_for. Это становится особенно заметным, если скорость обработки варьируется для каждого объекта данных и / или каждого объекта обработки.

Кроме того, кажется достаточным, чтобы за buffer_node следовали (возможно, reserving) join_node вместо concurrent_queue для сохранения обрабатываемых объектов для дальнейшего повторного использования. В этом случае function_node вернет объект обработки обратно в buffer_node, как только он завершит обработку объекта данных. Таким образом, график будет выглядеть следующим образом:

input_node     ->  input_port<0>(join_node);
buffer_node    ->  input_port<1>(join_node);
join_node      ->  function_node;
function_node  ->  buffer_node;

В этом случае параллелизм function_node можно оставить равным unlimited, поскольку за ним автоматически будет следовать число существующих объектов обработки ( доступные токены ) на графике.

Также обратите внимание, что генерация объектов данных из разных файлов также может выполняться параллельно. Если вы видите выгоду от этого, рассмотрите возможность использования function_node вместо input_node, так как последний всегда последовательный. Однако в этом случае используйте join_node с queueing политикой, поскольку function_node не зарезервирован.

Также, пожалуйста, рассмотрите возможность использования tbb :: parallel_pipeline вместо этого, как кажется, у вас есть Классификационная схема обработки c. В частности, эта и эта ссылка может быть полезной.

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