1GB ページ

今のx86て1GBページなんてのがあるのか。
実際TLBミスってどのくらい影響あるのかな。デスクトップだと影響が無い…気がするがTLBが256個だとしたら、これたったの1MBなんだよな。実にCore2DuoのL2の6分の1のサイズである。

4096/16 = 256回アクセスするとして、256回に一回、L2のレイテンシが見えるようになるとする。L2のレイテンシを12ぐらいだとすると、1アクセスあたり、0.046875。約5%ほどのオーバーヘッドがある。そこまでロードし続けるということも考慮すると、1%〜5%くらいか。でもそこまで広範囲にアクセスすると先にL2律速するから実際にはもっと減って…無視できるくらいなんでは?
むしろページテーブルをキャッシュしておくのがキャッシュを圧迫するほうが影響がでかくて、8/4096 = 0.2%…微妙だなぁ…まあ、なんでもいいから1%速くしてくれみたいな状態だと嬉しいのかも。

↓謎のコード。手元だとHugeTLB有効/無効で倍くらいレイテンシが違う。あとAtomはTLB64個に見える。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <xmmintrin.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

static unsigned int
rdtsc()
{
	int a, d;
	asm volatile ("rdtsc"
		      :"=a"(a), "=d"(d));
	return a;
}

char *
alloc16M(int huge)
{
	if (! huge) {
		return malloc(4096*4096);
	} else {
		int fd = open("/hugetlb/16M", O_CREAT|O_RDWR, 0755);
		char *ptr;
		ptr = mmap(0, 4096*4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
		unlink("/hugetlb/16M");
		return ptr;
	}
}

int
main(int argc, char **argv)
{
	int begin = atoi(argv[1]);
	int end = atoi(argv[2]);
	int huge = atoi(argv[3]);
	char *data = alloc16M(huge);
	int i, j, k;

	memset(data, 0, 4096*4096);

	for (i=begin; i<end; i+=1) {
		int l;
		int x = rdtsc(), y;
		for (l=0; l<16384; l++) {
			for (j=0; j<i; j++) {
				if (1) {
					char c = data[j*4096+(j*64)%4096];
					asm("#"::"r"(c));
				} else {
					data[j*4096+(j*64)%4096] = 0;
				}
			}
		}
		y = rdtsc();
		printf("%04d: %f\n", i, (y-x)/(double)(l*i));
	}

	return 0;
}