SSブログ

サイクルタイムを測定しよう (7) [PSoC]このエントリーを含むはてなブックマーク#

実験回路

サイクルタイムを測定した結果、プログラムの配置や分岐先のアドレスによって実行時間が異なっている事がわかりました。 今回は、もっと詳しくデータをとります。

実験に使ったソフトウェア

これまでと同じように関数に "nop" 命令を並べて、プログラムの配置位置を変更します。

// Measure the execution cycle time
uint32 measure(reg32 *reg) __attribute__((aligned(256)));
uint32 measure(reg32 *reg) {
    uint32  s;
    uint32  e;
    
    asm(
        "nop\n"   // 10
        "nop\n"   // 9
        "nop\n"   // 8
        "nop\n"   // 7
        "nop\n"   // 6
        "nop\n"   // 5
        "nop\n"   // 4
        "nop\n"   // 3
        "nop\n"   // 2
        "nop\n"   // 1
        "label_1:\n"
    );
    s = *reg;
    asm(
        "b label_2\n"
        "nop\n"   // 10
        "nop\n"   // 9
        "nop\n"   // 8
        "nop\n"   // 7
        "nop\n"   // 6
        "nop\n"   // 5
        "nop\n"   // 4
        "nop\n"   // 3
        "nop\n"   // 2
        "nop\n"   // 1
        "label_2:\n"
    );
    e = *reg;
    
    return e - s;
}

前半のアセンブラ表記で "nop" の数を変えると、分岐命令の配置アドレスが2バイト単位で変えられます。 さらに、後半のアセンブラ表記で "nop" の数を変えると、分岐先アドレスを2バイト単位で変えられます。 分岐先のアドレスは、分岐命令のアドレスにも依存します。 "nop" の数を変えながらサイクル数を測定し、分岐命令の位置と分岐先アドレスによってで測定されたサイクル数を並べると、以下の表のようになります。

分岐命令
020406080A0C0E10121416
分岐先047/7/7
067/7/77/7/7
087/7/77/7/77/7/7
0A7/7/77/7/77/7/77/7/7
0C7/7/77/7/77/7/77/7/79/8/7
0E8/7/78/7/78/7/78/7/79/8/79/8/7
109/8/79/8/79/8/79/8/77/7/77/7/77/7/7
129/8/79/8/79/8/79/8/77/7/77/7/77/7/77/7/7
14A/8/7A/8/7A/8/7A/8/77/7/77/7/77/7/77/7/79/8/7
16B/9/7B/9/7B/9/7B/9/78/7/78/7/78/7/78/7/79/8/79/8/7
189/8/79/8/79/8/79/8/79/8/79/8/79/8/79/8/77/7/77/7/77/7/7
1A 9/8/79/8/79/8/79/8/79/8/79/8/79/8/77/7/77/7/77/7/7
1C A/8/7A/8/7A/8/7A/8/7A/8/7A/8/77/7/77/7/77/7/7
1E B/9/7B/9/7B/9/7B/9/7B/9/78/7/78/7/78/7/7
20 9/8/79/8/79/8/79/8/79/8/79/8/79/8/7
22 9/8/79/8/79/8/79/8/79/8/79/8/7
24 A/8/7A/8/7A/8/7A/8/7A/8/7
26 B/9/7B/9/7B/9/7B/9/7
28 9/8/79/8/79/8/7
2A 9/8/79/8/7
2C A/8/7

この表からは、以下の事がわかります。

  1. 分岐先が分岐命令に近く、アドレスの下3ビットが 000 から 100 である場合、サイクル数は最小を保ちます。 これは、追加でプリフェッチを必要とするためです。
  2. アドレスの下3ビットが 110 であるアドレスに分岐する場合、どの条件であってもコストが最大になります。 これは、分岐先の8バイトブロックに続いて次の8バイトブロックもプリフェッチする必要があるためと考えられます。
  3. その次にコストが高いのは、アドレスの下3ビットが 100 である場合です。 プリフェッチのタイミングを1クロックだけ遅らせる事ができるので、一回分のプリフェッチが見えなくなるためと考えられます。
  4. 分岐先が遠い場合、分岐命令のアドレスとは無関係に、分岐先のアドレスに依存したサイクル数を要します。 これにより、純粋にプリフェッチの時間が見えているのだとわかります。

以上の考察より、サイクル数を減らしたければ、分岐先のアドレスが8バイトブロックの前半になるように配置を考える必要があります。 関数内で分岐先アドレスを制御するのは困難ですが、せめて関数の入り口アドレスを8バイト境界の前半に配置するようにオプションを付けると処理時間が短くなりそうです。


nice!(0)  コメント(0)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。