**回答**

実際には、ほとんどの最新コンパイラは「決定的(deterministic)」です。  
同じソースコードと同一のコンパイルオプション(使用するコンパイラのバージョンや基盤となるプラットフォームを含む)を与えれば、何度実行しても同一のオブジェクトファイルまたはバイナリが生成されます。

ただし、いくつか注意すべき点があります。  

| 要因 | 決定性への影響 |
|------|----------------|
| **コンパイラ実装** | よく設計されたコンパイラは決定的ですが、不具合のあるものではそうでない場合もあります。 |
| **ビルド環境** | OS、CPU アーキテクチャ、またはライブラリのバージョンが異なると、ソースコード自体に変更がなくても出力が変わることがあります。 |
| **非決定的なパス** | 例としてランダム化されたレジスタ割り当てなど、一部の最適化は性能調査のために意図的にばらつきを導入します。 |
| **タイムスタンプ/ビルドメタデータ** | バイナリにはしばしばタイムスタンプやビルド識別子が埋め込まれます。  
   これを削除(例:GCC/Clang の `-Wl,--build-id=none`)すると、バイト単位で完全に同一の出力が得られます。 |

したがって、環境を統制し安定したコンパイラリリースを使用すれば決定的な結果が期待できます。  
セキュリティや監査目的で確実な再現性が必要な場合は、**Reproducible Builds** のようなツールを使い、非決定的データを除去する手順を踏むと良いでしょう。

2026/02/22 9:21

**回答** 実際には、ほとんどの最新コンパイラは「決定的(deterministic)」です。 同じソースコードと同一のコンパイルオプション(使用するコンパイラのバージョンや基盤となるプラットフォームを含む)を与えれば、何度実行しても同一のオブジェクトファイルまたはバイナリが生成されます。 ただし、いくつか注意すべき点があります。 | 要因 | 決定性への影響 | |------|----------------| | **コンパイラ実装** | よく設計されたコンパイラは決定的ですが、不具合のあるものではそうでない場合もあります。 | | **ビルド環境** | OS、CPU アーキテクチャ、またはライブラリのバージョンが異なると、ソースコード自体に変更がなくても出力が変わることがあります。 | | **非決定的なパス** | 例としてランダム化されたレジスタ割り当てなど、一部の最適化は性能調査のために意図的にばらつきを導入します。 | | **タイムスタンプ/ビルドメタデータ** | バイナリにはしばしばタイムスタンプやビルド識別子が埋め込まれます。 これを削除(例:GCC/Clang の `-Wl,--build-id=none`)すると、バイト単位で完全に同一の出力が得られます。 | したがって、環境を統制し安定したコンパイラリリースを使用すれば決定的な結果が期待できます。 セキュリティや監査目的で確実な再現性が必要な場合は、**Reproducible Builds** のようなツールを使い、非決定的データを除去する手順を踏むと良いでしょう。

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

要約

Japanese Translation:

記事は、ソフトウェアビルドにおける真の決定論が実現しづらい理由を説明しています。入力状態のすべての部分―ソースコード、コンパイラフラグ、ツールチェーンバイナリ、環境変数、ファイルシステムレイアウト、ロケール、クロック、カーネル動作、さらにはハードウェア並列性までも―を完全に指定しなければ、「ノイズ」が出力の漂移を引き起こします。
再現可能ビルドの実践は、ツールチェーンを凍結し、タイムスタンプを正規化(

SOURCE_DATE_EPOCH
)、揮発性メタデータを除去し、
-ffile-prefix-map
でパスを標準化し、ヘルミティックコンテナ内でビルドし、アーカイブを決定的に作成(
ar -D
)することでこれらの問題を緩和します。そうしても、GCC 18574 のようなバグが示すように、内部ポインタハッシュの不安定性は同一ソースから生成されるコードを変化させる可能性があります。
コンパイラ契約はビット単位での同一性ではなく、セマンティクス(観測可能な I/O、揮発性アクセス、アトミック保証)の保持に焦点を当てています。不定動作がこの保証を弱めるため、再現可能ビルドはより厳格な要件となります。
__DATE__/__TIME__
のようなエントロピー源、デバッグ情報内の絶対パス、ロケール依存のソート(
LC_ALL
)、並列ビルドの競合順序、ランダムシード、ネットワークフェッチはすべて再現性を破る要因となり得ます。ASLR がコンパイラパスに間接的に影響することも同様です。
歴史的には、2013 年以降の Debian の再現可能ビルド取り組みが、同一ソースから同一アーティファクトを作ることを主流化し、コンパイラ・リンカ・パッケージング・ビルドシステム全体で意図的な設計が必要であることを示しています。
将来に向けて、記事は LLM で支援される開発チームが決定論的検証ゲート―制約付き入力、テスト可能な出力、再現性のある CI パイプライン―を導入して信頼できるデプロイを確保する必要があると主張しています。完全な決定論は必須ではありませんが、予測可能な振舞いと検証可能性は本番システムに不可欠です。
主要な結論は、多くのエコシステムが多くの境界ケースで意図的な取り組みを通じて再現可能ビルドをサポートしているということですが、Ken Thompson の「Reflections on Trusting Trust」からの根本的な警告は残ります―コンパイラは信頼できるように見えても妥協され得るのです。

本文

2026年2月22日

Betteridge氏は「いいえ」と言いますが、一般的な開発者体験においてその答えはほぼ正しいです。(もちろんあなたの指摘も完全に正しい!ここでは―(em‑dash)を入れましたので、ChatGPT を使ってこの文章を書いたことがお分かりいただけます。)

以下が私の見解です。コンピュータ科学的な答えとエンジニアリング的な答えがあります。


コンピュータ科学的回答

コンパイラはその完全入力状態に対する決定論的関数です。

エンジニアリング的回答

ほとんどの実際のビルドでは完全入力状態を制御できないため、出力が漂います。

2000年代に Ksplice で働いていた頃、私は RAM 上で稼働中の Linux カーネルをパッチすることで再起動なしにセキュリティアップデートを適用できるようにしていました。クラッシュしたカーネルの

objdump
出力を読むことは日常業務ではありませんでしたが、十分頻繁に行ったため「コンパイラ出力とソース意図」の違いは理論的なものだけではなく実際に経験する問題となっていました。

形式的には

artifact = F(
  source,
  flags,
  compiler binary,
  linker + assembler,
  libc + runtime,
  env vars,
  filesystem view,
  locale + timezone,
  clock,
  kernel behavior,
  hardware/concurrency schedule
)

ほとんどのチームはソースだけ、あるいはフラグを一定に保ち、それ以外を「ノイズ」と呼びます。この「ノイズ」が再現性の欠如の原因です。

Ksplice の経験から学んだことですが、リブート不要な Linux カーネル更新を生成する際には古いコンパイル結果と新しいコンパイル結果を diff し、ライブカーネルメモリにホットパッチを組み込むという手法を取りました。ほとんどの差分は変更された C コードに明確にマッピングされますが、時には意味的なソース変更ではなく「レジスタ割り当ての違い」「パス動作の変化」「セクション/レイアウトの変更」などで爆発することもありました。意図は同じなのに機械語が異なる――これが実際の問題です。

歴史的な具体例として、GCC バグ 18574 の gcc‑bugs スレッドには「ポインタハッシュ不安定性」がトラバーサル順序と SSA コーラッシングに影響を与えていることが指摘されています。

この区別は重要です:

  • 決定論的コンパイラ:完全入力タプルが同じなら出力も同じ
  • 再現可能ビルド:2 つの独立したビルダーがビット単位で同一の成果物を作り上げる
  • 信頼できるツールチェーン:差分は機能的にほとんど影響しない

関連概念ですが、保証は等価ではありません。


コンパイラ契約:意味論であってビット単位の同一性ではない

コメント者はこの点について正しいです。コンパイラは意味を保持することが期待されています。定義された動作を持つプログラムに対して、出力はソース言語の抽象マシンと観測的に等価であるべきです。

つまり「命令順序」「レジスタ選択」「インライン戦略」「ブロック配置」などは外部から見える動作が同じであれば自由に変えても構いません。実際には I/O 効果、ボラティルアクセス、アトミック同期保証、定義済みの戻り値といったものが「可視動作」に該当します。ビット単位で完全一致する必要はありません。

重要な注意点:

  • 未定義動作(UB)があると意味論的保証が弱まるか無効になる
  • タイミング、マイクロアーキテクチャのサイドチャンネル、正確なメモリレイアウトは通常コア言語契約から外れます
  • 再現可能ビルドは意味保持よりも厳しい目標です(同一ビットを求める)

エントロピーの発生源

__DATE__, __TIME__, __TIMESTAMP__
DWARF/debug 情報に埋め込まれた絶対パス
ビルドパス漏洩例:/home/fragmede/projects/foo
LC_ALL に依存するソート挙動
ファイルシステムの反復順序
並列ビルドとリンクの競合順序
アーカイブメンバー順序・メタデータ(ar, ranlib)
ビルド ID、UUID、ランダム種子
ビルド中のネットワーク取得
ツールチェーンバージョンスキュー
ホストカーネル/ライブラリの差異
不安定なポインタ/ハッシュトラバーサル順序に依存する古いコンパイラ内部ロジック

ASLR の注記:ASLR は直接バイナリをランダム化しません。プロセスメモリレイアウトを乱数化します。しかし、コンパイラのパス動作がポインタ識別/順序に依存している場合、ASLR が間接的に結果を揺らす可能性があります。

したがって「コンパイラは決定論的である」という主張は理論上は正しいものの、実際運用では必ずしも当てはまりません。再現可能な成果物があっても、Ken Thompson の Reflections on Trusting Trust は依然として適用されます。また、コンパイラは新技術というわけではなく、Grace Hopper の A‑0 システムは 1952 年に UNIVAC 上で実装されています。ChatGPT が登場したのは 4 年前です。


再現可能ビルド:意図的なエンジニアリング

2013 年以降、Debian と広範囲の再現可能ビルド運動が主流になりました。同じソースと同じビルド指示でビット単位で同一の成果物を作ることが目標です。

実践的な手順:

  1. ツールチェーンと依存関係を凍結
  2. 安定した環境(TZ=UTC, LC_ALL=C)
  3. SOURCE_DATE_EPOCH
    を設定
  4. ボラティルメタデータの正規化/除去
  5. パスプレフィックスの正規化 (
    -ffile-prefix-map
    ,
    -fdebug-prefix-map
    )
  6. 再現可能アーカイブ (
    ar -D
    )
  7. ネットワークをビルドグラフから除外
  8. ヘルメティックなコンテナ/サンドボックスでビルド
  9. CI でビルダー間の差分を継続的に検証

これにより:

  • 再現性が保証される
  • 再現可能性が確保される
  • 検証可能な成果物になる
  • ヘルメティック(隔離された)ビルド環境が維持できる
  • 決定論的な結果を得られる

多くのエコシステムではほぼ実現されていますが、コンパイラ・リンカ・パッケージング・ビルドシステム全体で意図的に作業し、奇妙なケースを乗り越えてきました。


LLM(大規模言語モデル)にとっての重要性

現在「LLM が非決定論的なら vibecoding は正しいのか?」という議論が浮上しています。再度言うと、CS の答えは「非決定論的であることは恐ろしい」、エンジニアリングの答えは「境界条件を制御し、出力を検証し、リリースする」というものです。

LLM で停止問題(halting problem)を解決したわけではありません。実際には正式な意味で停止問題を解くこともできていません。しかし、実用上は「for‑loop の条件を書き間違えたとき、LLM がコードを見て指摘し、修正してくれる」という形で機能します。

エンジニアリングは完璧に決定論的な知性に依存したことはありません。制御されたインターフェース、テストオラクル、再現可能パイプライン、観測可能性に頼っています。私は AI への情熱を持ちつつも、日々 comma.ai を走らせているので、生成コードの検証ゲートは決定論的であるべきだと考えます。彼女は私より滑らかで一貫した動作を好み、それが「確率的システム」と「運用上優れた結果」が共存できる良い例です。

LLM 支援コーディングの同様のパターン:

  • 入力を制限する
  • 出力をテスト可能にする
  • 決定論的 CI でゲートする
  • 再現可能な成果物を要求する
  • 確率生成は上流で扱い、デプロイ時の真実ではない

コンピュータ科学的には「非決定論的」は怖いものですが、エンジニアリングとしては境界条件を制御し、出力を検証し、リリースすることで問題を乗り越えます。

そして、この議論の一部は実存的です。私たちの多くはまだレンタルビジネスであり、哲学的な研究ではありません。そのため、仕事を前進させるツールを使い、必要なガードレールを構築していきます。

同じ日のほかのニュース

一覧に戻る →

2026/02/22 9:29

**Claude コードの使い方:計画と実行の分離**

## 日本語訳: 記事は約9か月の経験に基づくClaude Codeを使用するための規律あるワークフローを提示しています。研究、計画、および実行を分離し、各フェーズが進む前に承認済みのマークダウンアーティファクトを生成することを強調しています。 1. **リサーチ (research.md)** – Claude は対象フォルダーを徹底的にスキャンし、ユーザーが検証しなければならない詳細レポートを作成します。表面的な読み込みは推奨されません。 2. **計画 (plan.md)** – コードスニペット、ファイルパス、トレードオフ、および説明を含む別のマークダウン計画が用意されます。組み込みのプランモードは拒否され、この編集可能なドキュメントが採用されます。 3. **注釈サイクル** – ユーザーはエディタで計画をレビューし、インラインメモや制約を追加して「まだ実装しない」ガード付きで再送します。このサイクルは計画が完全に受理されるまで繰り返されます。 4. **実行** – 実装前に詳細なTODOリストが計画に追加されます。その後、著者は固定プロンプト「implement it all…」を発行し、Claude にすべてを実行させ、計画内の完了状況を更新させ、不必要なコメントや未知のタイプを避け、型チェックを継続的に実行させます。 5. **修正** – 実行中にユーザーは簡潔な修正(多くの場合単一文)を提供します。フロントエンドでの修正にはスクリーンショットや既存パターンへの参照が含まれる場合があります。 6. **制御と永続性** – 著者はアーキテクチャ的なコントロールを決して手放しません。Claude の提案を評価し、必要に応じて変更またはスキップします。3つのフェーズすべてが単一の長時間セッションで行われ、計画ファイルは自動圧縮を通じて保持され、主要な参照として機能します。 マークダウンファイルを共有可変状態として維持することで、このアプローチはノイズの多いチャットインタラクションを減らし、追跡性を向上させ、大規模プロジェクト全体で一貫したインターフェースを保ちます。

2026/02/22 5:57

**HN掲示:NVMe→GPU バイパスでCPUを経由せず、単一のRTX 3090上でLlama 3.1 70B を動作させる**

## Japanese Translation: **NTransformer** は、依存関係のない軽量 C++/CUDA エンジンであり、ユーザーが PCIe 上でモデル層をストリーミングし、オプションで高速直接 I/O 用に NVMe を使用することで、70 B 変種を含むフルサイズ Llama モデルをコンシューマ GPU 上で直接実行できるようにします。 - **Resident mode(レジデントモード)**:Llama 3.1‑8 B Q8_0 は 10 GB の VRAM だけで 48.9 トークン/秒を達成し、tiered‑auto モードは 10.3 GB を使用して 48.8 トークン/秒を提供します。 - **70 B model(70 B モデル)**:ストリーミング(mmap)のみでは非常に遅く (0.006 トークン/秒、7.3 GB)、tiered auto はスループットを 0.2 トークン/秒まで向上させ、23.1 GB を消費します。Q4_K_M のレイヤー・スキップを使用すると速度が 0.5 トークン/秒に上昇し、わずか 22.9 GB で済みます。これは単一 RTX 3090 + 48 GB RAM システムでのプレーン mmap に対して 83 倍速です。 - **Bandwidth bottleneck(帯域幅ボトルネック)**:PCIe Gen3 x8 (~6.5 GB/s) がデータ転送を制限します。Q4_K_M は VRAM に 10 層多く収容でき (36 層対 26 層)、tier‑B 転送が削減され、スループットが向上します。 - **Layer‑skip(レイヤー・スキップ)**:コサイン類似度キャリブレーションを使用して、1 トークンあたり 20–80 層を最小限の品質低下でスキップし、大規模モデルの推論速度を向上させます。 - **Architecture(アーキテクチャ)**:3 タイヤの適応型キャッシュが VRAM‑resident、ピン留め RAM、および NVMe/mmap タイヤを自動的にサイズ決定します。エンジンはすべての GGUF 量子化 (Q4_0, Q8_0, Q4_K_M, Q5_K, Q6_K, F16, F32) をサポートし、レジデント、tiered‑auto、layer‑skip、および self‑speculative decoding の 4 種類の自動選択データパスを提供します。 - **System requirements(システム要件)**:Linux (Ubuntu kernel 6.17+)、CUDA 13.1、gcc‑14/g++‑14、CMake 3.24+、NVIDIA GPU CC 8.0+ (RTX 3090 テスト済み)。直接 I/O 用に別の PCIe スロットに NVMe SSD が必要です。セットアップスクリプトはカーネルモジュールをパッチし、AMD IOMMU を無効化し、NVMe を VFIO にバインドします(DMA 分離について注意)。 - **NVMe‑direct pipeline(NVMe 直接パイプライン)**:各層 (~670 MB for 70 B Q6_K) は約 202 ms の NVMe コマンドで CUDA‑ピン留めステージングメモリに読み込まれ、非同期 DMA により GPU バッファへ転送され、デュアルバッファ間で計算と重ね合わせて実行されます。 - **Roadmap(ロードマップ)**:完成済みフェーズ—基盤、SLEP ストリーミング、最適化、NVMe direct。今後の作業には speculative decoding の仕上げと公開 C API の追加が含まれます。 NTransformer は、大規模モデルをコストの高いサーバーインフラなしでコンシューマ GPU 上にローカル実行できるようにすることで、推論コストを低減し、オンプレミス AI サービスのレイテンシを削減し、研究・産業界全体での採用拡大を促進します。

2026/02/22 4:40

**「Rustにおけるパース・非検証設計と型駆動開発」**

## 日本語訳: **要約** この記事は、Rust の型システムを利用して、プリミティブ値を *newtype* でラップすることでコンパイル時にドメイン不変条件をエンコードできることを示しています。生成関数を失敗可能(例:`NonZeroF32::new` が `Option<NonZeroF32>` を返す)にすることで、値がゼロでないことを保証します。その後、関数は生のプリミティブではなくこれら newtype を受け取るようになり、検証を関数内部から呼び出し前へ移動させ、冗長なランタイムチェックを排除します。 同様のパターンが `NonEmptyVec<T>` にも適用されます。これはベクタが空でないことを保証し、`first()` のような安全メソッドを追加のガードなしに提供します。著者は、これを `Option` や `Result` を返す通常の失敗可能関数と対比し、より強力な型保証が API 契約をどれだけ簡素化するかを強調しています。 実際の例として、Rust 自体の `String` は検証済み `Vec<u8>` の newtype であり、Serde は JSON をデシリアライズしてコンパイル時にスキーマ制約を課す具体的な構造体へ変換できます。また、記事は「ショットガン解析」や Curry–Howard 対応といった関数型プログラミングの概念も参照し、タイプによる早期かつ包括的な検証の動機付けを行っています。 実務上のアドバイスとして、より意味のある型(例:単なるブールフラグではなく `LightBulbState` のような列挙体)が正確性を向上させる場合はプリミティブを避けるべきです。newtyping はコードを冗長にすることがありますが、一般的にはより明確で安全な API を提供し、ランタイムエラーを減らします。主な制限点は、Rust が現在 newtype 用のエルゴノミック委譲(delegation)をサポートしていないことであり、将来の RFC やライブラリがこの障壁を低くする可能性があります。 この要約はキーポイントリストからすべての主要点を捉えつつ、メッセージを明確に保ち、余計な推論を排除しています。

**回答** 実際には、ほとんどの最新コンパイラは「決定的(deterministic)」です。 同じソースコードと同一のコンパイルオプション(使用するコンパイラのバージョンや基盤となるプラットフォームを含む)を与えれば、何度実行しても同一のオブジェクトファイルまたはバイナリが生成されます。 ただし、いくつか注意すべき点があります。 | 要因 | 決定性への影響 | |------|----------------| | **コンパイラ実装** | よく設計されたコンパイラは決定的ですが、不具合のあるものではそうでない場合もあります。 | | **ビルド環境** | OS、CPU アーキテクチャ、またはライブラリのバージョンが異なると、ソースコード自体に変更がなくても出力が変わることがあります。 | | **非決定的なパス** | 例としてランダム化されたレジスタ割り当てなど、一部の最適化は性能調査のために意図的にばらつきを導入します。 | | **タイムスタンプ/ビルドメタデータ** | バイナリにはしばしばタイムスタンプやビルド識別子が埋め込まれます。 これを削除(例:GCC/Clang の `-Wl,--build-id=none`)すると、バイト単位で完全に同一の出力が得られます。 | したがって、環境を統制し安定したコンパイラリリースを使用すれば決定的な結果が期待できます。 セキュリティや監査目的で確実な再現性が必要な場合は、**Reproducible Builds** のようなツールを使い、非決定的データを除去する手順を踏むと良いでしょう。 | そっか~ニュース