Comment detail

実行時間の測定 (Nested Flatten)

Mac OS X (PowerPC 32bit) アセンブリで。profile 関数は func と同じ引数を持つ、func 専用の関数です。(表示するのは面倒だったので)実行時間をクロックカウントで返します。

PowerPCはリアルタイムクロックをサポートせず、その代わりに64bit(32bitレジスタ2つ)のタイムベースレジスタというレジスタが用意されています。しかしタイムベースレジスタの精度はCPUの実装依存でして、正確な計測は保証されません。

さらに、二つのレジスタの値を取り出す際に、下位32bitのレジスタ値の桁が繰り上がる場合があります。繰り上がった場合は状態レジスタ(MSR)のビットフラグが立ちますが、このレジスタにアクセスする命令が特権命令のため、通常のプログラムでは桁の繰り上がりを調べられません。というわけで桁の繰り上がりの考慮はあきらめています。

使用例:

#include <stdio.h>

unsigned int profile(void (*fp)(int), int arg);
void func(int n);

void func(int n)
{
  /* 処理 */
}

int main()
{
  printf("time -- %u\n", profile(func, 3));
  return 0;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
        .machine ppc
        .globl _profile

;; unsigned int profile(void (*fp)(int), int arg)

;; r3->r0: fp: 関数ポインタ
;; r4: int arg
_profile:
        mr      r0, r3          ; ポインタを別のレジスタにコピー
        mr      r3, r4          ; 計測する関数の第一引数にする

        ;; レジスタをスタックに退避
        mftb    r4              ; タイムベースレジスタ
        stwu    r0, -4(r1)
        stwu    r3, -4(r1)
        stwu    r4, -4(r1)
        mflr    r12             ; リンクレジスタ
        stwu    r12, -4(r1)

        ;; 関数呼び出し
        mtctr   r0              ; カウントレジスタに関数ポインタをコピー
        bctrl

        ;; レジスタをスタックから復帰
        lwz     r12, 0(r1)
        mtlr    r12
        lwzu    r4, 4(r1)
        lwzu    r3, 4(r1)
        lwzu    r0, 4(r1)
        addi    r1, r1, 4

        ;; 実行時間を返す
        mftb    r3              ; 関数呼び出し後のタイムベースレジスタ
        sub     r3, r3, r4
        blr

Index

Feed

Other

Link

Pathtraq

loading...