<2012 12 20> Gcc/ARM/Linux Kernel关于浮点运算的一些说明(很有用!)
2012-12-20 20:43
260 查看
参考之前的两篇博文《ABI/EABI/OABI详解及ARM-linux 浮点运算解析与配置》《Why ARM's EABI Matters?有关ARM-Linux平台浮点计算性能。》
跟这篇博文的主题都有关系,这篇博文整理这方面的知识比较清楚,也便于应用。
=====================================================================
名字解释:
ABI,application binary interface (ABI),应用程序二进制接口。
编译版本问题:
GCC 4.0 为分界线
4.0版本以下,由于采用OABI接口,其对浮点的支持不太好
4.0版本以上,采用了新的EABI接口,其对软浮点和硬浮点的支持都比较好。
考虑在4.0版本以下时,其支持的ARM内核大多数没有硬浮点,所以可以分析资料比较少,
现在重点关注4.0版本以上。以下所述都是针对4.0版本以上的。
编译器相关的参数:
-mfloat-abi=soft 使用这个参数时,其将调用软浮点库(softfloat lib)来支持对浮点的运算,GCC编译器已经有这个库了,一般在libgcc里面。这时根本不会使用任何浮点指令,而是采用常用的指令来模拟浮点运算。但使用的ARM芯片不支持硬浮点时,可以考虑使用这个参数。在使用这个参数时,连接时一般会出现下面的提示:
undefined reference to `__aeabi_fdiv'
或者类似的提示,主要因为一般情况下连接器没有去主动寻找软浮点库,这时使用将libgcc库加入即可。
-mfloat-abi=softfp
-mfloat-abi=hard
这两个参数都用来产生硬浮点指令,至于产生哪里类型的硬浮点指令,需要由-mfpu=xxx参数来指令。这两个参数不同的地方是:
-mfloat-abi=softfp生成的代码采用兼容软浮点调用接口(即使用-mfloat-abi=soft时的调用接口),这样带来的好处是:兼容性和灵活性。库可以采用-mfloat-abi=soft编译,而关键的应用程序可以采用-mfloat-abi=softfp来编译。特别是在库由第三方发布的情况下。
-mfloat-abi=hard生成的代码采用硬浮点(FPU)调用接口。这样要求所有库和应用程序必须采用这同一个参数来编译,否则连接时会出现接口不兼容错误。
-mfpu=vfp
-mfpu=fpa
...
前面已经讲述了,-mfpu参数就是用来指定要产生哪种硬浮点指令。常见的有vfp,fpa等。
编译器使用时要注意的地方:
1.确认编译器默认是使用哪种参数来处理浮点操作的。写一个简单的浮点数程序:
#include <stdio.h>
int main(void)
{
double d1 = 10.3;
double d2 = 2.0;
double dret = d1/d2;
dret++;
printf("result :%f",dret);
return 0;
}
然后使用
arm-linux-gcc -c main.c -o main.o
再使用
arm-linux-objdump -d main.o
然后观察产生的指令,从而确定默认使用的是软浮点还是硬浮点。(确认的过程,看个人。晃一眼,里面如果有不熟悉指令,那可能就是硬浮点指令了)
2.确认编译器所带的库使用哪种参数来编译的。
3.确认所使用的芯片是否支持硬浮点,如果支持,是哪种类型的浮点指令。如果1,2与使用的芯片相冲突,这时就要考虑另寻编译器了。
这三点确认以后,我们在写自己的应用程序时,就会知道该怎样使用这些参数了。
Linux相关问题:
这里涉及两个问题:1.使用的ARM芯片不支持硬浮点
2.使用的ARM芯片支持硬浮点
问题1:使用的ARM芯片不支持硬浮点
在配置ARM Linux内核时,应该都会看到这样的配置:
menu "Floating point emulation"
comment "At least one emulation must be selected"
config FPE_NWFPE
...
这个是用来配置在内核里面模拟浮点处理器。
这个配置有什么作用呢?估计很少有人能够知道。其实它是这样的:
当使用的ARM芯片不支持硬浮点,而又采用了-mfpu=fpa -mfloat-abi=softfp/hard来编译应用程序。现在应该知道,采用这样的参数是要参数fpa硬浮点指令。但是使用的ARM芯片不支持硬浮点,这时这个配置就其作用了。因为使用了fpa硬浮点指令,但使用的ARM芯片不支持硬浮点,这样当程序运行到fpa硬浮点指令,会出现指令异常,便会陷入到内核里,这时这个模拟浮点处理器就来模拟这些浮点指令。现在应该清楚了,其作用了吧。但是现在有了更好的办法,前面已经讲过了,采用-mfloat-abi=soft参数来编译应用程序,这样效率会快得多。想想从用户态切换到内核态,以及由此产生的cache和TLB表的损失。所以可以考虑将这个配置抛弃了。
问题2:使用的ARM芯片支持硬浮点
一般ARM芯片支持硬浮点,都是采用协处理器方式的。与ARM内核本身一样,协处理器也有自己的寄存器。这样当多个进程同时涉及浮点运算时,会怎样?所以Linux内核为了支持硬浮点,也要做一些工作的。
内核配置:
config VFP
bool "VFP-format floating point maths"
depends on CPU_V6 || CPU_ARM926T || CPU_V7 || CPU_FEROCEON
如果使用的ARM芯片支持硬浮点,同时在应用程序里面使用了硬浮点,那么内核可能需要做一些工作。。上面这个配置是针对vfp硬浮点处理器的;如果是其他硬浮点处理,需要参考相关的资料,来确认要做哪些功能。如果可以确保所有时候,可以确保只有一个进程使用硬浮点处理器,那可以不需要考虑对硬浮点相关寄存器的保存和切换,问题是可以确认吗?
对于浮点运算,针对ARM芯片应该尽量避免。如果无法避免,那就需要综合考虑到底使用哪种方式?如何去操作?性能如何?都需要考虑,去实验测试是最好的。
跟这篇博文的主题都有关系,这篇博文整理这方面的知识比较清楚,也便于应用。
=====================================================================
名字解释:
ABI,application binary interface (ABI),应用程序二进制接口。
编译版本问题:
GCC 4.0 为分界线
4.0版本以下,由于采用OABI接口,其对浮点的支持不太好
4.0版本以上,采用了新的EABI接口,其对软浮点和硬浮点的支持都比较好。
考虑在4.0版本以下时,其支持的ARM内核大多数没有硬浮点,所以可以分析资料比较少,
现在重点关注4.0版本以上。以下所述都是针对4.0版本以上的。
编译器相关的参数:
-mfloat-abi=soft 使用这个参数时,其将调用软浮点库(softfloat lib)来支持对浮点的运算,GCC编译器已经有这个库了,一般在libgcc里面。这时根本不会使用任何浮点指令,而是采用常用的指令来模拟浮点运算。但使用的ARM芯片不支持硬浮点时,可以考虑使用这个参数。在使用这个参数时,连接时一般会出现下面的提示:
undefined reference to `__aeabi_fdiv'
或者类似的提示,主要因为一般情况下连接器没有去主动寻找软浮点库,这时使用将libgcc库加入即可。
-mfloat-abi=softfp
-mfloat-abi=hard
这两个参数都用来产生硬浮点指令,至于产生哪里类型的硬浮点指令,需要由-mfpu=xxx参数来指令。这两个参数不同的地方是:
-mfloat-abi=softfp生成的代码采用兼容软浮点调用接口(即使用-mfloat-abi=soft时的调用接口),这样带来的好处是:兼容性和灵活性。库可以采用-mfloat-abi=soft编译,而关键的应用程序可以采用-mfloat-abi=softfp来编译。特别是在库由第三方发布的情况下。
-mfloat-abi=hard生成的代码采用硬浮点(FPU)调用接口。这样要求所有库和应用程序必须采用这同一个参数来编译,否则连接时会出现接口不兼容错误。
-mfpu=vfp
-mfpu=fpa
...
前面已经讲述了,-mfpu参数就是用来指定要产生哪种硬浮点指令。常见的有vfp,fpa等。
编译器使用时要注意的地方:
1.确认编译器默认是使用哪种参数来处理浮点操作的。写一个简单的浮点数程序:
#include <stdio.h>
int main(void)
{
double d1 = 10.3;
double d2 = 2.0;
double dret = d1/d2;
dret++;
printf("result :%f",dret);
return 0;
}
然后使用
arm-linux-gcc -c main.c -o main.o
再使用
arm-linux-objdump -d main.o
然后观察产生的指令,从而确定默认使用的是软浮点还是硬浮点。(确认的过程,看个人。晃一眼,里面如果有不熟悉指令,那可能就是硬浮点指令了)
2.确认编译器所带的库使用哪种参数来编译的。
3.确认所使用的芯片是否支持硬浮点,如果支持,是哪种类型的浮点指令。如果1,2与使用的芯片相冲突,这时就要考虑另寻编译器了。
这三点确认以后,我们在写自己的应用程序时,就会知道该怎样使用这些参数了。
Linux相关问题:
这里涉及两个问题:1.使用的ARM芯片不支持硬浮点
2.使用的ARM芯片支持硬浮点
问题1:使用的ARM芯片不支持硬浮点
在配置ARM Linux内核时,应该都会看到这样的配置:
menu "Floating point emulation"
comment "At least one emulation must be selected"
config FPE_NWFPE
...
这个是用来配置在内核里面模拟浮点处理器。
这个配置有什么作用呢?估计很少有人能够知道。其实它是这样的:
当使用的ARM芯片不支持硬浮点,而又采用了-mfpu=fpa -mfloat-abi=softfp/hard来编译应用程序。现在应该知道,采用这样的参数是要参数fpa硬浮点指令。但是使用的ARM芯片不支持硬浮点,这时这个配置就其作用了。因为使用了fpa硬浮点指令,但使用的ARM芯片不支持硬浮点,这样当程序运行到fpa硬浮点指令,会出现指令异常,便会陷入到内核里,这时这个模拟浮点处理器就来模拟这些浮点指令。现在应该清楚了,其作用了吧。但是现在有了更好的办法,前面已经讲过了,采用-mfloat-abi=soft参数来编译应用程序,这样效率会快得多。想想从用户态切换到内核态,以及由此产生的cache和TLB表的损失。所以可以考虑将这个配置抛弃了。
问题2:使用的ARM芯片支持硬浮点
一般ARM芯片支持硬浮点,都是采用协处理器方式的。与ARM内核本身一样,协处理器也有自己的寄存器。这样当多个进程同时涉及浮点运算时,会怎样?所以Linux内核为了支持硬浮点,也要做一些工作的。
内核配置:
config VFP
bool "VFP-format floating point maths"
depends on CPU_V6 || CPU_ARM926T || CPU_V7 || CPU_FEROCEON
如果使用的ARM芯片支持硬浮点,同时在应用程序里面使用了硬浮点,那么内核可能需要做一些工作。。上面这个配置是针对vfp硬浮点处理器的;如果是其他硬浮点处理,需要参考相关的资料,来确认要做哪些功能。如果可以确保所有时候,可以确保只有一个进程使用硬浮点处理器,那可以不需要考虑对硬浮点相关寄存器的保存和切换,问题是可以确认吗?
对于浮点运算,针对ARM芯片应该尽量避免。如果无法避免,那就需要综合考虑到底使用哪种方式?如何去操作?性能如何?都需要考虑,去实验测试是最好的。
相关文章推荐
- <2012 12 15> ABI/EABI/OABI详解及ARM-linux 浮点运算解析与配置
- <2012 12 17> Why ARM's EABI Matters?有关ARM-Linux平台浮点计算性能。
- <2012 12 16> gcc-ARM交叉编译器死活不支持math.h中的isnormal、isfinite两个宏
- <2012 12 02> linux下利用valgrind工具进行内存泄露检测和性能分析
- 达内第15天培训知识总结,关于大数字的精确浮点运算以及linkList<>用法
- 关于新旧版本的GCC对浮点数运算的一些行为(读《CS:APP》)
- 关于arm-linux-gcc: error trying to exec 'cc1': execvp: 没有该文件或目录的错误
- 关于web.config中<customErrors>节点说明
- arm-linux-gcc/gdb 安装出现 浮点数例外的原因
- 关于Array.Sort<T> (T[], Comparison<T>)的一些小记录
- 关于arguments.callee.caller.arguments[0]获得event的一些问题<转>
- 关于arm-linux-gcc安装问题
- <2012 12 17> linux驱动中的platform总线架构(含具体IIC设备驱动)
- 关于web.config中<customErrors>节点说明
- 关于64位CentOS上ptrace报<linux/user.h> no such file 错误的解决方法
- 【计算机视觉】<资料站点>关于计算机视觉的一些测试数据集和源码站点
- 关于龙芯2号的一些说明(转载自LinuxFans.org)
- [ Java ] [ Spring ] Spring 一些配置项 及 <context:annotation-config/> 專文解释说明
- <2012 11 6 > linux设备驱动程序开发初探(6) 异步通讯机制: Kernel ---> APP
- 关于html<head>部分怎么写的一些思考