3

プログラムの一部の実行時間を推定するために単純なタイミングプロファイラーが必要でした(OCamlで書かれていますが、これは他の関数型言語にも当てはまると思います)。命令型言語で、timer.start/などの関数を使用しますtimer.stop。そこで、遅延評価を使用して試してみましたが、必要なものには非常にうまく機能しますが、このメソッドへの参照が見つからなかったため、アプローチに欠陥があるのか​​、より簡単な解決策があるのでしょうか。

ですから、問題は、関数型言語(特にOCaml)の同様の実装について知っていますか?もしそうなら、私にそれらを示してください、私は私の「貧乏人のプロファイラー」を改善するために彼らのアイデアのいくつかを借りたいです(私はこの質問を見ましたが、それは私をあまり助けませんでした)。私が見たところ、GHCにはすでにタイミング情報を収集する方法があるので、Haskellにとってはおそらく問題ではありません。

ちなみに、OCamlのマニュアル(17.4)にあるようにタイミングプロファイリングをやってみましたが、必要なものには「低レベル」すぎて、C関数レベルで多くの情報が得られ、評価が難しくなりました。正確には、OCamlコードのどの部分が原因です。

以下は、OCamlでの実装に従います(時間を測定するたびに「lazy」式を追加する必要がありますが、同時に、必要な情報量を細かく制御できます)。

open Unix (* for the timers *)

(** 'timers' associates keys (strings) to time counters, 
   to allow for multiple simultaneous measurements. *)
let timers : (string, (float * float)) Hashtbl.t = Hashtbl.create 1

(** starts the timer associated with key <name> *)
let timer_start (name : string) : unit =
  let now = Unix.times () in
  Hashtbl.replace timers name (now.tms_utime, now.tms_stime)

(** Returns time elapsed between the corresponding call to 
   timer_start and this call *)
let timer_stop (name : string) : float =
  try
    let now = Unix.times () in
    let t = Hashtbl.find timers name in
    (now.tms_utime -. fst t) +. (now.tms_stime -. snd t)
  with
    Not_found -> 0.0

(** Wrapper for the timer function using lazy evaluation *)
let time (s : string) (e : 'a Lazy.t) : 'a =
  timer_start s;
  let a = Lazy.force e in
  let t2 = timer_stop s in
  (* outputs timing information *)
  Printf.printf "TIMER,%s,%f\n" s t2; a


(** Example *)
let rec fibo n = 
  match n with
    | 0 -> 1
    | 1 -> 1
    | n' -> fibo (n - 1) + fibo (n - 2)

let main =
  let f = time "fibo" (lazy (fibo 42)) in
  Printf.printf "f = %d\n" f
4

2 に答える 2

2

Unix.times実時間ではなく、CPU時間を測定します。したがって、これは、すべての時間をCPUに費やす計算コードにのみ適しています。また、BTW hashtblは必要ありません。複数の同時測定の場合でも、開始時刻をで返し、それをで減算するだけtimer_startですtimer_stop

于 2012-08-15T08:04:09.557 に答える
1

@Jeffrey_Scofieldと@ygrekのアイデアを組み合わせた「最悪の男のタイミングプロファイラー」は、実に非常に単純で、ほとんど言及する必要がないため、私がそれを見つけられなかった理由が説明されます。だから私は彼らの答えをマージし、はるかに単純なバージョンを作成しました:

open Unix (* for the timers *)

(* Wrapper for the timer function using a "unit -> 'a" thunk *)
let time (s : string) (e : unit -> 'a) : 'a =
  let tstart = Unix.times () in
  let a = e () in
  let tend = Unix.times () in
  let delta = (tend.tms_utime -. tstart.tms_utime) +. 
              (tend.tms_stime -. tstart.tms_stime) in
  (* outputs timing information *)
  Printf.printf "TIMER,%s,%f\n" s delta; a

(* Example *)
let rec fibo n = 
  match n with
    | 0 -> 1
    | 1 -> 1
    | n' -> fibo (n - 1) + fibo (n - 2)

let main =
  let f = time "fibo" (fun () -> fibo 42) in
  Printf.printf "f = %d\n" f
于 2012-08-15T14:36:05.433 に答える