ホーム ] TIPS ウィンドウズ系 ] TIPS グラフィックス系 ] TIPS メルチメディア系 ] TIPS 理数系 ] TIPS 総覧 ]

上へ
W0001 時間を自動計測する
W0101 MDIメニュー
W0102 外部とのドラッグ&ドロップ

VB.NET2005 TIPS / ウィンドウズ系

W0001 時間を自動計測する

最終更新:2007/04/26 再掲

●解説

 それなりに正確に計測するには、対象となる処理部分(関数やサブルーティン)を有限の時間以上になるように繰り返さないといけない。

 しかし、計る対象が不明なので、ループ数は最初、試行錯誤で、後で実測値から算出して修正することになり、全く面倒くさい。しかも、これらは、CPU、OS、処理ルーティン(の改良)などにより、複雑に変化する。

 今回、未知なる対象の未知なる最適な測定時間を自動的に見つけ出し、最適な計測条件で計測する方法を紹介する。 但し、この方法では、純粋のプロセス時間ではなく、システムが消費する時間も含まれる。しかし、現実に体感する処理時間はそう言う環境での時間なので間違っている訳ではない。

→この新版としてMeasureTimeライブラリを提供している。

●原理

 ・計測対象をブラックボックス化するために、コールバック関数とし、処理の一元化(モジュール化)を計る。

 ・以下のロジックで、最適測定時間を自動的に得て、測定する。

  1. 最低測定時間を、2秒とする。(1〜4%の量子化誤差)

  2. ループ回数は、C = 1 から開始する。

  3. 計測時間T が、0 ならば、C = C * 100 とする。

  4. 計測時間が、2秒未満なら、C = 2 / (T / C) + 1 とする。

  5. 計測時間が、2秒以上であれば、終了とする。

  6. 未終了の場合は、上記3 から繰り返す。

  7. このロジックは、正確なループ回数を求めるのが目的ではない。ループ回数が大きすぎても、測定時間は正しいので、ループ回数を減らすことはしない。

●方法と実例

○コールバック関数

 測定対象をコールバック関数にしておけば、測定ロジックは一般化でき、モジュールとできる。このため、必要なら被測定関数群をコールバックテーブルにして置く。これにて、測定側は、ループ処理で行える。但し、コールバックは手続きに時間がかかるので、コールバックの外で時間を計測すると、誤差が大きくなる。そこで、コールバック関数内で時間計測する。以下の例を参照。

 AnyCB(ByRef T As Double, ByRef C As Long)
     ・・・・・・・・・
     T = Now.Ticks
     For i = 0 To C -1

        ・・・・・・・・・
        ・・・・・・・・・                                 'この関数での対象となる処理
     Next

     T = (Now.Ticks - T) * 100             '時間は、ns単位
  End Sub

○定義と一覧表

・コールバック関数は、以下のように定義する。 引数は必要に応じて変更する。パターンに応じて複数定義しても良い

Friend Delegate Sub CBFunction(ByRef T As Double, ByRef C As Long)

・以下のように、予め、測定したい関数を配列にして置く。

Dim CBT(20) As CBFunction       'コールバック関数一覧

CBT(0) = AddressOf AnyCBa     '測定したい実際の関数a
CBT(1) = AddressOf AnyCBb     '測定したい実際の関数b
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
CBT(k) = AddressOf AnyCBx     '測定したい実際の関数x

  あるいは、以下の例のように静的に生成しても良い。

   Dim CBT() As CBFunction = {AddressOf CBPIM, AddressOf CBPIG, AddressOf CBE}

・計測

  FullAutoMeasure が、全自動測定モジュール

以下を、i にて、必要分処理する。

LC = 1
FullAutoMeasure(CBT(i), T, LC)
→T に、正しく測定された時間、C に、その時のループ回数が返る。演算時間は、T/LC。

 もし、単独ならば、
 FullAuotMeasure(AddressOf CBXX, T, LC) で良い。

Dim Sec2 As Double =2000000000     '2秒をnsで表現したもの

Friend Sub FullAutoMeasure(ByVal CB As CBFunction, ByRef T As Double, ByRef C As Long)
   Dim best As Integer = 0
   While best = 0
      CB(T, C)                  'これで、対象の関数を動かす
      If T = 0 Then
         C = C * 100
      ElseIf T < Sec2 Then
         C = Sec2 / (T / C) + 1
      Else
         best = 1
      End If
   End While
End Sub

●感想

 測定時間自体は少し余計に掛かるが、ループ回数テーブルの修正時間がないので、トータルとしては、頗る早くなった。未知の対象でも、何もしないで正確に測定してくれる。1ns以下になる、CPU演算時間も計測できることを確認した。


古いマシンでの実測例:時間/ループ回数を表示