1. 非规则浮点数(subnormal)

根据IEEE754(http://zh.wikipedia.org/wiki/IEEE_754),浮点数由符号位、指数、尾数组成,对8字节的double 类型数据,指数位有11位,可以表示2的阶数范围 -1022~+1023,对应的指数部分的值是1~2046(加上1023的偏移)。

double类型的尾数位有52位,尾数默认的最高有效位为1,存储时省略,所以规则的浮点数范围是 +-2^-1022 ~ +- (2-2^-52)*2^1023,最小的规则正数大约是4.5E-307。除去0以外,指数部分取值0(尾数不为0)表示一类特殊的数——subnormal,取值小于2^-1022。

2. CPU对subnormal 数的处理

现代CPU对subnormal一般是硬件处理,ALU只能直接运算normal 数,对subnormal 触发处理器异常,然后处理。以Intel CPU为例,在Intel 的手册中,subnormal 写作denormal,处理涉及两个方面:

(1) normal 数的运算结果是 denormal:CPU设置 numeric underflow exception(#U),通过称作“gradual underlow”的运算过程,对尾数逐位向右移位,直到指数增大到正常范围。

(2) denormal 是源操作数:CPU设置 denormal operand exception(#D),这个异常在计算指令真正执行之前发生。处理过程与寄存器MXCSR中指定的相关模式有关,默认是与IEEE754兼容,但是也可以通过设置“denormal-are-zeros”模式(奔腾4和Xeon),将denormal操作数置0提升运算速度。

以上的处理器异常默认是由CPU自己处理(即masked),但是也可以通过设置,将这些异常暴露给用户处理。

3. subnormal 运算的性能

这里可以用一个microbenchmark来测试一下,不同的操作数,乘法运算效率相差有多少:

01 /** set xmm1,3,5,7 = x
02   * xmm0,2,4,6 = 1.0
03   */
04 static void mul_init( double x ) {
05         double dummy = 0.0;
06         __asm__ __volatile__ (
07                 'movsd  %1, %0':'=Yz'(dummy):'x'(x)
08         );
09         __asm__ __volatile__ (
10                 'movsd  %xmm0, %xmm1;'
11                 'movsd  %xmm0, %xmm3;'
12                 'movsd  %xmm0, %xmm5;'
13                 'movsd  %xmm0, %xmm7;'
14         );
15         dummy = 1.0;
16         __asm__ __volatile__ (
17                 'movsd  %1, %0':'=Yz'(x):'x'(dummy)
18         );
19         __asm__ __volatile__ (
20                 'movsd  %xmm0, %xmm2;'
21                 'movsd  %xmm0, %xmm4;'
22                 'movsd  %xmm0, %xmm6;'
23         );
24 }
25  
26 static void mul_latency_pack4() {
27         __asm__ __volatile__ (
28                 'mulsd  %xmm0, %xmm1;'
29                 'mulsd  %xmm2, %xmm1;'
30                 'mulsd  %xmm4, %xmm1;'
31                 'mulsd  %xmm6, %xmm1;'
32         );
33 }
34  
35 static void mul_throughput_pack4() {
36         __asm__ __volatile__ (
37                 'mulsd  %xmm0, %xmm1;'
38                 'mulsd  %xmm2, %xmm3;'
39                 'mulsd  %xmm4, %xmm5;'
40                 'mulsd  %xmm6, %xmm7;'
41         );
42 }
43  
44 static void measure_latency( int repeats )
45 {
46         int i = repeats;
47         while ( i > 0 ) {
48                 REPEAT_256( mul_latency_pack4(); )
49                 --i;
50         }
51 }
52  
53 static void measure_throughput( int repeats )
54 {
55         int i = repeats;
56         while ( i > 0 ) {
57                 REPEAT_256( mul_throughput_pack4(); )
58                 --i;
59         }
60 }
61  
62 int main(int argc, char *argv[])
63 {
64         int repeats = 100000;
65         double fnormal = 1.0;
66         mul_init( fnormal );
67  
68         double cost = 0.0;
69         TIMING( measure_latency(repeats/10), cost );
70         printf'Latency (normal): %.3e ns\n', cost * 1e9 * 10 / (double)repeats / 1024 );
71  
72         cost = 0.0;
73         TIMING( measure_throughput(repeats), cost );
74         printf'Throughput (normal): %.3e ops\n', (double)repeats * 1024 / cost );
75  
76         double fsubnormal = 1e-310;
77         mul_init( fsubnormal );
78  
79         cost = 0.0;
80         TIMING( measure_latency(repeats/10), cost );
81         printf'Latency (subnormal): %.3e ns\n', cost * 1e9 * 10 / (double)repeats / 1024 );
82  
83         cost = 0.0;
84         TIMING( measure_throughput(repeats), cost );
85         printf'Throughput (subnormal): %.3e ops\n', (double)repeats * 1024 / cost );
86  
87         return 0;
88 }

编译参数 -O3 -finline-functions,在我的2.4GHz主频的机器上,一个结果是:

1 Latency (normal): 2.090e+00 ns
2 Throughput (normal): 1.916e+09 ops
3 Latency (subnormal): 7.111e+01 ns
4 Throughput (subnormal): 1.871e+07 ops

相对于规则的浮点数,subnormal 运算的延迟增大到34倍,吞吐量减小100倍。

4. 解决方法

科学计算里,subnormal 有时很难避免。除了运算变慢之外,由于尾数的有效位减少,精度也降低,后续的运算有产生无穷大inf的风险等等。处理的难度:

(1) 无法确定哪一步操作将产生subnormal 时,对所有中间结果检查开销很大。

(2) subnormal 仍然是有意义的数,直接置0是不是会产生错误的结果(比如除0错误)。

对于inf 和nan 类的不正常的数,也同样有上面类似的问题。

理想的情况是,从算法上做一些处理,比如对产生subnormal 的源操作数做偏移或者截断,消除源头。总之还是比较棘手的。

非规则浮点数(subnormal)引起浮点运算变慢相关推荐

  1. C语言学习(十一)小数在内存中是如何存储的?定点数与浮点数各自的优势在哪?规格化浮点数与非规格化浮点数又表示什么?

    C语言学习(十一)小数在内存中是如何存储的?定点数与浮点数各自的优势在哪?规格化浮点数与非规格化浮点数又表示什么? 浮点数与定点数 小数在内存中以浮点数形式存储.浮点数并不是一种数值分类,他和整数.小 ...

  2. 八、非规则组织分析及其数学模型——平纹变化组织

    非规则组织顾名思义,无法通过一个数学模型来描述所有的非规则组织.对于每一个具体的非规则组织而言,其也有一定的规律性可循,即可通过分析每一个具体的非规则组织的组织点运动规律来建立相应的数学模型. 一.平 ...

  3. 相控阵天线(二):非规则直线阵列天线(稀布阵列、稀疏阵列、平方率分布阵列、含python代码)

    目录 非规则线阵概述 不均匀递变间距阵列 稀布阵列 稀疏阵列 不均匀相位递变阵列 不均匀幅度激励阵列 代码示例 非规则线阵概述 非规则线阵主要包括以下情况: 1. 不均匀间距阵列: a)不均匀间距递变 ...

  4. 17种常用的JS正则表达式 非负浮点数 非负正数

    <input type='text' id='SYS_PAGE_JumpPage' name='SYS_PAGE_JumpPage' size='3' maxlength='5' οnkeyup ...

  5. 非规则合并单元格内容合并

    实例需求:对于B列的非规则合并单元,将对应的A列单元格内容合并,并保存在B列中. 虽然在无数经典图书和文章中都告诫大家,合并单元格是数据分析的绊脚石,但是仍有无数数据分析行业的"烈士&quo ...

  6. flink+drools动态规则示例之温度跳变告警

    flink+drools动态规则示例之温度跳变告警 package com.mz.test;import com.google.common.collect.Lists; import lombok. ...

  7. 用正则表达式求非负整数 、匹配正整数、非正整数、负整数、整数、非负浮点数、正浮点数、非正浮点数、负浮点数、浮点数、有数字26个英文字母组成的字符串

    用正则表达式求非负整数 .匹配正整数.非正整数.负整数.整数.非负浮点数.正浮点数.非正浮点数.负浮点数.浮点数.有数字26个英文字母组成的字符串 // *** // 1.求非负整数: var str ...

  8. 【协作MIMO+非规则LDPC】协作MIMO系统上,中继协作解码转发策略和编码协作策略,采用非规则LDPC编码

    1.软件版本 MATLAB2013b 2.本算法理论知识 做非规则LDPC码的以编码协作形式的中继协议,比较以下三种情况下的误码率图和中断概率图: 源节点一个(配置一根天线),中继节点4个(每个节点配 ...

  9. 非规格化浮点数表示范围

    非规格化浮点数表示范围

最新文章

  1. 小游戏来了 游戏小程序你想知道的这有
  2. python with关键字学习
  3. tablewidget 行数自适应_控制|基于自适应遗传算法的增程式电动汽车能量管理策略优化...
  4. java 检测ip网速_java心跳测网速Demo
  5. Codeforces 671C Ultimate Weirdness of an Array 线段树 (看题解)
  6. shell脚本遍历分库分表数据
  7. as3:sprite作为容器使用时,最好不要指定width,height
  8. SQL Server 2012之初次安装
  9. [导入]MsAjax Lib- Date.format 函数
  10. 第八次立会顺利召开!
  11. Js获取或计算时间的相关操作
  12. Linux命令详解之 rm
  13. 计算机屏幕上的显示记录,什么样的桌面日历便笺既可以显示日期又可以提醒我所记录的时间表...
  14. SQL笔面试题:如何求取中位数?
  15. 寻仙服务器要维护多久,新寻仙正式服5.0.6.1更新公告
  16. linux双网卡配置两个ip,centos双线双ip配置,Windows双网卡双ip配置
  17. docke 安装rap_RAP2:使用docker镜像进行构建,启动部署
  18. iMac重装系统的问题:无法与恢复服务器取得联系/将安装器信息下载到目标卷宗失败
  19. 星际争霸兵种的诉苦(简略版)
  20. Blbl里面终末的女武神的精彩片段批量采集的方法

热门文章

  1. solo升级以及自动化更新的方法
  2. Xshell修改用户名字体颜色
  3. 系统进程相关知识(转载)
  4. SpringCloud- Ribbon 负载均衡 轮训算法
  5. 上海理工大学计算机专业考研难度,上海理工大学机械(专硕)专业考研难度分析-专业排名-难度大小...
  6. MLDN 魔乐科技 Oracle 学习笔记(2)
  7. sql server 各种等待类型-转
  8. VNC下载安装与使用(树莓派篇)
  9. 集团将管理盛大电子书建直销分销双渠道
  10. java倒序输出数字的方法