Haskellでのパフォーマンスについて推論するのに適したタイミングはいつですか?


8

サイモンペイトンジョーンズ自身は、厳密でないセマンティクスのため、Haskellでのパフォーマンスについての推論が難しいことを認識しています。

Haskellで重要なプロジェクトをまだ書いていないので、疑問に思います。プロジェクトの最初(基本的なデータ構造とIOライブラリを選択するとき)にのみパフォーマンスについて推論できますか。問題が発生したときはいつでも、プロファイラーで処理しますか?

別の言い方をすれば、パフォーマンスの問題があるときにパフォーマンスへの対処を延期することは可能ですか(つまり、それほど痛くない)、またはGHCがコードを実行する方法を予測することを学ぶ必要があります(例:厳密性アナライザーが決定するものを推測する) )?


パフォーマンスが重要な場合。
Thomas Eding 2013年

回答:


7

その他の回答は、パフォーマンスの推論に関する幅広いアドバイスを提供します。この回答は、厳密ではないセマンティクスを具体的に扱っています。

怠惰はパフォーマンスを推論することを難しくしますが、あなたが考えるほど複雑ではありません。怠惰は状況によっては非常に便利ですが、ほとんどの場合、遅延言語は厳密な言語が使用されるのと同じ方法で使用されます。したがって、厳密な言語のパフォーマンス推論は、遅延のある言語に(いくつかの調整を加えて)適用できます。

時間の複雑さに関して、熱心な評価は遅延評価よりも厳密に多くの作業を行います。ほとんどの場合、どちらの方法でも同じ結果が得られます。(より正確には、熱心な評価でエラーが発生しない場合は、遅延評価と同じ結果が生成されます。)したがって、Haskellプログラムの時間の複雑さを推測するために、熱心に評価するふりをすることができます。遅延が問題となるまれな状況では、この見積もりは高すぎるため、下方修正する必要があります。

遅延評価では、熱心な評価よりも時間の複雑さが低くなりますが、スペースの複雑さ、つまりスペースリークが発生することがあります。厳密な注釈を追加してプログラムをより熱心に実行させることにより、スペースの複雑さを修正できます。プロファイリングツールは、スペースリークの原因を追跡するのに非常に優れています。重大度に応じて、これを正当性デバッグまたはパフォーマンスデバッグのいずれかに分類します。


In terms of time complexity, eager evaluation does strictly more work than lazy evaluation. その主張は何に基づいていますか?熱心な評価がレイジー評価と同じ時点で終了すると仮定すると(つまり、無限シーケンスやそのようなもののレイジー評価に入らない)、熱心な生成アルゴリズムは常により速くまたは速くなります(つまり、少ない作業)生成ルーチンへの繰り返しの呼び出しのオーバーヘッドを必要としないため、遅延アルゴリズム。
メイソンウィーラー2013年

2
私がHaskellの皆さんを愛している理由は、あなたが話しているwtfをほとんど理解していないからだと思います。
Erik Reppen 2013年

3
@MasonWheeler:彼はおそらく漸近的な複雑さについて話しています。一定の要因は実装の問題です。さらに、両方のプログラムが終了したとしても、非厳密なプログラムでは作業が大幅に少なくなる可能性がall even [1..1e10]ありallます。厳密バージョンと遅延バージョンの両方を検討してください。コンパイラーには、Haskellのような言語でループ融合などの評価の順序を選択する余地もあります。
Tikhon Jelvis 2013年

1
@MasonWheeler遅延評価は、不要な用語の評価を回避します。私は権威の参照を見つけることが、ここで示す1つであることができなかった先行評価よりも遅延評価を行い、より少ない削減:en.wikibooks.org/wiki/Haskell/...
ヒートシンク

1

コーディングする前に大きなものを最適化し、完了したら小さなことを最適化します。

たとえば、コーディングを開始する前に、次のことについて考える必要があります。

  • 使用するライブラリ/フレームワークはまあまあ高速ですか?
  • データ構造をシンプルに保つようにしてください。
  • アルゴリズムと設計パターンをできるだけシンプルに保つようにしてください。
  • 私が使っている言語はどれくらい速いですか?

...等々。

次に、コードがほとんど完成したら、どの組み込み関数がより高速であるかなど、コードのその領域を書き換えてより効率的にするかどうかなどについて考えます。

これはどの言語にも当てはまりますが、実際には、作成するソフトウェアの種類によって異なります。Haskellは汎用言語であるため、おそらく(間違っている場合は修正してください)非常に高速である必要のあるものは何も作成していません。その場合は、低レベルの言語を使用する必要があります。速度が問題であるが、低水準言語を使用する必要があるほど十分でない場合は、上記に基づいてパフォーマンスを最適化する必要があります。

もちろん、人によってやり方は異なります。したがって、個人的な経験から、状況に応じて異なる方法で行うべきだと思われる場合は、おそらくそうするべきです。


5
問題は、ほとんどの言語で、ランタイムの動作を簡単に推論できることです。Haskellでは、これははるかに困難です。したがって、間違ったアプローチをとる可能性が高く、バグが発生する可能性が高くなります。
Simon Bergot 2013年

答えはうまく始まり、それからあなたは「改善できる小さなことを見る」と言います...ええ、いいえ。プロフィール。
Florian Margaine 2013年

3
この回答は広すぎるため、Haskellにはあまり役立ちません。OPがマクロとミクロの最適化についてすでに知っていると仮定します。この回答は、ランタイムとメモリのパフォーマンスについて推論するのが難しい非厳密言語であるHaskellにどのように適用されますか?
Andres F.

@FlorianMargaineプロフィール?
ダイナミック

0

ダイナミックの答えに追加したいと思います:

  • コードをモジュール化し、疎結合にします
  • モジュールの実装の詳細を非表示にします。

開発の後半でコードのボトルネックが何であるかを理解すると、プロジェクト全体をリファクタリングするのは非常に困難になります。コードが適切に構造化されていると、ボトルネックが見つけやすくなり、最適化/修正が容易になります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.