遅延評価といえばふと思ったこと

This entry was posted by on Monday, 10 April, 2006
>少し前に >Base64 を実装しました >
(『入門Haskell』にも、 State モナドの例題として Base64 がありますが、やはり実用的には State モナドでは遅いのでそのようにはしていません)。そこで面白いなーと思ったのは base64 の実行速度を試してみたときのこと。
> >そこそこ長いものをデコードした性能を測りたい、と思っていたのですが、まずエンコードとデコードの速度が明らかに非対称なのですね。このアルゴリズムでそんなに差があるわけがない。これは遅延評価が関わってきています。リストのデータ構造は中身については検知しないので、全体をぜんぜん計算しないままエンコードが終了しちゃうわけです。で、デコード時に必要になってウンウン計算していると。だからデコードの方が数倍の時間がかかっているわけですが、おおよそ足して二で割るとそれぞれの計算になるという話になるわけです。ちなみに、計算結果をいったん表示させてみると時間がわかります。 > >表示させると画面にいろいろ出すぎるのが嬉しくないので他に正格な評価を促す方法はないかと思ってやってみたのが、 length を計算する方法。ところがこれでもエンコードとデコードの差が大きい。これはなぜかというと、 length は長さしか計算せず、具体的な個々の文字については関知しない=計算しないわけです。ただ、デコードする時にエンコードされた文字が ‘=’ かどうかを調べているので、そこで個々の文字が何であるかが必要になり、計算が実行されますから、そのようなことが置こるわけです。いやーややこしい。 > >実際に性能評価をするのであれば、あらかじめエンコード後の正しいデータやデコード後のもとのデータの文字列を持っておき(もちろん中身をすべて正格に評価させ)、その上でエンコードしたものと比較を行い、計算が正しいかチェックしつつその時間を計測するということをする必要がありそうです。 > >文字列が文字のリストである、ってのは便利である局面の方が多いと思っていますが、中身が遅延されるということで面倒になる面もあるのだよなぁと思ったことでした。ほかにもファイルの読み込みとかで罠が待っています。 > >ところでこの Base64 ですが、もうひとつ速くないので何か良い方法はないか考え中です。まあ、そんなに速さに拘らなくても良いと思いますが。 FastPackedString か何かを使うか、 CString なり Array.IO なりを使い破壊的に計算する(その上で unsafePerformIO する)か、というあたりですかね。 > >(追記) IRC で shelarcy さんに指摘されて気付いたのですが、 >Crypto > に Base64 あるじゃん! ううっ、 MD5 は使ってたのに Base64 に気付かないとはアホ杉。 > >そしてこちらの方が私の実装より数倍速いです。どの辺の差なのかわからないのですが、仮説としては私がナイーブに Char を使っているのを Octet にしているところ(Charは UCS 文字なのでメモリ効率も良くなく、いろいろ困ったところがある)と、どうも Int を経由することでビット演算を高速にやっているみたい。そりゃそうした方が速いよな。我ながら阿呆だな。ほかにもいろいろ差はあるみたいですが。というか私のはバグがあるような……。 >

Comments are closed.