Rust 1.98で浮動小数点演算が高速化:新APIでコンパイラの最適化を制御

Faster floating point math with Rust's new API

Rust 1.98で浮動小数点演算が高速化:新APIでコンパイラの最適化を制御

Rust 1.98から、浮動小数点演算の最適化を許可する新しい「代数的演算子」が追加されました。従来はコンパイラが演算順序の変更を伴う最適化を控えていたため、整数演算に比べて浮動小数点演算が遅くなりがちでした。この新機能を使うと、精度が重要でない部分だけを指定して最適化を促せます。記事では、ペアワイズ加算や二乗誤差の総和の例で、実行速度が最大2倍向上することを示しています。

代数的演算子を使うことで、コンパイラはコードをより積極的に最適化できるようになり、私のコンピュータでは2倍高速なコードが生成されました。
  1. GeertB

    符号付き整数の加算が結合法則を満たすのは、オーバーフローが符号なし算術のようにラップアラウンドすると定義されている場合だけです。この条件はここで満たされています。なぜなら、デバッグビルドでのみオーバーフロー時にパニックするからです。しかし、記事が完全に無視しているグレーゾーンではあります。

  2. Asooka

    アイデアは好きですが、冗長すぎるのが嫌です。ブロック内のすべての算術を代数的算術に変換するマクロがあればいいのにと思います。名前も少し誤解を招きます。「algebraic_add」というと正確な代数的結果が得られると思ってしまいますが、実際には結合則のセマンティクスに基づく最適化を可能にするものです。

    余談ですが、マクロとして実装するなら、例えば

    fn fast_sum_f64(values: &[f64]) -> f64 {

    let mut total = 0;

    fp_opt!(associative, {

    for value in values {

    total += value;

    }

    });

    return total;

    }

    のような形になるでしょう。

    ここで疑問が生じます。算術演算をオーバーロードするカスタム型を操作する場合はどうなるのでしょうか。最もクリーンなアプローチは、カスタム型に最適化されたバージョンを定義させるか、既存のものに基づいて自動的に生成する別のマクロを持たせること、つまり最適化フラグを伝播させることだと思います。

  3. 14113

    > 浮動小数点演算は、コンパイラがコードの最適化に関して保守的であるため、整数演算よりも遅いことがよくあります。

    「保守的である」というのは厳密には正しくありません。より正確には、浮動小数点演算は整数演算とは異なるセマンティクスを持ち、整数の式に対してセマンティクスを保持する最適化が、浮動小数点の式に適用するとそうならない場合がある、ということです。したがって、ある最適化を整数式に適用することは可能でも、それを浮動小数点式に適用するとプログラムの意味が変わってしまう可能性があります。

    C/C++コンパイラは、`--ffast-math`フラグでこの問題を回避する方法を提供しています。これは基本的に、コンパイラが浮動小数点の最適化パスに対する制約を緩めることを可能にします。

    GCCでの動作例については、こちらを参照してください: https://gcc.gnu.org/wiki/FloatingPointMath

  4. rob74

    浮動小数点演算の専門家ではありませんが、「小さな数を足しても何も起こらないか?」という例が目に留まりました。なぜなら、使用されている数値は定数であり、一部の言語では任意精度だからです (https://stackoverflow.com/questions/57511935/what-is-the-pur...)。例えば、Goではこの問いにfalseと答えます(ただし、1e16 + 1を表示しようとすると「1e+16」と出力されます): https://go.dev/play/p/mSAktWpCRJA

  5. pjmlp

    理想的には、CPythonにも他のエコシステムのように現在のハードウェアに応じてこれを実行できるJITがあれば良いのですが、まだそこには到達していません。

この日のほかの記事

2026-08-11