Bug Inside:Pentiumで大きな間違いを犯す小さなチャンス

「Pentiumのバグは非常に特殊なため、通常のユーザーは27,000年ごとに遭遇します。」
-Intelガイド

「3ミリ秒ごとにエラーが発生するもっともらしいシナリオを次に示します。」
-Voen Pratt(SUNロゴデザイナーおよびKnut-Morris-Prattアルゴリズムの共著者)

66 MHz Intel Pentium(sSpec = SX837)とFDIVバグ

質問:電球をねじ込むのに何人のPentium開発者が必要ですか?
回答: 1.99904274017、このような回答は技術教育を受けていない人々を満足させるはずです。

そして今、主な質問:「トーマス・ニズリーは1994年6月の初めから1994年10月の終わりまで何をしたのですか?

画像


トーマス・ナイスリー


画像


大学で、ニズリー教授は素数のペア、トリプレット、およびクアドラプレットを研究しました。 1994年3月、数学者はPentiumを計算に関連付け 、1994年6月12.9991523619に 、彼は数字の不一致に気付きました。 間違いはどこですか?

5か月が経過しました。



これは、多くの場合、すべてが二重にチェックされ、バグがコードではなくプロセッサにあることを理解しているときの面白い感じです。


29.9999973251 10月29日、 Thomas Nisleyは、Undocumented Windows、Undocumented DOSの著者であるAndrew Schulmanの発見を発表しました。 Schultmanは自分のPentiumを持っていなかったため、 0.999999 9998 年11月Phar Lapの創設者であるRichard Smithに頼って、コンピューターのバグをテストしました。 ファーラップでは、Windowsの計算機とCの簡単なプログラムを使用して、部門にエラーがあることをすぐに確認しました。

リチャード・スミスはトーマス・ニズリーにメッセージをインテルや当時の他のいくつかの主要企業に送りました。マイクロソフト、メタウェア、ワトコムなど。

24時間にわたって、さまざまなPentiumシステムのバグに関する9.9999973251を超える確認が受信されました。

バグを説明する10月30日のThomas Nisleyの手紙
FROM:博士 トーマス・R・ナイスリー
数学の教授
リンチバーグ大学
1501レイクサイドドライブ
24501-3199バージニア州リンチバーグ

電話番号:804-522-8374
ファックス:804-522-8499
インターネット:nicely@acavax.lynchburg.edu

TO:誰が懸念するか

RE:Pentium FPUのバグ

日付:1994年10月30日

浮動小数点ユニットにバグがあるようです(数値
多くの、そしておそらくすべてのPentiumプロセッサのコプロセッサ)。

要するに、Pentium FPUは特定のエラー値を返しています
分割操作。 たとえば、

1 / 824633702441.0

正しく計算されない(8桁目以降のすべての数字
エラーがあります)。 これは通常のコンパイル済みコードで検証できます
Quattro ProやExcelなどのスプレッドシート、またはWindows電卓
(科学モードを使用)、コンピューティングにより

(824633702441.0)*(1 / 824633702441.0)、

これは正確に1でなければなりません(いくつかの非常に小さな丸め内で
エラー; 一般に、コプロセッサーの結果には19
10進数)。 ただし、テストされたPentiumは

0.999999996274709702

この計算のため。 同様の誤った値がx *(1 / x)に対して得られます
区間内のxのほとんどの値に対して

824633702418 <= x <= 824633702449、

そして、上記の乗算または除算によって得られた任意の間隔を通して
2の整数乗による間隔(さらに他の間隔があります
分割エラーも発生します)。

バグは、上記の値に対して1 /(1 / x)を計算することでも確認できます。
xの。 Pentium FPUは元のxを返せません(実際、
多くの場合、正確に3072 = 6 * 0x200大きい値を返します)。

このバグは、私がテストした、またはテストしたすべてのPentiumで確認されています
日付、Dell P90、Gateway P90、Micron P60、Insight P60、
およびPackard-Bell P60。 486以前では観測されていません
システム、PCIバスを備えたシステムです。 FPUがロックアウトされている場合(常にではない
可能)、エラーが消えます; しかし、その後Pentiumは「586SX」になり、
浮動小数点はエミュレーションで実行する必要があり、計算が遅くなります
およそ10倍。

このバグに関連する誤った結果に遭遇した
以前は1994年6月でしたが、1994年10月19日まではなかったと感じました
他の考えられるすべてのエラーの原因(ソフトウェアロジック、コンパイラ、
チップセットなど)。 このバグに関してインテルのテクニカルサポートに連絡しました
10月24日月曜日(電話番号51270)。 後で連絡する人
Intelの66 MHzシステムでバグが観察されたが、
そのようなバグがないという事実以外の詳細情報または説明
以前に報告または観察されていました。

詳細については、私に直接連絡するか、
の[anonymous.nicely.pentium_bug]ディレクトリからファイルをダウンロードする
インターネット上の匿名FTPを介したacavax.lynchburg.eduマシン(パスワード
匿名、ユーザーID =インターネットID)。 これらのファイルにはドキュメントが含まれています
ファイル、バグを示すDOS実行可能イメージ、および
デモンストレーション。 zipファイルはPKZIPバージョン2.04gを使用します。

他のPentiumからのテスト結果の聴取に興味があります。
486-DX4sおよび(誰かがまだ持っている場合)AMD、Cyrix、およびNexGenからも
Pentiumのクローン。

あなたは私に帰属を与えている限り、この情報を自由に使用することができます
名前と雇用主。

www.trnicely.net/pentbug/bugmail1.html

10月30日ナイスリーからの手紙-シュルマン
======== 10月 30-博士 Andrew SchulmanへのNicelyのメール=================

2351 S0 / CompuServeメール[MAIL]
94/10/30 15:25 EST
SB:Pentium FPUバグ
Fm:インターネット:nicely@ACAVAX.LYNCHBURG.EDU

送信者:nicely@acavax.lynchburg.edu
受信:arl-img-2.compuserve.comによるACAVAX.LYNCHBURG.EDUから
(8.6.4 / 5.940406sam)
id PAA15607; 日、1994年10月30日15:21:00 -0500
から:
受信:ACAVAX.LYNCHBURG.EDU(MX V4.0 VAX)id 29; 日、1994年10月30日
15:20:50 EST
日付:1994年10月30日15:20:49 EST
To:76320.302@COMPUSERVE.COM [[RMS:Andrew Schulman]]
メッセージID:<00986B92.4921C4D0.29@ACAVAX.LYNCHBURG.EDU>
件名:Pentium FPUバグ

FROM:博士 トーマス・R・ナイスリー
数学の教授
リンチバーグ大学
1501レイクサイドドライブ
24501-3199バージニア州リンチバーグ

電話番号:804-522-8374
ファックス:804-522-8499
インターネット:nicely@acavax.lynchburg.edu

TO:誰が懸念するか

RE:Pentium FPUのバグ

日付:1994年10月30日

浮動小数点ユニットにバグがあるようです(数値
多くの、そしておそらくすべてのPentiumプロセッサのコプロセッサ)。

[[RMS:残りの博士。 Nicelyのメッセージが続きます]]

11月1日からSchulman-Smithへの手紙
======= 11月 1-リチャード・スミス宛のアンドリュー・シュルマンのメール===============

From uunet!Compuserve.com!76320.302 Tue Nov 1 09:44:32 1994
日付:94年11月1日09:27:48 EST
From:アンドリュー・シュルマン
宛先:
件名:Pentiumのバグ?
ステータス:RO

リチャード、

これについて何か聞いたことがありますか?

アンドリュー

-転送されたメッセージ-
#:2351 S0 / CompuServeメール[MAIL]
94/10/30 15:25 EST
SB:Pentium FPUバグ
Fm:インターネット:nicely@ACAVAX.LYNCHBURG.EDU

[[RMS:残りの博士。 Nicelyのメッセージが続きます]]

CanopusフォーラムにRichard Smithが投稿
======= 11月 1-CISのCanopus froumへのRichard Smithの投稿======

263767 S1 /一般情報
94年11月1日22:40:54
SB:Pentiumチップのバグ?!?!?
Fm:リチャード・スミス[ファーラップ] 75070,2253宛先:すべて

今日、私の友人が添付のメッセージを私に送った。 博士のようです
リンチバーグ大学では、Pentiumフローティングのバグを発見したようです。
ポイント単位。 メッセージは詳細を提供します。 特定の値については、表示されます
Pentiumプロセッサが浮動小数点除算に対して間違った答えを取得する
操作。 興味深いのは、問題を簡単に再現できることです
Windows計算機を実行します。 これを読んでいる人は
メッセージは、所有しているPentiumシステムで問題の複製を試みることができます
ここで結果をカノープスに投稿してください。 マシンの詳細を入力してください
実行中の構成。 私が知っている少数の人々はすでに持っています
博士と同じ誤った結果を得ています いいね。

リチャード・スミス

[[RMS:Dr. Nicelyのメッセージが続きます]]


トーマス・ニズリーのバグに関する出版物


プレス


6.9999831538 1994年11月、Alex WolfeはElectronic Engineering Timesに記事を公開しました。

IntelはAlex Wolfeからのリクエストに応えて、1994年の夏にこのエラーを発見し、後でリリースされたプロセッサで修正されたと述べました。 しかし、Intelはリリースされた欠陥のあるプロセッサの数を特定できず、このエラーの重要性を平準化しようとしました。

Intelの広報担当者は、この欠陥は一般ユーザーには影響しないと強調しました。 ナイセルといえば、スミスは次のように述べています。「これは例外的なユーザーです。 彼は24時間逆数値を計算します。 彼が数か月の計算の後に発見したのは、8つの10進数が正しく、9番目だけが正しく表示されないという事実の例です。 つまり、ポイントの右側にある9番目の文字にのみ間違いがあります。 あなたがエンジニアであっても、これに気付くことはないと思います。」 [ ソース ]

1999年11月21日、1035年、 CNN 1994年11月17日にこの発表配布し、ニューヨークタイムズやAP通信などの主要メディアで間もなく公開されました。 他のインタビューでは、インテルは、エラーが平均的なユーザーにとって重要ではないという以前の声明を繰り返しました。

インテルは、プロセッサーをリコールする必要はないと考えており、 平均的なユーザーはこのエラーのために90億回のうち1回しか間違った結果を得る ことができないため、自宅やオフィスのコンピューターに顕著な影響ないと主張しています。

ティム・コー


1999年11月27日に、 Vitess SemiconductorのTim Coeはcomp.sys.intelニュースグループに関する記事を公開し、アルゴリズムの実装を「逆転」し、Pentiumプロセッサの動作のモデルを提案しました。 数日後、エラーに対するハードウェアおよびソフトウェアのパッチが登場しました。

Tim Coeによる元の手紙11月28日
ニュースグループ:comp.sys.intel
From:coe@vitsemi.com(ティムコー)
件名:Re:PentiumでのFDIVの明白なバグ!
送信者:coe@vitsemi.com(ティムコー)
組織:Vitesse Semiconductor
日付:月、94年11月28日06:33:42 GMT
行:548

PentiumハードウェアディバイダーのCモデルがあります
正確に予測したこのメッセージの最後に
記載されている失敗した除算の多くは、正確に
私が知っているすべての失敗した分割を確認します。

私は1989年から1991年までIEEEハードウェアFPUに取り組んでいました。
FPUデザイナーとして私は自然に興味があります
ハードウェア算術のアルゴリズム。 私は現在
完全に異なるものに取り組んでいますが、私は
関連する開発を時折サポートする
タスク。

Pentium FDIVに関連する最初の投稿を見ました
comp.sys.intelのバグ。 からの投稿を見たとき
アンドレアス・グルース(同梱)、パターンを見ました
Intelを完全にリバースエンジニアリングする機会
仕切り 私はこのタスクに精力的に取り組みました。
に可視性を得ることは非常にまれです
他の誰かの最先端デザインの詳細。

結果が表示されたときに投稿することにしました
インテルは、
バグの特性。 最高の特徴
バグの唯一の特徴
インテルは、発生する確率が90億分の1です
ランダムなオペランド。 最悪の特性
バグのほとんどは、特定のオペランドが
リスクは整数±非常に小さなデルタです。 の
整数3、9、15、21、27から非常に小さい整数
デルタは危険な除数です。 (特に
表現可能な最大の単精度、倍精度、
そして、3、9 ... 27未満の拡張精度数は
すべてが真剣に危険因子です。)他の悪い
私が聞いていなかったこのバグの特徴
Intelからの最悪の場合のエラーは、
バグによる4つの部分よりも大幅に大きかった
Nicely教授が観測した10億エラーあたり。

Intelがしようとしているように見えた
9分の1に焦点を合わせて露出を最小限に抑える
公表されたエラーの10億の確率
教授によって観察された10億分の4のエラー
いいね。 私は結論を出したので、Intelは
ユーザーコミュニティは、決定するときにIntelの仲間になる可能性があります
このバグが原因で危険にさらされる可能性のあるアプリケーション。

インテルは優れた技術的仕事をしていると思います。 後
すべて、私がcomp.sys.intelを読んでいた唯一の理由は
P90システムの購入を検討していたこと。
この後、私はまだP90システムを購入しますが、
私がするとき、私は固定チップと保証を求めます
システムを受け取った後、それが
売り手が言う固定チップが含まれていません
固定されていないチップのポストヘイストを交換します。 私は考えます
バグが完全に許されるとして発生したという事実、
私は多くのチップを設計しているため、設計されています
多くのバグ。

ここに含まれていない追加のプログラムを投稿しました
単精度オペランドのエラーをスキャンした
単一の精度よりも大きい誘導
最下位ビット。 のリストを受け取った
1738問題の単精度除算(64のうち)
兆)。 ハーブサベージがリストを提供しました。

次の除数とそのバイナリスケーリング
(これにより、2進指数のみが異なることを意味します)
分割エラーの95%以上を占めるようです:

3.0>除数> = 3.0-36 *(2 ^ -22)
9.0>除数> = 9.0-36 *(2 ^ -20)
15.0>除数> = 15.0-36 *(2 ^ -20)
21.0>除数> = 21.0-36 *(2 ^ -19)
27.0>除数> = 27.0-36 *(2 ^ -19)

上記の範囲のいずれかの除数を持つ除算
約20万分の1の確率で損失を被る
倍精度拡張演算における精度の向上。
分割エラーの残りの5%未満を考慮することができます
上記の36を2048に変更することにより。

すべての配当は上記に対して幾分危険にさらされています
除数 次の式は配当を識別します
特にエラーのリスクが高い
一般的なエラーと比較的大きなエラーの場合:

配当= intdividend + deltadividend
または
配当= intdividend-deltadividend
除数= intdivisor-デルタ除数
intdivisor = 3、9、15、21、27

次のいずれかが当てはまる必要があります。
IEEE表現の指数
問題の配当:

intdividend = intdivisor / 3 mod intdivisor
intdividend = 2 * intdivisor / 3 mod intdivisor

上記のdeltadividendおよびdeltadivisorの制限
やや複雑で、その詳細は
読者のための演習。 ;-)私は解決していません
制限の詳細。

comp.sys.intelへの以前の投稿は次のとおりです。 読んで
お楽しみください。

-ティム・コーcoe@vitsemi.com

-最初と2番目の投稿テキスト-Packard Bell P90 PCで、以下を実行しました
Microsoft Windows Desk Calculatorを使用した計算:

(4195835/3145727)* 3145727 [以前の投稿から修正されたタイプミス]

結果は4195579でした。
これは、256のエラーまたは16000〜16000の一部を表します。

ak@ananke.s.bawue.de(Andreas Kaiser)の書き込み
>通常、分割は正しいです(何を期待していましたか?)。 ほんの少し
>オペランドが間違って分割されています。 〜25.000.000.000の結果(P90)
>ランダムな引数(1..2 ^ 46以内)、偶数の結果を2で割ったもの
>奇数になるまで、一意の仮数パターン(2進指数
>もちろん、気にしません)。
>
> 3221224323
> 12884897291
> 206158356633
> 824633702441
> 1443107810341
> 6597069619549
> 9895574626641
> 13194134824767
> 13194134826115
> 13194134827143
> 13194134827457
> 13194138356107
> 13194139238995
> 26388269649885
> 26388269650425
> 26388269651561
> 26388276711601
> 26388276712811
> 52776539295213
> 52776539301125
> 52776539301653
> 52776539307823
> 52776553426399
>
>アンドリュース・グルース
>
> --------------------
>-アンドレアスカイザー-インターネット:ak@ananke.s.bawue.de
> -------------------- fidonet:2:246 / 8506.9

これらの数値を分析すると、そのうちの2つを除くすべてのものが
フォーム:

3 *(2 ^(K + 30))-1149 *(2 ^(K-(2 * J)))-デルタ*(2 ^(K-(2 * J)))

ここで、JとKは0以上の整数です。
デルタは実数であり、範囲はさまざまです
Jにありますが、通常は0〜1の間と見なすことができます。

上記の方程式の2 * J項は結論につながります
Pentium除算器は、計算する反復除算器であること
サイクルごとに2ビットの商。 (これは同意します
からの長い長い除算ごとに引用された39サイクル
Pentiumデータブック。 このタイプの技術名
分周器は基数4)

エラーの非常に低い確率(10 ^ 10分の1)は、
残りはキャリーセーブ形式で保持されていること。 (キャリー
保存形式は、数値が次の合計として表される場所です。
2つの数字。 この形式により、次の剰余計算が可能になります
キャリーを伝播せずに発生します。 運ぶ理由
保存フォーマットは、エラーの確率によって暗示されます
非常に難しいが、長く積み上げることは不可能ではない
合計ワードと
単語を運ぶ。)

数字セットは-2、-1、0、1、2であると仮定しました(
基数4のディバイダーの5桁の数字により、必要な
次の桁選択でのエラーのマージン。 長くするとき
基数10および10の可能な数字を使用して、手で割ることができます。
エラーのマージンなし。)

上記を考慮して、暫定版を書きました
以下に含まれるPentium分割ハードウェアのモデルは、
残りの部分でどのビットパターンが発生したかを見ることができます。
失敗することがわかっている数字と数字を実行した後
失敗しないように見えたそれらの近くに私は決定しました
プログラムにリストされている障害の条件。

で返される正確で誤った結果の分析
悪い除算は、ビットが減算されていることを示します
最上位ビットまたはその近くの残りから。
このプロセスのモデリングはプログラムに含まれています。

プログラムは、公開されたすべての
エラーと、
記事の始まり。

数字のシーケンスからの商の決定
読者のための演習として残されています;-)。

博士に感謝したい このウィンドウを提供してくれてうれしい
Pentiumアーキテクチャに。

-3番目の投稿-それ以来、Microsoftで次の計算を実行しました
次のPentiumマシン上のWindows Desk Calculator
結果:

(41.999999 / 35.9999999)* 35.9999999-41.999999 ==>(-0.75)*(2 ^ -13)
(48.999999 / 41.9999999)* 41.9999999-48.999999 ==>(-1.0)*(2 ^ -13)
(55.999999 / 47.9999999)* 47.9999999-55.999999 ==>(-1.0)*(2 ^ -13)
(62.999999 / 53.9999999)* 53.9999999-62.999999 ==>(-1.0)*(2 ^ -13)
(54.999999 / 59.9999999)* 59.9999999-54.999999 ==>(-1.0)*(2 ^ -13)
(5244795/3932159)* 3932159-5244795 ==>(-1.0)*(2 ^ 8)

私はそれらがさらに露出することを見越してこれらの計算を選択しました
Pentium FDIV障害モード。 彼らがやった。 誤った結果のサイズ
tentive Pentiumの最終バージョンと完全に一致しています
以下に含まれるディバイダーモデルは、決して起因するものではありません
Desk Calculatorのバグ。 これらの結果ピンの存在
モデルに含まれるほとんどの桁選択しきい値。

また、エラーを生成しない次の計算を実行しました
結果:

(38.499999 / 32.9999999)* 32.9999999-38.499999 ==> 0
(45.499999 / 38.9999999)* 38.9999999-45.499999 ==> 0

私はこのスレッドを非常に興味を持ってフォローしています。 一つの誤解
クリアする必要があるのは、これが拡張精度の問題であることです。 これ
50〜2000の単精度配当除数ペアのバグヒット(out
合計64兆回)別の誤解は大きさに関連しています
相対誤差の。 次の確率表を提案します
ランダムなダブルを実行するときに次の相対エラーが発生する
拡張精度除算:

relerror =(correct_result-Pentium_result)/ correct_result

エラー範囲| 確率
-1e-4 <relerror | 0
1e-5 <relerror <1e-4 | 0.3e-11
1e-6 <relerror <1e-5 | 0.6e-11
1e-7 <relerror <1e-6 | 0.6e-11
1e-8 <relerror <1e-7 | 0.6e-11


1e-18 <relerror <1e-17 | 0.6e-11
1e-19 <relerror <1e-18 | 0.6e-11

上記の分割失敗の調査により、両方の配当が
除数は整数から小さなデルタを引いたものです。 また注目されるのは
エラーはおおよそデルタ^(2/3)です。 除数の整数は実際には
リストされているものとそれらのバイナリスケーリングに制限されています。 の整数
配当ははるかに自由に選択できます。 このタイプの配当
除算ペアは、実際にフォワード統合時に頻繁に発生します
準安定点からの軌道。 これは、準安定点
システムでは、しばしば特定の正確な積分特性を持ち、
経路は準安定点から発散し、これらの特性は徐々に発散します
積分値から。 前方統合アルゴリズムの場合
たまたまこれらの特性を分割します
例7と3では、釘付けになります。

分周器モデルには、最大60ビットの除数と
最大64ビットの配当。 配当の最後の4ビットは細かく処理されます


失敗した配当除数の仮数のリストを16進数で示します。 ダッシュ
2つの数字の間は、包括的障害範囲を示します。 コンパイルする
プログラムを実行し、これらの数値を実行して、ビットが踊るのを見てください。

800bf6 bffffc
a00ef6 effffc

a808d2 8fffe
e00bd2 bfffe

a7ffd2 8fffe
c3ffd2 a7ffe
dfffd2 bfffe
fbffd2 d7ffe

f9ffdc7 efffe

b9feab7-b9feabf 8fff
b9ffab0e-b9ffab7f 8fffc

-次の二重拡張ペアは3回失敗します!!!
c3ffd2eb0d2eb0d2 a7ffe
e00bd229315 bfffe

9fffef5-9fffeff effff4
9ffff21-9ffff3f effff8
9ffff4d-9ffff7f effffc

f008e35-f008e3f 8ffff4
f008e6d-f008e7f 8ffff6
f008ea1-f008ebf 8ffff8
f008ed9-f008eff 8ffffa
f008f0d-f008f3f 8ffffc
f008f45-f008f7f 8ffffe
f008f7e 8ffffff1
f0023e 8fffff8

effff0d 8ffffc

a808d1b-a808d3f 8fffe
a808d67-a808d7f 8fffe4
a808db3-a808dbf 8fffe8
a808dff 8fffec

プログラムの実行例(最初に報告されたものを使用
エラー):

---配当仮数を16進数で入力:8
---除数仮数を16進数で入力:bfffffb829
---次の数字1
--- 111100000000000000000000000100011111010110111111111111111111111111100
--- 00000000000000000000000000000000000000000000000000000000000000000000000100
--- 111100000000000000000000000000010001反復番号1
---。
---。
---。
---次の桁-1
--- 001111111110010010101111010011000001011101000000000000000000000000000000
--- 11011111111111111111101101100100100100000000000000000000000000000000000000
--- 00011111111001001010101010110000反復回数14
---次の数字2
---バグ状態が検出されました。
---正しい結果の場合は0、誤った結果の場合は1を入力してください:1
--- 000000000110110101010000100000011111011001111111111111111111111100
--- 1111111100100101010110100110010010010010000000000000000000000000000100100
--- 1111111110010010101010101011100101反復番号15
---次の数字0
--- 11111101001000000010101110010101100100010111111111111111111111100000000
--- 00000001001010101000000000000100100100000000000000000000000000100000
--- 1111111001001010101010101110011001001反復回数16
---。
---。
---。

-ティム・コーcoe@vitsemi.com

Cのプログラム
#include main() { unsigned r0, r1, r2, r3, r4, r5, r6, s0, s1; unsigned t0, t1, t2, t3, cycle, f, incorrect, spup; unsigned thr_m2_m1, thr_m1_0, thr_0_1, thr_1_2, positive, errornum; char line[30], *linepoint; r0 = 0x0bffffc0; r1 = 0; r2 = 0x0800bf60; r3 = 0; printf("First digit of mantissas must be between 8 and f\n"); printf("Enter dividend mantissa in hex: "); *(line+15) = '0'; scanf("%s", line); linepoint = line; while (*linepoint != '\0') linepoint++; while (linepoint < line + 15) *linepoint++ = '0'; *(line+16) = '\0'; sscanf(line+15, "%x", &spup); spup = (spup >> 2) | (12 & (spup << 2)); *(line+15) = '\0'; sscanf(line+7, "%x", &r3); *(line+7) = '\0'; sscanf(line, "%x", &r2); printf("Enter divisor mantissa in hex: "); scanf("%s", line); linepoint = line; while (*linepoint != '\0') linepoint++; while (linepoint < line + 15) *linepoint++ = '0'; *(line+15) = '\0'; sscanf(line+7, "%x", &r1); *(line+7) = '\0'; sscanf(line, "%x", &r0); r4 = 0; r5 = 0; t0 = r2; while (!(t0 & 1)) t0 = t0 >> 1; printf("%d\n", t0); t0 = r0; while (!(t0 & 1)) t0 = t0 >> 1; printf("%d\n", t0); /* These thresholds are VERY tentative. */ /* There may be bugs in them. */ t0 = r0 >> 22; /* Next threshold is strongly indicated */ /* by the failure of 1/9895574626641 */ if (t0 < 36) thr_0_1 = 3; /* Next threshold is strongly indicated */ /* by the failure of 1/824633702441 */ else if (t0 < 48) thr_0_1 = 4; /* Next threshold is strongly indicated */ /* by the failure of 5244795/3932159 */ else if (t0 < 60) thr_0_1 = 5; else thr_0_1 = 6; thr_m1_0 = 254 - thr_0_1; if (t0 < 33) thr_1_2 = 11; else if (t0 < 34) { printf("This model does not correctly handle\n"); printf("this divisor. The Pentium divider\n"); printf("undoubtly handles this divisor correctly\n"); printf("by some means that I have no evidence\n"); printf("upon which speculate.\n"); exit(); } /* Next threshold is strongly indicated */ /* by the failure of 41.999999/35.9999999 */ else if (t0 < 36) thr_1_2 = 12; else if (t0 < 39) thr_1_2 = 13; /* Next threshold is strongly indicated */ /* by the failure of 1/1443107810341 and */ /* by the failure of 48.999999/41.9999999 */ else if (t0 < 42) thr_1_2 = 14; else if (t0 < 44) thr_1_2 = 15; /* Next threshold is strongly indicated */ /* by the failure of 55.999999/47.9999999 */ else if (t0 < 48) thr_1_2 = 16; /* Next threshold is strongly indicated */ /* by the failure of 62.999999/53.9999999 */ else if (t0 < 54) thr_1_2 = 18; /* Next threshold is strongly indicated */ /* by the failure of 54.999999/59.9999999 */ else if (t0 < 60) thr_1_2 = 20; else thr_1_2 = 23; thr_m2_m1 = 254 - thr_1_2; if (t0 == 35) errornum = 22; else if (t0 == 41) errornum = 26; else if (t0 == 47) errornum = 30; else if (t0 == 53) errornum = 34; else if (t0 == 59) errornum = 38; else errornum = 128; incorrect = 0; cycle = 1; /* The cycle limit would be ~34 instead of */ /* 18 for double extended precision. */ while (cycle < 18) { t0 = 255 & ((r2 >> 24) + (r4 >> 24)); if ((t0 > thr_m1_0) || (t0 < thr_0_1)) { s0 = 0; s1 = 0; positive = 0; printf("next digit 0\n"); } else if (t0 > thr_m2_m1) { s0 = r0; s1 = r1; positive = 0; printf("next digit -1\n"); } else if (t0 < thr_1_2) { s0 = ~r0; s1 = ~r1; positive = 4; printf("next digit 1\n"); } else if (t0 & 128) { s0 = (r0 << 1) | (r1 >> 31); s1 = r1 << 1; positive = 0; printf("next digit -2\n"); } else { s0 = ~((r0 << 1) | (r1 >> 31)); s1 = ~(r1 << 1); positive = 4; printf("next digit 2\n"); if ((t0 == errornum) && (((r2 >> 21) & 7) == 7) && (((r4 >> 21) & 7) == 7)) { printf("A bug condition has been detected.\n"); printf("Enter 0 for correct result or 1 for incorrect result: "); scanf("%d", &incorrect); if (incorrect) { /* These amounts that are subtracted from the */ /* remainder have NOT been extensively verified. */ if (errornum == 22) s0 = s0 - (3 << 25); else s0 = s0 - (4 << 25); } } } t0 = s0 ^ r2 ^ r4; t1 = s1 ^ r3 ^ r5; t2 = (s0 & r2) | (s0 & r4) | (r2 & r4); t3 = (s1 & r3) | (s1 & r5) | (r3 & r5); r2 = (t0 << 2) | (t1 >> 30); r3 = t1 << 2; r4 = (t2 << 3) | (t3 >> 29); r5 = (t3 << 3) | positive | (spup & 3); spup = spup >> 2; t0 = r2; f = 32; while (f--) { if (t0 & (1 << 31)) putchar('1'); else putchar('0'); t0 = t0 << 1; } t0 = r3; f = 32; while (f--) { if (t0 & (1 << 31)) putchar('1'); else putchar('0'); t0 = t0 << 1; } putchar('\n'); t0 = r4; f = 32; while (f--) { if (t0 & (1 << 31)) putchar('1'); else putchar('0'); t0 = t0 << 1; } t0 = r5; f = 32; while (f--) { if (t0 & (1 << 31)) putchar('1'); else putchar('0'); t0 = t0 << 1; } putchar('\n'); t0 = r2 + r4; f = 32; while (f--) { if (t0 & (1 << 31)) putchar('1'); else putchar('0'); t0 = t0 << 1; } printf(" iteration number %d\n", cycle++); } } 




ヴォーン・R・プラット


画像

2.99915236 1994年12月19日、スタンフォード大学のヴォーンR.プラットはcomp.archおよびcomp.sys.intelニュースグループへの手紙を発行しました。これは、エラーに遭遇する確率は「27回に1回」であるというインテルの見解に異議を唱えました000年。」 かなり妥当なシナリオで、3ミリ秒ごとに1回エラーをアクティブにする可能性を実証できました。 また、彼は、4.999999 / 14.999999のかなり無害な見た目の分割が、欠陥のあるプロセッサを使用した場合に0.00000407だけ正しい結果から逸脱することを示しました。

「この間違いは最も潜行性が高く、データの列を見たときにまったく警告を発しなかったかのように、ほとんど潜行性です。 したがって、10万分の1の小さなエラーは、世界中で実行されている何兆もの計算に長時間浸透する可能性があり、信頼できるプロセッサには絶対に必要ではないFPUで大規模なエラーチェックを実行することを除いて、実際にそれらを決定する方法はありません。 」

Voen Prattによる元の手紙
From:pratt@Sunburn.Stanford.EDU(ヴォーン・R・プラット)
ニュースグループ:comp.arch、comp.sys.intel
件名:FDIVバグの可能性が高い自然なシナリオ(だった:Intelの防衛で...)
日付:1994年12月3日15:20:17 GMT
組織:スタンフォード大学コンピュータサイエンス部。
行:194
メッセージID:<3bq2bh$ohc@Radon.Stanford.EDU>
参照:<3bdieq$lqf@engnews2.Eng.Sun.COM> <3bf666$6k4@hpsystem1.informatik.tu-muenchen.de> <3bnrgo$4gf@hermes.synopsys.com>
NNTP-Posting-Host:sunburn.stanford.edu
外部参照:Radon.Stanford.EDU comp.arch:15209 comp.sys.intel:20065
このメッセージでは、27,000年ごとに発生するIntelのデフォルトシナリオとは対照的に、3ミリ秒ごとに1回FDIVバグが発生するシナリオを示します。 さらに、遭遇したバグには不明瞭な数字は含まれていません。それらはすべて、5/15のような小さな「あざ」理論の形を取ります。 さらに、この例のように、発生するエラーのかなりの数が非常に大きくなります。 シナリオの妥当性は読者が判断できるようにします。 私の意図は、それが起こる可能性のあるものとして遭遇することです。

動機付け:記事<3bnrgo$4gf@hermes.synopsys.com>で、Joe Buckは次のように書いています。

>私はこの大騒ぎに本当に驚いています。 9件のうち1件
> 10億、本質的には単精度除算ではなく
>倍精度除算。 Pentiumユーザーの大多数は決してしません
>完全な単精度さえ必要とするもの:スプレッドシートを実行し、
>ドキュメントを作成し、ゲームをプレイします。 インテルが約10億を支払うべき理由
>(これは9個のゼロです)これらのすべてのルアーに新しいチップを搭載するためのドルですか?
90億分の1、ない。 ユーザーのプログラムで発生する実数が均一に分布することはよくある誤りです。 それらの実際の分布は、以下で説明するシナリオのように、プログラムがそのデータを取得する場所とそれが何を行うかに大きく依存します。

NOT単精度内に修正します。 もちろん、16ビットの語長を念頭に置いていない限り、 〜16ビットエラーの他の例は既に提供されていますが、上記の4.999999 / 14.999999のようなここでのエラーの形式は、特に劇的です。

このメッセージでは、数論、暗号、微分方程式、または行列の反転を伴わず、プロセスによってわずかに「ゆるめ」られた実数として表される1〜3桁の整数による単純な除算を含む、単純でもっともらしいシナリオを示します。私たち全員が何度も見ています。 このシナリオでは、FDIVバグは、27,000年ごとに1回ではなく、3ミリ秒ごとに1回、Pentiumがそれらに遭遇した割合を明らかにします。

ここでの重要な仮定は、このシナリオで遭遇する整数は、他の処理のために非常にわずかに「ゆるめ」られ、その後、何らかの理由で(たとえば、数値は10進計算機から自動的に取得される可能性がある)、いくつかの事前に決められた数に切り捨てられることです10進数、*精度*。 すべての整数は、固定された精度のために、この処理に対して一様に条件付けられます。 したがって、精度が6で、7を18で割ると、7は実際には6.999999で、18は17.999999です。つまり、同じ量(ここでは10 ^ -6)が両方のオペランドから減算されます。

1 <= i、j <= 1000の整数i、jのペアが100万個あります。次の表は、10進精度の低下と*許容度*(除算からの距離)間違った答えとしてカウントします)、100万の部門i / jのうちどれだけが間違っているかを調べます。 これらの商については、IEEE正解は10 ^ -17を超える相対誤差を持つと予想されます。 次の表では、「間違った」と定義して、相対誤差が最初の列で少なくとも10 ^ -15、2番目の列で少なくとも10 ^ -13などであると定義しています。 (つまり、テーブルを横切っていくとうるさくなり、商が間違っていると認識する回数が少なくなります。)



精度が6桁の場合、切り捨て誤差は100万分の1で、簡単に覚えられる量です。 この場合、カクテルパーティーでの制作の場合のみ、読者は最悪の犯罪者のうちの2人または3人を記憶したいと思うかもしれません。

私のお気に入りは5/15、つまり4.999999 / 14.999999で、他の鑑定士がより公正な答えとして0.33333329を要求するときに0.33332922でPentiumによって評価されます。

もう1つの悪いケースは7/48(6.999999 / 47.999999)です。これは、より刺激的な推測が0.14583332である場合に、Pentiumが0.14583204を推測します。

もう1つの候補:9/54(8.999999 / 53.999999)、ペンティアムは0.16666439でギャンブルし、0.16666665にペナルティを失います。

これらの例の3つの本質的な特徴を強調します。 第1に、基本的な算術演算は非常に小さな整数(わずかに「打たれた」)であるため、これらの正確なエラーに気付くかどうかにかかわらず、発生する可能性が大幅に高まります。 第二に、あざは100万分の1や1000万分の1などの単純な量である可能性があり、0.000000142883のようなあいまいな量である必要はなく、状況で発生するあざがあなたにとって悪い可能性が大幅に増加します。 第三に、エラーはFDIVの両方のオペランドに均一に適用できるため、オペランドのエラーを個別に調整する必要がないため、これらのエラーのいずれかが発生する可能性がさらに高くなります。

これらの3つの例の奇妙な特徴は、時間が経てば私が追求しておらず、統一された説明を持っているかもしれないし、持っていないかもしれないことです上記の^^で。 これにより、次の3つの例でPentiumをエミュレートするための単純なヒューリスティックが得られます。ポケットカルキュレーターで4.999999 / 14.999999などを計算し、2桁の繰り返し数字を削除します。 結果は、繰り返し文字列を超えて1桁(5/15の場合は実際には2桁)になります。

これら3つの例の相対誤差は、精度よりも大幅に大きいことに注意してください。

許容差10 ^ -5で生き残るのは26ペアのみです。 記録の精度6の14の間違ったもの:5 / 15、5 / 30、5 / 60、5 / 120、9 / 54、9 / 108、9 / 216、9 / 432、9 / 864、 10 / 60、10 / 120、10 / 240、10 / 480、および10/960。 (7/48は0.9 * 10 ^ -5だけオフになっています。許容誤差10 ^ -5をほとんど逃していません。)精度5の場合、10人の悪者は18 / 27、20 / 30、33 / 144、36 / 108です。 、40 / 120、44 / 192、72 / 432、72 / 864、80 / 480、および80/960。 精度4の場合、2つの区分は82/96と120/288です。 具体的には、81.9999 / 95.9999は0.8541665を期待したときに0.854156を返し、119.9999 / 287.9999は0.416656を返し、0.4166665が必要でした。 (うーん、delete-two-repeatsルールはここでも機能します;非常に興味深い...)

精度の概念として基数10を想定していましたが、特別なものではなく、他の基数も同様の結果をもたらすはずです。 特に、10本ではなく13本の指を進化させた場合、許容範囲10 ^ -9で11桁から3桁に対応するテーブルは、0、31、211、547、802、784、417、109、0になります。

このシナリオでは、少なくとも私にはかなり悪い光のように見えるものにFDIVのバグが入りますが、最悪のシナリオのようなものではないと主張します。 シナリオの2つの重要な要素は、そのシナリオがFDIVバグをトリガーするレートと、そのシナリオの本質が実際にどのくらいの頻度で発生するかです。 シナリオの「損傷指数」は、これら2つの要因の積です。 実際のPentium時間の数千時間を占めるが、10分ごとにバグをトリガーするだけのシナリオは、上記のシナリオよりも高いダメージインデックスを持っている可能性があり、その強さは数ミリ秒ごとにバグをトリガーするが、その弱点はそれが実際に実際にどれほどありそうかについての不確実性。 ただし、これは完全に信じがたいシナリオではないことを認めなければなりません。

-ooooooooooooooooooooooo-ooooooooooo

ここに、上記の表を印刷するコードを追加します。 Cで調和しないと思う人にとっては、これが「精度」と「許容」の正確な意味を探す場所です。

 #include #include main(argc, argv) char *argv[]; { int i, j, cnt, digits; double prec, tol, ibruis, jbruis, pent, true; for (digits = 15, prec = 1e-15; digits > 2; digits--, prec *= 10) { printf("%4.d\t\t", digits); for (tol = 1e-15; tol < 1e-4; tol *= 100) { cnt = 0; for (i = 1; i <= 1000; i++) for (j = 1; j <= 1000; j++) { ibruis = i - prec, jbruis = j - prec; pent = ibruis/jbruis; true = (1.11*ibruis)/(1.11*jbruis); cnt += (fabs(pent - true) > tol*true); } printf("%4d ", cnt); } printf("\n"); } } 


真の商、つまりtrue =(1.11 * ibruis)/(1.11 * jbruis)を取得するためのヒューリスティックは、FDIVバグをヒットする確率を少なくともある程度インテルに近づけるのに十分なだけオペランドをランダム化する迅速で汚れたものです27,000年に1回の推定。 1.11を1.01に置き換えたとき、結果は同じであり、Intelの見積もりと合わせて、飛行機の建設を目的としないプログラムには十分であると思われました。

ヴォーン・プラット

[ ソース ]

11.99991035 1994年12月17日 、IBMはPentium Study、IBM Memoをリリースし、Intelの声明に疑問を投げかけました。

1999年12月19日、973251に、 Intelは、Pentiumプロセッサを必要に応じて交換し始めたことを発表しました。 アンディ・グローブは公に謝罪した。 歴史は、1994年の最後の四半期である475,000,000ドルの利益の半分以上をIntelにもたらしました。

マスコミは沈静化しなかったが、人々は死を望んだ。

画像


アラン・エーデルマン


画像


9999163362年9月18日に 、アラン・エーデルマンはこのエラーの詳細な分析を行ったレポートを公​​開しました。

画像


画像


続きを読む




PS


「ファンから」トップ10のインテルのスローガン

Source: https://habr.com/ru/post/J314534/


All Articles