Наскільки загальне та метапрограмування з використанням шаблонів C ++ корисно в обчислювальній науці?


17

Мова C ++ забезпечує загальне програмування та метапрограмування через шаблони. Ці методи знайшли свій шлях у багато великих наукових обчислювальних пакети (наприклад, MPQC , LAMMPS , CGAL , Trilinos ). Але що вони насправді сприяли науково-обчислювальним значенням, що виходить за рамки загальних, неметальних мов, таких як C або Fortran, з точки зору загального часу розробки та зручності використання для однакової чи достатньої ефективності?

З огляду на наукове завдання на обчислення, чи загальне та метапрограмування за допомогою шаблонів C ++ продемонструвало поліпшення продуктивності, експресивності чи зручності використання, виміряне будь-якими добре зрозумілими орієнтирами (рядки коду, зусилля людини тощо)? Відповідно, які ризики пов'язані із використанням шаблонів C ++ для загального та метапрограмування?


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

1
Я повністю видалив коментарі зі зрушення. Якщо ви хочете, щоб це повторно спілкувались у чаті чи метах, я радий це зробити. Дивіться мою мета тут .
Арон Ахмадія

3
Також дивіться пов’язане тут питання щодо порад щодо використання та коли уникати шаблонів виразів .
Арон Ахмадія

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

1
OpenFOAM широко використовує шаблони та інші функції C ++.
Dohn Joe

Відповіді:


14

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

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

Зрозуміло, жодна з цих тем відразу не підключається до ООП. Знову ж таки, ООП, я б сказав, загальновизнана науковою обчислювальною спільнотою. Навіть менше, ніж загальне програмування, це не тема дискусій: кожна успішна бібліотека, написана за останні 15 років (будь то написана на C ++, C або Fortran), використовує методи OOP.


4
tmp може бути складним для початківців користувачів, але це часто робиться дуже добре всередині бібліотеки. Це одна з тих технік, яка дійсно може зменшити кількість коду, але вам дійсно потрібно знати, що ви робите. Якщо ви не вірите мені, перейдіть, прочитайте джерело Eigen або Elemental. Його прекрасний код, який без шаблонів був би майже неможливим.
aterrel

5
Звичайно, це техніка з цінністю. Але це важко підтримувати, і його часто важко використовувати, якщо він піддається зовнішньому інтерфейсу. Однак, я думаю, що однією з причин TMP не був успіх, який люди спочатку могли очікувати, - це те, що компілятори стали дуже хорошими. TMP переживає той факт, що багато речей відомо під час компіляції, а потім їх можна перенести як константи в фактичний код. Але компілятори стали досить непоганими у складі інліній, клонування функцій тощо, і тому значна частина користі сьогодні може бути отримана за допомогою "звичайного" програмування.
Вольфганг Бангерт

15

Дозвольте навести приклад на основі досвіду. Більшість бібліотек, якими я користуюся щодня, користуються OOP певним чином. OOP здатний приховати складність, необхідну для багатьох доменів, це не механізм, який справді допомагає в продуктивності. Що може статися, це те, що бібліотека здатна використовувати конкретні оптимізації на основі ієрархії об'єктів, але здебільшого йдеться про приховування складності від користувача. Знайдіть шаблони дизайну, вони є механізмами, які часто використовуються для досягнення цієї складності.

Візьміть PETSc як приклад. PETSc використовує модель інспектора / виконавця OOP, де будь-який з його алгоритмів розглядає наявні підпрограми в заданому об'єкті і вибирає, який слід виконати для виконання розпорядок. Це дозволяє користувачеві відокремити проблеми, наприклад, дія матриці може включати будь-який тип заблокованої або оптимізованої програми та бути ефективно використаною численними ітераційними рішеннями. Надаючи користувачеві можливість вказувати власні типи даних та оцінки, вони отримують кілька важливих процедур, а також мають функціональність усієї бібліотеки.

Ще один приклад, який я наведу - це FEniCS і deal.II. Обидві ці бібліотеки використовують OOP для узагальнення за великою кількістю методів Кінцевих елементів. І в обох, і від типу елементів, і порядок елементів, і квадратура, і так далі є взаємозамінним. Незважаючи на те, що обидві ці бібліотеки "повільніші", ніж деякі спеціалізовані структуровані коди FEM, вони здатні вирішувати широкий спектр проблем із значною складністю FEM, невідомою користувачеві.

Мій останній приклад - «Елементаль». Elemental - це нова щільна лінійна бібліотека алгебри, яка сприйняла труднощі в управлінні комунікаторами MPI та розташуванням даних дуже простою мовною конструкцією. Результат полягає в тому, що якщо у вас є серійний код FLAME, змінюючи типи даних, ви також можете мати паралельний код через Elemental. Ще цікавіше ви можете пограти з розподілом даних, встановивши розподіл, рівний іншому.

OOP слід розглядати як спосіб управління складністю, а не парадигму конкуренції з ручним прокатом. Крім того, якщо це зробити погано, це призведе до великих витрат, тому потрібно тримати час та оновлювати механізми, якими вони користуються.


3

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

Використовуючи moduleабо classзаяви, можна передавати лише те, що потрібно під час дзвінка, оскільки решта аргументів стосуються налаштування проблеми (тобто розміру масивів та коефіцієнтів).

На моєму досвіді у мене було SUBROUTINEдзвінки з 55 аргументами (вмикання і виведення), і я зменшив це до 5, що покращує код.

Це цінність.


3

Я твердий прихильник загального програмування та метапрограмування наукових обчислень. Я фактично розробляю безкоштовну програмну бібліотеку C ++ для методів Галеркина, засновану на цих методах під назвою Feel ++ (http://www.feelpp.org), який постійно набирає обертів. Правда, все ще існують труднощі, такі як повільний час складання і що крива навчання може бути крутою, якщо хочеться зрозуміти, що відбувається за сценою. Це, однак, надзвичайно цікаво і душевно. Якщо це зробити на рівні бібліотеки і приховати складність за мовою, що залежить від домену, ви отримаєте надзвичайно потужний інструмент. У нас в розпорядженні дуже широкий спектр методів використання та порівняння. Для навчальних цілей наукових обчислень це приголомшливо, як для досліджень, так і для нових чисельних методів, також для великих масштабних застосувань, добре ми працюємо над цим, але поки що це добре, ми вже можемо зробити деякі приємні речі. У нас є інженери, фізики та математики, які використовують його: більшість із них просто використовують мову для варіативного формулювання, і вони цим задоволені. Дивлячись на деякі рецептури, якими маніпулюють наші колеги-фізики, я не хотів би бачити їх виконанням "вручну" без мови високого рівня, щоб описати варіативну формулювання. Я особисто вважаю, що ці "методи" чи "парадигми" тепер необхідні для вирішення складності наукового обчислювального коду з необхідністю множення коду на величезний коефіцієнт. Ймовірно, є необхідність покращити підтримку метапрограмування на C ++, але це вже в хорошій формі, тим більше, що C ++ 11.


2

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


Цей папір мене зводить з розуму. Порівняйте найшвидший звичайний Fortran, який ви маєте, з MKL, і він також втратить. Налаштована вручну збірка - це не те, до чого прагнуть, це те, що ви робите, коли кожен наносекунд рахує і може бути використаний дуже багато людей.
aterrel

@aterrel: Це саме той контраст, про який я дивуюсь. Знаючи, що вам доведеться провести ручну оптимізацію як самий останній етап розвитку, яку мову ви б обрали в якості основи для використання до останнього етапу? Чи є у нас важкі дані, щоб підказати, яку мову вибрати?
Смерть,

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

0

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

Однак шаблони можуть також створювати значні накладні витрати. Вони часто можуть створювати розширення коду, що може впливати на використання кешу інструкцій. Крім того, загальні підходи часто можуть сковувати компілятор під час оптимізації - це не завжди прямий шлях до аналізу коду при використанні загальних підходів. Завжди проблеми з автоматизацією - включаючи оптимізацію компілятора - дуже часто вихідний код не є кешованим.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.