OCamlコンパイラ向けの新しいC++バックエンド
(github.com/ocaml)- OCamlコンパイラにC++コード生成をサポートする新しいバックエンドが提案され、既存のCベースのバックエンドの限界を補完
- 変換されたコードは純粋関数型スタイルで記述され、可変状態や標準ライブラリの使用なしに
Listモジュールの一部を再実装 - 実行には**C++コンパイラ(g++)**が必要で、テンプレート深さ制限の解除や引数受け渡しのためのオプションをサポート
- 性能はコンパイラごとに差があり、改良された優先度キュー方式のふるいアルゴリズムを適用すると速度とメモリ効率が向上
- コミュニティはこれを関数型言語とテンプレートメタプログラミングの結合実験として評価し、Rustへの拡張可能性にも言及
C++バックエンド追加提案
- OCamlコンパイラ(
ocamlc)にC++バックエンドを追加するパッチが提案- 既存ランタイムとFFIで使われている非インクリメンタルなCバックエンドを改良したもの
ocamlc -incr-c primes.mlコマンドでOCamlコードをC++へ変換可能
- 変換されたC++コードは純粋関数型スタイルで書かれており、可変状態をサポートしない
- このため標準ライブラリは利用不可で、例では
Listモジュールの一部を純粋関数型で再実装 - 出力は
Cons<hd, tl>形式のネスト構造で表現され、C++の::演算子との衝突を避けるため別の構造を使用
- このため標準ライブラリは利用不可で、例では
- 実行には**C++コンパイラ(g++)**が必要で、
-Dlimit=100オプションで引数を渡せる- 実行結果はコンパイラのエラーメッセージ形式で出力
- 大規模計算では
-ftemplate-depth=999999オプションでテンプレート深さ制限を解除可能
- 性能はコンパイラによって差がある
g++は10000以下の素数計算に約30秒、11GiBのメモリを使用clang++は1秒未満で警告の後にセグメンテーションフォルトが発生- O’Neillの優先度キュー方式のふるいアルゴリズムを適用すると8秒、3.1GiBに改善
- 今後の拡張方向としてRust対応にも言及
- Rustが部分的な
impl specializationを完成させればOCamlプログラムを実行できるようになるだろうと述べられている
- Rustが部分的な
コミュニティの反応と議論
-
機能テストとフィードバック
redianthusは非一様再帰データ型のサポート有無を質問stedolanは%predint未実装によるエラーを修正し、その型が正常に動作することを確認
-
ユーモアと反応
avsmは「C--が必要だったのにC++とは、C#で妥協しよう」という冗談を投稿stedolanは「来年は複素数 ℂ を試す」と返答- 😂、❤️、🚀 などの絵文字リアクションが多数付き、コミュニティの好意的な反応が見られた
-
技術的提案
AdelKSはテンプレートの代わりにconstexpr評価を使う代替案を提示- コンパイル時に素数を計算し、バイナリへ直接埋め込むサンプルコードを共有
LoganDarkは「それは純粋に楽しむためのものだ」と、テンプレート使用理由をユーモラスに返答
-
追加の議論
redianthusは「これでC++は本当の関数型言語になった」と発言- OCamlの純粋関数型データ構造をC++で実装できることを強調
dzmitry-lahodaはRustでもすでにOCamlを実行できるプロジェクト(contextgeneric/cgp)に言及
性能と実行例
- 基本例: 素数計算プログラム
ocamlc -incr-c primes.ml→primes.cppを生成g++ -Dlimit=100 primes.cppを実行すると素数一覧を出力
-
高性能設定
g++ -ftemplate-depth=999999 -Dlimit=10000 primes.cpp- 約30秒、11GiBのメモリを使用
-
改良アルゴリズム適用時
- 8秒、3.1GiBへ性能向上
結論
- このPRはOCamlをC++へ変換する新しいバックエンド実験であり、 関数型言語とテンプレートメタプログラミングの結合可能性を示している
- コミュニティはこれを技術的ユーモアと創造的実験の結合例として受け止め、活発に反応
- Rustなど他言語への拡張可能性も示された
1件のコメント
Hacker Newsのコメント
本当に素晴らしい内容。長時間動作するC++コードを書くときのコツを一つ挙げたい
奇妙なことに、C++インタプリタにはtail call optimizationがまったくない
そのため、ほとんどの慣用的なC++コードでは、
reverse、map、range、filterのような関数を自前で実装して、スタックがあふれないようにしているこういう形で実装しておくと、保守する人がずっと楽になるはず。コマンドラインフラグに頼らず、移植性のあるアプローチを使うのがよい
「こうした高度なデータ構造を使うと、g++ は 10000 以下の素数をわずか 8 秒で計算し、メモリは 3.1GiB しか使わない」という一文を見て笑ってしまった
ついにノートPCでも素数計算ができるようになった
「このコードは idiomatic で読みやすい C++ に翻訳される」という部分には本当に共感した
C++が好きな立場からすると、これは本当に読みやすいC++コードだと思う
typedef I<((I<((n::val (p::val))>::val) != (I<0>::val))> res;のような部分は本当に魔法レベルのテンプレートトリックだC++で型定義の中に条件式を入れているのは初めて見た
後で見返したら、これは実際のコードではなくテンプレート評価ロジックの一部だった
つまり、高水準言語のコンパイラロジックの一部をテンプレートエンジンにオフロードしているわけだ
こうしたアプローチは、パーサーに時間をかけるより効率的かもしれない
そのため、いま開発中のelevateコンパイラフレームワークの lowering ターゲットとして C++ を使ってみようかという気になった
「C++ is a purely functional language」という一文を見たとき、最初はタイプミスかと思って眉が上がった
だが、誤植ではないとわかってからは、なおさら興味深く感じた。残りの内容も素晴らしかった
この記事のおかげで一日が楽しくなった。ありがとう
Stephen Dolanはやはり期待を裏切らない。毎回驚かされる
「C++は純粋関数型言語であり、変更可能な状態をサポートしない。C++プログラムを実行するにはC++インタプリタが必要だ」という部分を見て、
一瞬エイプリルフールの冗談かと思った。もう4月は過ぎているのに