オペランドの値がほぼ同じで符号が違う場合は、桁落ちが発生して多数の上位ビットがゼロとなる場合があるので、リーディングゼロカウンタを用いてノーマライズをする必要があることを述べたが、良く考えてみると、このような必要が出るのは、両方のオペランドのEXP値の差が0か1の場合で、かつ、符号が異なる場合だけである。

それ以外のケースでは、加算でオーバーフローが生じて1ビットの右シフトが必要になるとか、引き算で最上位ビットがゼロとなり、1ビットの左シフトが必要となる程度で、ノーマライズのために多数ビットのシフトは必要ない。一方、前者のケースでは、EXP値の差は0か1であるので、桁合わせのためのシフトは高々1ビットのシフトで良いが、後者のケースでは、桁合わせのために、最大ではオペランド長の右シフトを必要とする。

このコラムの整数の割り算シリーズの最終回のシフタの項で述べたように、長いシフタは遅延時間も長いので、高速に演算を行うためには、出来るだけシフタの通過段数を減らしたい。ということで、次の図に示すように、この二つのケースの処理を分離した浮動小数点加算器が考案された。

図15:EXPの差が大きいパスと多数ビットの桁落ちが発生するパスの処理を分離した2パス浮動小数点加算器。

このように2つのパスに分離することにより、EXPの差が多い処理では、桁合わせの長いシフタが入るが、ノーマライズのシフトは短いシフトだけで良い。そして、EXPの差が小さく多数ビットの桁落ちが発生する処理では、桁合わせのシフトは短く、ノーマライズのために長いシフタが入り得るということで、どちらのパスも長いシフタは1回通過するだけになり、1パスで桁合わせと、ノーマライズに長いシフタを2回通過する設計に較べて、高速に演算することができる。

2パスに分離すると浮動小数点加算器に必要なトランジスタ数が増えるが、潤沢にトランジスタが使える現代のマイクロプロセサでは、高速化のために、このような2パスの浮動小数点加算器が用いられることが多い。

浮動小数点加算のパイプライン処理

浮動小数点加算は、これまでに述べたように、多くの処理ステップが必要であり整数の加算に比べて長い計算時間を必要とする。これを1クロックで実行しようとすると、クロックが非常に低くなって、プロセサ全体としては効率が悪い。このため、一般には、次の図に示すように、パイプライン構成が採られる。

図16:パイプライン浮動小数点加算器の例。

この例では、図15の各処理ステップが1クロックで実行され、入力レジスタにオペランドがセットされてから4サイクル後に出力レジスタに加算結果が得られる。図17に示すように、サイクル1に加算1を開始すると、加算結果が得られるのはサイクル4の終わりであるが、このようなパイプライン構成とすることにより、加算1の終了を待たず、サイクル2に加算2を開始するというように、毎サイクル新しい加算を開始することができる。

原油を送るパイプラインで、オイルが目的地に到着するのを待たず、次々とオイルを送り込む様子に似ている(?)ので、このような処理をパイプライン処理と呼んでいる。

図17:浮動小数点加算のパイプライン実行の様子。

しかし、パイプライン処理も常に毎サイクル、新しい演算が開始できるとは限らない。図18のように、後続の加算3で加算1の結果を必要とする場合には、加算1の結果が得られるサイクル5にならないと加算3は開始できない。

図18:加算3で加算1の結果に加算を行う場合の処理。

このケースでは、サイクル3とサイクル4には新たな加算が開始できず、オイルのパイプラインのアナロジーで行くと空気を送っているということで、このような無駄な空きサイクルをパイプラインバブルと呼ぶ。

余談であるが、本物のパイプラインでは、油種を切り替える場合には、混ざり合わないように、間には水を入れるそうである。本物のパイプラインバブルは、気泡ではなく、オイルよりも比重の重い水である。