Какую модель параллельного программирования вы рекомендуете сегодня, чтобы использовать преимущества многоядерных процессоров завтрашнего дня? - PullRequest
46 голосов
/ 17 сентября 2008

Если бы вы писали новое приложение сегодня с нуля и хотели, чтобы оно масштабировалось до всех ядер, которые вы могли бы использовать завтра, какую модель параллельного программирования / систему / язык / библиотеку вы бы выбрали? Почему?

Меня особенно интересуют ответы по этим осям:

  1. Программист производительность / простота использования (могут ли смертные успешно использовать его?)
  2. Область целевого приложения (с какими проблемами это (не) хорошо?)
  3. Стиль параллелизма (поддерживает ли он задачи, конвейеры, параллелизм данных, сообщения ...?)
  4. Ремонтопригодность / будущее (кто-нибудь еще будет использовать его через 20 лет?)
  5. Производительность (как она масштабируется на каких видах оборудования?)

Я намеренно размываю природу приложения в ожидании получения хороших общих ответов, полезных для различных приложений.

Ответы [ 22 ]

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

Выезд Эрланг . Google для этого, и смотреть различные презентации и видео. Многие из программистов и архитекторов, которых я уважаю, весьма заинтересованы в его масштабируемости. Мы используем его там, где я работаю довольно интенсивно ...

1 голос
/ 10 мая 2011

Параллельное программирование IMO состоит из трех частей: определить параллелизм и указать параллелизм. Определить = Разбить алгоритм на параллельные части работы, указать = выполнять фактическое кодирование / отладку. Identify не зависит от того, какую платформу вы будете использовать для определения параллелизма, и я не думаю, что фреймворк может там сильно помочь. Он хорошо знаком с вашим приложением, целевой платформой, общими компромиссами в параллельном программировании (задержки оборудования и т. Д.), А также наиболее важным опытом. Указать однако можно обсудить и вот на что я постараюсь ответить ниже:

Я перепробовал много фреймворков (в школе и на работе). Поскольку вы спрашивали о многоядерных процессорах, которые являются общей памятью, я остановлюсь на трех каркасах общей памяти, которые я использовал.

Pthreads (на самом деле это не фреймворк, но, безусловно, применимо):

Pro: -Потоки чрезвычайно общие. Для меня pthreads - это сборка параллельного программирования. Вы можете закодировать любую парадигму в pthreads. -Это гибко, так что вы можете сделать его так высоко, как вы хотите. Нет никаких внутренних ограничений, чтобы замедлить вас. Вы можете написать свои собственные конструкции и примитивы и получить максимальную скорость.

Con: -Отзывает вас сделать все сантехника, как управление рабочими очередями, распределение задач, самостоятельно. Фактический синтаксис уродлив, и в вашем приложении часто содержится много дополнительного кода, что делает код трудным для написания, а затем трудным для чтения.

OpenMP:

Плюсы: -Код выглядит чистым, сантехника и разделение задач в основном под капотом -Semi гибкий. Это дает вам несколько интересных опций для планирования работы

Минусы: - Нужен простой цикл для параллелизма. (Более новый Intel verion тоже поддерживает задачи, но задачи такие же, как у Cilk). Подлежащие структуры могут быть или не быть хорошо написаны для производительности. Реализация GNU просто в порядке. ICC от Intel работал лучше для меня, но я бы лучше сам написал кое-что для повышения производительности.

Cilk, Intel TBB, Apple GCD:

Плюсы: -Правимо оптимальные базовые алгоритмы для параллелизма на уровне задач -Порядочный контроль последовательных / параллельных задач -TBB также имеет фреймворк параллелизма конвейера, который я использовал (это не лучший, чтобы быть откровенным) -Изменяет задачу написания большого количества кода для систем на основе задач, что может быть большим плюсом, если у вас короткие руки

Минусы: -Меньше контролировать производительность базовых структур. Я знаю, что Intel TBB имеет очень плохо работающие базовые структуры данных, например, рабочая очередь была плохой (в 2008 году, когда я ее увидел). -Код выглядит иногда ужасно со всеми ключевыми словами и модными словами, которые они хотят, чтобы вы использовали -Требует прочитать много ссылок, чтобы понять их «гибкие» API

1 голос
/ 23 мая 2010

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

Возможно, наиболее широко применяемым сегодня являются очереди задач в стиле Cilk (теперь доступны в .NET 4). Они отлично подходят для задач, которые могут быть решены с использованием метода «разделяй и властвуй» с предсказуемой сложностью для подзадач (таких как параллельные map и reduce над массивами, где известна сложность аргументов функции, а также алгоритмы, такие как быстрая сортировка), и охватывает много реальных проблем.

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

1 голос
/ 28 августа 2009

Полезный путь может быть OpenCL , который предоставляет средства для распределения определенных видов вычислительных нагрузок по разнородным вычислительным ресурсам, т.е. тот же код будет работать на многоядерных процессорах, а также на обычных графических процессорах. ATI недавно выпустила именно такой набор инструментов . Набор инструментов CUDA от NVidia похож, но несколько более ограничен. Также кажется, что у Nvidia есть OpenCL SDK в работах

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

1 голос
/ 28 августа 2009

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

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

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

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *.

1 голос
/ 28 августа 2009

Мы использовали PARLANSE , язык параллельного программирования с явной частичной спецификацией параллелизма за последнее десятилетие, для реализации масштабируемой системы анализа и преобразования программ ( DMS Software Reengineering Toolkit ), который в основном выполняет символические, а не числовые вычисления. PARLANSE - это скомпилированный C-подобный язык с традиционными скалярными типами данных символьные, целочисленные, с плавающей запятой, динамические типы данных строка и массив, составные типы данных структуры и объединения, а также функции с лексической областью. В то время как большая часть языка - ваниль (арифметические выражения над операндами, операторы if-then-else, циклы do, вызовы функций), параллелизм - нет. Параллельность выражается путем определения отношения «предшествует» для блоков кода (например, a перед b, a перед c, d перед c) записано как

(|;  a  (... a's computation)
     (<< a) b ( ... b's computation ... )
     (<< a) c ( ....c's computation ...)
     (>> c) d ( ... d's computation...)
)|;

где операторы << и >> ссылаются на «заказ во времени». Компилятор PARLANSE может видеть эти параллельные вычисления и предварительно распределять все структуры, необходимые для вычисления зерна a, b, c, d и генерируют пользовательский код для запуска / остановки каждого из них, тем самым сводя к минимуму накладные расходы на запуск и остановку этих параллельных зерен.

См. Эту ссылку для параллельного итеративного углубления поиска оптимальных решений для 15-головоломки , которая является старшим братом 4-х 4-головоломки. Он использует только потенциал параллель в качестве конструкции параллелизма (|| abcd) , которая говорит, что в вычислениях нет ограничений частичного порядка a b c d , но он также использует спекуляции и асинхронно прерывает задачи, которые не могут найти решения. В коде немало идей.

PARLANSE работает на многоядерных ПК. Большая программа PARLANSE (мы построили много с 1 миллионом + строк или более) будет иметь тысячи этих частичных порядков, некоторые из которых вызывают функции, которые содержат другие. До сих пор у нас были хорошие результаты с использованием до 8 процессоров и скромные выплаты до 16, и мы все еще настраиваем систему. (Мы думаем, что реальная проблема с большим количеством ядер на современных ПК - пропускная способность памяти: 16 ядер, подсистема памяти которых создает огромную пропускную способность).

В большинстве других языков параллелизм не раскрывается, поэтому его трудно найти, и системы времени исполнения платят высокую цену за планирование вычислений, используя примитивы планирования общего назначения. Мы думаем, что это может привести к катастрофе или, по крайней мере, к низкой производительности из-за закона Амхдаля: если количество машинных инструкций для составления графика гранулирования велико по сравнению с работой, вы не можете быть эффективными. OTOH, если вы настаиваете на том, что детали вычислений со многими машинными инструкциями сохраняют затраты на планирование относительно низкими, вы не можете найти детали вычислений, которые являются независимыми, и поэтому у вас нет никакого полезного параллелизма для планирования. Таким образом, основная идея PARLANSE состоит в том, чтобы минимизировать стоимость планирования зерен, чтобы зерна могли быть маленькими, чтобы их можно было найти в реальном коде. Понимание этого компромисса пришло из полного отказа парадигмы чистого потока данных, которая делала все параллельно с крошечными параллельными порциями (например, оператор добавления).

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

1 голос
/ 02 июня 2009

Очередь заданий с системой из нескольких рабочих (не уверен в правильной терминологии - очередь сообщений?)

Почему?

Главным образом, потому что это нелепо простая концепция. У вас есть список материалов, которые необходимо обработать, а затем множество процессов, которые получают задания и обрабатывают их.

Кроме того, в отличие от причин, скажем, Haskell или Erlang настолько параллельны / параллелизуемы (?), Они полностью независимы от языка - вы можете тривиально реализовать такую ​​систему в C, Python или любом другом языке (даже используя shell сценариев), в то время как я сомневаюсь, что bash получит программную транзакционную память или исчисление соединений в ближайшее время.

1 голос
/ 23 октября 2008
1 голос
/ 17 сентября 2008

Qt concurrent предлагает реализацию MapReduce для многоядерности, которая действительно проста в использовании. Это multiOS.

1 голос
/ 17 сентября 2008

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

...