7

Criterionで関数をベンチマークする前に、関数の入力の評価を強制するにはどうすればよいですか? いくつかの関数のベンチマークを試みていますが、入力サンクを評価する時間を除外したいと考えています。問題のコードは、入力にボックス化されていないベクトルを使用しますが、これはIntベクトルに対してはディープシーケンスできません。以下のコード スニペットの例:

-- V is Data.Vector.Unboxed
shortv = V.fromList [1..10] :: V.Vector GHC.Int.Int16
intv = V.fromList [1..10] :: V.Vector GHC.Int.Int32

main :: IO ()
main = defaultMain [
          bench "encode ShortV" $ whnf encodeInt16V shortv
          ,bench "encode IntV" $ whnf encodeInt32V intv
       ]

Criterion ベンチマークには、上記の関数をベンチマークするときのshortvおよびintv入力をビルドする時間が含まれます。基準測定値は以下のとおりです。入力のビルド時間も含まれているように見える各関数で約 400ns を測定します。

benchmarking encode ShortV
mean: 379.6917 ns, lb 378.0229 ns, ub 382.4529 ns, ci 0.950
std dev: 10.79084 ns, lb 7.360444 ns, ub 15.89614 ns, ci 0.950

benchmarking encode IntV
mean: 392.2736 ns, lb 391.2816 ns, ub 393.4853 ns, ci 0.950
std dev: 5.565134 ns, lb 4.694539 ns, ub 6.689224 ns, ci 0.950 

ここで、ベンチマーク コードのメイン セクションが次のように変更された場合 (2 番目のベンチ関数を削除することにより):

main = defaultMain [
          bench "encode ShortV" $ whnf encodeInt16V shortv
       ]

encodeInt16V関数がベンチマークされる前に shortv 入力が評価されるようですこのベンチマークは、入力を構築する時間を除いて、関数の実行時間を測定するため、これは私にとって実際に望ましい出力です。以下の基準出力:

benchmarking encode ShortV
mean: 148.8488 ns, lb 148.4714 ns, ub 149.6279 ns, ci 0.950
std dev: 2.658834 ns, lb 1.621119 ns, ub 5.184792 ns, ci 0.950

同様に、"encode IntV" ベンチマークのみをベンチマークすると、そのベンチマークでも最大 150ns の時間が得られます。

Criterion のドキュメントから、より正確なベンチマークのために遅延評価を回避しようとしていることを知っています。それは理にかなっており、ここでは実際の問題ではありません。私の質問は、shortv と intv の入力を作成して、ベンチ関数に渡される前に評価されるようにする方法です。現時点では、defaultMain を制限して一度に 1 つの関数のみをベンチマークすることでこれを実現できますが (上記で示したように)、これは理想的なソリューションではありません。

編集1

ここで Criterion ベンチマークで何か他のことが起こっています。これは、リストではなくベクトル配列でのみ発生するようです。shortv と intv を出力して完全な評価を強制すると、ベンチマークはまだ 150ns ではなく 400ns の時間を測定します。以下のコードの更新:

main = do
  V.forM_ shortv $ \x -> do print x
  V.forM_ intv $ \x -> do print x
  defaultMain [
          bench "encode ShortV" $ whnf encodeInt16V shortv
          ,bench "encode IntV" $ whnf encodeInt32V intv
       ]

基準出力 (また、正しくないように見える 158.4% の外れ値があります):

estimating clock resolution...
mean is 5.121819 us (160001 iterations)
found 253488 outliers among 159999 samples (158.4%)
  126544 (79.1%) low severe
  126944 (79.3%) high severe
estimating cost of a clock call...
mean is 47.45021 ns (35 iterations)
found 5 outliers among 35 samples (14.3%)
  2 (5.7%) high mild
  3 (8.6%) high severe

benchmarking encode ShortV
mean: 382.1599 ns, lb 381.3501 ns, ub 383.0841 ns, ci 0.950
std dev: 4.409181 ns, lb 3.828800 ns, ub 5.216401 ns, ci 0.950

benchmarking encode IntV
mean: 394.0517 ns, lb 392.4718 ns, ub 396.7014 ns, ci 0.950
std dev: 10.20773 ns, lb 7.101707 ns, ub 17.53715 ns, ci 0.950
4

1 に答える 1

3

evaluatedefaultMain を呼び出す前に使用して、ベンチマークを実行できます。それが最もクリーンなソリューションかどうかはわかりませんが、次のようになります。

main = do
  evaluate shortv
  evaluate intv
  defaultMain [..]
于 2011-12-04T23:17:12.603 に答える