郭思雨,王 磊
(中原工學(xué)院前沿信息技術(shù)研究院,河南 鄭州 450007)
目前,浮點(diǎn)計(jì)算被廣泛應(yīng)用于各個(gè)領(lǐng)域,現(xiàn)有的計(jì)算機(jī)硬件設(shè)計(jì)及IEEE-754[1]標(biāo)準(zhǔn),決定了浮點(diǎn)數(shù)是實(shí)數(shù)的有限精度編碼[2],不能精確表示出實(shí)數(shù),在進(jìn)行浮點(diǎn)計(jì)算時(shí),可能會(huì)導(dǎo)致不精確或者異常的結(jié)果。由于浮點(diǎn)數(shù)轉(zhuǎn)整數(shù)出現(xiàn)的整數(shù)溢出異常,歐洲Ariane 5火箭在1996年發(fā)射時(shí)出現(xiàn)了嚴(yán)重的升空自爆現(xiàn)象[3],造成了巨額的經(jīng)濟(jì)損失。因此,提前發(fā)現(xiàn)和規(guī)避,是目前解決浮點(diǎn)計(jì)算異常問題的關(guān)鍵。
能夠?qū)Ξ惓L幚砥鸬街笇?dǎo)作用的異常檢測方面的研究也在蓬勃發(fā)展。當(dāng)前的測試研究可以分為2類:(1)對浮點(diǎn)異常的研究。文獻(xiàn)[2]提出了利用值-范圍分析來加速浮點(diǎn)異常檢測的符號(hào)執(zhí)行;文獻(xiàn)[4]提出的Ariadne,使用實(shí)數(shù)算法對變換后的程序進(jìn)行符號(hào)執(zhí)行,以發(fā)現(xiàn)可能到達(dá)或觸發(fā)異常的候選實(shí)數(shù)輸入集;文獻(xiàn)[5]提出的FPChecker(Floating-Point Checker),使用Clang/LLVM(Low Level Virtual Machine)編譯器檢測GPU內(nèi)核并在運(yùn)行時(shí)檢測異常。這類方法多基于符號(hào)執(zhí)行方法,符號(hào)執(zhí)行是一種經(jīng)典的程序分析技術(shù),它使用符號(hào)輸入來探索可行的程序路徑,但是使用符號(hào)執(zhí)行技術(shù)檢測浮點(diǎn)異常的代價(jià)是昂貴的。(2)對整數(shù)溢出的研究。文獻(xiàn)[6]基于動(dòng)態(tài)檢測技術(shù),通過檢測所有可能產(chǎn)生溢出的操作實(shí)現(xiàn)了RICH(Run-time Integer CHecking)工具[6];盧錫城等人[7]提出了一種二進(jìn)制高危整數(shù)溢出錯(cuò)誤的全自動(dòng)測試方法DAIDT(Dynamic Automatic Integer-overflow Detection and Testing);Brick[8]能夠檢測和定位真實(shí)軟件中的大部分基于整數(shù)的漏洞,并具有較低的誤報(bào)率;文獻(xiàn)[9]基于靜態(tài)區(qū)間分析,提出了利用future bounds對變量進(jìn)行處理的整數(shù)溢出分析算法。
綜上所述,現(xiàn)有的方法不是針對浮點(diǎn)數(shù)學(xué)函數(shù)而設(shè)計(jì)的,其研究重點(diǎn)集中在整數(shù)溢出錯(cuò)誤,而浮點(diǎn)函數(shù)的運(yùn)算降低了整數(shù)溢出存在的可能性。在申威1621平臺(tái)上也沒有專門針對浮點(diǎn)數(shù)學(xué)函數(shù)的異常檢測方法,并且目前的研究中對于檢測結(jié)果的全面性沒有進(jìn)行相關(guān)的評估。鑒于此,面向基于匯編實(shí)現(xiàn)的浮點(diǎn)數(shù)學(xué)函數(shù)[10],本文提出了一種針對浮點(diǎn)數(shù)學(xué)函數(shù)的異常檢測方法。該檢測方法對浮點(diǎn)異常類型進(jìn)行分類后,在編譯函數(shù)源碼時(shí)進(jìn)行插樁。該方法能自動(dòng)檢測異常、用生成的測試用例對函數(shù)進(jìn)行全面檢測的同時(shí)記錄了代碼覆蓋率。
浮點(diǎn)環(huán)境由數(shù)據(jù)結(jié)構(gòu)和運(yùn)算組成,并通過硬件、系統(tǒng)軟件和軟件庫提供給程序員,實(shí)現(xiàn)了IEEE-754標(biāo)準(zhǔn)。浮點(diǎn)異常(即異常)是指在浮點(diǎn)算術(shù)運(yùn)算中出現(xiàn)的異常,即IEEE-754標(biāo)準(zhǔn)中定義的5種類型的浮點(diǎn)異常:無效操作、被零除、上溢、下溢和不精確異常。浮點(diǎn)函數(shù)是指申威高性能基礎(chǔ)數(shù)學(xué)函數(shù)庫中的浮點(diǎn)數(shù)學(xué)函數(shù),包括三角函數(shù)、指數(shù)函數(shù)、對數(shù)函數(shù)和雙曲函數(shù)等初等函數(shù)。代碼覆蓋率描述了測試數(shù)據(jù)作為輸入時(shí)函數(shù)的運(yùn)行情況,通過代碼覆蓋率可以對該檢測過程進(jìn)行評價(jià)。
本文提出的浮點(diǎn)異常檢測方法是指在測試階段對函數(shù)程序進(jìn)行必要的插樁修改,對其內(nèi)部的運(yùn)算指令進(jìn)行異常檢測。
浮點(diǎn)控制寄存器FPCR(Floating-Point Control Register)包含浮點(diǎn)異常的狀態(tài)、浮點(diǎn)舍入模式、浮點(diǎn)異常自陷控制和特殊數(shù)據(jù)的控制等。浮點(diǎn)控制寄存器FPCR有64位,其中[59:58]位是動(dòng)態(tài)舍入模式位;[57:52]位記錄浮點(diǎn)運(yùn)算指令產(chǎn)生的6種算術(shù)異常,也記錄浮點(diǎn)SIMD(Single Instruction Multiple Data)運(yùn)算指令中第0個(gè)元素進(jìn)行運(yùn)算產(chǎn)生的6種算術(shù)異常;[40:36]位、[24:20]位和[8:4]位分別表示浮點(diǎn)SIMD運(yùn)算指令中第1、第2和第3元素進(jìn)行運(yùn)算產(chǎn)生的5種算術(shù)異常,由于本文所涉及到的函數(shù)為標(biāo)量函數(shù),所以這些位暫時(shí)作為保留位;[63]位是算術(shù)異常的總標(biāo)志位,指示是否存在異常。該寄存器通過浮點(diǎn)指令WFPCR和RFPCR進(jìn)行訪問。
申威1621處理器支持IEEE-754標(biāo)準(zhǔn)定義的5種浮點(diǎn)算術(shù)異常,本文研究的浮點(diǎn)數(shù)學(xué)函數(shù)主要包括一系列初等函數(shù)[11],如三角函數(shù)、指數(shù)函數(shù)和對數(shù)函數(shù)等。本節(jié)對浮點(diǎn)算術(shù)異常進(jìn)行相應(yīng)分類檢測,由于產(chǎn)生上溢異常只可能是使浮點(diǎn)數(shù)增大的運(yùn)算或操作,產(chǎn)生下溢異常只可能是使浮點(diǎn)數(shù)減小的運(yùn)算或操作,因此,通過對faddd、fmuld等指令的檢測判斷是否產(chǎn)生上溢,通過對fsubd、fdivd等指令的檢測判斷是否產(chǎn)生下溢(其中還需對fdivd指令進(jìn)行被零除異常的檢測),通過對輸入?yún)?shù)的檢測判斷是否觸發(fā)無效操作異常。如果舍入后的結(jié)果與舍入前的真值不一致,或舍入時(shí)產(chǎn)生了上溢而申威1621處理器實(shí)現(xiàn)中無上溢自陷,則產(chǎn)生非精確結(jié)果(Inexact Result)異常。由于不精確經(jīng)常發(fā)生[4,12],并且通常是有限精度不可避免的結(jié)果,例如,當(dāng)1.0除以3.0時(shí),會(huì)出現(xiàn)不精確的異常,因?yàn)楸嚷?/3不能精確表示為浮點(diǎn)數(shù),因此暫不針對不精確異常進(jìn)行分析。通過以上3種分類對浮點(diǎn)計(jì)算異常進(jìn)行具體檢測。下面針對這3種分類進(jìn)行詳細(xì)說明:
(1) 無效操作異常檢測。
若當(dāng)前操作的一個(gè)操作數(shù)為非有限數(shù)或?qū)σ獔?zhí)行的操作而言是非法的(浮點(diǎn)比較指令的操作數(shù)為無窮大時(shí)不產(chǎn)生自陷),或用戶輸入的參數(shù)不滿足參數(shù)域的范圍或輸入?yún)?shù)類型不匹配(如將雙精度數(shù)傳給單精度函數(shù))等操作,將會(huì)產(chǎn)生無效操作異常。由于無效操作異常產(chǎn)生在用戶輸入?yún)?shù)階段,因此可在進(jìn)入函數(shù)正常運(yùn)算前對用戶的輸入進(jìn)行檢查,避免浮點(diǎn)數(shù)的特殊數(shù)參與到浮點(diǎn)運(yùn)算中引發(fā)浮點(diǎn)算術(shù)異常,影響浮點(diǎn)函數(shù)的可靠性。浮點(diǎn)數(shù)的特殊數(shù)包括SNaN(Signaling Not a Number)、QNaN(Quiet Not a Number)、Infinity和Denormal等無法正常處理的數(shù)據(jù)。SNaN一般用于標(biāo)記未初始化的值,QNaN一般表示未定義的算術(shù)運(yùn)算結(jié)果。
在進(jìn)入函數(shù)計(jì)算之前,對函數(shù)的定義域及輸入?yún)?shù)進(jìn)行對比檢測,判斷參數(shù)是否符合函數(shù)定義域,判斷是否產(chǎn)生無效操作異常和非規(guī)格化數(shù)異常。檢測輸入?yún)?shù)是否為特殊數(shù)SNaN和QNaN的源碼為:
1. fcmpeq $f16,$f16,$f14
2. fbeq $f14,L$9
3.L$9:
4. faddd $f16,$f16,$f0
5. ret
非數(shù)NaN(Not a Number)是計(jì)算機(jī)科學(xué)中一類數(shù)值數(shù)據(jù)類型的值,表示未定義或不可表示的值,常在浮點(diǎn)數(shù)運(yùn)算中使用。因?yàn)镹aN是一個(gè)范圍,而不能代表一個(gè)確定的值,因此利用NaN!=NaN對輸入?yún)?shù)$f16進(jìn)行判斷,如果$f16!=$f16,則該輸入?yún)?shù)為非數(shù)。其它特殊數(shù)可以通過參數(shù)定義域范圍檢測,在函數(shù)開始運(yùn)算之前,把函數(shù)定義域放入數(shù)據(jù)表內(nèi)。判斷輸入?yún)?shù)是否在函數(shù)定義域內(nèi),若在,則繼續(xù)參與運(yùn)算;若不在,則直接返回,并報(bào)出無效操作異常。
(2)上溢異常檢測。
上溢異常是在舍入過程中產(chǎn)生的,當(dāng)舍入結(jié)果的幅值(絕對值)超過目標(biāo)格式的最大有限值時(shí)即產(chǎn)生上溢異常。標(biāo)量浮點(diǎn)運(yùn)算指令或SIMD浮點(diǎn)運(yùn)算指令中的第0個(gè)元素進(jìn)行浮點(diǎn)算術(shù)運(yùn)算或轉(zhuǎn)換操作的結(jié)果產(chǎn)生上溢時(shí),F(xiàn)PCR寄存器的第54位置1。只有可以使浮點(diǎn)數(shù)增大的浮點(diǎn)運(yùn)算指令才可能會(huì)導(dǎo)致上溢異常的出現(xiàn),因此針對申威1621處理器中的相關(guān)運(yùn)算指令進(jìn)行檢測,如faddd、fmuld和fmad等浮點(diǎn)運(yùn)算指令。
根據(jù)浮點(diǎn)控制寄存器FPCR對應(yīng)的上溢異常位進(jìn)行檢測,具體內(nèi)容如下所示:
①檢測前的源碼:
…
1. faddd $f16,$f1,$f10
…
②插入檢測代碼后的源碼:
…
1. rfpcr $f8
2. fimovd $f8,$1
3. faddd $f16,$f1,$f10//需要檢測的操作
4. rfpcr $f9
5. fimovd $f9,$2
6. sll $1,9,$1
7. srl $1,63,$1//取出FPCR對應(yīng)上溢異常位
8. sll $2,9,$2
9. srl $2,63,$2
10. cmpeq $1,$2,$3/*判斷對比上溢異常位是否發(fā)生變化*/
11. beq $3,L$1/*如果觸發(fā)上溢異常,則跳轉(zhuǎn)至L$1分支,記錄該異常*/
12.L$1:
13. call detection//調(diào)用該函數(shù)記錄異常具體信息
…
其中,faddd為浮點(diǎn)加運(yùn)算;rfpcr為讀取當(dāng)前浮點(diǎn)控制寄存器FPCR的值;fimovd為雙精度浮點(diǎn)數(shù)傳送到整數(shù);cmpeq是等于比較。
以上代碼,具體含義為:在源碼編譯時(shí),檢測函數(shù)中是否有faddd或fmuld等匯編指令。若有,則將以上內(nèi)容放置到該指令前后,對比判斷是否產(chǎn)生上溢異常。若產(chǎn)生異常,則調(diào)用detection函數(shù),記錄異常的具體信息,如輸入?yún)?shù)、異常類型等信息;若不產(chǎn)生異常,則繼續(xù)執(zhí)行其余代碼。
(3) 下溢及被零除異常檢測。
下溢異常是在舍入過程中產(chǎn)生的,當(dāng)舍入結(jié)果的幅值(絕對值)小于目標(biāo)格式的最小有限值時(shí)即產(chǎn)生下溢異常。標(biāo)量浮點(diǎn)運(yùn)算指令或SIMD浮點(diǎn)運(yùn)算指令中的第0個(gè)元素進(jìn)行浮點(diǎn)算術(shù)運(yùn)算或轉(zhuǎn)換操作的結(jié)果產(chǎn)生下溢時(shí),F(xiàn)PCR寄存器的第55位置1。只有可以使浮點(diǎn)數(shù)減小的浮點(diǎn)運(yùn)算指令可能會(huì)導(dǎo)致下溢異常的出現(xiàn),因此針對申威1621處理器中的相關(guān)運(yùn)算指令進(jìn)行檢測,如fsubd、fdivd等浮點(diǎn)運(yùn)算指令。
被零除異常為當(dāng)除數(shù)為0 ,而被除數(shù)為有限數(shù)時(shí)觸發(fā)的異常,也泛指有限數(shù)運(yùn)算導(dǎo)致無窮結(jié)果的異常,例如4.0/0.0,log(0.0)等。在浮點(diǎn)數(shù)學(xué)函數(shù)實(shí)際運(yùn)算過程中,一般只被除法指令FDIVS/FDIVD觸發(fā)。被零除異常的檢測可以在檢測到除法指令時(shí),若被除數(shù)是一個(gè)不會(huì)引起無效操作異常的數(shù)據(jù),則對除數(shù)進(jìn)行判斷,若除數(shù)為0,則報(bào)出被零除異常。下溢異常的檢測與上溢異常的檢測方法基本一致,需要檢測是否產(chǎn)生下溢時(shí),在使浮點(diǎn)數(shù)減小的浮點(diǎn)運(yùn)算指令前后檢測FPCR寄存器第55位是否發(fā)生變化(由0變?yōu)?)。
檢測的主要流程為在源碼編譯時(shí)動(dòng)態(tài)檢測相關(guān)指令,檢測到相關(guān)指令后,對其前后進(jìn)行插樁,插樁內(nèi)容為檢測指令運(yùn)算前后FPCR的值,運(yùn)行時(shí)對比FPCR對應(yīng)異常位是否發(fā)生變化。如果發(fā)生改變,記錄并輸出當(dāng)前對應(yīng)的異常類型、相應(yīng)的指令操作及輸入?yún)?shù)至文件內(nèi)。具體檢測過程如圖1所示。此外,也可以將異常觸發(fā)的條件當(dāng)作插樁的內(nèi)容,放在相應(yīng)的指令操作之后,判斷是否觸發(fā)異常,如通過對比結(jié)果是否大于相應(yīng)浮點(diǎn)類型能表示的最大值來判斷是否產(chǎn)生上溢。除通過檢測浮點(diǎn)控制寄存器FPCR值的變化外,還可以通過IEEE-754標(biāo)準(zhǔn)定義的產(chǎn)生異常的條件進(jìn)行檢測。
Figure 1 Detection process analysis圖1 檢測過程分析
采用插樁方法檢測異常的目的是快速檢測出使函數(shù)觸發(fā)異常的輸入?yún)?shù)范圍以及異常的具體信息,減少后期定位異常的工作量。本文使用的插樁方法是在源碼的編譯過程中,對生成的匯編指令進(jìn)行插樁,保證任何函數(shù)都可以被檢測。插樁的位置在函數(shù)實(shí)現(xiàn)源碼中對浮點(diǎn)數(shù)的運(yùn)算或者轉(zhuǎn)換指令中,對指令的所在行前后進(jìn)行插樁,通過對比運(yùn)算前后FPCR的值判斷函數(shù)在此處是否觸發(fā)異常。在檢測到異常發(fā)生時(shí),可選擇終止檢測或繼續(xù)執(zhí)行其余代碼。選擇繼續(xù)執(zhí)行其余代碼前,需調(diào)用detection函數(shù)對此時(shí)檢測到的異常信息進(jìn)行記錄,以便程序員檢查程序中出現(xiàn)的所有異常(不僅僅是第一個(gè)),即當(dāng)發(fā)現(xiàn)異常時(shí),輸出一份簡短的報(bào)告,程序繼續(xù)執(zhí)行,不會(huì)中止。
檢測浮點(diǎn)數(shù)學(xué)函數(shù)實(shí)現(xiàn)源碼的異常時(shí),除了直接對浮點(diǎn)數(shù)學(xué)函數(shù)源碼的相應(yīng)指令進(jìn)行插樁檢測外,有些異??梢酝ㄟ^對具體異常的產(chǎn)生條件分析出來。如,被零除異常和整數(shù)溢出異常的可能觸發(fā)條件可以限定為FDIVS/FDIVD及FCVTDL/FCVTLW這4條指令的執(zhí)行,由于可能觸發(fā)這兩類異常的情況較少,可以先檢測函數(shù)中是否有以上4條指令,對檢測內(nèi)容進(jìn)行進(jìn)一步細(xì)化。具體而言,可以通過對除法指令FDIVS/FDIVD的搜索,實(shí)現(xiàn)對被零除異常的檢測;通過對轉(zhuǎn)換指令FCVTDL/FCVTLW的搜索,實(shí)現(xiàn)對整數(shù)溢出異常的檢測。
測試用例是用于檢測函數(shù)異常的輸入數(shù)據(jù)集,通過輸入該數(shù)據(jù)集,對浮點(diǎn)數(shù)學(xué)函數(shù)進(jìn)行大規(guī)模的檢測。IEEE-754標(biāo)準(zhǔn)規(guī)定,對于32位的浮點(diǎn)數(shù),最高的1位是符號(hào)位S,接著的8位是指數(shù)位E,剩下的23位為有效數(shù)字位M;對于64位的浮點(diǎn)數(shù),最高的1位是符號(hào)位S,接著的11位是指數(shù)位E,剩下的52位為有效數(shù)字位M。本文根據(jù)IEEE-754浮點(diǎn)數(shù)的規(guī)定及浮點(diǎn)數(shù)的理論分布生成測試用例。測試用例的生成規(guī)則:(1) 符號(hào)位[13],根據(jù)定義域區(qū)間,判斷測試用例的正負(fù)屬性;(2) 指數(shù)位,覆蓋輸入?yún)^(qū)間內(nèi)所有浮點(diǎn)數(shù)的指數(shù);(3) 尾數(shù)位,針對每一個(gè)指數(shù)值,產(chǎn)生N個(gè)均勻分布的隨機(jī)數(shù)(相對于浮點(diǎn)數(shù)分布的基本特征均勻)。上述3部分構(gòu)成完整的測試用例,保證了測試用例的完整性和有效性,為下一步檢測做好了充分的數(shù)據(jù)準(zhǔn)備。
代碼覆蓋率是一種度量,它描述了對程序源代碼的測試程度[14]。這是白盒測試的一種手段,它可以發(fā)現(xiàn)測試用例無法覆蓋到的程序。測試人員可以創(chuàng)建代碼覆蓋缺失的測試用例,以提高覆蓋率并確定代碼覆蓋率的定量度量。在大多數(shù)情況下,代碼覆蓋系統(tǒng)會(huì)收集有關(guān)正在運(yùn)行程序的信息。它還將其與源代碼信息相結(jié)合,以生成有關(guān)測試套件的代碼覆蓋率報(bào)告。代碼覆蓋率可以幫助評估測試的效率,提供定量測量手段,可以了解對代碼的測試程度。
統(tǒng)計(jì)代碼覆蓋率可以明確測試過程中軟件的運(yùn)行情況,從而對測試結(jié)果進(jìn)行評估。在本文中使用代碼覆蓋率的目的是為了在檢測過程中,通過查看代碼覆蓋率來檢驗(yàn)對各個(gè)函數(shù)檢測的全面性,避免漏報(bào)。可以根據(jù)代碼覆蓋率相應(yīng)調(diào)整測試用例,以達(dá)到對浮點(diǎn)數(shù)學(xué)函數(shù)全面檢測的目的。
本文在AFL(American Fuzzy Lop)的基礎(chǔ)上對代碼覆蓋率部分進(jìn)行移植修改,使其能夠在申威平臺(tái)上正常使用。統(tǒng)計(jì)代碼覆蓋率的主要流程如圖2所示。左上圖表示插樁前的一個(gè)函數(shù),b0 (block 0)表示一個(gè)基本塊,即程序順序執(zhí)行的語句序列。在每個(gè)基本塊的開始插入代碼覆蓋率計(jì)算指令。計(jì)算指令的內(nèi)容為表示一個(gè)塊的隨機(jī)數(shù)和命中處理函數(shù)。當(dāng)運(yùn)行測試程序時(shí),把隨機(jī)數(shù)運(yùn)算的結(jié)果作為地址,該地址指向的內(nèi)容加一完成記錄。用隨機(jī)數(shù)R0表示基本塊b0的標(biāo)識(shí),用*((R0?1)^R1)++表示從基本塊b0跳轉(zhuǎn)到基本塊b1執(zhí)行了一次。詳細(xì)解釋如圖2所示。
Figure 2 Code coverage process圖2 代碼覆蓋率流程
本文將實(shí)現(xiàn)的浮點(diǎn)異常檢測方法應(yīng)用于申威高性能數(shù)學(xué)函數(shù)庫中的浮點(diǎn)數(shù)學(xué)函數(shù)。函數(shù)庫由基礎(chǔ)函數(shù)庫及SIMD擴(kuò)展數(shù)學(xué)庫組成,本文主要研究基礎(chǔ)數(shù)學(xué)庫,基礎(chǔ)數(shù)學(xué)庫的函數(shù)分類主要包括三角函數(shù)、反三角函數(shù)、指數(shù)對數(shù)函數(shù)、貝塞爾函數(shù)及其他函數(shù)等初等函數(shù)。在下面的檢測中,對部分函數(shù)的檢測結(jié)果進(jìn)行了分析,包括sin、cos、logf等函數(shù)。
根據(jù)申威1621處理器對浮點(diǎn)運(yùn)算的定義及對浮點(diǎn)控制寄存器FPCR的設(shè)置,當(dāng)輸入操作數(shù)沒有產(chǎn)生異常時(shí),對正常浮點(diǎn)運(yùn)算的中間結(jié)果,先進(jìn)行舍入,后根據(jù)不同的舍入方式來判斷異常。結(jié)果產(chǎn)生異常時(shí),會(huì)在FPCR中記錄相應(yīng)異常標(biāo)志位。以此對該基礎(chǔ)數(shù)學(xué)函數(shù)庫進(jìn)行檢測。在用于檢測的測試用例生成后,開始對程序進(jìn)行大規(guī)模檢測。
首先,在相應(yīng)的浮點(diǎn)域內(nèi),生成均勻分布的浮點(diǎn)數(shù)數(shù)據(jù)。該均勻分布的數(shù)據(jù)集基于浮點(diǎn)數(shù)分布的基本特征[15],符合IEEE-754浮點(diǎn)數(shù)的理論分布:數(shù)字越接近零,數(shù)據(jù)分布越密集;數(shù)字離零越遠(yuǎn),數(shù)據(jù)分布越稀疏。其次,在完成對上一步生成的數(shù)據(jù)測試后,在測試結(jié)果文件內(nèi),查看函數(shù)在哪些數(shù)據(jù)或哪些位置產(chǎn)生異常的頻率較高,分析出異常熱點(diǎn)數(shù)據(jù)。以此熱點(diǎn)數(shù)據(jù)為數(shù)據(jù)中心,在該數(shù)據(jù)周圍生成大量數(shù)據(jù)集用于進(jìn)一步測試。最后,在某一數(shù)據(jù)周圍生成了測試集后,對函數(shù)進(jìn)行有針對性的大規(guī)模測試,得出最終結(jié)果。測試用例的完整性和有效性對測試的代碼覆蓋率有一定影響。檢測具體流程如圖3所示。
Figure 3 Test flow chart圖3 檢測流程圖
(1) 按照上述檢測流程,如表1所示為部分函數(shù)檢測過程中產(chǎn)生異常的參數(shù)及其異常類型。代碼覆蓋率的結(jié)果為數(shù)據(jù)集在測試過程中記錄函數(shù)中的代碼被測試到的比例。代碼覆蓋率越高,測試結(jié)果的可信度越高。對代碼覆蓋率的統(tǒng)計(jì)結(jié)果顯示,本文生成的測試集可以檢測到函數(shù)的所有代碼分支。開發(fā)人員可以根據(jù)該結(jié)果對函數(shù)進(jìn)行進(jìn)一步處理。
Table 1 Test results
(2) 152個(gè)函數(shù)中各異常(上溢、下溢、被零除和無效操作)出現(xiàn)的函數(shù)個(gè)數(shù),統(tǒng)計(jì)結(jié)果如表2所示。在檢測時(shí),發(fā)現(xiàn)輸入特殊數(shù)NaN并沒有觸發(fā)無效操作異常,即函數(shù)未對特殊數(shù)NaN進(jìn)行處理。在此檢測結(jié)果基礎(chǔ)上,對NaN進(jìn)行了特殊數(shù)的處理,處理主要依據(jù)NaN是唯一一個(gè)與自身不相等的存在。檢測到異常進(jìn)行報(bào)告是必須的,收到報(bào)告進(jìn)行處理可以最大程度降低發(fā)生意外的可能。
Table 2 Exception functions
(3) 加入插樁檢測后的性能變化。
圖4對部分有上溢異常的函數(shù)插樁檢測前后的性能進(jìn)行了對比,節(jié)拍數(shù)的變化如圖4所示。性能測試結(jié)果顯示:經(jīng)過插樁檢測后,函數(shù)的平均性能降低了38.43%((插樁后節(jié)拍數(shù)-插樁前節(jié)拍數(shù))/插樁前節(jié)拍數(shù));插樁后的運(yùn)行速度雖然有下降,但對于大多數(shù)函數(shù)而言,進(jìn)行插樁異常檢測帶來了幾拍到幾十拍的性能消耗,在可接受的范圍內(nèi)。
Figure 4 Performance comparison before and after pile insertion testing圖4 插樁檢測前后的性能對比
需要特別說明的是,檢測出的異常是否會(huì)對系統(tǒng)造成重大不良影響,需要開發(fā)人員對檢測出的異常進(jìn)行進(jìn)一步的分析。浮點(diǎn)數(shù)的表示精度有限,不能精確表示出實(shí)數(shù),部分異常是由可表示精度有限導(dǎo)致的。因此,開發(fā)人員可以通過分析檢測出異常信息,對異常進(jìn)行進(jìn)一步的判斷。
上述測試結(jié)果表明,該浮點(diǎn)異常檢測方法科學(xué)有效,插樁后的函數(shù)具有檢測浮點(diǎn)異常的功能。既滿足了對浮點(diǎn)數(shù)學(xué)函數(shù)異常的檢測,也滿足了對函數(shù)性能干擾盡量小的要求。實(shí)驗(yàn)數(shù)據(jù)表明,上溢出和下溢出異常在所有發(fā)生的異常中占有較大的比例,對特殊數(shù)的檢測中無效操作異常發(fā)生較多,被零除異常發(fā)生較少。當(dāng)面臨大量復(fù)雜程序時(shí),檢測的計(jì)算量變大,將會(huì)導(dǎo)致性能下降較多,這點(diǎn)后續(xù)需繼續(xù)優(yōu)化。本文提出了浮點(diǎn)異常分類檢測方法,以盡可能全面地在測試階段發(fā)現(xiàn)異常。
本文實(shí)現(xiàn)了一種檢測浮點(diǎn)數(shù)學(xué)函數(shù)異常并統(tǒng)計(jì)測試的代碼覆蓋率的方法。通過測試,該方法能夠有效地檢測出函數(shù)中出現(xiàn)的異常,同時(shí)對浮點(diǎn)數(shù)學(xué)函數(shù)的性能影響較小。本文提出的檢測浮點(diǎn)異常的編譯時(shí)插樁及異常分類方法也可以用于其他平臺(tái)檢測其他內(nèi)容,具有一定的通用性。