2014年5月31日土曜日

[OCaml]Core_benchでベンチマーク


Core_benchを使ってみたので、コードを残しておこう。
ベンチマークを取ったのは、マージソートをする関数。
Core_benchは
$ opam install core_bench
でインストールできる。

open Core.Std
open Core_bench.Std

let make_random_list seed n len =
  Random.init seed;
  let rec make_list len lst =
    if len = 0 then lst
    else make_list (len - 1) ((Random.int n) :: lst) in
  make_list len []

let rec merge xs1 xs2 =
  match (xs1, xs2) with
    ([], _) -> xs2
  | (_, []) -> xs1
  | (hd1 :: tl1, hd2 :: tl2) ->
    if hd1 < hd2
    then hd1 :: (merge tl1 xs2)
    else hd2 :: (merge xs1 tl2)

let rec merge_sort xs =
  match xs with
    [] -> []
  | [_] -> xs
  | [a; b] ->
    if a <= b then xs
    else [b; a]
  | _ ->
    let divide_list xs = List.split_n xs ((List.length xs) / 2) in
    let (xs1, xs2) = divide_list xs in
    merge (merge_sort xs1) (merge_sort xs2)

let run_bench tests =
  Bench.bench
    tests

let bench () =
  let lst1 = make_random_list 0 100 1000 in
  [ Bench.Test.create ~name:"merge_sort1" (fun () ->
       ignore (merge_sort lst1))
  ]
  |> run_bench

Bench.bench関数の仕様が変わったようで、Real World OCamlに書かれていたコードは動かなかった。
この関数に渡すパラメタで、ベンチマークのカスタマイズできるようだけど、試していない。
utopによる実行結果は、以下の通り。
表形式で実行結果が表示された。

utop[1]> #require "core_bench";;
utop[7]> bench ();;
Estimated testing time 10s (1 benchmarks x 10s). Change using -quota SECS.
┌─────────────┬──────────┬─────────┬──────────┬──────────┬───────────┐
│ Name        │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │   mGC/Run │
├─────────────┼──────────┼─────────┼──────────┼──────────┼───────────┤
│ merge_sort1 │   1.08ms │ 57.29kw │  919.07w │  919.07w │ 218.65e-3 │
└─────────────┴──────────┴─────────┴──────────┴──────────┴───────────┘
- : unit = ()
utop[8]>

ふと思ったのだけど、merge_sort関数をマルチスレッドで動かす、お手軽な方法はあるのかな?

参考