前編はコチラ

複素数の積の計算

最後の2つの命令(FMAddSub、FMSubAdd)は256bitにパックされたデータの偶数番目と奇数番目でCの加算と減算が逆になるという、ちょっと変な演算である。この命令に関しては、スライドの下の説明には、複素演算に使うと書かれている。

実数の積和演算を行う場合は、前回説明した4種のFMA命令で良いが、各要素が複素数の積和演算を行う場合は、複素数の積と和の計算が必要になる。複素数の和は、実部同士、虚部同士を加算すれば良いが、A+BiとC+Diの積は実部が(A×C-B×D)、虚部は(A×D+B×C)と計算する必要がある。FMAddSubとFMSubAdd命令は、この計算をするための命令である。

AMDのSoftware Optimization Guide for AMD Family 15h Processorsに載っている複素数の積の計算方法

AMDのSoftware Optimization Guideには、複素数の積の計算コードが載っている。256bitのYMMレジスタには32bitの単精度浮動小数点データが8個格納できるので、まず、ymm0に一方の4つの複素数[x3i、x3r、x2i、x2r、x1i、x1r、x0i、x0r]をロードする。ここでxNrはN番目の複素数の実部、xNiは虚部である。次に、ymm1にもう一方の4つの複素数[y3i、y3r、y2i、y2r、y1i、y1r、y0i、y0r]をロードする。そして、要素を複製する命令を使って、虚部だけを2つずつ並べたものをymm2、実部だけを2つずつ並べたものをymm0に入れる。さらに、要素の入れ替え命令を使ってymm3にymm1の実部と虚部のペアの位置を入れ替えたものを作る。

そしてvmulps命令でymm2とymm3を掛けて結果をymm2に入れ、次にvfmaddsub213ps命令でymm1とymm0を掛けて、ymm2を加える。この時、vfmaddsub命令は、奇数番目の要素ではymm2の要素を加算し、偶数番目の要素ではymm2の要素を減算するので、実部は、xNr*yNr - xNi*yNiのようになり、虚部はxNr*yNi + xNi*yNrという正しい結果が得られる。このような偶数番目と奇数番目の要素で加算と減算が変わる命令がないと、これと同じ処理を行うにはもっと多くの命令を必要とする。

なお、SPARC64 VIIIfxやBG/Qなどは、一方のオペランドの偶数番目の実部と他方のオペランドの奇数番目の虚部を掛けるというFMA命令を持っており、AVX2のような要素の複製と入れ替えの命令を必要とせず、より効率的に複素数の積を計算できるようになっている。

ロードストア系の強化

HaswellではFMA演算器が2組となり、浮動小数点演算のピーク演性能が2倍になった。となると、この演算に伴うデータの出し入れも強化する必要がある。A+B→Cのような普通の演算では、AとBをキャッシュから読み、演算結果Cをキャッシュに格納するというのが典型的な動作である。Haswellでは、従来のロード、ストアアドレスを計算するポート2と3(最初に掲げた実行パイプラインの図を参照)に加えて、ポート7にストアアドレスを計算するパイプラインを新設した。これにより、ポート2と3でAとBのアドレスを計算し、ポート7でCのアドレスを計算するという動作すべてを並行して実行することができるようになった。

また、L1データキャッシュからの読み出しは64B/Cycleであり、256bitのYMMレジスタの2つのエントリへのロードが同時に可能となり、書き込みは32B/CycleでYMMレジスタの1つエントリ全体をストアできるようになっている。つまり、ということで、Haswellの浮動小数点演算系は、Sandy Bridgeと比べると、ピーク演算性能が2倍になっただけでなく、キャッシュバンド幅も2倍になっている。

HaswellはSandy Bridgeと比べてピーク演算性能とキャッシュバンド幅が2倍に向上している(IDF 2012 Fallにおける発表スライドより抜粋)

なお、3オペランドのFMA演算ですべてのオペランドをキャッシュから読み出すとなると能力不足であるが、積和の計算などのように、1つのオペランドはYMMレジスタを使い、キャッシュから読んでくるのは2つのオペランドというようなケースが多いので、多くの場合は、これで間に合う。

L1キャッシュのバンド幅はFMA演算1回分であり、2つのFMA演算器をフルに動かそうとすると、おおよそ半分程度のオペランドアクセスはL1キャッシュを使わずレジスタだけを使うコードとする必要がある。

また、この図の右の表に書かれているように、HaswellではFMA演算を5サイクルで実行することができるようになり、以前の世代のプロセサと比べると3サイクル短い時間で処理できるようになった。前の命令の演算結果に依存する命令が多い計算では、この演算レーテンシが直接実行時間に効くので、そのようなループでは性能向上が見込める。

HaswellではL1データキャッシュから、毎サイクル64B(256bit×2)のLoadと32B(256bit)のStoreが可能となり、L2→L1データキャッシュのバンド幅も64BとSandy Bridgeに比べて倍増している(IDF 2012 Fallにおける発表スライドより抜粋)

また、HaswellではL2 TLBで2MBページがサポートされ、総エントリ数も1024に倍増された。Sandy Bridgeの4KBページ×512エントリでは、TLBが一時にカバーできるメモリは2MBに過ぎない。これを超えるデータメモリを使うプログラムでは、L3キャッシュにはヒットしてもTLBミスでロード、ストア命令の実行が非常に遅くなってしまうという問題があり、いかにTLBミスを減らすようなコードを書くかということが高性能の実現には必要となっていた。

これに対して、Haswellですべて2MBページを使ったとすると、2MB×1024でTLBは2GBのメモリまでカバーでき、TLBミスによる性能低下を大きく減少させることができる。

(後編に続く)

■Intel 次世代プロセッサ「Haswell」関連記事
【レポート】HPC性能が大幅に強化されたHaswell(前編) (2012年10月3日)
【レポート】IDF 2012 - 次期Intel Core「Haswell」の内部構造を探る - Uncore(GPU/Media Block)編 (2012年9月25日)
【レポート】IDF 2012 - 次期Intel Core「Haswell」の内部構造を探る - マイクロアーキテクチャ編 (2012年9月18日)
【レポート】IDF 2012 - 次期Intel Core「Haswell」の内部構造を探る - 拡張命令(AVX2/TSX)編 (2012年9月18日)
【レポート】トランザクションメモリのサポートが明らかとなったIntelのHaswell (2012年2月16日)