使用龙芯2f性能计数器评测程序性能_第1页
使用龙芯2f性能计数器评测程序性能_第2页
使用龙芯2f性能计数器评测程序性能_第3页
使用龙芯2f性能计数器评测程序性能_第4页
使用龙芯2f性能计数器评测程序性能_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、使用龙芯2f性能计数器评测程序性能评测一个程序的性能有多种方法,对目前大多数benchmark,程序执行时间是一个很重要的标准。但大多数情况下时间仅仅能给出一个结果,却给不了更多的信息,如cache miss,cpu功能部件的利用率,访存指令,分支预测等。这些信息对于知道一个程序的优化往往会起到很重要的作用。很多现代的cpu都有一些内置的计数器用来记录这些事件,x86环境下可以调用一些库对这些计数器进行设置和访问,具体可以参考这里。关于x86下使用performance counter的方法很多,而且资料也很容易找到,大家google一下就好了。龙芯从早一个版本(loongson 2e)就提供

2、了性能计数器,龙芯2f的计数器基本同2e大概上没有什么区别,定义了两个性能计数器(performance counter),分别映射到cp0(协处理器)的第24、25号寄存器。25号寄存器是64位,其高32位用作counter1,对应的event1,低32位用作counter0,对应event0,event0和event1是由24号寄存器的5-12位控制的,其中5-8位为event0,9-12位为event1,用户可以通过设置24号寄存器相应的位来控制counter记录的事件,event0和event1对应的事件如下所示:event0:0000周期0001分支指令0010指令0011指令并且域

3、rs=31 0100一级i-cache缺失0101 alu1操作已发射0110 mem操作已发射0111 falu1操作已发射1000猜测指令1001从主存中读1010固定发射队列满的次数1011重排队列满的次数1100 cp0队列满的次数1101 tlb重填例外1110例外1111内部例外event1:0000提交操作0001分支预测失败0010预测失败0011 jr且rs=31预测失败0100一级d-cache缺失0101 alu2操作已发射0110 falu2操作已发射0111 uncached访问1000 bht猜测错误1001写到主存1010浮点指针队列满的次数1011分支队列满的次

4、数1100 itlb缺失1101例外总数1110投机缺失1111队列向前加载要使用计数器,首先要设置24号寄存器中event0和event1所对应的域。比如你要测一级i-cache miss和一级d-cache miss,那么就要把24号寄存器设置成0x44f(0-4位以及其他位为默认值)。但是有一个问题,龙芯2f协处理器只有在内核态下才能更改,因此我们要更改24号寄存器,需要模块的帮助。龙芯的协处理器是通过mfc0/dmfc0来读和通过mft0/dmft0来写的,如果在用户态下使用mft0/dmft0指令,会在运行时得到非法指令的错误信息。即便是在内核态下,很多寄存器也是只读的。下面我们写一

5、个简单的小模块来更改event0和event1:loongson_counter.c#include linux/init.h#include linux/module.h module_license(dual bsd/gpl);static int event_init(void)unsigned int event=0x44f;asm volatile(mtc0%0,:r(event);return 0;static void event_exit(void)module_init(set_init);module_exit(set_exit);makefileifneq($(kerne

6、lrelease),)obj-m:=loongson_counter.o else kerneldir?=/lib/modules/$(shell uname-r)/build pwd:=$(shell pwd)clean:rm-rf*.o*core.depend.*.cmd*.ko*.mod.c.tmp_versions default:$(make)-c$(kerneldir)m=$(pwd)modules endif make生成模块后,使用insmod loongson_counter.ko将模块加载,这时就可以使用25号寄存器记录i-cache miss和d-cache miss了。

7、在具体程序中,如果你要计算一个函数带来的cache miss,可以在这个函数开头通过mfc0/dmfc0指令读取计数器中的初始值,然后在函数结尾,再读取一次,两次相减就得到了该函数造成的cache miss。注意硬件性能计数器是一个全局的计数器,即如果你在运行你要测试的函数同时运行了其他程序,其他程序造成的cache miss也会记录在计数器里。所以在保持cpu独占的情况下可以测试几次取平均值。下面以一个sort()函数为例示例怎么在函数中应用:sort.cvoid sort()usigned int icache_init,dcache_initi,cache_miss,dcache_mis

8、s;asm volatile(.set mips3ntdmfc0%0,ntdsra%0,32ntmfc0%0,nt:=r(dcache_init),=r(icache_init);/把counter的初始值记录下来qsort(.);.;asm volatile(.set mips3ntdmfc0%0,ntdsra%0,32ntmfc0%0,nt:=r(dcache_miss),=r(icache_miss);/记录函数运行后计数器的值fprintf(stderr,i cache miss is:%dn,icache_miss-icache_init);fprintf(stderr,d cach

9、e miss is:%dn,dcache_miss-dcache_init);/红色部分为使用performance counter所加入的代码现在我们已经可以使龙芯2f的计数器起作用了,但是还存在一个问题,如果我有一个代码量相对比较多的程序,想做一个工具来多方面的评测这个程序,许要使用到各种不同的计数器事件,而又不想每次都重新编译加载一个内核来改变这个事件,这时候就需要写一个相对稍复杂一些的模块用来设置事件,下面是我写的一个模块,可以通过write系统调用来改变事件。loongson_counter.c#include linux/module.h#include linux/init.h#

10、include linux/fs.h#include linux/cdev.h module_license(dual bsd/gpl);module_author(sponge);module_description(change event of performance counter);module_alias(set_event);/function convert char to int int convert_event(char*array)int ret=0;int i;for(i=0;i=3;i+)/printk(ret is:%x,i is%x,arrayiis%cn,re

11、t,i,arrayi);if(arrayi=1)ret=ret+(1(3-i);else if(arrayi=0)continue;else return-einval;return ret;/function used to modify the register int event_write(struct file*filp,const char _user*buff,size_t count,loff_t*f_pos)int e0,e1;/variables hold the event number char buff_k9;/buffer holds date transform

12、from user space char event05;char event15;/these two array hold event number in form of char int i;/loop counter int regval;/the value that will transform to if(count!=9)return-einval;/copy user date if(copy_from_user(buff_k,buff,9)return-efault;/convert user date to array for(i=0;i=3;i+)event0i=buf

13、f_ki;event1i=buff_ki+4;/convert char to int if(e0=convert_event(event0)=-einval)return-einval;if(e1=convert_event(event1)=-einval)return-einval;/printk(event0 is%x,event1 is%xn,e0,e1);/compute regval=(e0 5)|(e1 9)|0xf;asm volatile(mtc0%0,:r(regval);/unsigned int val=0;/asm volatile(mfc0%0,:=r(val);/

14、printk(kern_emergcurrent cp0_24 value is 0x%xn,val);return 0;struct cdev event;struct file_operations event_ops;/init function static int init_event(void)/register the device event if(register_chrdev_region(mkdev(33,0),1,pcounter)return-efault;/register operations event_ops.write=event_write;cdev_init(&event,&event_ops);cdev_add(&event,mkdev(33,0),1);return 0;/clean function static void exit_event(void)/unregister device cdev_del(&event);unregister_chrdev_region(mkdev(33,0),1);module_init(init_event);module_exit(exit_event);makefile跟上一个例子的基本一致。使用该模块的方法为:1、在root下使

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论