アカウント名:
パスワード:
数値演算の精度を端折って高速化したと。
浮動小数点演算で、64ビットのdouble型演算の代わりに、可能な限り32ビットのfloat型の演算を使用することで、大幅にその演算速度が向上したという。
数値演算の精度が問題になる場面で、不具合が起きなければいいが・・・Officeスウィート系のWebアプリは怖くて使えんなあ。
明らかに処理の内容を変えて「高速化」というのは疑問を感じますね。それで、C++に迫ったといわれてもなんか違う。
世の中の最適化を全否定だな。答えが一緒なら処理なんて関係ないでしょ。
型が単精度から倍精度に変わるんだよ?常に答えが一緒になるとは限らないでしょ。
んで、最適化によって値が変わる可能性があるから、Cとかにはvolatileが用意されてるわけで。JavaScriptにvolatileに相当するものは私の知る限りは無いはず。そういう言語で値が変わるかも知れない最適化ってのはちょっと問題ある気がする。
JavaScriptの仕様的にはオーバーフローしたら倍精度に勝手に変換するみたいだけど、そこら辺どうなんだろ。仕様に合わせて内部処理を最適化しただけって話ならいいんだけど。
ごめん、*可能な限り*単精度、って書いてあるね。なら問題無いのか。
Mozilla Hacksの元記事確認してみたが、最適化しても大丈夫っぽい。
まず、a,bをfloatとして、(float)((double)a + (double)b) と a + b は、倍精度で加算するか単精度で加算するかの違いがあるが、必ず同じ結果になるらしい。さらにこれと同じようなことが、加減乗除や平方根などで成り立つよう。
(倍精度で計算するとdouble roundingになるので単精度計算よりむしろ悪い結果を返してしまうコーナーケースが考えられるため、非自明な性質な気がするが、入力が単精度の値であることを使ってきちんと見ていけば計算結果にコーナーケースが出ないのと言えるのだと思う。気になるなら参照されてる論文見れば良いかと)
なお、a + b + cについて同じようなことを考えると、これは正しくない。たとえば、(1 + 2^-24) + 2^-24とか。
で、JavaScriptでは倍精度浮動小数点数しか存在しない。そして、浮動小数点数同士の計算は倍精度として行わないといけない。そこで、Math.froundという、倍精度浮動小数点数を単精度相当の値に変換する関数を用意する。これはES6に入るんだそうな(ただしfroundが無くてもFloat32Arrayに入れるというイディオムで一応変換可能)。
a = Math.fround(a); b = Math.fround(b); x = Math.fround(a + b);
とすれば、先の (float)((double)a + (double)b) と同じことなので、安全に単精度数同士の加算として扱える。
なので、emscriptenに、floatへ代入する際にガシガシMath.fround()で囲ってもらえば高速化できると。
# 型とはなんだったのか
普通に入力する値は1.5とか2.0とかが大半なんで、ポインタ算をしなければfloatで最適化した方がいい、ってことなんだろうね。C++だってautofloatみたいな型をでっちあげて、必要な時だけfloatとしてふるまうようにすれば、ずっと高速化できるってことだと思う。やっぱりポインタ算は鬱陶しいだろうけど。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
犯人はmoriwaka -- Anonymous Coward
数値演算の精度が問題になることないの? (スコア:0)
数値演算の精度を端折って高速化したと。
浮動小数点演算で、64ビットのdouble型演算の代わりに、可能な限り32ビットのfloat型の演算を使用することで、大幅にその演算速度が向上したという。
数値演算の精度が問題になる場面で、不具合が起きなければいいが・・・Officeスウィート系のWebアプリは怖くて使えんなあ。
Re: (スコア:0)
明らかに処理の内容を変えて「高速化」というのは疑問を感じますね。
それで、C++に迫ったといわれてもなんか違う。
Re: (スコア:0)
世の中の最適化を全否定だな。答えが一緒なら処理なんて関係ないでしょ。
Re: (スコア:0)
型が単精度から倍精度に変わるんだよ?
常に答えが一緒になるとは限らないでしょ。
んで、最適化によって値が変わる可能性があるから、Cとかにはvolatileが用意されてるわけで。
JavaScriptにvolatileに相当するものは私の知る限りは無いはず。
そういう言語で値が変わるかも知れない最適化ってのはちょっと問題ある気がする。
JavaScriptの仕様的にはオーバーフローしたら倍精度に勝手に変換するみたいだけど、そこら辺どうなんだろ。
仕様に合わせて内部処理を最適化しただけって話ならいいんだけど。
Re: (スコア:0)
ごめん、*可能な限り*単精度、って書いてあるね。
なら問題無いのか。
Re:数値演算の精度が問題になることないの? (スコア:3, 参考になる)
Mozilla Hacksの元記事確認してみたが、最適化しても大丈夫っぽい。
まず、a,bをfloatとして、(float)((double)a + (double)b) と a + b は、倍精度で加算するか単精度で加算するかの違いがあるが、必ず同じ結果になるらしい。さらにこれと同じようなことが、加減乗除や平方根などで成り立つよう。
(倍精度で計算するとdouble roundingになるので単精度計算よりむしろ悪い結果を返してしまうコーナーケースが考えられるため、非自明な性質な気がするが、入力が単精度の値であることを使ってきちんと見ていけば計算結果にコーナーケースが出ないのと言えるのだと思う。気になるなら参照されてる論文見れば良いかと)
なお、a + b + cについて同じようなことを考えると、これは正しくない。たとえば、(1 + 2^-24) + 2^-24とか。
で、JavaScriptでは倍精度浮動小数点数しか存在しない。そして、浮動小数点数同士の計算は倍精度として行わないといけない。そこで、Math.froundという、倍精度浮動小数点数を単精度相当の値に変換する関数を用意する。これはES6に入るんだそうな(ただしfroundが無くてもFloat32Arrayに入れるというイディオムで一応変換可能)。
a = Math.fround(a);
b = Math.fround(b);
x = Math.fround(a + b);
とすれば、先の (float)((double)a + (double)b) と同じことなので、安全に単精度数同士の加算として扱える。
なので、emscriptenに、floatへ代入する際にガシガシMath.fround()で囲ってもらえば高速化できると。
# 型とはなんだったのか
Re: (スコア:0)
普通に入力する値は1.5とか2.0とかが大半なんで、ポインタ算をしなければfloatで最適化した方がいい、ってことなんだろうね。C++だってautofloatみたいな型をでっちあげて、必要な時だけfloatとしてふるまうようにすれば、ずっと高速化できるってことだと思う。やっぱりポインタ算は鬱陶しいだろうけど。