Как сказать многоядерному / многопроцессорному компьютеру обрабатывать вызовы функций в цикле параллельно? - PullRequest
7 голосов
/ 11 сентября 2008

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

Многие из более интенсивных операций ведут себя детерминистически и поддаются параллельной обработке.

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

Я прочитал статью Google MapReduce, и хотя я мог бы использовать общий принцип в ряде мест, на данный момент я не буду ориентироваться на большие кластеры, скорее это будет одноядерный или многопроцессорный компьютер для версии 1.0. Так что в настоящее время я не уверен, смогу ли я на самом деле использовать библиотеку, или мне пришлось бы самому бросить простую базовую версию.

Я нахожусь на ранней стадии процесса проектирования и до сих пор нацеливаю C-что-то (для критических битов скорости) и Python (для критических битов производительности) в качестве моих языков. Если есть веские причины, я мог бы перейти, но пока я доволен своим выбором.

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

Ответы [ 9 ]

3 голосов
/ 15 сентября 2008

Если вы все еще планируете использовать Python, возможно, вы захотите взглянуть на Обработка . Он использует процессы, а не потоки для параллельных вычислений (благодаря Python GIL) и предоставляет классы для распределения «рабочих элементов» по ​​нескольким процессам. Используя класс пула, вы можете написать код, подобный следующему:

import processing

def worker(i):
    return i*i
num_workers = 2
pool = processing.Pool(num_workers)
result = pool.imap(worker, range(100000))

Это параллельная версия itertools.imap, которая распределяет вызовы между процессами. Вы также можете использовать методы apply_async пула и хранить ленивые объекты результатов в списке:

results = []
for i in range(10000):
    results.append(pool.apply_async(worker, i))

Подробнее см. В документацию по классу пула .

Gotchas:

  • обработка использует fork (), поэтому вы должны быть осторожны с Win32
  • объекты, передаваемые между процессами, должны быть замаскированы
  • если рабочие относительно быстрые, вы можете настроить размер, т.е. количество рабочих элементов, отправляемых рабочему процессу в одной партии
  • обработка. Пул использует фоновый поток
3 голосов
/ 11 сентября 2008

Вы можете реализовать алгоритм из Google MapReduce , не имея физически отдельных машин. Просто считайте каждую из этих «машин» «нитями». Потоки автоматически распределяются по многоядерным машинам.

3 голосов
/ 11 сентября 2008

Ну, если .net - это опция, они приложили немало усилий для Параллельных вычислений .

2 голосов
/ 12 сентября 2008

Я мог бы что-то здесь упустить, но это кажется довольно простым, используя pthreads.

Установите небольшой пул потоков с N потоками в нем и один поток для управления всеми ними.

Главный поток просто сидит в цикле, делая что-то вроде:

  1. Получить блок данных из БД
  2. Найти следующую свободную тему. Если нет свободной темы, подождите
  3. Передать чанк рабочему потоку
  4. Вернитесь и получите следующий кусок из DB

Тем временем рабочие потоки сидят и делают:

  1. Отметить себя свободным
  2. Дождитесь, пока мачтовая нить выдаст мне порцию данных
  3. Обработка порции данных
  4. Отметить себя снова как свободный

Метод, с помощью которого вы можете реализовать это, может быть простым, как два контролируемых мьютексом массива. Один из них содержит работающие потоки (пул потоков), а другой указывает, свободен или занят каждый соответствующий поток.

твик N по своему вкусу ...

2 голосов
/ 11 сентября 2008

Если вы работаете с компилятором, который будет его поддерживать, я бы посоветовал взглянуть на http://www.openmp.org для способа аннотирования вашего кода таким образом, некоторые циклы будут распараллелены.

Это делает намного больше, и вы можете найти это очень полезным.

Их веб-страница сообщает, что gcc4.2 будет поддерживать, например, openmp.

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

Intel TBB или boost :: mpi также могут вас заинтересовать.

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

Возможно, вас заинтересует код libdispatch , который является реализацией открытого кода Apple Grand Central Dispatch.

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

Я разработал библиотеку MapReduce для многопоточного / многоядерного использования на одном сервере. Все заботится о библиотеке, и пользователь просто должен реализовать Map и Reduce. Он позиционируется как библиотека Boost, но еще не принят как формальная библиотека. Проверить http://www.craighenderson.co.uk/mapreduce

0 голосов
/ 10 марта 2009

Тот же пул потоков используется в Java. Но потоки в пулах потоков можно сериализировать, отправлять на другие компьютеры и десериализовать для запуска.

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