(转载)一篇有趣的文章


在用32位的定点处理器AMD Alchemy AU1200(已经出售给RMI了)做一些事情, AU1200应该算是很NB也很容易上手的处理器,
不过和大多数嵌入式处理器一样,同样没有浮点处理器,所有的算法都必须用定点数重写, 我曾经以为这是一个很头痛的问题,不过现在看来,
要解决定点数运算中产生的单步误差(Step Error)和累积误差(Accumulative Error)才是真正要命的问题,特别是后者,
简直能把人逼疯.

要解决累积误差,我能想到的,无非就是两种方法:
   

  • 其一: 定时RESET整个程序,让程序复位,变量归零.
  • 其二:定时补偿误差,不过这个似乎难点儿,鬼才知道那些浮点转定点再经过一大堆运算会变成什么样子.

而我们现在能做的,无非是尽量提高定点数的精度,32位不够,上64位,64不够,上96位.......不过,再长的定点数,随着程序运行时间的增加,再小的误差也会累积成为很大很大的数.尤其是在这种动辄几十秒就产生上千万次循环的算法里面........

最近看到一篇文章,也是关于累积误差的事儿,那可是真正要命的,也一再提醒我,对待这个问题,马虎不得....

1990
年底至次年初,老布希发动美国对伊拉克的第一次战争,他们称之为「沙漠风暴」Deseart
Storm。就像本世纪初由小布希发动的第二次美伊战争一样,大多数美军的伤亡都发生在自己人的不慎 (称为「友军火力」friendly
fires)。沙漠风暴中美军最大的一次伤亡事件,于 1991 年 2 月 25 日发生在沙乌地阿拉伯之德兰 (Dhahran)
军营。当时正是用餐时间,伊拉克的飞毛腿 (Scud) 飞弹击中了营房,一次造成 28
人死亡。那时我在美国宾州留学,当地报纸更详细地说,那批阵亡大兵多半来自宾州,许多人的家乡还是我曾经造访的乡村小镇,造成我更深刻的印象。


毛腿飞弹是当年伊拉克最神勇的武器:机动、快速、准确。一开始的时候,以色列和美国都吃了它的苦头,居然没有有效拦截它的反制武器。后来,美国发现扔在仓
库角落的爱国者 (Patriot) 飞弹竟然恰好是飞毛腿的剋星,就赶快徵调它上战场。以科技眼光来看,爱国者是个老掉牙的地对空飞弹:它设计于
1960 年代,主要服役于 1970
年代的西欧,所有的武器控制系统都是在那时候设计和製造的,程式也是那时候写的。它部署在欧洲的主要任务是拦截苏联的中、高空飞机或巡弋飞弹,当时假设拦
截对象的飞行速度大约二马赫 (时速约 2500
公里)。而且,爱国者被设计成机动性强、不容易被发现的小型发射砲台。它可以被车子载著跑,藏在树林里,发射之后就逃跑换个地点躲藏。这就意味著,爱国者
飞弹的电脑开机时间,通常不会很长,经常不到一小时。在当时的这些任务前提之下,爱国者的控制电脑做得比较简单:它的计算储存器只有 24
位元,也就是说,就无号整数而言,它的 CPU 只能处理介于 0 与 16777215 之间的整数。

读者必须明白,武器上面的电脑不
是 Intel 或 Sparc 这种东西,它们是非常特别的设备,因此程式设计师通常没有 C 语言与 UNIX 作业系统这种奢侈的享受
(你还以为是 Java 吗?),他们要不是使用非常特殊的程式语言工具,就是直接用组合语言写程式。

1970
年代的工程师为爱国者设计了轻简的硬体,而程式设计师也因应写了「够用」的软体。他们用 24
位元的整数来模拟小数,设定小数点下必有四位,这就是一种「定点数」:小数点固定在第四、五位数之间。譬如 31.4 就记做 314000,而
2.71828 记做 27183。爱国者的控制电脑用这种方式计算,并且把某种时间的计算结果累加到一个变数内。很显然地,时间在 10-5
秒就要被四捨五入到10-4
秒,因此将会造成误差。这小小的误差会累积在一个纪录时间的变数里面,执行得越久、累积的误差越多。具体地说,每一小时会累积 0.0034
秒的误差。而这个数据在爱国者飞弹的控制系统中非常重要,因为要用它和观测所得的目标物速度 (譬如说飞毛腿飞弹)
来计算导引雷达的方位变化,使得雷达可以锁定目标物,然后发射爱国者飞弹升空拦截。

过去,爱国者飞弹并不太在乎这些误差。原因有二:

   1. 理论上爱国者飞弹是机动性的,它躲躲藏藏,每次开机不会太久
   2. 它的假想敌飞得不算太快,所以稍微的误差不会导致导引雷达失效

但是,1990 年它老驥伏櫪、临危受命,情况却大不相同:

   1. 这次它被部署在固定营地中,长时间开机,以备随时拦截随时可能射过来的飞毛腿飞弹
   
   2. 飞毛腿的飞行速度是五马赫 (时速约 6150 公里),所以前述的小小累积误差,对于导引雷达的追踪能力就有比较大的影响 (每小时误差看来「只有」0.0034 秒,而时速五马赫的东西已经飞了 7 公尺)


军并非不知道这个道理。根据 2 月 11 日由以色列军方协助作成的研究,发现爱国者飞弹的控制系统若连续开机 8 小时,则会造成导引雷达 20%
的偏差。据此推算,若连续开机 20 小时,则偏差超过
50%,此时爱国者将会和飞毛腿擦身而过,连边也碰不上更别谈拦截了。此时已经来不及升级硬体,而软体虽然可以改写,但是一时还写不出来。因此美军下了一
道很合理的「使用说明」命令:

    爱国者飞弹的控制系统必须 *每小时重新开机* 一遍

这样就可以使累积时间的变数归零,重新开始,也就不至于累积太多的误差。每次重新开机需要 90 秒,这段时间没有防御功能,因此美军安排了审慎的重开机时间表,使得大家不会在同一段时间重新开机。


是,就像电影里面演的笨蛋大兵一样,那一批负责德兰基地爱国者飞弹的大兵,居然让它连续开机了 100
个小时,完全没有遵守「使用手册」的命令。或许他们觉得那台电脑跑得好好的,不明白为什么要重新开机;或许他们每个人都以为前一班的人重开过了;或许一切
都是命中注定;我不知道。 2 月 25 日从那个基地发射出来的「拦截飞弹」完全朝著反方向射出去,我不知道有没有因此炸死其他军民?就这样,有
28 名从美国宾州新报到的阿兵哥,还没上战场就在吃饭的时候给炸死了。

而改写的软体,恰好在 2 月 26 日送达德兰基地--就在这个事件的后一天。

事实上,在沙漠风暴战争期间,爱国者飞弹的控制软体一共改写了六次,也重灌了六遍。每次重灌大约需要两小时,在这段期间它没有防御能力。

这个事件并非程式设计师或者硬体的错误,而是使用者的错误。不过,不论如何,问题的关键也就在于「资料型态」的有限性,以及它在计算中所产生「无可避免」的误差。(来自http://libai.math.ncu.edu.tw/bcc16/pool/)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值