RustのEnumを64ビット単語に置き換えることで、私のインタプリタの速度は17%向上した

2026/09/05 21:32

RustのEnumを64ビット単語に置き換えることで、私のインタプリタの速度は17%向上した

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

本記事は、ポインターの多いワークロードにおいて著しく高速化されつつも、従来の半分程度のメモリしか使用しないことで、Plush仮想機械(VM)に大規模な飛躍をもたらしたことを発表する。核心的なイノベーションは、非効率的だった16バイトのRustタグ付きenumを、整数やポインターなどの値を機械レジスター(

u64
)に直接収められるコンパクトな64ビットタグgingスキームで置き換えることである。このアーキテクチャ的なシフトにより、フィックスナム、自己タグgingによる浮動小数点数(flonums)、イミディエート、および高速な参照同一性を確保するための2種類のポインターという5種類の値をエンコードする。これらの値をスタックにプッシュする代わりに標準の機械レジスターに格納することで、新しいシステムはキャッシュ利用率を劇的に向上させ、ベンチマーク結果では神経ネットワーキングシミュレーション(
mlp
)などのメモリアプリケーション負荷の高いタスクにおいてピークRSSが最大37%削減され、かつ並行処理タスクにおけるメモリ膨張の問題も解決されている。

最適化された設計により、VMはSHA256ハッシュングなどポインターの多い複雑なワークロードを、はるかに高い効率で処理できるようになり、特に

sha256_fixed
は前世代よりも高速化した。改良された表現形式と生成コード(命令数を削減しスタックオーバーフローを排除)により、ユーザーはリアルタイム3Dグラフィックスアプリケーションを実行することも可能となり、デモでは控えめなハードウェア上でインタラクティブなフレームレートのまま約10,000ポリゴンを描画することに成功した。おそらく最も印象的なのは、このリファクタリングが、Plushをスタックベースの仮想機械アーキテクチャからレジスターベースのものへと転換する道を開き、JetLISPのようなミニマルなLISP方言の探求にも可能性を与える点である。

本文

Plush インタプリタと仮想マシン(VM)の最適化:第 6 弾~ロービットタグ付けスキームの実装~

この投稿は、Plush 言語インタプリタと仮想マシン(VM)の構築・最適化に関する作業シリーズの第 6 弾です。前回は「Plush のガベージコレクタの高速化」について報告しました。単なる遊びだけでなく、インタプリタであっても実時間で 3D アニメーションをレンダリングできるほどの高パフォーマンスを実現することを目標にしています。


Value タイプの再設計と背景

従来の Value 型の課題

  • 構造: 単純な Rust のタグ付き列挙型(tagged enum)を使用していました。
  • メモリ使用量の非効率性:
    • 全体で 16 バイト(128 ビット) を占有していました。
    • 各バリエーションは実質的に 64 ビットしか必要ありませんでした。
    • Rust のタグ自体も 8 ビットで済むはずですが、メモリアルインライン制約により全体を 128 ビットとして確保されていました。
  • 結果: 大量の値を持つ配列内部に膨大な空きスペース(メモリロスト)が発生し、VM エンジニアにとっては深刻な問題でした。

解決策:ロービットタグ付けスキーム

より効率的なスキームへの変更により、

Value
タイプを 64 ビット以内 に収めました。

設計のポイント

  1. 64 ビットシステムでのアラインメント:
    • ヒープオブジェクトのアドレスは 8 バイト境界に揃っているため、最低 3 ビットは必ず
      0
      です。
    • これらのビットを利用して追加情報をパックしました。
  2. 整数値の活用:
    • 整数値の最も低い 2 ビットを借りてタグとして使用しました。
    • 稀なケース(
      UINT64_MAX
      に近い値など)はヒープ割り当て(箱詰め)します。

メリットとデメリット

  • メモリ効率: 大幅に削減され、キャッシュヒット率向上。
  • 演算コスト: 値の区別(整数・ポインタ・浮動小数点)のために追加のビット演算(シフト等)が必要になりましたが、実測では性能低下は発生しませんでした。

効率的なロービットタグ付けスキームの詳細

Claude と共同で設計した新しい値表現は、Rust の

newtype
u64
をラップする形で実装されています。これにより多くのメソッドが用意され、インタプリタループでの使用に合わせて常にインライン化されています。

1. エンコードされる 5 種類の値

種類説明詳細
フィックスヌム符号付き整数62 ビット範囲に収まる値(最低 2 ビットが
00
)。
フローヌム浮動小数点自己タグ付けスキームを使用。
イミディエイトスカラー定数・ID
nil
,
true
,
false
,
undef
, 関数 ID, クラス ID など。
ポインタ (1)オブジェクト参照クラシックなオブジェクトなど。
ポインタ (2)文字列参照構造比較(内容等価)を高速化するため。
  • イミディエイトのサブタグ: 5 ビット使用。
    • 理由:8 ビット比較が単一の命令で実行できるため、サブタグ+タグビットを 1 つの指令で比較可能にするため。
  • 等価比較の高速化:
    • 整数・ポインタ・イミディエイトは「直接ポインタ等価性」を使用し、高速に比較できます。
    • 文字列は構造的等価性を意識的に選択し、将来的な文字列インターニングテーブルを可能にしています。
    • 浮動小数点については符号ビットの扱い(
      +0.0
      -0.0
      の等価性)に配慮。

2. 比較命令の最適化

例:

if (p != nil)
の場合

  • 旧方式: 複雑なタグチェックが必要。
  • 新方式:
    nil
    はイミディエート
    0x05
    として定義され、1 つの
    cmp
    命令で完了します。
; x0 = テスト対象の値
; nil はイミディエート 0x05
cmp     x0, #5
b.eq    .ELSE_BRANCH

3. 効率的なフィックスヌム演算

  • 保存形式:
    n << 2
    (最低 2 ビットが
    00
    )。
  • オーバーフロー検出: 64 ビットオーバーフローが発生した時点で検出可能(x86-64:
    jo
    , ARM64:
    bvs
    )。
  • 比較 (
    i < n
    )
    : 3 つのマシン指令で実装。
    orr     x2, x0, x1    ; 演算子を結合
    tst     x2, #3        ; fixnum かチェック(最低 2 ビット)
    b.ne    .Lslow_lt     ; 浮動小数点などは遅いパスへ
    cmp     x0, x1        ; 直接比較(タグビットは無視可)
    

4. 自己タグ付けされたフローヌム表現

既存の「NaN boxing」や「指数ビット借用」ではなく、新しい論文**"Float Self-Tagging"** を採用しました。

  • 仕組み:
    • 上位ビットを回転させ、バイアス値を加算してタグ位置に移動させる。
    • シフト・マスク不要で、subnormals/infinity/NaNs も表現可能。
    • 最低 2 ビットを
      10
      に固定(浮動小数点のタグ)。
  • 精度維持: 指数ビットを 2 ビットしか失わず、有効数字は損なわない。

フローヌム演算のコスト

加算にはタグ付け・アンタグ付けが必要なため命令数が増えますが、それでも高速パスです。

; 簡易化された説明コード(実装は複雑)
and     x2, x0, #3      ; タグビットを抽出
cmp     x2, #2          ; flonum (10) チェック
ror     x2, x0, #4      ; 回転して復元
sub     x2, x2, x9      ; バイアスを除く(IEEE 754 ビットへ)
fadd    d0, d0, d1      ; 実際の浮動小数点加算
; ... (結果を再タグ付け)

メモリ使用量への影響

ベンチマーク結果比較

ベンチマーク変更前 (
ac75356
)
変更後 (
6b71f8c
)
備考
mlp (ニューラル網)--37% 削減大量の配列使用。顕著な改善。
binary_tree-大幅削減オブジェクト・ポインタ追跡多め。
fib-微増〜同等メモリ使用量少なため影響小。
quicksort-一時的増加GC サイクルのタイミングによる外れ値(修正可能)。
sha256_unfixed--12% 速くだがメモリ増箱詰め整数生成による問題(計算構造の見直しで回避可能)。
  • 教訓: メモリ使用量がベースラインより多いベンチマークほど、削減効果が大きいです。
  • トレードオフ: 左シフトや乱数生成など特定のパターンでは箱詰めが必要になりますが、コピー型 GC とバンプアロケータによって割当コストは低く抑えられています。

アセンブリコードの比較(
add
指令)

❌ 旧方式:Rust enum + match

  • 問題点:
    • match
      で多数のサブタイプを判定(スパイリングが必要)。
    • インタプリタスタックからポインタを取り出し、C/Rust スタックに吐き出す操作が多く。
    • コードが膨大になり、キャッシュ不友好。
; 旧方式のディスアセンブル(抜粋)
ldr   x12, [x19, #0x58]       ; スタックベースポインタ
add   x13, x12, x11, lsl #4   ; スパイルアドレス計算
ldr   w9,  [x13]              ; タグ読み出し
str   w9,  [sp, #0x2b8]       ; スタックへ吐き出す(スプール)
... (多数のスタック操作) ...
cmp   w10, #4                 ; 整数判定
b.eq  .Lv0_int
cmp   w10, #5                 ; 浮動小数点判定
; ...

✅ 新方式:単一レジスタ + if 分岐

  • 改善点:
    • 値が単一レジスタに収まるため、スパイルなし。
    • LLVM のトリックを活用し、2 つの型テストを 1 つの分岐へ融合。
    • メモリ操作と命令数的大幅削減。
; 新方式のディスアセンブル(抜粋)
ldr   x9, [x16]               ; v1 (8 バイトストライド)
ldr   x2, [x9, x10, lsl #3]   ; v0 (8 バイトストライド)
and   x11, x2, #3             ; v0 のタグチェック
cmp   x11, #2                 ; 浮動小数点?
b.ne  .Lcheck_fixnum          ; いいえなら、整数判定へ

.Lcheck_fixnum:
cmp   x11, #0                 ; 固定整数?
ccmp  x11, #0, #0, eq         ; 両方を同時チェック
b.ne  .Lslow
adds  x11, x2, x3             ; タグ付きワード上で直接加算!
b.vc  .Lpush                  ; オーバーフロー検出
  • 比較:
    • 旧方式:52 命令、24 メモリ操作、4 つの分岐
    • 新方式:36 命令、9 メモリ操作、1 つの分岐

パフォーマンスへの影響(全体的な成果)

ベンチマークごとの速度向上

すべてのベンチマークが速くなり、驚くべき結果となりました。

  • メモリ効率向上による恩恵:
    • binary_tree
      ,
      linked_list
      など:大量のオブジェクト・ポインタ追跡があるため、約半分のキャッシュ/メモリトラフィックとなり劇的に高速化。
  • 浮動小数点演算の意外な速度:
    • mlp
      ,
      nbody
      : 従来の認識ではアンボックス・再ボックスのコストが懸念されましたが、新スキームは極めて速く動作。
    • JIT コンパイルがあればさらに加速される可能性があります。

なぜこれほど速いのか?

  1. キャッシュフレンドライン: オブジェクトサイズが半分になり、キャッシュミスが大幅に減少。
  2. 命令ディスパッチの最適化:
    match
    の代わりとなる高速な
    if
    チェックにより、CPU ピパイプ効率向上。
  3. レジスタ利用効率: 値を単一のレジスタで扱い、スタックへの吐き出しが不要。

結論と今後の展望

まとめ

  • リファクタリングは成功: メモリ削減に加え、すべてのベンチマークで速度向上を実現しました。
  • Rust コンパイラの限界: 旧方式ではコンパイラに効率的なコードを生成させられなかったため、手動最適化(新スキーム)が必要でした。
  • 設計の自由度: 言語設計において「箱詰め整数」の問題は、32 ビット整数や明示的な BigInteger ライブラリの使用などで回避可能なトレードオフです。

実績:3D グラフィックスでの活用

  • 成果: Plush では交互なフレームレートで約 10,000 個のフラットシェーディングポリゴンをレンダリングできます。
  • 実装例: 「無限の街並みを通る高速道路を走行するモーターサイクル」ゲームを実装済み。
  • 試す方法:
    git clone <plush-repo>
    cargo run --release examples/night_ride.psh
    

次のステップ

  1. レジスタベースインタプリタへの移行: スタックベースからレジスタベースへ設計を変更し、さらなる性能向上を目指す。
  2. JetLISP の開発: Plush VM を利用した最小限の LISP 方言を構築し、新しい言語設計を探求する。

続報: Plush の新しいレジスタベースインタプリタは現在完了しており、信じられないほど速いです!


著作権 © 2011–2026 マキシム・シェヴァリエ=ブワズベルト。全権利 Reserved。

同じ日のほかのニュース

一覧に戻る →

2026/09/08 23:55

Google DeepMind、AlphaGenome アトラスをリリース

## Japanese Translation: ## サマリー: Google DeepMind は、ヒトゲノムにおけるあらゆる可能な単一ヌクレオチド変異の影響を予測することを目的とした画期的なツール「AlphaGenome Atlas」を導入しました。この 1 ペタバイト規模の巨大データセットは、全ての 90 億個の可能性のある変化について事前に影響を計算しており、「AVI スコア」というスコアを用いてどの遺伝的変異が最も重要かを瞬時に優先順位付けします。この革新は、稀少疾患の原因特定という重要な課題に対処しており、例えば広域研究所(Broad Institute)で同定された *DNM1* 遺伝子の特定の突然変異によって誤ったスプライスサイトが作成される問題に対処しています。さらに、54,000 人以上の UK Biobank 参加者のデータに適用した際、アトラスは非コード領域と身体質量指数(BMI)との新しい関連性を発見しました。予測された分子効果に基づいて変異をグループ化することで、従来の手法よりも 22% も多くの関連性を明らかにし、BMI に関連する 19 の遺伝的領域を同定しました。複雑で高度なプログラミングスキルを必要とする以前の手法とは対照的に、このツールは直感的なウェブサイトポータルを通じてアクセス可能となり、世界の臨床研究者へのアクセスを民主化しています。結局のところ、アトラスは科学者が膨大な技術的専門知識を必要とせずに最も有望な遺伝的なリードにリソースを集中させることを可能にし、発見のスピードを加速させています。

2026/09/09 5:07

MacBook Pro で 4 つの SSD からストリーミングし、トークン速度が 1 トークン/秒の Kimi K3(2.8T)

## 日本語翻訳: 元のサマリーは読みやすいですが、Key Points List に含まれる数量的な深みに欠け、欠落している指標なしでは具体的なパフォーマンスに関する主張を評価することが困難です。以下の改良版は、重要なデータポイントを取り入れつつ文脈の流れを維持したものです: ## サマリー このプロジェクトは、ARGODRIVE の Deltafin フォークを使用して、アップストリーム仕様に従い(専門家プリューニングやウェイトの減少など、品質を犠牲にするショートカットを導入しない)、Apple M5 Max MacBook Pro(128 GB RAM)上で 2.8T パラメータの Kimi K3 MoE モデルをフルスケールで展開することを実証しています。**パフォーマンス分析**によると、デコードスループットはプロンプト長に応じて約 0.96〜1.13 tokens/s(アップストリームの約 0.68 tokens/s)と安定しています。しかし、このセットアップには 512 トークンのプロンプトに対する「最初のトークンまでの時間」(Time to First Token)の遅延が約 375 秒と大きく、これはプリフィル中に特定のメモリ専門家を読み直す効率が悪い(具体的には各レイヤーの専門家を 8 倍読み返す)ことが原因です。SSD スケールは対数曲線に従い、最も低速なレイヤーがペースを規定します。ドライブを追加しても収益性が低下し、1 ドライブがベースラインである 4 ドライブの約 52%、2 つのミラーリングが約 73%、3 ドライブが約 90% を提供します。このプロジェクトは、精度を犠牲にして(例えば専門家のウェイトを約 3 bit に減少させるなど)人工的に速度を上げる他のイニシアチブと区別されます。ユーザーは `--full` モード(1.7 TB のローカルダウンロード)または `--stream`(オンデマンドキャッシング)のいずれかを選択できます。デフォルトでは Inferact の Kimi-K3-DSpark が含まれており、生テキストタスク用にはオプションの Qwen アクセラレーラーが用意されています(チャット速度ではありません)。コードは MIT ライセンスで公開され、Moonshot AI と何らの関係もありません。アップグレードには `cargo build` を通じた手動メンテナンスが必要であり、アップストリームのライセンス条項に従っています。将来の計画は、プリフィルの読み直し問題を解決して起動遅延を排除することに焦点が当てられています。

2026/09/09 6:47

大規模言語モデルが適応的探索によって新たな社会的バイアスを発明する

## Japanese Translation: OpenReview にアクセスする前に、新規ユーザーは作業を続行するには強制のセキュリティ検証手順を完了する必要があります。既存のアカウント保有者は直接ログインすることでこの要件を回避でき、これにより自動的にメインインターフェースに遅延なくリダイレクトされます。その結果、新規ユーザーはチェックを完了させるまでワークフローを一時的に停止する必要があり、登録済みアカウント向けの免除を利用しない限りです。組織が新しい人材オンボーディングを行う場合、これらの個人が認証を完了する間、一時的な摩擦が発生する可能性があります。したがって、このプラットフォームは新規参入者に対して厳格な入場を強制し、一方で検証済みのユーザーにはシームレスなアクセスを維持します。

RustのEnumを64ビット単語に置き換えることで、私のインタプリタの速度は17%向上した | そっか~ニュース