浮動小数点数の演算の丸めモードを制御するコメントを残す以前、Haskellで浮動小数点数の丸めモードを制御したいという話を書いた。Haskellでの浮動小数点数の方向付き丸めを考える以前の記事では、丸めモードを変える方法としてはC言語のfesetroundだけを扱ったが、高速化するなら各アーキテクチャ固有の方法を使えた方が有利である。動的な丸めモード指定ではない静的な丸めモードについてもこの記事では触れる。挙動を指定するレジスタがあり、そこで丸めモードを指定できることが多い[要出典]。C言語などの一部のプログラミング言語でも、そういうプロセッサの丸めモードを扱えるような機能が用意されている。併用することにより丸めモードを変更できる。過去記事でも触れたので、詳しくは省略する。実行環境によっては浮動小数点数の丸めモードの変更がサポートされていないこともありうる(WebAssemblyとかはいかにも非対応そうだ)。いう場合、fesetroundは0以外の値を返す。欠点として、環境によっては遅い場合がある。Cの関数として実装されている以上、コンパイラーがインライン化でもしてくれない限り関数呼び出しのコストが発生する。する覚悟があるのであれば、C99の方法ではなく実行環境ごとの組み込み関数・インラインアセンブリを使った方が早い。FPUとSSE系の両方の丸めモードを変更する。FPUかSSE系のいずれかしか使わないのであれば、fesetroundの代わりにここで述べるプラットフォーム依存な方法を使うことで丸めモードの切り替えを高速化できる。Wordと呼ばれる状態を持ち、そのうち2ビットが丸めモードを指定する。FPUのデータレジスタは内部的に80ビット(精度64ビット)の幅があり、デフォルトではIEEE754のbinary64やbinary32準拠とならないことで悪名高い。fieldと呼ばれるビットをいじればこの辺の挙動を変えて演算を精度53ビットや精度24ビットで行うことが可能となる。Word)の命令を使う。Wordにロードする方である。FPUがもともとコプロセッサだったことが関係するのかは知らないが、これらの命令に指定できるのはメモリ上のアドレスであり、汎用レジスタは指定できない。SSE2最近のx86向け(特にx86_64)にコンパイルしたコードでは、単精度・倍精度の浮動小数点数演算にはSSE2が使われることが多いと思う。SSE2ではMXCSRレジスタを使って浮動小数点数の諸々を設定できる。FPUのそれと同じように、汎用レジスタではなく、メモリ上のアドレスを指定する必要がある。なんで?ARMARMではFPSCRレジスタを使って浮動小数点数に関する諸々を設定できる。result;}AArch64ではFPCRレジスタを使う。result;}普段使いのパソコンがARM系という人はまだ少ないだろう。これらのコードを実機で試すには、ラズパイを使っておくのが手軽だと思う。上記のARM32向けのコードは筆者の家に転がっていた古いラズパイで動作を確かめた。筆者の家にはラズパイ3も多分転がっているので、それを使えばAArch64向けのコードも検証できるはずだが、発掘が面倒なのでAArch64向けのコードは試していない。動的な丸めモード指定はC言語で標準化されていたり、多くの(?)プロセッサで実装されていたりするが、問題点もある。コンパイラの最適化との相性が悪い。丸めモードの変更の順番を入れ替える可能性がある。みたいなプラグマでコンパイラに注意を促すことができるようになってはいるが、GCCやClangはこのプラグマを実装していない。頻繁に丸めモードを変更する場合、実際の演算ではなく丸めモードを変更する命令の実行だけでそれなりに時間がかかってしまいそうだ(筆者は実測したわけではないので具体的な数値は出せない)。これらの理由から、動的に丸めモードを指定するのではなく、静的に、命令自体で丸めモードを指定できることが望ましい。みたいに関数自体を分けると書きたい。CPUの命令に直接対応するような組み込み関数を想定している。最近のアーキテクチャでは、静的な丸めモード指定(命令自体に丸めモードを埋め込む)ができるものがある。プログラミング言語やコンパイラ基盤でも、静的な丸めモード指定に対応しようという動きがあるようだ(たとえアーキテクチャが静的な丸めモードに対応していなくても、処理系が正しい最適化をできるようになるという点で、プログラミング言語や中間言語で静的な丸めモード指定をできるようにする意義はある)。prefix)SSE4.1のROUNDSD等の命令(浮動小数点数を整数に変換する)では、(MXCSR等のレジスタを参照するのではなく)命令自体に丸めモードを埋め込めるようになっている。encodingではこれを発展させて、他の算術命令についても命令自体に丸めモードを埋め込めるようになった。等の組み込み関数を使う。第3引数で丸めモードを指定するのだが、ここはコンパイル時定数である必要がある。