В какой степени универсальное и метапрограммирование с использованием шаблонов C ++ полезно в вычислительной науке?


17

Язык C ++ обеспечивает общее программирование и метапрограммирование с помощью шаблонов. Эти методы нашли свое применение во многих крупномасштабных научных вычислительных пакетах (например, MPQC , LAMMPS , CGAL , Trilinos ). Но что они на самом деле внесли в научное вычисление в значении, которое выходит за рамки неуниверсальных, неметаязыковых языков, таких как C или Fortran, с точки зрения общего времени разработки и удобства использования для равной или адекватной эффективности?

При выполнении научной вычислительной задачи, продемонстрировали ли дженерик и метапрограммирование с помощью шаблонов C ++ улучшение производительности, выразительности или удобства использования, измеряемых какими-либо хорошо понятными критериями (строки кода, трудозатраты и т. Д.)? Соответственно, какие риски связаны с использованием шаблонов C ++ для универсального и метапрограммирования?


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

1
Я полностью удалил комментарий под откос. Если вы хотите, чтобы он был перенесен в чат или мета, я с удовольствием это сделаю. Смотрите мою мету здесь .
Арон Ахмадиа

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

Я не думаю, что правильно говорить, что LAMMPS использует шаблоны или метапрограммирование. LAMMPS - это объектно-ориентированный код, который в большинстве случаев очень похож на Fortran. Я не думаю, что MPQC также имеет много шаблонов, но он сильно объектно-ориентирован и полиморфен.
Джефф

1
OpenFOAM интенсивно использует шаблоны и другие функции C ++.
Дон Джо

Ответы:


14

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

Конечно, универсальное программирование - это совершенно другая проблема, о чем свидетельствуют Trilinos, deal.II (моя собственная библиотека), DUNE и многие другие библиотеки - выражение одной и той же концепции, работающей с различными типами данных, - это не просто, и сообщество в значительной степени приняло его, пока оно остается в рамках, позволяющих избежать проблем метапрограммирования. Я думаю, что общее программирование квалифицируется как очевидный успех.

Конечно, ни одна из этих тем не связана напрямую с ООП. ООП, я бы сказал, общепринятый в научном компьютерном сообществе. Даже в меньшей степени, чем общее программирование, это не предмет обсуждения: каждая успешная библиотека, написанная за последние 15 лет (написана ли она на C ++, C или Fortran), использует методы ООП.


4
tmp может быть трудным для начинающих пользователей, но это часто делается очень хорошо внутри библиотеки. Это один из тех методов, которые действительно могут уменьшить объем кода, но вам действительно нужно знать, что вы делаете. Если вы не верите мне, прочитайте источник Eigen или Elemental. Его красивый код, который без шаблонов был бы практически невозможен.
Aterrel

5
Конечно, это техника с ценностью. Но его сложно поддерживать, и его часто трудно использовать, если он подвергается воздействию внешнего интерфейса. Тем не менее, я думаю, что одной из причин, по которой TMP не вполне достигла успеха, которого люди могли ожидать изначально, является то, что компиляторы стали очень хорошими. TMP основывается на том факте, что многие вещи известны во время компиляции, и затем могут быть распространены как константы в реальный код. Но компиляторы довольно хорошо разбираются в встраивании, клонировании функций и т. Д., И сегодня значительную часть преимуществ можно получить с помощью «нормального» программирования.
Вольфганг Бангерт

15

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

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

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

Мой последний пример - Элементаль. Elemental - это новая библиотека плотной линейной алгебры, которая взяла на себя сложность управления коммуникаторами MPI и определения местоположения данных до очень простой языковой конструкции. В результате, если у вас есть серийный код FLAME, изменив типы данных, вы также можете получить параллельный код через Elemental. Еще интереснее можно поиграть с распределением данных, установив на распределение равное другому.

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


3

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

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

По моему опыту, у меня были SUBROUTINEвызовы с 55 аргументами (in & out), и я сократил их до 5, чтобы сделать код лучше.

Это ценность.


3

Я решительный сторонник общего программирования и метапрограммирования для научных вычислений. Я на самом деле разрабатываю библиотеку C ++ для свободного программного обеспечения для методов Галеркина, основанную на этих методах под названием Feel ++ (http://www.feelpp.org), которая постоянно набирает обороты. Верно, что все еще существуют трудности, такие как медленные времена компиляции и что кривая обучения может быть крутой, если кто-то хочет понять, что происходит за кулисами. Это, однако, чрезвычайно интересно и потрясающе. Если сделать это на уровне библиотеки и скрыть сложность языка, специфичного для предметной области, вы получите чрезвычайно мощный инструмент. Мы располагаем очень широким спектром методов, которые можно использовать и сравнивать. Для учебной цели научных вычислений это замечательно, для исследований и новых численных методов, а также для крупномасштабных приложений, хорошо, мы работаем над этим, но пока все хорошо, мы уже можем сделать некоторые хорошие вещи. У нас есть инженеры, физики и математики, использующие его: большинство из них просто используют язык для вариационной формулировки, и им это нравится. Глядя на некоторые формулировки, которыми манипулируют наши коллеги-физики, я бы не хотел, чтобы они выполнялись «вручную» без языка высокого уровня для описания вариационной формулировки. Я лично считаю, что эти «методики» или «парадигмы» сейчас необходимы для решения сложных задач в научном вычислительном коде, когда приходится умножать размер кода на огромный фактор. Вероятно, существует необходимость улучшить поддержку метапрограммирования на C ++, но он уже в хорошей форме, особенно после C ++ 11.


2

Возможно, вы найдете документ http://arxiv.org/abs/1104.1729 актуальным для вашего вопроса. В нем рассматриваются шаблоны выражений (конкретное применение шаблонного метапрограммирования, используемого в научном коде) с точки зрения производительности.


Эта бумага сводит меня с ума. Сравните самый быстрый простой Фортран, который у вас есть, с MKL, и он тоже проиграет. Сборка с ручной настройкой - это не то, к чему вы стремитесь, это то, что вы делаете, когда каждая наносекунда имеет значение и может быть повторно использована очень большим количеством людей.
Aterrel

@aterrel: Это именно тот контраст, который мне интересен. Зная, что вам придется проводить ручную оптимизацию как самый последний этап разработки, какой язык вы бы выбрали в качестве базового для использования до последнего этапа? Есть ли у нас точные данные, чтобы предложить какой язык выбрать?
Смертельное дыхание

9
@Deathbreath: Я повторю ответ, который я сделал и в нескольких других потоках - в общем, настройка последнего бита скорости из вашего кода - это то, что вы делаете очень редко. Но вы постоянно программируете алгоритмы высокого уровня. Так что выбирайте язык, который позволяет вам быстро делать большие вещи. Всегда есть способ как-то включить низкоуровневые вещи, но это не должно быть тем, что определяет ваш выбор языка программирования.
Вольфганг Бангерт

0

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

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

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

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