13

例外はやや遅く、パフォーマンスが問題になる場合 (たとえば、Java、F# など) は避けるべきであるとよく読んでいます。Hashtbl.findそれは、要素が見つからない場合に例外を返すなどの一般的な OCaml 関数に適用されますか?

特に、アプリケーションを効率的にしたい場合、たとえば をHashtable.mem呼び出す前に、要素のメンバーシップを常にテストする必要がありますHashtbl.findか? それとも、関数の余分な比較はmemパフォーマンスに悪影響を及ぼしますか?

4

3 に答える 3

22

OCaml 例外処理により、例外の発生とキャッチが非常に高速になります。実装方法に関する内部の詳細については、この SO スレッドを参照してください。私はそれを正確にベンチマークするように注意していませんが、私のランダムな推測では、間接関数呼び出しの範囲内にあると思います.

OCaml の例外は、言語の残りの部分に比例して、たとえば F# の例外よりも大幅に高速であることが知られています。これは、コードを OCaml から F# に移植する人々にパフォーマンスの問題を引き起こしました。OCaml では、例外はパフォーマンスの問題を引き起こしません。

Hashtbl.membeforeを呼び出すHashtbl.findと、例外をキャッチするよりも遅くなる可能性があります。慣用的なスタイルはtry Hashtbl.find .. with Not_found -> ....

optionそうは言っても、OCaml コミュニティでは、例外ではなく型を使用して、より明示的なエラー処理スタイルを使用するという賢明な動きがあります。理論的根拠はパフォーマンスに基づくものではなく、タイプチェッカーがエラー状況の処理を忘れるのを防ぐという事実に基づいています。新鮮な新しい API を設計するときは、それを好みます。例外を発生させるサードパーティ関数を使用する場合は、考えられるすべての例外をすぐにキャッチしてください。そうしないと、一般的にデザインの臭いがするので、非常に正当化する必要があります。

その便利さから、OCaml 例外は純粋な制御フロー メカニズムとしてもよく使用されます (まれな障害状態を通知するためではありません)。次のようなコードが表示されます。

try
  for i = 0 to .... do
    if .. then raise Exit
  done; false
with Exit -> true

最後に、実装の選択に悪いアプローチを取っている可能性があると感じています。パフォーマンスに関する一般的なマイクロ質問をすることは、通常は行うべき方法ではありません。正確さと読みやすさを第一に考えてください。パフォーマンスに関する質問は、通常は後で、測定可能/プロファイリング可能な状況でのみ行う必要があります。

于 2012-08-28T14:50:30.017 に答える
5

Hashtbl.mem最初にbeforeの具体的な質問に答えるにはHashtbl.find: テーブル内の要素の存在のチェックは 2 回行う必要があるため、実行しないでください。どちらの方法でもコストはO(1)になりますが、最初に呼び出すHashtbl.memと、ハッシュ値とルックアップが 2 回計算されます。これは、例外を取得するよりもかなり時間がかかる可能性があります。

一般的なアドバイスとして、例外の可能性が低い場合にのみ、例外を発生させる関数を作成してください。型システムでは例外が考慮されないため、より堅牢な実装では、可能性のある例外'a optionに加えて戻り値が返されます。ocaml コア'aライブラリは、関数が例外をスローする可能性があることを明確にするためにのサフィックスを使用しますが、通常は例外をスローしない関数を優先します。_exn

したがって、ハッシュテーブルの場合、(完璧な世界では) 2 つの関数が必要です。

Hashtbl.find_exn : 'a t -> key -> 'a (* throws Not_found *)

Hashtbl.find : 'a t -> key -> 'a option

疑わしい場合は、2 番目のものを使用してください。純粋に高速でない場合は、元のハッシュ テーブルの周りに単純なラッパーを書くことができます。

find_safe h k = try Some (Hashtbl.find h k) with Not_found -> None

于 2012-08-28T14:23:14.347 に答える
0

例外はやや遅く、パフォーマンスが問題になる場合 (たとえば、Java、F# など) は避けるべきであるとよく読んでいます。要素が見つからない場合に例外を返す Hashtbl.find などの一般的な OCaml 関数に適用されますか?

いいえ。例外が遅く、主流の言語で例外的な状況が発生した場合の民間伝承はナンセンスです。例外は、もう 1 つの制御フロー構造です。OCaml の例外は高速で、例外的でない状況でよく使用されます。最後に (数年前) 見た例外は、OCaml では C++ よりも約 6 倍速く、Java よりも約 100 倍速く、.NET よりも約 600 倍高速でした。

パフォーマンス関連の理由ではなく、明示的なローカル制御フローが必要なため、OCaml で例外を回避することがあります。通常、match非ローカル例外の伝播の可能性ではなく、呼び出し元に成功/失敗ユニオン型を強制します。これは、パフォーマンスよりも重要な正確性を向上させるために行われます。

于 2014-03-17T12:26:02.467 に答える