私は SPOJ の PRIME1 の問題に対してかなり貧弱な試みを行ってきました。ByteString を使用すると、問題のテキストを読み取る際のパフォーマンスが大幅に向上することがわかりました。ただし、ByteString を使用して結果を書き出すと、実際には Prelude 関数を使用するよりもわずかに遅くなります。私はそれが間違っているのか、それともこれが期待されているのかを理解しようとしています.
(putStrLn.show) と同等の ByteString を 3 つの異なる方法で使用して、プロファイリングとタイミングを実行しました。
- 各候補をテストして、それが素数かどうかを確認します。もしそうなら、それをリストに追加して (putStrLn . show) で書き出します。
- すべての素数のリストを作成し、(putStrLn . unlines. show) を使用してリストを書き出します。
- すべての素数のリストを作成し、map (putStrLn . show) を使用してリストを書き出します。
ある関数でリストを作成し、別の関数でそれを使用しているため、番号 2 と 3 のパフォーマンスが遅くなると予想しました。数値を生成しながら出力することで、リストにメモリを割り当てないようにしています。一方、putStrLn を呼び出すたびにシステム コールを呼び出しています。右?それでテストしたところ、実際には#1が最速でした。
オプション #1 と Prelude ([Char]) 関数を使用すると、最高のパフォーマンスが得られました。ByteString を使用したオプション #1 が最高のパフォーマンスになると予想していましたが、そうではありませんでした。私は怠惰な ByteString のみを使用しましたが、これが問題になるとは思いませんでした。そうでしょうか?
いくつかの質問:
- 大量の整数を stdout に書き込むために、ByteStrings のパフォーマンスが向上すると思いますか?
- パフォーマンスの向上につながる回答を生成して書き出す方法のパターンがありませんか?
- 数値をテキストとして書き出すだけの場合、ByteString を使用する利点はいつありますか?
私の作業仮説は、Integer を ByteString で書き出すのは、それらを他のテキストと組み合わせていない場合は遅くなるというものです。Integers と [Char] を組み合わせると、ByteString を使用した方がパフォーマンスが向上します。つまり、次の ByteString の書き換え:
putStrLn $ "the answer is: " ++ (show value)
上記のバージョンよりもはるかに高速になります。これは本当ですか?
読んでくれてありがとう!