CPU黒歴史 大損失と貴重な教訓を生んだPentiumのバグ

文●大原雄介(http://www.yusuke-ohara.com/)

2013年01月15日 12時00分

 今回のCPU黒歴史のネタは、安藤壽茂先生にも指摘された(関連リンク)「バグ付きPentium」の話である。何分18年前という古い話なので、ご存知ない方も多かろうと思う。そのため、まずは歴史的な経緯から説明したい。

担当編集が所有していた、バグ付きPentium入りのアクセサリーの拡大写真

NetNewsから火が付き
あっという間に広がったFDIVバグの話題

 18年前の1994年10月、米バージニア州リンチバーグ大学のThomas R.Nicely教授が、インテルに対して「Pentiumで非常に小さな値で割り算を行なうと、結果がおかしくなる」というレポートを送ったことに端を発する。インテルはこのエラーが起きたことは認めたものの、「そんな話はこれまでレポートされたことがない」と返答した。

 そこで教授は、自身の送った内容とインテルからの返答を添えて、この問題が他のプロセッサー(486や他のPentium、あるいはPentium互換プロセッサー)でも発生するかどうか試してほしい、と複数の知り合いにメールを送り(関連リンク2)、それは直ちにNetNewsに掲載されることになった。

 1994年、まだウェブはまったく一般的ではなく、インターネットそのものの帯域ももっと細かった。当時利用されていたのはメール(それもテキストのみ)と、NetNewsと呼ばれるバケツリレー式のテキストデータ配信システム、それとGopherと呼ばれる(やはりテキストベースの)情報検索システム程度である。

 この中で、「ウェブページ+掲示板的」な役割を果たしていたのがNetNewsで、筆者の記憶が正しければ、最初に「comp.sys.intel」というNetNewsに投稿されたはずである。この「comp.sys.***」というNetNewsは、インターネットにつながっているマシンを使える多くのユーザーが読んでいた。そして、当時インターネットにつながるマシンを使える人は、圧倒的にコンピューター関係技術者が多かったから、あっという間にこの話はネット中に広まることになった。

 ここから事態は加速的に進展してゆく。同年11月7日、「Electronic Engineering Times」(現EE Times、米国で一番歴史が長い電子業界誌)が、これに関する記事を公表。11月21日にはCNNがニュースとして取り上げた。当初インテルはこの問題を認めず、その後には「問題はあるが軽微なもので実害はない」としていた。

 インテルは「一般のユーザーでは、この問題に起因して問題が起こる頻度は27万年に一度」と説明したことに対して、米IBMは「一般的な表計算を利用する場合、6時間に1度の頻度で計算が誤りとなる」とこれに反する見解を表明。さらに同年12月12日には、IBMが発売していたPentiumベースのマシンを、この問題が修正されるまで出荷停止にすると表明するに至る。そして、当時Pentium搭載マシンを出荷していた多くのPCメーカーが、これに続くことになった。

 12月19日にはNew York Timesがこれに関する記事を掲載。これによって当時は、「Pentium」という言葉が「バグを抱えているもの」の代名詞に使われるほどだった。結局インテルは12月20日に、公式に謝罪を表明。すでに出荷したPentiumにバグがあったこと。そのバグのあったPentiumはすべてバグを修正したものに無償交換すること。およびこの無償交換にともなう費用を4億2000万ドル(後に4億7500万ドルに上方修正)と見込んでいることを発表して、ようやく事態は収束に向かうことになった。

 ちなみに、1994年度におけるインテルの売上は115億2000万ドル。純利益は22億9000万ドル(関連リンク3)と発表されていたから、純利益の17%ほどがこれで吹っ飛んだ計算になる。

 ここまで騒ぎが大きくなった理由のひとつには、大手PCメーカー、特にIBMの存在が関わっていたことは否めない。IBMは当時、インテルからPentiumやPentium Proを購入してワークステーションやサーバー向け製品を出荷している大手メーカーであったが、同時に競合するCPUである「PowerPC」を推進しているCPUメーカーでもあった。

 また、IBMは「Blue Lightning」という486互換プロセッサーもリリースしていたから、インテルとの関係は微妙なものだった。当時からインテル自身と、インテルからコンポーネントを購入してPCを販売しているベンダーの「利益率の違い」は火種になっており、そうしたこともあったためか、IBMはこのバグを過剰に宣伝した嫌いはある。

 インテルのこうした動きは、当然ながら互換CPUメーカーには追い風であった。例えば、問題が露呈してすぐに「Cyrix Instead」という広告を打ったCyrixはなかなか優秀だったと思う(言うまでもなく「Intel Inside」のパロディだ)。他にも当時のNetNewsでは、「Intel Insane」(インテル狂ってる)が流行ったことを筆者も覚えている。

 その追い風がそれほど続かなかったのは、一度全量交換を決めてからの、インテルの動きが素早かったためだ。ほどなくIBMなどからの製品出荷も再開されることになった。

Pentiumで採用された割り算の方式
SRT法とは?

 そもそもPentiumのバグ問題とは何だったのか? それは「割り算を行なう時に変な結果になる場合がある」というものだ。除算命令である「FDIV」を実行する時のみ発生したので、俗に「FDIV問題」(FDIV bug、FDIV flaw)と呼ばれている。これはPentiumの世代から、計算の高速化を狙って導入した「SRT法」に起因する。

 元々インテルでは486まで、「引き放し除算」(nonrestoring divisionとも)という方式を使っていた。例えば「987÷12」を計算する場合、人間は図1のような方法で計算する。

図1 人間が「987÷12」を計算する場合

 ところがCPUの計算は、当然二進数になる。「987」は「1111011011」で、「12」は「1100」になる。そこで2進数で同じように計算すると図2のようになる。

図2 CPUが「987÷12」を計算する場合

 まず上位4桁(除数の1100が4桁だから)をマッチングすると、商が「1」と出る。ここから1bit右にシフトして、先程のあまりの「011」に次の「0」を加えて、「0110」と「1100」をマッチングし、商が0になる。そんな調子で、1bitずつシフトしながら割り算を繰り返してゆき、最終的に商が「1010010」(82)で、あまりが「11」③と計算できるわけだ。こうして「シフト演算+減算」だけで、除算は構成できる。

 言うまでもなく、この方式は時間がかかる。なにせ1回につき1bitずつしか処理できないからだ。例えば32bit同士の演算を考えた場合、最悪なのは非除数(割られる数)が32bitで、除数(割る数)が1bitのケースだ。この場合、減算32回とシフト31回が必要になるから、合計63回の演算をしないと結果がでない。

 Pentium以降で採用されたSRT法(SRT Division)とは、一度に2bitを演算する方法である。この方式は開発者であるSweeney、Robertson、Tocherの名を取って、SRT法と呼ばれている。そもそも引き放し除算の場合、1bitずつの処理になるから、商は常に「0」か「1」である。では2bitならばどうかというと、商は0、1、2、3のいずれかになる。そこで、A÷Bを計算する場合には、以下の3つを同時に計算する。

  • ①A÷B
  • ②A÷2B
  • ③A÷3B

 この3つの計算により、以下のように判断できる。

③の商が「1」 商は「3」
③の商が0、②の商が「1」 商は「2」
③と②商が0、①の商が「1」 商は「1」
③②①の商が「0」 商は「0」

 この方式は一見すると、手間がかかるように見える。だが、2倍は2進数の場合シフト演算1度で済むし、3倍は「1倍+2倍」で、これも比較的容易である。何より、①~③を同時に行なえるから、回路規模こそ増えるものの時間は短縮できる。

 2bit分の演算をもう一歩進めたのがSRT法である。前ページでの①~③の関係を、図にまとめたのが図3になる。除数と非除数、各々の商の関係をまとめたもので、「正規化」というのは、「0~1の間になるように調整」という意味である。

図3 一度に2bitの演算をグラフ化したもの

 この図3に、さらに「引き戻し法」と呼ばれる方法を加えたものが図4になる。引き戻し法とは、除算の結果として「余りが負になる」ことを許すというものだ。負になった場合、あとで余りを正に引き戻す処理が入ることから、「引き戻し法」と呼ばれる。この場合、1桁ならあまりは-1、0、1の3種類となる。それが2桁なので、あまりは-2から2までの5種類となる。

図4 図3の計算に引き戻し法を加えた場合のグラフ

 図4の例では、商が重なりあう場所がいくつかあるが、これは「商がどちらの場合もあり得る」という意味だ。最終的な商はどちらかに確定するが、その判断は後の引き戻しの処理で決まる。

 図4の右上を拡大したのが図5である。この例では、除数を16等分(1マスあたり32分の1)、余りを12等分(1マスあたり2分の1)としたが、数ヵ所の例外を除けば、除数と余りから「商を得られるテーブル」が構築できることがわかる。数ヵ所の例外は、余りをもう一段細かくする(1マスあたり1/4)ことで、これを回避できる。

図5 図4の右上部分のグラフを拡大。マス目を埋めるように商が並んだテーブルができる

 結果として、「ある2bitの除算の商が、テーブルを参照するだけで求められる」ことになり、大幅な高速化が可能になる……というのが、このSRT法の要点である。ある2bitの商を算出すると、次の2bit分の余りが算出できるので、これを繰り返すことで除算が可能になるわけだ。

なぜFDIVバグは発生したのか

 Pentiumに話を戻そう。Pentium FDIVバグが発生した理由は、このテーブルの値が5ヵ所間違っていたことによるものだった。その結果、このテーブルの当該ヵ所を参照する割り算は、必ず値がおかしくなる。残念ながら、これはファームウェアで修正できるレベルではなかったし、当時はまだ「CPUのバグをファームウェアで修正をする」という概念がなかったから、CPUの交換が必要になったのは致し方ないところだろう。

お詫びと訂正:掲載当初、テーブルの値が1ヵ所間違っていたと記載していましたが、正しくは5ヵ所でした。ここに訂正するとともに、お詫びいたします。(2013年1月18日)

 この話をなぜCPU黒歴史第1シーズンで触れなかったかというと、確かに大問題は大問題であったのだが、結果から言えばそれほどインテルに悪影響を与えなかったからだ。むしろ、インテルのサポート対応を良くするうえで、効果的だったとも言える。

 確かに、FDIVバグを持ったPentiumの交換には非常に金がかかった。しかしこのトラブルがあったにも関わらず、Pentiumの売れ行きはすぐ元に戻り、Socket 5からSocket 7の時代にかけて、広く利用される製品となった。当時、浮動小数点演算を積極的に扱うユーザーは、それほど多くなかった。科学技術計算系はともかく、一般消費者は「まだ整数演算だけできればOK」という時代だったから、とも言える。また、最終的なインテルの対応に好感を持った消費者が、少なくなかったこともこれを後押しした。

 またインテルはこれに懲りて、問題があったらすぐに公開して対応するという姿勢を全社的に整えることとなる。これにより、それまではあまり表に出てこなかった「エラッタ」※1のリストなどもこの後は入手が容易になった。
※1 Eratta、CPUが抱えるバグや設計上の問題点。

 Pentium関係のバグでは、1997年に発覚した「F00Fバグ」※2の方が重大だった。しかしインテルが速やかに情報を公開するとともに、解決法を提供したため、OSベンダー側がこれに対応して、バグを発生させないように対処したことで、大きな影響はなかった。
※2 「lock cmpxchg8b eax」という命令を処理しようとすると、ハングアップする。本来は不正命令として例外処理を行なうべき命令。

 その後インテルがリリースした製品でも、Intel 820チップセットや、最近ではIntel 6シリーズチップセット、Intel SSD 520などでリコールの問題が起きている。だが、これらが深刻な影響を与えずに済んでいるのは、やはりPentium FDIVバグの教訓がいまだにきちんと生きていることの証拠と考えられる。

 その意味では、インテルの黒歴史のひとつになりそうだったのが、一転して貴重な体験をもたらした功労者となったのがPentium、と言えるだろう。

■関連記事