現在、私のソリューションをProjet Eulerのproblem 14に最適化しようとしています。 私は本当にHaskellのを楽しみにして私はそれが問題のこれらの種類のために非常に良いフィットだと思う、ここで私が試した三つの異なるソリューションがあります:あなたは、実際の問題を見ればHaskellでのキャッシュと明示的な並列処理
import Data.List (unfoldr, maximumBy)
import Data.Maybe (fromJust, isNothing)
import Data.Ord (comparing)
import Control.Parallel
next :: Integer -> Maybe (Integer)
next 1 = Nothing
next n
| even n = Just (div n 2)
| odd n = Just (3 * n + 1)
get_sequence :: Integer -> [Integer]
get_sequence n = n : unfoldr (pack . next) n
where pack n = if isNothing n then Nothing else Just (fromJust n, fromJust n)
get_sequence_length :: Integer -> Integer
get_sequence_length n
| isNothing (next n) = 1
| otherwise = 1 + (get_sequence_length $ fromJust (next n))
-- 8 seconds
main1 = print $ maximumBy (comparing length) $ map get_sequence [1..1000000]
-- 5 seconds
main2 = print $ maximum $ map (\n -> (get_sequence_length n, n)) [1..1000000]
-- Never finishes
main3 = print solution
where
s1 = maximumBy (comparing length) $ map get_sequence [1..500000]
s2 = maximumBy (comparing length) $ map get_sequence [500001..10000000]
solution = (s1 `par` s2) `pseq` max s1 s2
は今、多くの可能性がキャッシュにありますほとんどの新しいシーケンスには既に計算されているサブシーケンスが含まれるためです。比較のために
は、私もCでバージョンを書いた:
は、キャッシングと実行時間:0.03秒
キャッシングせずに実行時間:0.3秒だけ非常識だ
!確かに、キャッシングは時間を10分の1に短縮しましたが、キャッシングを行わなくても私のHaskellコードよりも少なくとも17倍は速いです。
私のコードで何が問題になっていますか? なぜHaskellは私のために関数呼び出しをキャッシュしませんか?関数は純粋なキャッシングであるため、キャッシュは些細なものではなく、使用可能なメモリの問題だけで済むはずです。
私の3番目の並列バージョンの問題点は何ですか?なぜ終わらないの?
言語としてのHaskellに関して、コンパイラは自動的にいくつかのコード(折りたたみ、マップなど)を並列化するか、Control.Parallelを使用して明示的に行う必要がありますか?
編集:私はthisに遭遇しました。彼らは、彼の機能が末尾再帰的ではないと述べた。私のget_sequence_lengthテールは再帰的ですか?どうすればいい?
EDIT2:ダニエル・へ
:返信用
どうもありがとう、本当にすごいです。 私はあなたの改善を試してきました。私は本当に悪いことをいくつか見つけました。
私はWindws 7(64ビット)、8GバイトのRAMを搭載した3.3 GHZクアッドコアについてテストを行っています。
Integerをintに置き換えて言うと、まず、メモリが足りなくなったときに、+ RTS kSize -RTSを指定してもメモリが不足していても、奇妙な結果が出ました。
は最終的に私はすごい...
、Windows上のすべてのHaskellプログラムは、32ビットとして実行されているので、int型は無限再帰を引き起こしあふれたことを意味し、(stackoverflowのは素晴らしいです...)thisを見つけました代わりにLinux仮想マシン(64ビットghc)でテストを実行し、同様の結果が得られました。
あなたは 'main3' ... –