Как я могу реализовать алгоритм для многоядерных в Java? - PullRequest
0 голосов
/ 14 марта 2009

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

Разделение любого алгоритма на разные потоки имеет смысл только при наличии свободного процессора.

Есть ли хорошие библиотеки, которые могут помочь распараллелить некоторые шаги, если есть свободные процессоры?

Я приведу несколько примеров.

  • Если есть только один процессор, нет смысла создавать несколько потоков. Это уменьшит скорость.
  • Если на основном дуэте запущены 2 процесса (запросы на сервере), запускать потоки также не имеет смысла.
  • Если в основном дуэте есть только один процесс, это имеет смысл.

Абстрактный алгоритм имеет 4 шага A, B, C и D. Шаги A, B и C могут выполняться параллельно. Шаг D требует результатов из A, B и C.

Редактировать: я имею в виду математический алгоритм. Нет ввода-вывода, нет событий и т. Д.

Ответы [ 7 ]

4 голосов
/ 14 марта 2009

Это не обязательно так.

В зависимости от алгоритма часто имеет смысл разделить его на несколько потоков, даже если доступно только одно ядро. Если есть ожидания на сокетах, IO и т. Д., Вы можете получить выгоду от этого. Если есть 2 процесса, «другой» процесс может не использовать 100% другого ядра, поэтому многопоточность здесь может помочь. В этом случае доверьтесь своей ОС, чтобы правильно с ней справиться.

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

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

3 голосов
/ 15 марта 2009

Посмотрите на различные параллельные классы в Java 5 и далее. Скорее всего, вам нужен ThreadPoolExecutor - http://java.sun.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html.

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

1 голос
/ 16 марта 2011

Абстрактный алгоритм имеет 4 шага A, B, C и D. Шаги A, B и C могут выполнить параллельно. Шаг D нуждается в результаты A, B и C.

Это однострочник, использующий нотацию Ateji PX, расширение языка Java:

[ A(); || B(); || C(); ]; D();

Ваша ответственность как программиста состоит в том, чтобы выразить, где есть потенциал для параллельного выполнения, это роль параллельных баров "||" в коде. Планировщик теперь может наилучшим образом использовать доступное оборудование, а именно запускать A, B и C на трех разных ядрах, когда это возможно.

Это очень высокоуровневое представление, возможно, больше параллелизма может проявляться внутри A, B или C.

1 голос
/ 15 марта 2009

Наличие большего количества потоков / процессов, чем ядер, не обязательно является плохой вещью. Если ваш код является строго математическим с небольшим количеством операций ввода-вывода и без побочных эффектов, тогда да, оптимальным является соответствие 1: 1 между ядрами и потоками. Но это обычно не так. Ввод / вывод занимает эоны по сравнению с тактовыми циклами. Зачем полностью останавливать ядро ​​во время ожидания ввода-вывода, когда ОС может переключиться в другой поток, чтобы продолжать пухнуть?

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

1 голос
/ 15 марта 2009

У меня часто есть фиксированный пул потоков, который динамически равен количеству потоков, равному количеству процессоров (см. Runtime) Я добавляю задачи в этот пул потоков, чтобы он использовал все доступные процессоры.

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

1 голос
/ 14 марта 2009

Для некоторых идей посмотрите на JSR166 и JSR166y (что-то вроде системы fork-join с рабочим воровством (166) и параллельным массивом (166y)).

Немного приятного чтения и краткого обзора будущих направлений Java. Выглядит неплохо (сильная поддержка параллельного и параллельного программирования высокого уровня).

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

Я думаю, вам нужен ConcurrentContext от Javolution. Смотрите на http://javolution.org/target/site/apidocs/javolution/context/ConcurrentContext.html

...