Tag Archives: 精度保証

GPGPUで精度保証付き計算

金融の計算において、計算精度は超重要である。精度が低ければ価格付けに失敗し大損するかもしれない。
CUDAには、__fadd_rn(x, y)、__fadd_rz(x, y)、__dadd_rd(x, y)、__dadd_ru(x, y)、のように四則演算で丸めの方向を指定可能な関数が用意されている。数学関数の誤差についての情報も与えられておりGPGPUで精度保証計算を行うことが可能である。
前回同様、ブラックショールズモデルでのオプションプライシングを例に精度保証付き計算の実験を行った。条件は下記の通り。

  • 計測対象のオプション明細は1024万件。パラメータは乱数により発生させる。
  • プレミアムを算出。(デルタ、ガンマはめんどーなので省略した。)
  • 計算はすべてdouble型で行う。(単精度版は後半)
  • Amazon EC2のクラスタ GPU クアドラプル エクストララージを使用。GPUはFermi M2050を1つ使用。CPUは1コアのみ使用。コンパイルは全部CUDAでやっている。(CPUには不利な条件だが、CPUとの計算時間は比較しない。)
  • 四則演算については丸めの方向を指定しつつ区間演算で精度保証を行う。
  • 数学関数については誤算情報を加味しつつ区間を設定し精度保証を行う。(わりとてきーにやっている。)

結果は下記の通り。数字の順はGPUで精度保証計算をしたプレミアムの下界、CPUでの計算結果、GPUでの計算結果、GPUで精度保証計算をしたプレミアムの上界となっている。最後の時間は、CPUでの計算時間、GPUへのデータ転送と初期化にかかった時間、GPUで精度保証付き計算をしたときにかかった時間(結果の転送時間込み)、GPUでふつーに計算したときにかかった時間(結果の転送時間込み)。

GPU lower < CPU | GPU < GPU upper
PREMIUM[0]: 0.405499973123749 < 0.405499973123820 | 0.405499973123821 < 0.405499973123893
PREMIUM[1024000]: 4.029060162124779 < 4.029060162124900 | 4.029060162124893 < 4.029060162125027
PREMIUM[2048000]: 0.733045301526717 < 0.733045301526774 | 0.733045301526773 < 0.733045301526825
PREMIUM[3072000]: 1.977617064175732 < 1.977617064175853 | 1.977617064175839 < 1.977617064175931
PREMIUM[4096000]: 0.162532300560706 < 0.162532300560737 | 0.162532300560734 < 0.162532300560762
PREMIUM[5120000]: 0.767333091428844 < 0.767333091428927 | 0.767333091428925 < 0.767333091428991
PREMIUM[6144000]: 8.282037131422769 < 8.282037131422967 | 8.282037131422962 < 8.282037131423138
PREMIUM[7168000]: 0.020357967912149 < 0.020357967912157 | 0.020357967912157 < 0.020357967912164
PREMIUM[8192000]: 0.442812778153888 < 0.442812778153947 | 0.442812778153947 < 0.442812778154016
PREMIUM[9216000]: 0.727449524196905 < 0.727449524196972 | 0.727449524196975 < 0.727449524197043
CPU time: 2779.697021 (ms)
GPU Initial time: 2082.956055 (ms)
GPU Processing time 1: 442.318848 (ms)
GPU Processing time 2: 89.383057 (ms)

GPUで精度保証付きの計算を行うために普通の5倍くらいの時間がかかる。単精度で計算すると下記のようになる。

GPU lower < CPU | GPU < GPU upper
PREMIUM[0]: 0.39829 < 0.39859 | 0.39859 < 0.39882
PREMIUM[1024000]: 4.04288 < 4.04349 | 4.04350 < 4.04403
PREMIUM[2048000]: 0.72358 < 0.72385 | 0.72385 < 0.72404
PREMIUM[3072000]: 1.98723 < 1.98767 | 1.98767 < 1.98803
PREMIUM[4096000]: 0.16034 < 0.16050 | 0.16050 < 0.16059
PREMIUM[5120000]: 0.77226 < 0.77262 | 0.77262 < 0.77288
PREMIUM[6144000]: 8.28720 < 8.28772 | 8.28772 < 8.28814
PREMIUM[7168000]: 0.02022 < 0.02033 | 0.02033 < 0.02036
PREMIUM[8192000]: 0.44575 < 0.44603 | 0.44603 < 0.44622
PREMIUM[9216000]: 0.72577 < 0.72608 | 0.72608 < 0.72630
CPU time: 8085.477051 (ms)
GPU Initial time: 2080.006104 (ms)
GPU Processing time 1: 200.956787 (ms)
GPU Processing time 2: 45.681152 (ms)

この例についてはCPUについては単精度の方が倍精度より遅い。理由としては最適化(特にSSEなのかFPUなのか)やらコンパイラやらCPUの特性やらメモリやらの話題があるがここでは省略する。
単精度の場合も普通の計算とくらべて5倍くらいの時間がかかっている。計算量もそうだが分岐命令が追加されたペナルティが大きいものと思われる。
単精度の方は精度保証有り無しの時間の比率が変わるかを調べる事が主目的であるため、四則演算以外の関数に関わる精度保証を非常に荒く行っている。上界、下界の差が広いのはそのためである。
以上の結果から、ブラックショールズモデルでのオプションプライシングで精度保証付き計算を行うためには通常の5倍程度の計算時間が必要であることがわかる。

補記

最初に計算精度が超重要とか書いたけれども、そもそもブラックショールズモデルではボラティリティスマイルや金利なんかの期間構造を無視してしまっているので、そのモデルに起因する差異のほうが数値計算上の誤差より大きい。なので、精度保証をやる意味はあんまり無(ry・・・いやすこしはあるかm・・・まぁちょっとは・・・
現実問題での上界下界を求めたければ正のバイアスがかかる式と負のバイアスがかかる式で挟み撃ちーという感じでやる必要がある。(アメリカンオプションのプライシングで見かける。とはいえ、そこまでやっても実際問題モデル誤差は残る。。。)
それはおいといて計算時間が5倍というのはそんなもんかなという印象。上界、下界のために最低2倍の計算とメモリが必要で、かつ、割り算の場合は正負の場合分けが必要なため分岐が入ってしまう。
精度保証付き数値計算は面白い考え方だと思うが、イマイチ流行っていない気がしなくも無い。コンパイラオプションなりVMの設定なりで気軽に使える時代が来たら利用する機会はありそうだが。。。