2008-09-11 7 views
7

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

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

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

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

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

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

+1

Не могли бы вы обновить текст, чтобы добавить ссылку на документ google mapreduce, я думаю, что это отличный ресурс (http://labs.google.com/papers/mapreduce.html). – 2008-09-15 20:01:10

ответ

2

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

Настройте небольшую нитью с N потоками в ней и получите одну нить, чтобы контролировать их все.

Мастера резьбы просто сидит в цикле делать что-то вроде:

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

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

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

Способ по который вы реализуете, может быть таким же простым, как два управляемых mutex массивами. В нем есть обработанные потоки (threadpool), а другой - если каждый соответствующий поток свободен или занят.

Tweak N по своему вкусу ...

3

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

2

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

Это делает намного больше, а также может показаться вам очень полезным.

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

3

Если вы еще планируете использовать Python, вы можете захотеть взглянуть на Processing. Он использует процессы, а не потоки для параллельных вычислений (из-за 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)) 

Для получения дополнительной справки см the documentation of the Pool class.

Gotchas:

  • обработки использует вилку(), так что вы должны быть осторожны на Win32
  • объектов, передаваемых между процессами должны быть pickleable
  • если рабочие относительно быстро, вы можете настроить chunksize, т.е. количество рабочих элементов отправить к рабочему процессу в одной партии
  • processing.Pool использует фоновый поток
0

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

0

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

0

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

0

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