3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

論文 "Instruction Set Migration at Warehouse Scale" から読み解く、細くとも長持ちする Linux C言語プログラムの作り方

Last updated at Posted at 2025-12-05

株式会社 ACCESS の三原といいます。かつてはガラケー向けブラウザのコーディングに従事し、現在は発電設備などで現地の機材から上がるデータをインターネットに再送するゲートウェイのデーモンを Linux 上に C 言語などで実装しています。

環境が変わっても動作する C 言語プログラムというあり得ないはずの存在について、Google は実現を迫られて結果を論文にまとめています

C言語プログラムは、環境が変わればコンパイルしても期待通りに動作しないことは当たり前、期待する方が悪い。そう語られます。

ところが、そうも言っていられない状況に入った会社があります。それも生半可な会社ではありません。Google です。

Google は、長年にわたってデータセンターに x86 と x86_64 アーキテクチャの CPU を購入して導入してきました。しかし外部企業に、と言っても相手先は Intel と
AMD ですが、事業の根幹を他社に委ねていることは Google レベルの企業にとっては好ましくない事態です。そこで CPU を自社開発すると決断して Arm アーキテクチャをベースにして Google Axion プロセッサをデータセンターに導入し始めました。ですが CPU は製造できても、もっと大事な問題が持ち上がります。

CPU 以上に大切な、しかも自社のノウハウの塊である、C/C++ で書かれたプログラムを x86_64 向けから Arm 向けに移植すると、どれだけの困難に直面するのか?

この問題に Google は真剣に取り組み、得られた知見を公開しています。

Google の論文は金字塔ですが、僕が書く記事では裏から見ます。

Google が直面した課題をあらかじめ避けるように開発を進めれば、C 言語プログラムであっても環境の変化に追随することに特段の作業は不要ではないか?

論文 "Instruction Set Migration at Warehouse Scale" が指摘した課題

論文 "Instruction Set Migration at Warehouse Scale" は数々の課題を指摘しますが、それでも以前に想定されていたよりは課題は減っていると指摘します。

However, modern ISAs are generally well-supported in upstream compilers, runtime libraries, and the Linux kernel. As a result, modern compilers mostly “just work” for a new ISA, and previous ISA migrations have smoothed
the path to packages supporting cross-compilation by default. For example, 98% of Debian packages build for RISC-V, although it only became an official Debian architecture in 2023.

("1 Introduction" より抜粋)

現在ではツールチェインが充実しているため、多くのプログラムはコンパイルすると動作するようになっています。

その上で、種々の課題について、ビルドスクリプトをマルチターゲットにするなど環境についてではなく、プログラム本体について x86 から Arm へ移植するにあたって問題となったことを挙げていきます。

"3.3 Phose 1: Large users" という、多くの開発者が関わっていることを示す一見では CPU 命令セットについて触れていないとみなしかねない説に以下が述べられています。

  1. x86 固有の組込み関数(intrinsics)を置き換える
  2. long double は x86 と Arm で挙動が異なるため absl::float128 に置き換える
  3. 浮動小数点数演算の精度に依存する(事情については 2 にて指摘)脆弱なテストを修正する
  4. x86 固有のフラグを用いているところを修正する
  5. x86 が持つ厳格なメモリオーダーにより隠蔽されている問題を修正する
  6. Out-of-memory つまりメモリ不足時の挙動が x86 に依存しているところを修正する
  7. マルチターゲット向けにビルドする際の社内インフラの負荷について解決する
  8. サポート対象外の依存関係と動的ライブラリについて整理する
  9. Google が用いている Borg クラスター管理システムにおけるタスクスケジューリングのトラブルを解決する

7 から 9 については Google の社内インフラですから、CPU 命令セットの違いに関わる点は 1 から 6 です。いずれも重篤です。しかし。

実際に列挙してみたら意外と少なかった、それが率直な感想です。

課題の中でメモリオーダーに触れた点については深く見る必要があり、外部から資料をお借りします。

複数のスレッドで共有メモリにアクセスする際に書き込みと読み込みの順序がどのように観測されるのかについて、ハードウェアの違い(ただ、区分を示す単語は CPU アーキテクチャの名前)によって異なると述べます。

SCは命令が書かれた順番通り実行されるような、プログラマーの直感に合うモデルです。

(中略)

今節で定式化したSCは、直感的で扱いやすいメモリモデルです。にもかかわらず現実のCPUがこのモデルに従っていないのは、パフォーマンスが理由です。次の節では、そのあたりの事情を解説します。

パフォーマンスを向上させることを目的に、複数のスレッドで共有メモリにアクセスする際に順序が入れ替わることもありうると規定されていると述べています。

ではプログラマーが意図した通りには動作しないかというと、少し違ってきます。

高水準言語のプログラミングをするときに、メモリモデルを意識する必要はあるでしょうか? 基本的にはないというのが回答です。これはSC for DRF programs (Sequential Consistency for Data Race Free programs) というフレーズで知られています。2つ以上のスレッドが同期操作なしに同じメモリアドレスにアクセスし、そのなかに書き込み操作があった場合を、データ競合と言います(より厳密な定義は[1]の5.4節を参照してください)。
したがってプログラマーはロックなどを適切に使い、データ競合が発生しないようにプログラミングすることで、SCな実行を期待できるというわけです。

高水準言語のプログラマーは基本的にSCを期待できるという主張には例外が存在します。C, C++, Rust, Javaなどの言語にはメモリオーダーを指定できるアトミック操作があります(C++、Rust、Java)。SCに相当するメモリオーダーを指定している限りは問題ありませんが、より緩いメモリオーダーを指定する場合にはそれに対応するメモリモデルの理解が不可欠です。

基本的にプログラマーにとってはソースコードに書いた通りに動作するものであって、原則から外れた挙動を実行させるにはプログラマーからの積極的な働きかけを必要とするということです。

「建前でなく本音で話してよ」という賢さが逆に仇となるほどの、OS と言語処理系の品質保証の高さ

上記の議論から、私たちは、特に日本社会に生きてきた私たちからは疑問が上がるでしょう。そういうルールになっているけれども、本当に動くの? 建前でなく本音で話してよ? そうおっしゃる人が多いでしょう。

その賢さが裏切られたというのが、Google の論文が含む裏の意味です。OS と言語処理系の品質保証は高く、言語仕様と標準ライブラリ関数の man の規定に沿って書いていれば確実な動作を期待でき、CPU 命令セットが違うからと斜に構えると損をするし自分のコードのバグに気づかず言語処理系のミスに押し付けかねないことを暗に示したのです。

下手な例え話を二つ記します。

「アンディ・ウォーホルって人間について知りたいと思ったら、僕の映画や絵をただ、表面的に見てくれればいい。そこに僕がいるから。裏には何もないんだ。」
…… アンディ・ウォーホル

20世紀後半の現代美術家であるアンディ・ウォーホルは、自分は表面以外に何も持ち合わせていないと明かします。Linux の動作を規定する POSIX や C 言語は20世紀後半に開発されたものですから、時期が同じであり構造も相似しています。

日本のオタク文化から引けば漫画「【推しの子】」のキャラであるアイドルのアイでしょうか。アイドルの裏面を暴く攻防は物語の中核ですが、当のアイは本物の嘘つきで周囲に気取らせません。

先に挙げた「メモリモデル入門(Sequential ConsistencyとTotal Store Orderを理解する)」に示唆する言葉が記されています。

JLSの “the program will appear to be sequentially consistent” という表現に注目しましょう。プログラムが本当にSCに実行されているかどうかではなく、そのように見える(appear to be) ことが重要です。すなわちメモリアクセス順序の入れ替えが起きていることと、それを観測できることは別です。

漫画「【推しの子】」に戻ると、アイの人となりについて、よほどの人物は裏を知っていますが、一般のファンには見抜けません。見抜けると思えば、力量の差を見誤っています。

Linux で C 言語プログラムを書く際には、漫画「【推しの子】」のアイを見るように、表面の綺麗事だけを見ていると破綻することはなく幸せになってしまう。そんな世界が妄想ではなく現実に存在しそうです。

愚直に C 言語プログラムを書く、それは長持ちのコツ

題名に、このように記しました。

細くとも長生きする Linux C言語プログラムの作り方

結局は次に落ち着きます。

  • C言語の仕様に沿って書き、CPU 命令セット依存の記述は避ける
  • 標準ライブラリ関数を man に記された規定に沿って使う

これだけです。しかし大きなことです。上にように書いても環境が変わると動作しなくなると考えられてきたのは一種の「神話」であり、環境が変わっても結構期待通りに動作することが Google レベルで確認できたということです。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?