2012/12/05(水)TLB miss hit対策

論理-物理アドレスの変換は、ハードウェア(MMU)の力を借りて実現しています。
この機構、アーキテクチャによって異なりますが、
一般的*1
4KByte/pageを単位として管理されているようです。

*1 : 狭い視野なので、一般じゃないかも

hugetlb

libhugetlbfs
コレを使うことで、実行ファイル(ELFファイル)の読み出し先にhugepageを割り当て、
TLB miss hitを軽減することができます。
リンカの設定や、実行時の処理・PRELOAD処理が必要となり、アプリの起動時間が解析・転送時間だけ
遅れますが、CPU cacheに載らない範囲のランダムアクセスが多い場合には有効ではないでしょうか。

余力と根気があれば、例を踏まえて追記したいと思います。
(ぐぐれば ベンチマークを掲載しているWEB pageもございます)

[powerpc]oprofileの実装を追う

2012/07/25Linux::powerpcimport
oprofileがなぜ存在するのか。
ftraceとは何が異なるのかを確認するため、実装を追いかけた。
アーキテクチャ依存する部位も含むため、大枠はこれで理解するといいかもしれない。
QorIQをターゲットとして捜査したので、ほかのpower architectureは各自で追いかけていただきたい。

参考:
http://ssvb.github.com/2011/08/23/yet-another-oprofile-tutorial.html

参照したファイル類

linux-2.6/drivers/oprofile/oprof.c
linux-2.6/drivers/oprofile/oprofile_stats.c
linux-2.6/drivers/oprofile/oprofile_files.c
linux-2.6/drivers/oprofile/oprofile_stats.c
linux-2.6/drivers/oprofile/event_buffer.c
linux-2.6/drivers/oprofile/buffer_sync.c
linux-2.6/drivers/oprofile/cpu_buffer.c
linux-2.6/include/linux/ring_buffer.h
linux-2.6/kernel/trace/ring_buffer_benchmark.c
linux-2.6/kernel/trace/ring_buffer.c
linux-2.6/arch/powerpc/oprofile/common.c
linux-2.6/arch/powerpc/kernel/head_booke.h
linux-2.6/arch/powerpc/kernel/head_fsl_booke.S
linux-2.6/arch/powerpc/kernel/cpu_setup_fsl_booke.S
linux-2.6/arch/powerpc/kernel/traps.c
linux-2.6/arch/powerpc/kernel/pmc.c

platform initialization

linux-2.6/arch/powerpc/kernel/cpu_setup_fsl_booke.S

_GLOBAL(__setup_cpu_e500v1)
_GLOBAL(__setup_cpu_e500v2)
	mflr	r4
	bl	__e500_icache_setup
	bl	__e500_dcache_setup
	bl	__setup_e500_ivors
	mtlr	r4
	blr

FILE: linux-2.6/arch/powerpc/kernel/cpu_setup_fsl_booke.S

"PerformanceMonitor"へ飛ぶようにセットしてる。
/* Adjust or setup IVORs for e500v1/v2 */
_GLOBAL(__setup_e500_ivors)
	li	r3,DebugCrit@l
	mtspr	SPRN_IVOR15,r3
	li	r3,SPEUnavailable@l
	mtspr	SPRN_IVOR32,r3
	li	r3,SPEFloatingPointData@l
	mtspr	SPRN_IVOR33,r3
	li	r3,SPEFloatingPointRound@l
	mtspr	SPRN_IVOR34,r3
	li	r3,PerformanceMonitor@l
	mtspr	SPRN_IVOR35,r3
	sync
	blr
	/* Performance Monitor */
	EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD)

linux-2.6/arch/powerpc/kernel/traps.c

PerformanceMonitor()を用意、
void performance_monitor_exception(struct pt_regs *regs)
{
	perf_irq(regs);
}

linux-2.6/arch/powerpc/kernel/pmc.c

perf_irq() が定義されている。以下の関数で、ユーザ定義?の関数に差し替えることができる。
oprofile driverで差し替えとる。
int reserve_pmc_hardware(perf_irq_t new_perf_irq)

linux-2.6/arch/powerpc/oprofile/common.c

static void op_handle_interrupt(struct pt_regs *regs)
{
	model->handle_interrupt(regs, ctr);
}
初期化処理で、ハンドルを奪う。
static int op_powerpc_setup(void)
{
	/* Grab the hardware */
	err = reserve_pmc_hardware(op_handle_interrupt);
driver登録時点で、以下の初期化が行われている。
int __init oprofile_arch_init(struct oprofile_operations *ops)

		case PPC_OPROFILE_FSL_EMB:
			model = &op_model_fsl_emb;


linux-2.6/arch/powerpc/oprofile/op_model_fsl_emb.c

static void fsl_emb_handle_interrupt(struct pt_regs *regs,
				    struct op_counter_config *ctr)
oprofile_add_ext_sample()でイベント登録。
イベントがなければぬける。
うっひょ-

linux-2.6/drivers/oprofile/cpu_buffer.c

カウントはこちらで行う。
static inline void
__oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
			  unsigned long event, int is_kernel)
{
	struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer);
	unsigned long backtrace = oprofile_backtrace_depth;

	/*
	 * if log_sample() fail we can't backtrace since we lost the
	 * source of this event
	 */
	if (!log_sample(cpu_buf, pc, backtrace, is_kernel, event))
		/* failed */
		return;

	if (!backtrace)
		return;

	oprofile_begin_trace(cpu_buf);
	oprofile_ops.backtrace(regs, backtrace);
	oprofile_end_trace(cpu_buf);
}

void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
			     unsigned long event, int is_kernel)
{
	__oprofile_add_ext_sample(pc, regs, event, is_kernel);
}

集計は?

ユーザ空間でoprofiledとかctrlが間接的に呼び出す。
上記kernel空間で取得したPC/backtraceデータを用いて、どの区間を何ステップ走行したか、で
実行時間を推定している。
集計結果だけを見ているようでは、厳密な測定結果とはいえないだろう。
ざっくりとみる分には、それでもいいかもしれないですね。
profile取得のオーバヘッドと、サンプリング周期と測定対象の解像度とを十分に考慮してくださいね。

sirq/hoghogeってなに?

2012/07/05Linux::taskimport

"sirq-XXX"とは?

コレ参考になる。筑波大学の講義か。
http://www.coins.tsukuba.ac.jp/~yas/coins/os2-2011/2012-02-14/

要約すると??

優先度の高いtaskで、driverのbottom halfやprotocol stackの処理を行う。
kernel threadで、SMPならcoreごとに名前が異なる。("ksoftirqd/0","ksoftirqd/1"とか)

ソースコードを追う

FILE: kernel/softirq.c

static const char *softirq_names [] =
{
  [HI_SOFTIRQ]		= "high",
  [SCHED_SOFTIRQ]	= "sched",
  [TIMER_SOFTIRQ]	= "timer",
  [NET_TX_SOFTIRQ]	= "net-tx",
  [NET_RX_SOFTIRQ]	= "net-rx",
  [BLOCK_SOFTIRQ]	= "block",
  [BLOCK_IOPOLL_SOFTIRQ]= "block-iopoll",
  [TASKLET_SOFTIRQ]	= "tasklet",
  [HRTIMER_SOFTIRQ]	= "hrtimer",
  [RCU_SOFTIRQ]		= "rcu",
};


static struct notifier_block __cpuinitdata cpu_nfb = {
	.notifier_call = cpu_callback
};

static __init int spawn_ksoftirqd(void)
{
	void *cpu = (void *)(long)smp_processor_id();
	int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);

	BUG_ON(err == NOTIFY_BAD);
	cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
	register_cpu_notifier(&cpu_nfb);
	return 0;
}
early_initcall(spawn_ksoftirqd);
展開すると以下イメージで処理される。
cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
		for (i = 0; i < NR_SOFTIRQS; i++) {
			per_cpu(ksoftirqd, hotcpu)[i].nr = i;
			per_cpu(ksoftirqd, hotcpu)[i].cpu = hotcpu;
			per_cpu(ksoftirqd, hotcpu)[i].tsk = NULL;
		}
		for (i = 0; i < NR_SOFTIRQS; i++) {
			p = kthread_create(run_ksoftirqd,
					   &per_cpu(ksoftirqd, hotcpu)[i],
					   "sirq-%s/%d", softirq_names[i],
					   hotcpu);
			if (IS_ERR(p)) {
				printk("ksoftirqd %d for %i failed\n", i,
				       hotcpu);
				return NOTIFY_BAD;
			}
			kthread_bind(p, hotcpu);
			per_cpu(ksoftirqd, hotcpu)[i].tsk = p;
		}
cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
		for (i = 0; i < NR_SOFTIRQS; i++) {
			param.sched_priority = MAX_RT_PRIO-1;
			p = per_cpu(ksoftirqd, hotcpu)[i].tsk;
			sched_setscheduler(p, SCHED_FIFO, &param);
			per_cpu(ksoftirqd, hotcpu)[i].tsk = NULL;
			kthread_stop(p);
		}
		takeover_tasklets(hotcpu);

2012/04/12(木)PowerPC固有

"SPE use in kernel()"メッセージが出てくる

kernel configurationで、SPEを有効にしていない。
無効命令ハンドラに飛んできて、あきまへんと云ってくる。

IPには命令のアドレスが入っている模様。場所の特定が可能だろう。
∵emulateしたあと+4しているので。

http://lxr.free-electrons.com/source/arch/powerpc/kernel/traps.c?v=2.6.33;a=powerpc
http://lxr.free-electrons.com/source/arch/powerpc/kernel/process.c?v=2.6.33;a=powerpc#L198
http://lxr.free-electrons.com/source/arch/powerpc/kernel/head_fsl_booke.S?a=powerpc
http://lxr.free-electrons.com/source/arch/powerpc/kernel/entry_32.S

BookE系であたりました。致命傷ではないですが、気持ち悪いです。
直しておきましょう。(使わない、といいながら使ってるやんけ、という状態だったはず)