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


18

Я хочу разработать параллельное программное обеспечение для научных вычислений с нуля. Я хочу несколько мыслей, на каком языке начать. Программа включает в себя чтение / запись данных в текстовые файлы и параллельное выполнение тяжелых вычислений со многими факторизациями LU и использованием разреженных линейных решателей. Возможные решения, о которых я думал, это Fortran 2003/2008 с OpenMP или совмещенным массивом, C ++ с openmp cilk + или TBB, python. Любые другие, документированные, предложения приветствуются! Я очень хорошо знаю C, Fortran и Java (в таком порядке). Я сделал несколько сценариев на Python, но основные вещи.

Я знаю, что фортран очень быстр, но его трудно поддерживать и распараллеливать. Говорят, что C ++ медленный, если вы не используете внешние библиотеки и т. Д. Python, который мне нравится, но реалистично ли писать полнофункциональное программное обеспечение промышленного уровня?

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

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

Петрос


5
Как победитель C ++, я бы не назвал Fortran сложным в обслуживании. Ремонтопригодность по большей части связана с передовой практикой, а не с выбором языка. Медленность C ++ перепродана. Кроме того, я бы порекомендовал вам дополнить этот пост, чтобы описать ваши требования к размеру данных и времени выполнения. Я видел, как «большие» меняются на 9 или 10 порядков в зависимости от того, с кем я разговариваю.
Билл Барт

@BillBarth Проблема с существующим кодом на Фортране состоит в том, что три человека были задействованы с использованием различных методов. Я из C, один парень из F77 и другой из Matlab. Данные не подлежат распределению и размеру для самой большой по размеру системы (я принимал участие в последнее время). Код смог смоделировать систему с 72000 дифференциальных и 74000 алгебраических уравнений за временной интервал 240 с в 350 с (прошедшее время). Я сократил это до 170 с использованием OpenMP для распараллеливания. Теперь мне нужно запустить несколько дел параллельно (для проверки безопасности).
Electrique

4
@BillBarth слишком скромен в продаже своих навыков C ++, но он также слишком щедр в своем утверждении, что «медлительность C ++ перепродана». На scicomp.stackexchange.com было несколько потоков C ++ и Fortran, которые обсуждали этот вопрос, и общий вывод заключался в том, что это просто неправда, поскольку C ++ медленнее, чем Fortran, почти во всех случаях. Я лично считаю, что сегодня это можно считать городским мифом. Что это очень верно, что если принять во внимание ремонтопригодности кода, то Fortran не тариф очень хорошо сегодня.
Вольфганг Бангерт

2
@BillBarth и другие, если вы хотите продолжить обсуждение общих достоинств Fortran, C ++ и других языков, пожалуйста, отнесите их в чат Scicomp и @ любому, с кем бы вы хотели обратиться.
Арон Ахмадиа

1
@AronAhmadia: ах, давай, у меня есть так много, чтобы сказать Джеду ;-) (Джед: в другой раз. В нашем случае нет STL для разреженных матриц, но много в структурах данных адаптивной сетки.)
Вольфганг Bangerth

Ответы:


19

Позвольте мне попробовать и разбить ваши требования:

  • Ремонтопригодность
  • Чтение / запись текстовых данных
  • Сильные интерфейсы / возможности для факторизации LU
  • Разреженные линейные решатели
  • Производительность и масштабируемость для больших данных

Из этого списка я бы рассмотрел следующие языки:

C, C ++, Фортран, Python, MATLAB, Java

Джулия - новый многообещающий язык, но сообщество все еще формируется вокруг него, и оно не было развернуто ни в каких новых важных кодах.

Чтение / запись текстовых данных

Это легко получить право на любом языке программирования. Убедитесь, что вы должным образом буферизируете и объединяете свой доступ ввода / вывода, и вы получите хорошую производительность на любом из языков, которые вам следует рассмотреть. Избегайте потоковых объектов в C ++, если вы не знаете, как использовать их эффективно.

Сильные интерфейсы / возможности для факторизации LU

Если вы выполняете плотную факторизацию LU, вы захотите использовать LAPACK или ScaLAPACK / Elemental для параллельной функциональности. LAPACK и ScaLAPACK написаны на Фортране, Elemental написан на C ++. Все три библиотеки эффективны, хорошо поддерживаются и документированы. Вы можете взаимодействовать с ними на любом из языков, которые вы должны рассмотреть.

Разреженные линейные решатели

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

Производительность и масштабируемость для больших данных

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

Что касается производительности на узле, если вы сами пишете числовые подпрограммы, проще всего добиться хорошей производительности последовательного интерфейса в Fortran. Если у вас есть небольшой опыт работы с C, C ++ или Python, вы можете получить очень сопоставимую производительность (C и C ++ не имеют себе равных, даже если Fortran, Python и MATLAB занимают около 25% времени без особых усилий). MATLAB делает это с помощью JIT-компилятора и очень хорошей выразительности линейной алгебры. Скорее всего, вам потребуется использовать Cython, numpy, Numberxpr или встраивать числовые ядра, чтобы получить заявленную производительность от Python. Я не могу комментировать производительность Java, потому что я не очень хорошо знаю язык, но подозреваю, что он не так уж далек от Python, если он написан экспертом.

Примечание по интерфейсам

Я надеюсь, что убедил вас, что вы сможете делать все, что хотите, на любом из языков программирования, которые вы рассматриваете. Если вы используете Java, интерфейсы C будут немного сложными. Python имеет превосходную поддержку интерфейса C и Fortran через ctypes, Cython и f2py. LAPACK уже упакован и доступен через scipy. MATLAB обладает всеми необходимыми функциями в своих собственных библиотеках, но его нелегко масштабировать или особенно легко запускать в кластерах. Java может поддерживать интерфейсы C и Fortran с JNI , но обычно не встречается в кластерах и в параллельном программном обеспечении для научных вычислений.

Ремонтопригодность

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

Рекомендация

Мне лично очень повезло с Python, и я рекомендую его для многих вычислительных проектов. Я думаю, что вы должны строго рассмотреть это для вашего проекта. Python и MATLAB, вероятно, являются наиболее выразительными из языков, доступных для научных вычислений. Вы можете легко связать Python с любым другим языком программирования, вы можете использовать f2py, чтобы обернуть вашу текущую реализацию на Фортране и пошагово переписать те части, которые вы пожелаете в Python, проверяя, поддерживаете ли вы функциональность. В настоящее время я бы порекомендовал сочетание официальной реализации Python 2.7 с scipy . Вы можете легко начать работу с этим стеком из свободно распространяемого дистрибутива Python Enthought .

Вы также можете сделать большую часть этого в C, C ++ или Fortran. C и C ++ являются очень привлекательными языками для профессиональных разработчиков с большим опытом, но часто путают новых разработчиков и в этом смысле, вероятно, не являются хорошей идеей для более академического кода. Fortran и MATLAB популярны в академических вычислениях, но слабы в продвинутых структурах данных и выразительности, которые предлагает Python (например, вспомним объект dict Python).

Смежные вопросы:


1
Очень хорошо документированный, всеобъемлющий ответ. Под Фортраном я много использую Lapack. Я посмотрю на python и попытаюсь обернуть мой код на Fortran для начала и медленно и медленно перейду к Python. Единственное, что меня пугает, это 25% времени, которое я мог бы потратить. Но если это принесет пользу с более выразительным кодом и лучшей обработкой параллельных вычислений, я пойду на это. Я упомянул общую память только потому, что в настоящее время программное обеспечение работает в интерактивном режиме (внесение изменений в данные и повторный запуск) на компьютерах с общей памятью с 2,4,8,24,48 ядрами исследователей в Uni под Windows и Linux.
Electrique

3
Я не знаю, как вы можете претендовать на 25% накладных расходов для числовых ядер, написанных на Python. Чистые числовые ядра Python часто на 100 раз медленнее, чем C. Numpy и Numberxpr могут неплохо справляться с определенными выражениями, но это вряд ли написание новых числовых ядер на Python. Cython может сделать некоторые вещи быстрыми, но обычно не в пределах 25% от C. Python - прекрасный «клейкий» язык, но я думаю, что Aron продает его как универсальное решение для задач, чувствительных к производительности.
Джед Браун

I / O является слабым местом Fortran, потому что Fortran требует много структуры в I / O. Мой личный опыт общения с коллегами в моей лаборатории, которые работают с Cython, совпадает с тем, что Джед говорит о Cython; по крайней мере один из них пишет вручную настроенный C, чтобы заменить Cython для задач, требующих высокой производительности, и тогда я считаю, что производительность Python, вызывающего полученный код C, ближе к утверждению Aron. Кроме того, если вы собираетесь упомянуть PETSc и Python, вы можете также упомянуть petsc4py. Последнее, что я видел (это было несколько лет назад), не было хороших интерфейсов MPI для Java. Это изменилось?
Джефф Оксберри

@GeoffOxberry: привязки Java MPI существуют, но не обновлялись почти десятилетие. Я считаю их статус сомнительным. Fortran имеет множество опций ввода / вывода, которые можно сделать очень быстро. Я бы порекомендовал изучить Parallel HDF5 (и HDF5 в целом). Если ввод-вывод действительно доминирует (более 50% времени выполнения), могут потребоваться более серьезные меры, но в противном случае качество и портативность HDF-подобного интерфейса, вероятно, того стоят.
Билл Барт

@BillBarth: Я должен это проверить. Мой комментарий о вводе-выводе в Fortran исходит от того, что кто-то когда-то рекомендовал мне написать синтаксический анализатор входного файла на Fortran. Это возможно благодаря усилению большой структуры, но я просто не видел легко и широко используемых библиотек синтаксического анализатора regex или XML в Fortran (чтобы привести некоторые примеры). Для этого есть веская причина: мы единственные, кто больше использует Фортран. Возможно, мы думаем о разных вариантах использования.
Джефф Оксберри

2

В дополнение к очень полному ответу Арона, я бы взглянул на различные темы в scicomp.stackexchange, которые касались вопроса о том, какой язык программирования выбрать - как относительно скорости программ, так и вопроса о том, насколько легко или сложно это писать и поддерживать программное обеспечение на этих языках.

Тем не менее, в дополнение к тому, что там было написано, позвольте мне сделать несколько замечаний:

(i) Вы включаете в свой список совместный массив Fortran. Насколько мне известно, количество компиляторов, которые на самом деле его поддерживают, очень мало - и мой, по сути, будет нулевым. Наиболее широко доступным компилятором Fortran является GNU gfortran, и хотя текущие источники разработки анализируют подмножество совместных массивов, я считаю, что он фактически не поддерживает ни один из них (т. Е. Он принимает синтаксис, но не реализует ни одну из семантик) , Это, конечно, общее замечание о новых стандартах Fortran: отставание, с которым компиляторы фактически поддерживают новые стандарты, измеряется через несколько лет - компиляторы только полностью внедрили Fortran 2003 за последние пару лет и только частично поддерживают Fortran 2008. Это не должно мешать вам использовать что-либо из этого, если у вас есть компилятор, который поддерживает то, что вы используете,

(ii) То же самое верно и в отношении C ++ / Cilk +: да, Intel разрабатывает это в ответвлении GCC, но оно недоступно ни в одном из выпусков GCC и, вероятно, не будет в течение некоторого времени. Вы можете ожидать, что это займет еще как минимум 2-3 года, пока вы не найдете Cilk + с версиями GCC, установленными на типичных машинах Linux.

(iii) C ++ / TBB - это отдельная история: TBB существует довольно давно, имеет очень стабильный интерфейс и совместим с большинством любых компиляторов C ++, которые существовали в течение последних нескольких лет (как в Linux, так и в Windows). , Мы использовали его в сделке. II уже несколько лет с хорошими результатами. Там также есть очень хорошая книга.

(iv) У меня есть собственное мнение об OpenMP, а именно, что это решение в поисках проблемы. Он хорошо работает для распараллеливания внутренних циклов, что может представлять интерес, если у вас очень регулярные структуры данных. Но это редко, что вы хотите сделать, если вам нужно что-то распараллелить - потому что вы действительно хотите распараллелить внешние циклы. И для этого такие решения, как TBB, являются намного лучшими решениями, потому что они используют механизмы языка программирования, а не пытаются описать то, что происходит вне языка (через #pragmas), и таким образом, что у вас нет доступа к дескрипторам потоков. , индикаторы состояния результата и т. д. изнутри вашей программы.

(v) Если вы экспериментируете, вы также можете взглянуть на новые языки программирования, разработанные для параллельного программирования и, в частности, для задач, подобных тем, которые вы описываете. По сути, есть два, на которые я бы посмотрел: X10 и Chapel . Я видел хорошие учебные пособия по часовне, и они, кажется, хорошо разработаны, хотя сегодня оба, конечно, также являются замкнутыми решениями.


Для сведения, Intel утверждает, что параллельный (распределенная память) ко-массив Fortran встроен в их текущие компиляторы. Мы рассматриваем это на TACC, но мне пока нечего сообщать. Cray также имеет реализацию в своем компиляторе, но она доступна только на небольшом целом числе машин по всему миру. Я не думаю, что кто-то реализует полный стандарт Fortran 2008 по отношению к совместным массивам, но в некоторых компиляторах есть более чем зарождающаяся поддержка. Cilk +, конечно, также доступен с компиляторами Intel, но быть уверенным, вероятно, еще не разумно.
Билл Барт

Стандарт Fortran 2008 не был утвержден до конца 2010 года, поэтому через несколько лет CAF станет широко доступным. G95 на самом деле имела (несвободную) реализацию, но больше не разрабатывается (разработчик присоединился к PathScale).
Стали

Большая часть G95 в конечном итоге оказалась в Gfortran, но, возможно, CAF не является частью этого.
Вольфганг Бангерт

Я считаю, что компилятор Intel обеспечивает хорошую поддержку совместного массива. Они создали его, используя mpiexec. Это не будет моим первым выбором. Приятно то, что одна и та же реализация может работать на общей и распределенной памяти (я провел несколько тестов). Поскольку процессоры с разделяемой памятью opteron достигают 60-ядерных процессоров по действительно разумным ценам, я хочу сначала ознакомиться с опциями общей памяти.
Electrique

2

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

Более конкретно, хотя, что касается параллелизма, я бы посоветовал вам попытаться немного нестандартно мыслить. У OpenMP есть свои сильные стороны, но он застрял в том, чтобы взять последовательный код и использовать параллелизм здесь и там. То же самое, по сути, для Intel TBB.

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

Хорошая новость заключается в том, что, опять же, если вы серьезно относитесь к своей реализации, вы можете делать то, что делает Cilk, например, переписывать вашу задачу как набор взаимозависимых задач и распределять их по нескольким процессорам / ядра, все по своему усмотрению, либо используя pthreads, либо неправильно используя OpenMP для порождения процессов. Хорошим примером того, как это можно сделать, является планировщик QUARK, используемый в библиотеке PLASMA . Хорошее сравнение его производительности против Cilk дано здесь .


Я посмотрю на предлагаемые ссылки. Сравнительная статья очень хорошая! Благодарность! Я думал о pthreads, но хочу, чтобы программа была кроссплатформенной. Из того, что я знаю, у pthreads есть проблемы под окнами (неправильно?).
Electrique

@ p3tris: «p» в pthreads - для POSIX, поэтому он настолько переносим, ​​насколько это возможно. Существуют некоторые совместимые реализации Windows, такие как pthreads-win32или внутри cygwinпроекта.
Педро

На основании stackoverflow.com/q/2797690/801468 я вижу, что есть много вещей, необходимых для сортировки, чтобы использовать его. Учитывая, что я не программист, я бы предпочел придерживаться чего-то более проверенного.
Electrique

2

Там было небольшое обсуждение Coarray Fortran в вышеупомянутых комментариях. В настоящее время, насколько мне известно, поддержка coarray в компиляторах примерно такая:

  • У Cray есть компилятор, который поддерживает по крайней мере основные функции coarray. Я использовал его для написания кода, который должен был быть «образовательным», но я бы сказал, что вы можете написать настоящий код на coarray fortran. Синтаксис и концепции в основном намного проще, чем MPI, но, как всегда, есть много ловушек, и ловушки отличаются от MPI.
  • Intel Fortran имеет поддержку Coarray, созданную поверх их библиотеки MPI. Возможно, это ограничивает их теоретическую пиковую производительность, но я не видел никаких метрик.
  • Gfortran поддерживает Coarrays, но только для одного изображения (или одного ранга, если говорить в MPI). Следовательно, нет реального распараллеливания, пока не выйдет gfortran 4.8 или 4.9.

Вообще, я был бы осторожен, если бы начал код на основе coarray. Синтаксис прост и намного удобнее, чем Fortran / C / C ++ с MPI, но, тем не менее, он не такой полнофункциональный. Например, MPI поддерживает множество операций сокращения и т. Д., Что может быть очень удобно для вас. Это действительно зависит от вашей потребности в общении. Если вы хотите пример, дайте мне знать, и я могу предоставить вам несколько, если я могу выкопать файлы.


Да, больше информации о готовности Coarray Fortran для такого рода проблем, безусловно, было бы полезно. Добро пожаловать в Scicomp!
Арон Ахмадиа

1

Взгляните на Spark - это распределенная среда для вычислений в памяти, которая использует преимущества функционального программирования. Структура программы в Spark сильно отличается по сравнению с MPI, в основном вы пишете такой же код, как для одного компьютера, который автоматически распределяется как функции для данных, находящихся в памяти. Он поддерживает Scala, Java и Python.

Логистическая регрессия (scala):

//load data to distributed memory
val points = spark.textFile(...).map(parsePoint).cache()
var w = Vector.random(D) // current separating plane
for (i <- 1 to ITERATIONS) {
  val gradient = points.map(p =>
    (1 / (1 + exp(-p.y*(w dot p.x))) - 1) * p.y * p.x
  ).reduce(_ + _)
  w -= gradient
}
println("Final separating plane: " + w)

Существует расширение под названием MLib (библиотека машинного обучения), которое использует библиотеку Fortran для некоторых низкоуровневых вычислений (я думаю, для Python используется numpy). Итак, идея проста: сконцентрируйтесь на своем алгоритме и оставьте оптимизации на более низких уровнях (порядок обработки, распределение данных и т. Д.).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.