history

青木日記 RSS

<前の日 | この月 | 次の日>

2004-03-15

Alphaでもクロックカウント

http://mput.dip.jp/mput/?date=20040314#p01

「タイムスタンプカウンタは Pentium と Alpha と PowerPC にある」 なんて言われてしまうと Alpha でも誰かがやらなければなるまい。 "Alpha Architecture Reference Manual" を見てみると なんとなくそれっぽい PCC (Process Cycle Counter) register というのを発見した。

下位 32 ビット (PCC_CNT) は CPU サイクル N ごとにインクリメントされるらしい。 N は 1 から 16 までの実装依存……てなんだよそりゃ。 PowerPC みたいにバスクロックでカウントされるのかなあ。

一方、上位 32 ビット (PCC_OFF) は OS 依存らしい。OS? でも「OFF」はたぶん「offset」の略だろうな。 普通に実装してあれば 64 ビット整数として読めるってことか。

あっ、それも書いてあった。 OpenVMS と Tru64UNIX はプロセスごとのタイムスライスを持つようだ。 マシン全体ではないのね。

PCC レジスタは RPCC (Read PCC) 命令で読めるらしい。 ふーむ。こんな感じでいいのかなあ。

#include <stdio.h>
 
static unsigned long
rpcc(void)
{
    __asm__ volatile (
      "rpcc $0\n"
    );
    return;
}
 
#define PCC_CNT(pcc) ((pcc) & 0xffffffffL)
#define PCC_OFF(pcc) ((pcc) >> 32)
 
static void
print_rpcc()
{
    unsigned long pcc = rpcc();
 
    printf("PCC     = %016lx\n", pcc);
    printf("PCC_CNT =         %08lx\n", PCC_CNT(pcc));
    printf("PCC_OFF = %08lx\n", PCC_OFF(pcc));
}

これだと rpcc() の返り値が正しくないように見えるが、 Alpha では返り値を整数レジスタ 0 ($0) で返すので アセンブラレベルではうまくいく。と思う。 unsigned long を返す関数を定義してコンパイルしてみたら ほぼ同じコードになったのでたぶん大丈夫だろう。

この関数を使い 1 秒 sleep しつつ PCC を表示してみる。 できれば Tru64 でやりたかったんだけど、 まだ gcc を入れてないのでとりあえず NetBSD/Alpha だ。

aamine@asv800 % ./rpcc
PCC     = 3a7950a5579ad207
PCC_CNT =         579ad207
PCC_OFF = 3a7950a5
 
PCC     = 309d4e756ba2cda0
PCC_CNT =         6ba2cda0
PCC_OFF = 309d4e75
 
PCC     = 26a43e187fa3ce87
PCC_CNT =         7fa3ce87
PCC_OFF = 26a43e18
 
PCC     = 1c8d622f93a4cb79
PCC_CNT =         93a4cb79
PCC_OFF = 1c8d622f
 
PCC     = 1258c7a0a7a5cd87
PCC_CNT =         a7a5cd87
PCC_OFF = 1258c7a0

えっと、なんか PCC_OFF が変化しすぎ? なんだろうなこの値は。これは NetBSD カーネルも読まないとだめか。

つづく。

(18:01)

Alphaでもクロックカウント (2)

NetBSD のヘッダファイル alpha/alpha_cpu.h で、 alpha_rpcc() という直球な関数を発見した。

static __inline unsigned long
alpha_rpcc(void)
{
        unsigned long v0;
 
        __asm __volatile("rpcc %0" : "=r" (v0));
        return (v0);
}

こう書けばよかったのか。

(18:09)

Alphaでもクロックカウント (3) Tru64UNIX の場合

一方 Tru64UNIX では、alpha/kintrinsics.h という 怪しげなヘッダファイルに rpcc() という関数の宣言を発見した。 しかし「k」intrinsics だけあってカーネルの内部関数だったらしい。

しかたがないので、まずダミー関数を書いておいて cc -S rpcc.c でアセンブリソースを生成し、return 77 に相当する部分を rpcc $0 に置き換えた。うまくいくかな。

~/c/test/rpcc % for i (a b c d e) { ./rpcc; sleep 1 }
5a0f27cda62505f6
410e81e0bf212645
286c7741d7c2c8d4
0fc9d1aff0642e68
f72717a20907be70

取れた。値の遷移には NetBSD と同じ傾向が見られる。 ますます謎だ。

(19:03)

i.loveruby.net ダウン

今日 3/15 (月) の 19:30 ごろ、 i.loveruby.net が原因不明の過負荷状態に陥ったため一時マシンを停止しました。 いちおう直ったみたいですが、まだ妙に重いですね。やばいかなこれは。

(19:46)

名前
メールアドレス

<前の日 | この月 | 次の日>
2002|04|05|06|07|08|09|10|11|12|
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|04|05|06|09|10|
2009|07|
2010|09|

Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved. LIRS