Комментарии 11
Честно говоря, не очень понятно, зачем такие сложности — расширение языка. Да и чем подход радикально отличается от "классического" распараллеливания на общем пуле потоков (кроме того, что это делается вручную, а не автоматически)? Какой-то выделенной поддержкой векторных вычислителей и тем, что все детали реализации очереди сокрыты от пользователя? Поясните, пожалуйста.
Сразу скажу, что я не являюсь сколь-нибудь квалифицированным специалистом по части "гетерогенных" вычислений (на кластере, на GPU и т.д.). Вот несколько мыслей, которые мне удалось из прочитенного и понятого сформулировать.
"Инвазивный подход" требует изменения синтаксиса языка, наличие транслятора/препроцессора/особую поддержку в компиляторе. Это снижает управляемость тем, что происходит за занавесом, со стороны программиста. Плохо продуманные синтаксические конструкции могут породить другие синтаксические конструкции, чтобы закрыть дыры в первых.
Как уже отмечалось, ручное распараллеливание дает большую управляемость процессом, потенциально более расширяемо, в т.ч. и на поддержку кластерных и векторных вычислений. При наличии хорошего API тоже можно все записывать единообразно.
- Не понятно, как вообще компилятор / препроцессор будет организовывать работу в кластере.
По поводу оптимизаций компилятора сказать ничего не могу, но как-то интуитивно — особой разницы не будет. Поле для оптимизаций ведь у нас не очень большое — мне только стек и видится (первый пример в статье, например). А эмуляция стека в коде и "нативный" стек в принципе отличаются только тем, что при переполнении стековой памяти легко получить stack overflow. Поправьте, если несу бредятину)
Что же касается организации компилятором работы в кластере (при работе с топологиями из ПППВ), то у меня подход вполне стандартный: программа в неизменном виде исполняется на каждом узле, каждый узел внутри программы идентифицируется номером, в зависимости от номера программой выполняется тот или иной фрагмент кода. В качестве низкоуровневого интерфейса транслятор использует MPI.
Что же касается оптимизаций в компиляторе, то сравню с OpenMP. Например, если говорить о реализации обработки дерева, то можно, конечно написать на OpenMP 3.0 рекурсивную функцию, которая будет порождать подзадачи и затем ставить барьер на ожидание их завершения. Это две директивы, при этом транслятор, скорее всего, будет генерировать для каждой из них независимый код. В предложенном подходе можно написать ПППВ, причем потребуется одна директива распараллеливания, причем компилятор работает с ПППВ/ФППВ стандартным образом, который при желании можно попытаться довести до совершенства. Поэтому мне кажется, что в случае OpenMP у транслятора меньше информации для наиболее оптимальной организации параллельной работы.
Ну, возможно, Вы и правы. За счет сужения области применения получаем более оптимальную трансляцию. (Но, опять же, не компиляцию.)
Честно говоря, я всегда был убежден, что синтаксические конструкции — просто синтаксический сахар. Те же async/await
в Boost прекрасно "эмулируются" переключением контекстов (Boost.Context)...
Надо будет как-нибудь попробовать Ваш инструмент в деле, чтобы не разглагольствовать попусту)
Да, хотелось бы взглянуть на результат работы. Вы его описываете-описываете) Надо же пощупать. Что же это за такие "еще некоторые интересные вещи"?
Идеи о новых возможностях обычного/параллельного программирования (расширение C++)