2016/03/16(水)kv-0.4.29

kvライブラリを0.4.29にアップデートしました。

細かいバグフィックスが主で、大きな変更や機能追加はありません。

小野 寛生様のご指摘により、conv-double.hpp, conv-dd.hppで配列の外側にアクセスする可能性のある危険な書き方を直しました。ご指摘ありがとうございました。また、Visual C++では丸めの向きを変更するのに_controlfpを用いていますが、_controlfp_sが推奨されている点もご指摘いただき、そのように直しました。また、ついでにVisual C++ 2013でmpfrを用いたものを除く全てのサンプルファイルがコンパイル可能なことを確認しました。

Visual C++での丸めの向きの変更に関しては、非標準である_controlfpではなくVisual C++ 2013で追加された標準規格のfesetroundを使いたいとずっと思っていました。しかし、最近上向き丸めと下向き丸めが逆になっているというとんでもないバグを抱えていることが分かり、当分これは使えないと判断しました。

fesetroundの丸めモードが逆になる

困ったものです。interval-simpleというkvの区間演算部分だけを切り出した簡単なライブラリを公開していますが、こちらは単純化のためfesetroundを用いた実装をしていたのですが、丸めの向きが逆では致命的過ぎるのでifdefで分けてVisual C++のときは_controlfp_sを使うように直しました。

(2016/4/4に追記)

Visual Studio 2015 update2 が出たので試してみましたが、同じ結果でした。x64では相変わらず上向き丸め下向き丸めが逆になります。

2016/01/28(木)googleのAlphaGoが人類を超えた!?

昨日の深夜に発表され、瞬く間に大騒ぎになったgoogleの囲碁AIがプロに勝った件、メモ代わりにまとめておきます。

最初に知ったのは、現在最強の囲碁プログラムの一つ、Crazy Stoneの作者のつぶやきでした。そこにyoutubeへのリンクが。まもなく、NHKの記事が出て、それらによると、googleがネイチャーに論文を発表し、AlphaGoと名付けられた囲碁AIが史上初めて人間のプロ棋士にハンデ無しで勝ったということでした。
  • 中身はモンテカルロ木探索にディープラーニングを組み合わせたもの
  • 中国のプロに5戦全勝
  • 3月に現在人類最強の一人と思われるイ・セドルと対局
ネイチャーの論文は
にありますが、基本的に有料です。

googleのブログの記事はこちら
開発の中心となったのは、最近Googleに買収されたイギリスのAIを研究するDeepMind社のDemis Hassabis氏。DeepMind社の記事はこちら。
この記事中に、無料で読める論文のプレプリントへのリンクがあります。

まだ論文は読んでいませんが、既存の最強の囲碁ソフトに500戦499勝とか、既存の最強の囲碁ソフトに4子おかせて勝率8割とか、恐ろしい噂が聞こえてきます。プロ棋士に勝った棋譜を見た感想もとても強いというものが多く、3月のセドルとの対局が楽しみです。

2015/12/23(水)kv-0.4.28

kvライブラリを0.4.28にアップデートしました。

今回はライブラリ本体の変更はほとんどなく、highderiv.hpp(高階微分の計算)、test-rounding.cc(丸めモードの変更が正常に動いているか簡易チェック)を追加したくらいです。webのドキュメントは、psaやaffineにいくらか加筆しています。明日、応用数理セミナーの講演でこのライブラリの話をするのでその前に区切りとして全ての変更を放出しておきたかったという理由もあります。

test-rounding.ccの追加は、前回日記で触れたcygwinのsqrt問題があったので、とりあえず軽くチェックしようと思ったためです。いろいろな環境でテストしてみたところ、概ね以下のような感じです。
  • Linux, Macは64bit OSで64bitコンパイルしていれば問題なし
  • x86の32bitモードはFPUが使われてしまうためIEEE754に従っておらず、お勧め出来ない。
  • Windowsでは、cygwin, msys2で最適化をしないと、sqrtに丸めの向きが変わらない問題が発生。VC++の64bitなら問題なし。
sqrtはVC++の32bitモードでも問題が発生することが分かっており、VC++由来のライブラリを使っている環境ではsqrtの方向付き丸めをエミュレーションで何とかすることも考えてみます。

2015/12/16(水)cygwinのsqrtの丸めモード変更

普段は自分は使っていないのですが、学生の一人がcygwinを使っていて、奇妙な現象を見つけたのでメモ代わりに記録しておきます。

問題は、cygwinのsqrtで丸めの向きが最適化をかけないときに変わらないというものです。環境は64bitのwindows7で、cygwinも64bitの最新のものです。gccは4.9.3でした。
#include <stdio.h>
#include <math.h>
#include <fenv.h>

int main()
{
        volatile double x, y, z;

        x = 2.;
        fesetround(FE_DOWNWARD);
        y = sqrt(x);
        fesetround(FE_UPWARD);
        z = sqrt(x);
        fesetround(FE_TONEAREST);

        if (y == z) {
                printf("sqrt error\n");
        }
}
このようなプログラムで、
cc cygwin-sqrt.c
のように最適化オプションをつけないでコンパイルしたとき、丸めの向きが上向きでも下向きでも結果が同じになってしまいます。
cc -O3 cygwin-sqrt.c
のように最適化をかければ問題ありません。いろいろ試すと、-O0ではアウト、-O1, -O2, -O3はセーフでした。

volatileを使わない場合最適化をかけることで結果がおかしくなるのはさほど珍しくありませんが、このように最適化をかけない状態で結果が異常になるのはとても珍しいです。

cc -Sでアセンブリソースを表示させてみると、最適化無しでは単に外部のsqrt関数を
        call    sqrt
と呼んでいるのに対して、-O3だと
        sqrtsd  %xmm0, %xmm1
のようにSSE2で直接計算するコードが生成されているので、どうやら外部(libm?)のsqrtに問題がありそうです。

以前にVisual C++で似たようなことがあったので、それとも関係あるのでしょうか。どなたか詳しい方に教えて欲しいものです。

これで丸めの向きが変わらないのはIEEE754的にまずいので、そんな腐った環境は無視するというのも一つの考え方でしょうが、こういう事例が多くあるようならsqrtに関しては丸めモード変更に期待しないで何とかすることを検討するべきかも。kvライブラリでいえば-DKV_NOHWROUNDを付ければ問題なくなるので、それをデフォルトにするとか。
OK キャンセル 確認 その他