最初から倍精度対応を見据えたSSEの実装と
トランジスター数による限界
![]() |
|---|
| 拡張命令の変遷で見たCPUロードマップ |
![]() | Pentium III。写真はコード名「Tualatin」と呼ばれた第3世代のもの |
|---|
拡張命令から見るx86 CPUの第2回を始めよう。まずインテルは、1999年2月にリリースした「Pentium III」で、「KNI」(Katmai New Instruction)こと「SSE」(Streaming SIMD Extension)を導入した。名称冒頭の「Streaming」は単なるマーケティング的な用語であり、少なくともこの時点でのSSEには、ストリーミング的なデータを扱う機能は一切なかった。
それはともかく、このSSEはインテルのある種明確な意思を感じる。それは「SSEはMMXを置き換えるもの」という事だ。これはAMDの「3DNow!」と比較すると明確である。3DNow!とは、MMXに浮動小数点演算機能を付加するための、いわばMMXの拡張という扱いだ。整数演算はMMX任せということで一切サポートしておらず、またレジスターもMMX同様に、浮動小数点演算(FP)レジスターの64bit分をマッピングしたMM0~MM7のレジスターを使って演算する(FPレジスターそのものは、IEEE854の拡張精度をサポートするため80bit分ある)。
これに対してSSEでは、新たに128bit幅のXMM0~XMM7のレジスターを定義し、このレジスターに対する単精度浮動小数点演算命令を新規に用意している。整数演算はSSEには含まれないので(後述)、その点ではSSEと3DNow!はどちらも「MMXに浮動小数点演算能力を追加」と言えなくもないのだが、レジスター互換性をあっさりと放棄した事は大きい。実際、これに続くSSE2では整数演算も追加され、結果としてMMXのニーズはほとんどなくなっている。
これは命令セットからもあきらかだ。基本的には、MMXもSSEもレジスター間演算なので、対象となるレジスターを新たに追加したら、命令の互換性が失われるのは当然とも言える。ではなぜSSEに128bit長のレジスターを追加したかと言えば、恐らくはSSE2の世代で、倍精度浮動小数点演算に対応することを当初から予定していたためだろう。倍精度浮動小数点の格納には64bitが必要になるから、MMXレジスターをそのまま流用すると、値がひとつしか格納できず、これではSIMDの意味がないからだ。
もっとも、XMMレジスターの実装に大量のトランジスタを割いたこともあり、それほど大規模な演算ユニットを実装することはできなかった。128bit長のレジスターが8個というのは、通常の32bitレジスターを32個追加することに相当する。昨今の製造プロセスを使うのであればたいした分量ではないのだが、1999年当時のプロセスでは、この実装は容易ではなかった。
当初登場したPentium IIIは、0.25μmプロセスを使うKatmaiコアだったが、同じ0.25μmプロセスを使ったDeschutesコアのPentium IIと比較すると、トランジスター数とダイサイズはこうなる。
| CPUコア | トランジスター数 | ダイサイズ |
|---|---|---|
| Katmai | 950万個 | 128mm2 |
| Deschutes | 750万個 | 118mm2 |
つまり、これ以上機能を詰め込むのは無理だった。なにせ当時は2次キャッシュをオンダイ(CPUと同じダイ)にするのも難しく、Pentium IIや(Katmaiベースの)Pentium IIIは、2次キャッシュ用のSRAMを別チップで搭載していたほどだった。性能面での寄与や低コスト化を考えると、2次キャッシュをオンダイにするほうが先であり、SSE用に大規模な演算回路を突っ込む余地はほとんど無かった。
その結果、Pentium IIIのSSEの処理性能は、3DNow!を備えたAMDのK6-2などとたいした差がなかった。Pentium IIIの場合、1個のXMMレジスターに4つの単精度浮動小数点の値を格納してSIMD演算ができるが、演算のスループットは2サイクルだった。対するK6-2は、MMXレジスターに2つの単精度浮動小数点の値を格納して演算するが、演算のスループットは1サイクルである。つまり、十分に最適化できれば同一周波数のPentium IIIとK6-2は同じ演算性能となるわけで、この時点での性能差はない状況だった。
















