Язык C ++ обеспечивает общее программирование и метапрограммирование с помощью шаблонов. Эти методы нашли свое применение во многих крупномасштабных научных вычислительных пакетах (например, MPQC , LAMMPS , CGAL , Trilinos ). Но что они на самом деле внесли в научное вычисление в значении, которое выходит за рамки неуниверсальных, неметаязыковых языков, таких как C или Fortran, с точки зрения общего времени разработки и удобства использования для равной или адекватной эффективности?
При выполнении научной вычислительной задачи, продемонстрировали ли дженерик и метапрограммирование с помощью шаблонов C ++ улучшение производительности, выразительности или удобства использования, измеряемых какими-либо хорошо понятными критериями (строки кода, трудозатраты и т. Д.)? Соответственно, какие риски связаны с использованием шаблонов C ++ для универсального и метапрограммирования?
источник
Ответы:
Я думаю, что в целом метапрограммирование шаблонов оказалось непригодным на практике - оно компилируется слишком медленно, а получаемые нами сообщения об ошибках просто невозможно расшифровать. Барьер для входа для новичков также слишком высок при использовании метапрограммирования.
Конечно, универсальное программирование - это совершенно другая проблема, о чем свидетельствуют Trilinos, deal.II (моя собственная библиотека), DUNE и многие другие библиотеки - выражение одной и той же концепции, работающей с различными типами данных, - это не просто, и сообщество в значительной степени приняло его, пока оно остается в рамках, позволяющих избежать проблем метапрограммирования. Я думаю, что общее программирование квалифицируется как очевидный успех.
Конечно, ни одна из этих тем не связана напрямую с ООП. ООП, я бы сказал, общепринятый в научном компьютерном сообществе. Даже в меньшей степени, чем общее программирование, это не предмет обсуждения: каждая успешная библиотека, написанная за последние 15 лет (написана ли она на C ++, C или Fortran), использует методы ООП.
источник
Позвольте мне привести пример, основанный на опыте. Большинство библиотек, которые я использую изо дня в день, так или иначе используют ООП. ООП способен скрыть сложность, необходимую для многих доменов, это не тот механизм, который действительно помогает с производительностью. Может случиться так, что библиотека может использовать определенные оптимизации, основанные на иерархии объектов, но по большей части это скрытие сложности от пользователя. Посмотрите шаблоны проектирования, они являются механизмами, часто используемыми для выполнения этой сложности сокрытия.
Возьмите PETSc в качестве примера. PETSc использует модель инспектора / исполнителя OOP, где любой из его алгоритмов просматривает доступные подпрограммы в данном объекте и выбирает, какие из них выполнить для выполнения подпрограммы. Это позволяет пользователю разделять задачи, например, действие матрицы может включать в себя любые виды заблокированных или оптимизированных процедур и эффективно использоваться многочисленными итерационными решателями. Предоставляя пользователю возможность указывать свои собственные типы данных и оценки, они ускоряют несколько важных подпрограмм, а также все функциональные возможности библиотеки остаются доступными.
Другой пример, который я приведу, это FEniCS и deal.II. Обе эти библиотеки используют ООП для обобщения большого числа методов конечных элементов. И то, и другое: тип элемента, порядок элемента, квадратурное представление и т. Д. Взаимозаменяемы. Хотя обе эти библиотеки «медленнее», чем некоторые специализированные структурированные коды FEM, они способны решать самые разнообразные проблемы, причем большая часть сложности FEM неизвестна пользователю.
Мой последний пример - Элементаль. Elemental - это новая библиотека плотной линейной алгебры, которая взяла на себя сложность управления коммуникаторами MPI и определения местоположения данных до очень простой языковой конструкции. В результате, если у вас есть серийный код FLAME, изменив типы данных, вы также можете получить параллельный код через Elemental. Еще интереснее можно поиграть с распределением данных, установив на распределение равное другому.
ООП следует рассматривать как способ управления сложностью, а не парадигму для конкуренции с ручной сборкой. Если вы сделаете это плохо, это приведет к большим накладным расходам, поэтому нужно следить за временем и обновлять механизмы, с которыми они его используют.
источник
То, что
OOP
делают языковые функции для научных вычислений, позволяет создавать более компактные операторы кода, которые помогают лучше понимать и использовать код. Например,FFT
подпрограммы должны нести большое количество аргументов для каждого вызова функции, что делает код громоздким.С помощью операторов
module
илиclass
можно передать только то, что необходимо во время вызова, так как остальные аргументы относятся к настройке проблемы (т.е. размер массивов и коэффициенты).По моему опыту, у меня были
SUBROUTINE
вызовы с 55 аргументами (in & out), и я сократил их до 5, чтобы сделать код лучше.Это ценность.
источник
Я решительный сторонник общего программирования и метапрограммирования для научных вычислений. Я на самом деле разрабатываю библиотеку C ++ для свободного программного обеспечения для методов Галеркина, основанную на этих методах под названием Feel ++ (http://www.feelpp.org), которая постоянно набирает обороты. Верно, что все еще существуют трудности, такие как медленные времена компиляции и что кривая обучения может быть крутой, если кто-то хочет понять, что происходит за кулисами. Это, однако, чрезвычайно интересно и потрясающе. Если сделать это на уровне библиотеки и скрыть сложность языка, специфичного для предметной области, вы получите чрезвычайно мощный инструмент. Мы располагаем очень широким спектром методов, которые можно использовать и сравнивать. Для учебной цели научных вычислений это замечательно, для исследований и новых численных методов, а также для крупномасштабных приложений, хорошо, мы работаем над этим, но пока все хорошо, мы уже можем сделать некоторые хорошие вещи. У нас есть инженеры, физики и математики, использующие его: большинство из них просто используют язык для вариационной формулировки, и им это нравится. Глядя на некоторые формулировки, которыми манипулируют наши коллеги-физики, я бы не хотел, чтобы они выполнялись «вручную» без языка высокого уровня для описания вариационной формулировки. Я лично считаю, что эти «методики» или «парадигмы» сейчас необходимы для решения сложных задач в научном вычислительном коде, когда приходится умножать размер кода на огромный фактор. Вероятно, существует необходимость улучшить поддержку метапрограммирования на C ++, но он уже в хорошей форме, особенно после C ++ 11.
источник
Возможно, вы найдете документ http://arxiv.org/abs/1104.1729 актуальным для вашего вопроса. В нем рассматриваются шаблоны выражений (конкретное применение шаблонного метапрограммирования, используемого в научном коде) с точки зрения производительности.
источник
Шаблоны очень хороши для удаления проверок типа / домена во время выполнения. Об этом можно позаботиться во время компиляции. Теоретически это может повысить производительность по сравнению с реализацией того же типа в C или Fortran, где проверка типов может быть выполнена только во время выполнения - проверки реализованы в исходном коде. Тем не менее, вы можете достичь тех же результатов в C, используя опции прекомпилятора, но это нужно делать вручную, в отличие от шаблонов.
Тем не менее, шаблоны также могут создавать значительные накладные расходы. Они часто могут создавать раздувание кода, которое может повлиять на использование кэша команд. Кроме того, универсальные подходы часто могут сковывать компилятор во время оптимизации - это не всегда просто для анализа кода, когда используются универсальные подходы. Это всегда проблема автоматизации - включая оптимизацию компилятора - очень часто выходной код не подходит для кэширования.
Преимущества проверки типа / домена, хотя, безусловно, более безопасные, являются единственным реальным преимуществом, которое я вижу с точки зрения производительности, и они, как правило, незаметны. Но, как я уже сказал, общий эффект может быть отрицательным в зависимости от того, что вы делаете. Вот почему зачастую лучше оптимизировать код вручную, если у вас есть значительные узкие места.
источник