1. 思路
平时CPU读取数据时会从cache或者内存中读取数据。如果想单纯从内存中读取数据,那么需要把cache关闭。然后从内存中顺序读取数组。读取速率bandwidth、数组大小arraysize、读取时间time之间的计算公式如下:
b
a
n
d
w
i
d
t
h
=
a
r
r
a
y
s
i
z
e
t
i
m
e
bandwidth = \frac{arraysize}{time}
bandwidth=timearraysize
2. 关闭cache
首先在Linux系统下关闭cache,使用如下代码将cache关闭。(代码参考1,代码参考2)
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int disableCache_init(void)
{
printk(KERN_ALERT "Disabling L1 and L2 caches.\n");
__asm__(".intel_syntax noprefix\n\t"
"mov rax,cr0\n\t"
"or rax,(1 << 30)\n\t"
"mov cr0,rax\n\t"
"wbinvd\n\t"
".att_syntax noprefix\n\t"
: : : "rax" );
return 0;
}
static void disableCache_exit(void)
{
printk(KERN_ALERT "Enabling L1 and L2 caches.\n");
__asm__(".intel_syntax noprefix\n\t"
"mov rax,cr0\n\t"
"and rax,~(1 << 30)\n\t"
"mov cr0,rax\n\t"
"wbinvd\n\t"
".att_syntax noprefix\n\t"
: : : "rax" );
}
module_init(disableCache_init);
module_exit(disableCache_exit);
makefile如下
EXTRA_CFLAGS = -m64
obj-m += disableCache.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
使用下面Linux命令编译源代码
$ make
编译完成后使用命令insmod将程序载入kernel module中,并且使用dmesg查看是否载入成功
$ insmod disableCache.ko
$ dmesg
载入后系统log中会出现如下输出
3. 开始测试bandwidth
在关闭cache的情况下使用下面代码测试bandwidth
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
// 测试读取BIG_ARR一共需要多长时间,然后计算出bandwidth
#define BIG_ARR 999999
int main()
{
int *block = (int *)calloc(BIG_ARR, sizeof(int));
int i, temp;
clock_t start = clock(), total_time;
for(i = 0; i < BIG_ARR; ++i)
temp += block[i];
total_time = clock() - start;
double sec = (double)total_time / (double) CLOCKS_PER_SEC;
printf("read %d times from main memory need %lf sec\n\
The bandwidth is %lfbyte/sec\n",\
BIG_ARR, sec, BIG_ARR / sec);
return 0;
}
得到的运行结果如下(这里代码输出计算字节数时忘记乘上sizeof(int),因此最后的结果需要乘4)
得到 b a n d w i d t h = 359453271 i n t / s e c ≈ 1.44 M / s e c bandwidth = 359453271 \ int/sec \approx 1.44M/sec bandwidth=359453271 int/sec≈1.44M/sec
4. 启用cache
实际上将关闭cache载入kernel module的模块卸载就可以了,用下面的指令
$ rmmod disableCache.ko
$ dmesg
在系统输出的log的中可以看到如下输出,说明已经将cache启用。
注:本测试在Intel i3上完成,AMD需要对cr0寄存器进行其他操作,代码参考2。