アカウント名:
パスワード:
確かに、一つ前のエントリ [srad.jp]の prog7からは、遅延させたくない箇所を一部だけ先行評価にしています。
では遅延評価を捨てたのか、というと、そういうわけでもありません。 入力文字列(ここではwc'関数の最後の引数)はあくまで遅延評価になっています。prog7からprog9まで一環してこの点は変えてません。 先行評価に負けたというよりは、 両方の戦略を適材適所で使い分けてます、という感じでしょうか。
もうちょっと中身に踏み込むと、 「普通」のHaskellは、基本的に「必要な時、必要な部分だけ」評価していきます。 このプログラムの場合だと、csのreductionと wc'の計算がそれぞれ対応して進んでいきます。 そうすると、「数を数える」という枝葉の部分が後回しになります (この計算結果はプログラム終了時にしか使わないので)。 とはいえ、はっきり言って「整数を1増やす」なんて処理は、 「後で計算できるように計算内容を積んでおこう」とするより、 いっそ計算してちゃった方がメモリにもCPUにも優しいです。 というわけで、この辺りは、 パフォーマンス向上のため人間側が補助してやって、 「結果は使わんかもしれんがここは先行評価したまえ」と指示してるわけです。
-- そんな補助をしなくても処理系で良きに計らって欲しいというのも当然の欲求で、 -- 例えば「結果が無駄になったら捨てりゃいいんだし、投機的に実行してもいいんじゃね?」 -- という投機的実行版Haskellとか、別のCPUに計算させちゃえとか、色々な研究があるようです。 -- 「最終形に辿りつく限り、どんな順序で評価しても結果は同じ」 -- という純粋関数型ならではの研究と言えるかもしれません。
さて、このエントリのprog8から使っているunboxed typeは、 さらに一歩機械べったりに歩み寄ったデータ型です。 Haskell内の普通のデータには、 内部的には「評価済みか未評価か」の区別がありますが、 unboxed typeは常に評価済みの、 C言語等と同様の生のデータだということになっています。 「評価済みかどうか」といった余分な情報を持っていないので、 整数型のような小さなデータなら、 コンパイラがregisterに格納するよう最適化することもできます。 そうなると、加算などは機械語1命令で実行できたりします。 -- GHCのユーザガイドでは、とある数値計算主体のプログラムで、 -- 標準の型を使うより「3倍速かった」とか言ってます。 -- 多分赤いです。(意味不明)
ついでに、本文中で説明し忘れましたが、プログラム先頭の
{-# OPTIONS_GHC -fglasgow-exts #-}
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
一つのことを行い、またそれをうまくやるプログラムを書け -- Malcolm Douglas McIlroy
遅延評価を捨てたって事? (スコア:0)
Re:遅延評価を捨てたって事? (スコア:1)
確かに、一つ前のエントリ [srad.jp]の prog7からは、遅延させたくない箇所を一部だけ先行評価にしています。
では遅延評価を捨てたのか、というと、そういうわけでもありません。 入力文字列(ここではwc'関数の最後の引数)はあくまで遅延評価になっています。prog7からprog9まで一環してこの点は変えてません。 先行評価に負けたというよりは、 両方の戦略を適材適所で使い分けてます、という感じでしょうか。
もうちょっと中身に踏み込むと、 「普通」のHaskellは、基本的に「必要な時、必要な部分だけ」評価していきます。 このプログラムの場合だと、csのreductionと wc'の計算がそれぞれ対応して進んでいきます。 そうすると、「数を数える」という枝葉の部分が後回しになります (この計算結果はプログラム終了時にしか使わないので)。 とはいえ、はっきり言って「整数を1増やす」なんて処理は、 「後で計算できるように計算内容を積んでおこう」とするより、 いっそ計算してちゃった方がメモリにもCPUにも優しいです。 というわけで、この辺りは、 パフォーマンス向上のため人間側が補助してやって、 「結果は使わんかもしれんがここは先行評価したまえ」と指示してるわけです。
-- そんな補助をしなくても処理系で良きに計らって欲しいというのも当然の欲求で、
-- 例えば「結果が無駄になったら捨てりゃいいんだし、投機的に実行してもいいんじゃね?」
-- という投機的実行版Haskellとか、別のCPUに計算させちゃえとか、色々な研究があるようです。
-- 「最終形に辿りつく限り、どんな順序で評価しても結果は同じ」
-- という純粋関数型ならではの研究と言えるかもしれません。
さて、このエントリのprog8から使っているunboxed typeは、 さらに一歩機械べったりに歩み寄ったデータ型です。 Haskell内の普通のデータには、 内部的には「評価済みか未評価か」の区別がありますが、 unboxed typeは常に評価済みの、 C言語等と同様の生のデータだということになっています。 「評価済みかどうか」といった余分な情報を持っていないので、 整数型のような小さなデータなら、 コンパイラがregisterに格納するよう最適化することもできます。 そうなると、加算などは機械語1命令で実行できたりします。
-- GHCのユーザガイドでは、とある数値計算主体のプログラムで、
-- 標準の型を使うより「3倍速かった」とか言ってます。
-- 多分赤いです。(意味不明)
ついでに、本文中で説明し忘れましたが、プログラム先頭の
の部分は、(unboxed typeのような)GHCの拡張機能を使うよ、 というコンパイラディレクティブです。 コンパイル時のオプションに直接-fglasgow-extsオプションを 指定しても同じです。