诡异的精度diff追查
一、Query-diff测试发现的问题
Query-diff是检索端常用的测试方法,其思想是使用一组相同的检索信息分别请求一个系统或模块的基线版本和待测版本。通常,基线版本和待测版本只存在少量差异(程序功能/配置等)。发送请求后,比较两个版本返回的检索结果,从而验证差异是否对最终计算结果造成了影响。
本case中的被测模块A由C++编写,输出的核心数据为一个单精度浮点数,记为Q。
在A模块某次升级后执行query-diff测试时,发现Q值存在精度diff,比例约为1%,最大diff在小数万分位,而该次升级预期是无diff的。
二、深入追查
通常出现diff,首先要明确追查的方向,如果一眼看不出原因,就需要使用排除法来逐个验证怀疑对象,缩小范围,减小不必要的精力投入。于是列出了两大排查方向:环境或程序。
先看环境:
l 在环境现场仔细检查了新旧环境的配置和词表,符合预期,排除了环境搭建工具的因素。
l 由于此次升级是前向兼容的,将新旧环境的配置和词表统一,重新测试,diff复现,排除了配置差异的因素。
环境似乎没有问题,再来验证程序:
l 因已做了多组测试,验证结果没有改变,排除了随机策略diff的可能。
l 打印debug日志,检查了处理过程中的每一步中间结果,均无问题,只在计算Q值的最后环节出现了diff,相继排除了线程脏数据,进程级cache脏数据,变量类型转换等风险点。
l 为彻底确认,直接将新旧环境里的程序都替换为新版本,重新测试,如果真是程序所致,应当无diff。然而,diff复现了!明明没有随机diff的啊?!!
此时排查到了瓶颈,环境和程序的原因似乎都不对。
冷静下来重新思考,之前的排查分别把环境的概念解释为使用的配置和词表,认为两者相同,环境就相同。这是片面的,环境的含义还应当包含系统和硬件的编译环境和运行环境。于是有了新的验证思路:
l 新旧版本的程序都使用公司的云编译集群产出,应当没有问题,不过为防止想当然,还是认真检查了编译参数并在本地相同机器重新编译了新旧版本,确认diff复现,排除编译因素;
l 将新旧环境拷贝到同一台机器,重压请求,diff消失!确认为运行环境因素
运行环境包括操作系统和硬件层面,趁热打铁,继续追查:
l 确认出现diff的两台机器操作系统一致,均为centos 4.3,排除了操作系统;
l 硬盘和内存的型号差异造成diff的可能性较小,暂不验证;
l 新环境所在机器cpu版本Xeon E5645,旧环境所在机器cpu版本 Xeon E5-2620,怀疑cpu型号不同所致,另找了一台与旧环境cpu一致的机器部署新环境,重新测试,diff消失,目标锁定cpu。
二、揭开真相
分析cpu,在简单排除了核数,最大线程数,一二三级缓存的嫌疑后,cpu特性列表中的指令集差异引起了我的注意。
补充知识一:cpu指令集的作用
指令集是存储在CPU内部,对CPU运算进行指导和优化的硬程序。拥有这些指令集,CPU就可以更高效地运行。为解释指令集的优化方式,得提到两种技术:SISD(单指令单数据)和SIMD(单指令多数据)。
以加法指令为例,使用SISD的CPU对加法指令译码后,执行部件先访问内存,取得第一个操作数,之后再一次访问内存,取得第二个操作数,后才能进行求和运算。而在使用SIMD的CPU中,指令译码后几个执行部件同时访问内存,一次性获得所有操作数进行运算。这个特点使SIMD特别适合于数据密集型运算。
Cpu指令集中的SSE系列和AVX用于浮点数运算,而AVX正是两个cpu的差异之一,嫌疑很大。现在需要找到程序使用AVX进行优化的证据。
可是,在ASQ模块中并没有直接优化的代码逻辑,涉及Q值计算的程序中虽然调用了静态libA的接口,而libA的代码也未使用指令集。不过,libA联编了静态libB,于是一路往底层追查,查到编译依赖的第四层,是IDL提供的libX,代码保密无法查看。
只好向相关RD请教,RD告知libX中确实使用了SSE指令优化,以及Intel提供的数学函数库MKL,却没有用到AVX。
难道又是条走不通的死路?抱着最后一点希望,查询了MKL在intel官方的介绍发现意外收获,MKL中引入了AVX优化!【1】
现在还差最后一步,得确认AVX就是diff来源的元凶。很快,在intel的产品手中找到了进一步的证据【2】:
AVX2中的FMA指令,在矩阵乘法、点积、多项式评估等涉及浮点数运算方面的效率和精度相对以往的指令集都有所提升,因为FMA可以将乘法与累加操作一次性完成。官方论坛里也找到了相关技术人员的帖子佐证【3】:
补充知识二:计算机中浮点数存储方式
float和double在存储方式上都是遵从IEEE的规范的,float遵从的是IEEE R32.24 ,而double 遵从的是R64.53。
无论是单精度还是双精度在存储中都分为三个部分:
1. 符号位(Sign) : 0代表正,1代表为负
2. 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储
3. 尾数部分(Mantissa):尾数部分
其中float的存储方式如下表所示:
|
总长度 |
尾数部分 |
指数部分 |
符号位 |
单精度 |
32bit |
0-22 |
23-30 |
31 |
双精度 |
64bit |
0-51 |
52-62 |
63 |
扩展双精度 |
80bit |
0-63 |
64-78 |
79 |
硬件层面上,cpu的浮点运算逻辑都是放在FPU(浮点运算单元)上实现的(无论SSE还是AVX),FPU的默认计算精度是80bit,而SSE和AVX输出的float精度没那么高(均为32bit),如果FPU中计算精度存在差异(前提是均大于32bit),计算输出时截断为32bit再存入内存,必然会因近似截断造成结果diff。
由于intel底层算法保密,只能猜测AVX和SSE的优化函数实现时设置的FPU精度有所不同,但精度差异的结论是确定的。
此时真相已浮出水面:AVX的FMA相比SSE精度上多1bit,存在迭代计算时,差异将会累计。而Q值的产生经历复杂的矩阵运算,这个微小的1bit差异被放大至小数点万分位。同时,Intel保证了各机器的兼容性,MKL的代码在不支持AVX的cpu上运行时会被降级为SSE。
补充知识三:使用SSE和AVX优化程序的方法
仍以加法指令为例,对于相关头文件的引入和编译指令相关准备此处不进行介绍,可参考相关资料。
基本版:
简单地循环累加求和。
SSE优化版
SSE寄存器128bit,16字节,一次可以存4个单精度浮点数,可以每4个一组存入寄存器,使用内置加法函数求和,之后再对4个分组和进行相加,最后加上分组剩余的几项,得到最终结果。
AVX优化版
AVX优化方式与SSE类似,但AVX寄存器使用256bit,32字节,可以存8个单精度浮点数,需要每8个float一组存入寄存器。
现在随机生成输入数组,撰写简单的测试用例,就可以验证优化的效果了,以下是三种算法的性能比较,单位为每秒可累加float的数量。结果中,SSE效率提升到普通版的4倍,而AVX是8倍!【4】
二、总结和启示
问题总结:
l Query-diff兼容性测试时发现模块A新旧版本计算出的Q值存在diff;
l 排查后,确定精度diff来自程序因运行环境cpu支持的浮点数指令集差异(AVX/SSE)
l 该case中diff占比和绝对值均较小,目前虽不至影响线上服务,但若算法进一步复杂,diff积累至百分位,便会导致策略失效。
l 其他模块的浮点数运算若用到指令集优化,也需要排查是否相同问题。
解决方案:
l 分配测试资源时,保证新旧环境所在机器cpu一致;
l 执行query-diff前加入环境检查机制,再次确认硬件无差异;
l 线上部署服务时,也需要确定机器支持AVX指令集,达到性能和精度最优;
l 排查其他模块是否有类似使用指令集优化的情况,提前规避风险。
启发和建议:
l 浮点数运算密集型程序可考虑使用SSE/AVX等指令集函数优化性能,通常可显著提高运行效率(SSE:4倍,AVX:8倍);
l 使用指令集时注意控制迭代使用的次数(即将指令集函数的输出再次作为指令集函数的输入),避免精度diff累积到不容忽视的程度;
l 可以将query-diff测试应用到更多的兼容性测试场景中,如比较CPU,操作系统,基础库等底层系统和硬件差异对应用程序的影响。
软件工程离不开硬件的支持,编译、运行环境的差异都有可能造成服务性能的差别和最终计算结果的差别。此类问题,在开发、测试、上线各个阶段都需要特别注意。做一个“软硬结合”的程序员很重要!
参考资料:
【1】 https://software.intel.com/zh-cn/articles/whats-new-in-intel-mkl
【2】 https://software.intel.com/zh-cn/articles/intel-xeon-processor-e7-88004800-v3-product-family-technical-overview
【3】 https://software.intel.com/en-us/forums/topic/507004
【4】 http://www.cnblogs.com/zyl910/archive/2012/10/22/simdsumfloat.html

根据美国司法部的解释,蓝色警报旨在提供关于可能对执法人员构成直接和紧急威胁的个人的重要信息。这种警报的目的是及时通知公众,并让他们了解与这些罪犯相关的潜在危险。通过这种主动的方式,蓝色警报有助于增强社区的安全意识,促使人们采取必要的预防措施以保护自己和周围的人。这种警报系统的建立旨在提高对潜在威胁的警觉性,并加强执法机构与公众之间的沟通,以共尽管这些紧急通知对我们社会至关重要,但有时可能会对日常生活造成干扰,尤其是在午夜或重要活动时收到通知时。为了确保安全,我们建议您保持这些通知功能开启,但如果

Android中的轮询是一项关键技术,它允许应用程序定期从服务器或数据源检索和更新信息。通过实施轮询,开发人员可以确保实时数据同步并向用户提供最新的内容。它涉及定期向服务器或数据源发送请求并获取最新信息。Android提供了定时器、线程、后台服务等多种机制来高效地完成轮询。这使开发人员能够设计与远程数据源保持同步的响应式动态应用程序。本文探讨了如何在Android中实现轮询。它涵盖了实现此功能所涉及的关键注意事项和步骤。轮询定期检查更新并从服务器或源检索数据的过程在Android中称为轮询。通过

为了提升用户体验并防止数据或进度丢失,Android应用程序开发者必须避免意外退出。他们可以通过加入“再次按返回退出”功能来实现这一点,该功能要求用户在特定时间内连续按两次返回按钮才能退出应用程序。这种实现显著提升了用户参与度和满意度,确保他们不会意外丢失任何重要信息Thisguideexaminesthepracticalstepstoadd"PressBackAgaintoExit"capabilityinAndroid.Itpresentsasystematicguid

1.java复杂类如果有什么地方不懂,请看:JAVA总纲或者构造方法这里贴代码,很简单没有难度。2.smali代码我们要把java代码转为smali代码,可以参考java转smali我们还是分模块来看。2.1第一个模块——信息模块这个模块就是基本信息,说明了类名等,知道就好对分析帮助不大。2.2第二个模块——构造方法我们来一句一句解析,如果有之前解析重复的地方就不再重复了。但是会提供链接。.methodpublicconstructor(Ljava/lang/String;I)V这一句话分为.m

如何将WhatsApp聊天从Android转移到iPhone?你已经拿到了新的iPhone15,并且你正在从Android跳跃?如果是这种情况,您可能还对将WhatsApp从Android转移到iPhone感到好奇。但是,老实说,这有点棘手,因为Android和iPhone的操作系统不兼容。但不要失去希望。这不是什么不可能完成的任务。让我们在本文中讨论几种将WhatsApp从Android转移到iPhone15的方法。因此,坚持到最后以彻底学习解决方案。如何在不删除数据的情况下将WhatsApp

原因:1、安卓系统上设置了一个JAVA虚拟机来支持Java应用程序的运行,而这种虚拟机对硬件的消耗是非常大的;2、手机生产厂商对安卓系统的定制与开发,增加了安卓系统的负担,拖慢其运行速度影响其流畅性;3、应用软件太臃肿,同质化严重,在一定程度上拖慢安卓手机的运行速度。

1.启动ida端口监听1.1启动Android_server服务1.2端口转发1.3软件进入调试模式2.ida下断2.1attach附加进程2.2断三项2.3选择进程2.4打开Modules搜索artPS:小知识Android4.4版本之前系统函数在libdvm.soAndroid5.0之后系统函数在libart.so2.5打开Openmemory()函数在libart.so中搜索Openmemory函数并且跟进去。PS:小知识一般来说,系统dex都会在这个函数中进行加载,但是会出现一个问题,后

1.自动化测试自动化测试主要包括几个部分,UI功能的自动化测试、接口的自动化测试、其他专项的自动化测试。1.1UI功能自动化测试UI功能的自动化测试,也就是大家常说的自动化测试,主要是基于UI界面进行的自动化测试,通过脚本实现UI功能的点击,替代人工进行自动化测试。这个测试的优势在于对高度重复的界面特性功能测试的测试人力进行有效的释放,利用脚本的执行,实现功能的快速高效回归。但这种测试的不足之处也是显而易见的,主要包括维护成本高,易发生误判,兼容性不足等。因为是基于界面操作,界面的稳定程度便成了


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SublimeText3汉化版
中文版,非常好用

Dreamweaver CS6
视觉化网页开发工具

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中