MIPS处理器下浮点指令的处理方法

  这几天编译qt,运行起来非常慢,组长让我试一下软浮点的编译器,说处理器不支持浮点,用软浮点编译器编译下会运行快一点,对于软浮点不是很明白,就网上搜集了一下,总结一下:

   在嵌入式领域,为了节省成本和减少功耗,很多芯片都是没有浮点运算模块的,一般该模块叫做FPU(float processunit)。对于不支持硬件浮点的处理器下,linux内核有一个模块叫math-emu的软件模块,就是用整数运算模拟浮点数运算,一般位于arch/mips/目录下。那么在应用空间的程序是怎么跑到该内核空间的模块呢。简单说就是,用工具链编译含有浮点运算的文件时,没有指定用软浮点,所以遇到浮点运算的时候还是将其编译成浮点运算指令。但是,编译生成的执行文件最终在执行到浮点运算指令的时候就有问题了。因为芯片没有FPU,所以浮点指令对于芯片来说是属于不认识或者叫不支持的指令,那么他就会产生一个异常。内核在初始化的时候为这个异常设置了异常处理函数,当内核捕捉到这个异常后进入异常处理函数执行。而这个异常处理函数就是内核浮点模拟运算模块的入口。内核将运算的结果再通过寄存器返回给系统空间,这样在应用空间来看的话就好像普通运算一样,没有什么区别。

 
    但是,应用空间 使用内核实现的浮点运算模块进行浮点运算 ,效率不是很高。这主要是基于两个方面,一个是因为需要反复的产生异常从而进行应用空间和内核空间的切换,浪费时间,另一个是因为,内核的浮点模拟模块效率并不高,因为异常处理时并不知道产生异常的指令到底是加减乘除指令,还是浮点比较等指令。所以,他需要先用switch确定一下该指令到底需要什么运算然后再进行模拟,最后返回运算结果。
 
  我起初运行非常慢就是因为这个原因,处理器没有硬件浮点,而是使用内核的软浮点运算模块。
 
   
  另外一种浮点运算的解决方案就是使用软浮点库
。方法就是在编译的时候使用编译选项-msoft-float,然后在链接的时候加上软浮点库。软浮点库的源文件在网上应该找的到。这样加上该编译选项后,编译器在编译浮点运算时,并不将浮点运算翻译成浮点运算指令而是,将其在编译阶段就转化成整形数,然后调用相应的软浮点运算库中浮点运算指令模拟函数,这样一条浮点运算指令在同软浮点运算库链接完成后就成了一堆整形数运算。这样的可执行文件能够充分的利用芯片的流水线,而且避免了应用空间和系统空间的切换,并且运算指令的类别判定放在了编译阶段,提高了运行阶段的效率。

  通常情况下,用软浮点和用内核浮点模拟模块相比,运算效率快一个数量级,相当的可观!
 
 
 
需要注意的几个问题:
 
    内核浮点和软浮点不能混用。 什么意思呢?比如一个工程中A库里面有函数的参数是浮点类型的,B库调用A库的这个函数,那么不能B库编译的时候带-msoft-float,而编译A库的时候却不带(直接使用内核浮点)。或者是A库带-msoft-float,而B库不带。通常网上很多文章说使用软浮点时,一定要使用支持软浮点的工具链,我想应该是因为使用软浮点时,工具链中很多系统库必须是 -msoft-float选项下编译出来的,典型的就是数学库libm.a,不然调用到该库中的函数时就可能计算错误。所以存在调用关系时,必须调用者和被调者在是否带-msoft-float选项上保持一致

对于实际的例子,比如我编译qt,我使用软浮点的交叉编译器编译qt,qt是要运行在开发板的linux内核上,因此linux也必须用软浮点的交叉编译器编译。

你可能感兴趣的:(linux,kernel)