• <tr id="yyy80"></tr>
  • <sup id="yyy80"></sup>
  • <tfoot id="yyy80"><noscript id="yyy80"></noscript></tfoot>
  • 99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

    提高VC 6.0中函數(shù)執(zhí)行時(shí)間測試可信度的研究

    2019-07-17 06:45:12張合花張全法
    中州大學(xué)學(xué)報(bào) 2019年3期
    關(guān)鍵詞:運(yùn)算符測試工具調(diào)用

    張合花,張全法,馬 冰

    (鄭州大學(xué) 物理工程學(xué)院,河南 鄭州 450001)

    C/C++程序可以獲得很高的運(yùn)行速度,而許多情況下對程序的運(yùn)行速度有著很高的要求,特別是需要實(shí)時(shí)處理大量信息的時(shí)候。但是C/C++程序?qū)懗龊笸€需要進(jìn)行優(yōu)化來提高速度。常用的優(yōu)化技巧包括:盡量采用自增、自減運(yùn)算和賦值縮寫,利用指針法訪問數(shù)組,合理使用內(nèi)聯(lián)函數(shù)和寄存器變量,采用位運(yùn)算代替一些乘法或除法運(yùn)算,盡可能將浮點(diǎn)數(shù)運(yùn)算轉(zhuǎn)化為整數(shù)運(yùn)算,正確運(yùn)用內(nèi)存拷貝函數(shù),等等[1-4]。

    對程序優(yōu)化后通常需要測試運(yùn)行速度,以便確認(rèn)取得了優(yōu)化效果并了解優(yōu)化程度。文獻(xiàn)[5]通過編程測試程序運(yùn)行時(shí)間,這非常麻煩,并且僅適用于它小于一個(gè)時(shí)間片。實(shí)際上,VC 6.0作為許多高校教學(xué)平臺(tái)程序員慣用的開發(fā)工具,其內(nèi)部集成了一個(gè)使用非常方便的測試工具,可以用來測試程序中各個(gè)函數(shù)的執(zhí)行時(shí)間,已經(jīng)在不少方面獲得了應(yīng)用[3-4]。然而實(shí)驗(yàn)證明,在某些情況下該工具所給的測試數(shù)據(jù)非常不可靠。為此,提出了獲得具有更高可信度之函數(shù)執(zhí)行時(shí)間的方法。

    1 實(shí)驗(yàn)用程序及集成測試工具使用方法

    1.1 實(shí)驗(yàn)用程序

    利用VC 6.0新建Win32 Console Application類型的空白項(xiàng)目,然后添加頭文件MyClass.h,內(nèi)容如下(為節(jié)省篇幅,對代碼做了盡可能的簡化,并利用先注釋掉部分代碼再逐步修改的方法,將本研究所用的多個(gè)程序揉和在了一起,下同):

    externint x;

    classA{public:

    //A(){a = x++;}

    //標(biāo)記①

    //~A(){a = 0;}

    //標(biāo)記②

    //A();

    //標(biāo)記③

    //~A();

    //標(biāo)記④

    int a;};

    class B{int b;};

    接著添加源文件MyClass.cpp,內(nèi)容如下:

    #include "MyClass.h"

    //A::A(){a = x++;}

    //標(biāo)記⑤

    //A::~A(){a = 0;}

    //標(biāo)記⑥

    最后添加源文件main.cpp,內(nèi)容如下:

    #include

    #include "MyClass.h"

    using namespace std;

    int x = 1;

    voidfunc(){A *p = new A[100];delete[]p;}

    void consume(){B *p = new B[100];delete[]p;}

    void main(){

    for(int i = 0; i < 10000; i++){

    //標(biāo)記⑦

    //consume();

    //標(biāo)記⑧

    func();}}

    //標(biāo)記⑨

    程序中,func()函數(shù)先利用矢量形式的new運(yùn)算符動(dòng)態(tài)創(chuàng)建變量數(shù)組,再利用矢量形式的delete運(yùn)算符動(dòng)態(tài)釋放內(nèi)存,為主要測試對象。consume()函數(shù)的功能與它相同,不過創(chuàng)建對象時(shí)所用類型不同,其作用后面說明。

    1.2 集成測試工具使用方法

    利用VC 6.0提供的工具測試函數(shù)執(zhí)行時(shí)間的完整步驟是:①單擊Build彈出菜單上的Set Active Configuration菜單項(xiàng),設(shè)置程序的當(dāng)前編譯、運(yùn)行版本為Debug或Release版。②同時(shí)按下Alt和F7鍵,在彈出的對話框的Link選項(xiàng)卡上,選中Enable Profiling復(fù)選框。③單擊Build彈出菜單上的Rebuild All菜單項(xiàng),編譯、鏈接程序。④單擊Build彈出菜單上的Profile菜單項(xiàng),在彈出的對話框上確保單選按鈕Function timing處于選中狀態(tài),再點(diǎn)擊OK按鈕啟動(dòng)測試。程序退出后在Output面板上的輸出窗口即可看到各函數(shù)的執(zhí)行時(shí)間,此后步驟可以簡化,不必每次都完整進(jìn)行。

    輸出結(jié)果中,F(xiàn)unc Time稱為函數(shù)的部分總執(zhí)行時(shí)間,它是多次調(diào)用所需時(shí)間的總和,但是不包括在其內(nèi)部調(diào)用其他函數(shù)所需時(shí)間。Func+Child Time稱為總執(zhí)行時(shí)間,它是多次調(diào)用所需時(shí)間的總和,且包括在其內(nèi)部調(diào)用其他函數(shù)所需時(shí)間,將其除以調(diào)用次數(shù)即為前面所說的函數(shù)執(zhí)行時(shí)間。Hit Count為函數(shù)調(diào)用次數(shù),F(xiàn)unction為對應(yīng)的函數(shù)。

    2 問題的發(fā)現(xiàn)

    2.1 發(fā)現(xiàn)問題所用程序

    上述程序稱為設(shè)計(jì)1。在其基礎(chǔ)上:將標(biāo)記①所在行前面的注釋符號刪除后的程序稱為設(shè)計(jì)2;將標(biāo)記②所在行前面的注釋符號刪除后的程序稱為設(shè)計(jì)3;將這兩行前面的注釋符號同時(shí)刪除后的程序稱為設(shè)計(jì)4。

    按照C++編程思想,new運(yùn)算符內(nèi)部首先調(diào)用malloc()函數(shù)動(dòng)態(tài)分配內(nèi)存,再調(diào)用自定義類型的構(gòu)造函數(shù)初始化對象;delete運(yùn)算符內(nèi)部首先調(diào)用自定義類型的析構(gòu)函數(shù)清除對象,再調(diào)用free()函數(shù)動(dòng)態(tài)釋放內(nèi)存[6]。因此,可用來比較沒有自定義構(gòu)造函數(shù)和析構(gòu)函數(shù)、僅有前者、僅有后者、二者皆有等情況下func()函數(shù)執(zhí)行時(shí)間的差異。

    2.2 實(shí)驗(yàn)條件與測試結(jié)果

    實(shí)驗(yàn)所用計(jì)算機(jī)型號為Lenovo G50-70m,操作系統(tǒng)為Win10,其CPU為Intel Core i3-4030U,主頻為1.90 GHz,下同。分別在Debug和Release版下對func()函數(shù)的總執(zhí)行時(shí)間測試10次。對于Release版,優(yōu)化策略為最大速度,下同。

    由于操作系統(tǒng)的多任務(wù)特性,每次運(yùn)行程序同一函數(shù)的執(zhí)行時(shí)間存在明顯差異。為此采取的措施有:利用for循環(huán)增加函數(shù)總執(zhí)行時(shí)間的有效位數(shù)并減小波動(dòng)幅度,若某次測試結(jié)果偏離平均值太多則舍棄重測,對總執(zhí)行時(shí)間測試多次求平均值,等等。得到測試數(shù)據(jù)后計(jì)算平均總執(zhí)行時(shí)間及標(biāo)準(zhǔn)偏差,結(jié)果如表1所示。VC 6.0給的時(shí)間以ms為單位,小數(shù)點(diǎn)后面有3位數(shù)字??紤]到數(shù)據(jù)的波動(dòng)性,僅給出了2~3位數(shù)字,下同。

    表1 設(shè)計(jì)1~4中func()函數(shù)的總執(zhí)行時(shí)間 ms

    2.3 測試結(jié)果分析

    設(shè)計(jì)2~4的平均總執(zhí)行時(shí)間均比設(shè)計(jì)1的對應(yīng)值大許多。這是因?yàn)闆]有自定義構(gòu)造函數(shù)和析構(gòu)函數(shù)時(shí),new運(yùn)算符會(huì)調(diào)用默認(rèn)構(gòu)造函數(shù),delete運(yùn)算符會(huì)調(diào)用默認(rèn)析構(gòu)函數(shù),而默認(rèn)構(gòu)造函數(shù)和析構(gòu)函數(shù)皆為空函數(shù),執(zhí)行速度一定比自定義構(gòu)造函數(shù)和析構(gòu)函數(shù)快許多。Release版的平均總執(zhí)行時(shí)間小于Debug版的對應(yīng)值。這是因?yàn)镈ebug版需要嵌入調(diào)試信息而Release版不需要。

    Debug版下設(shè)計(jì)2和3的平均總執(zhí)行時(shí)間大約相等。這是因?yàn)樽远x構(gòu)造函數(shù)和析構(gòu)函數(shù)差別很小,二者的執(zhí)行時(shí)間差別應(yīng)該不大,而默認(rèn)構(gòu)造函數(shù)和析構(gòu)函數(shù)的執(zhí)行時(shí)間差別也應(yīng)該不大。Debug版下設(shè)計(jì)4的平均總執(zhí)行時(shí)間大約為設(shè)計(jì)2與3平均總執(zhí)行時(shí)間之和再減去設(shè)計(jì)1的平均總執(zhí)行時(shí)間。根據(jù)上述分析,正應(yīng)該如此。問題是,Release版下設(shè)計(jì)3的平均總執(zhí)行時(shí)間大約為設(shè)計(jì)2的20倍,設(shè)計(jì)4的平均總執(zhí)行時(shí)間大約為設(shè)計(jì)3的2倍,這不符合預(yù)期。而Release版下函數(shù)的執(zhí)行時(shí)間通常是最應(yīng)該關(guān)心的。

    3 假設(shè)與驗(yàn)證

    3.1 引起問題之原因的假設(shè)

    經(jīng)過仔細(xì)觀察發(fā)現(xiàn),Release版下對于設(shè)計(jì)2進(jìn)行測試時(shí),在VC 6.0給的結(jié)果中找不到執(zhí)行自定義構(gòu)造函數(shù)的總執(zhí)行時(shí)間,對于設(shè)計(jì)3有自定義析構(gòu)函數(shù)的總執(zhí)行時(shí)間,對于設(shè)計(jì)4二者皆有。然而很容易證明,對于設(shè)計(jì)2程序運(yùn)行時(shí)確實(shí)調(diào)用了自定義構(gòu)造函數(shù)。于是可以假設(shè):對于使用了矢量形式之new和delete運(yùn)算符的函數(shù),測試其Release版執(zhí)行時(shí)間時(shí),測試工具在僅有自定義構(gòu)造函數(shù)情況下未統(tǒng)計(jì)自定義構(gòu)造函數(shù)的執(zhí)行時(shí)間。

    3.2 假設(shè)的具體化

    為了使假設(shè)更具體,在設(shè)計(jì)1的基礎(chǔ)上,將標(biāo)記③和⑤所在行前面的注釋符號同時(shí)刪除后的程序稱為設(shè)計(jì)5;將標(biāo)記④和⑥所在行前面的注釋符號同時(shí)刪除后的程序稱為設(shè)計(jì)6;將這四行前面的注釋符號同時(shí)刪除后的程序稱為設(shè)計(jì)7。設(shè)計(jì)5~7與設(shè)計(jì)2~4的區(qū)別在于,自定義構(gòu)造函數(shù)和(或)析構(gòu)函數(shù)皆由內(nèi)聯(lián)成員函數(shù)變成了非內(nèi)聯(lián)成員函數(shù)。按照同樣的方法對設(shè)計(jì)1和設(shè)計(jì)5~7中func()函數(shù)的總執(zhí)行時(shí)間進(jìn)行測試和計(jì)算,結(jié)果如表2所示。

    表2 設(shè)計(jì)1和5~7中func()函數(shù)的總執(zhí)行時(shí)間 ms

    此時(shí)Release版下設(shè)計(jì)5和6的平均總執(zhí)行時(shí)間大約相等,設(shè)計(jì)7的平均總執(zhí)行時(shí)間也大約為設(shè)計(jì)5與6平均總執(zhí)行時(shí)間之和再減去設(shè)計(jì)1的平均總執(zhí)行時(shí)間。因此,將前述假設(shè)具體化為:對于使用了矢量形式之new和delete運(yùn)算符的函數(shù),測試其Release版執(zhí)行時(shí)間時(shí),測試工具在僅有內(nèi)聯(lián)自定義構(gòu)造函數(shù)情況下,未統(tǒng)計(jì)自定義構(gòu)造函數(shù)的執(zhí)行時(shí)間。若果真如此,將設(shè)計(jì)2中func()函數(shù)在Release版下的總執(zhí)行時(shí)間近似取為168 ms,將比由測試工具所給數(shù)據(jù)得到的8.0 ms具有更高的可信度。

    3.3 實(shí)驗(yàn)對假設(shè)的支持

    假設(shè)的正確性必須通過人工測試來驗(yàn)證。人工測試時(shí)必須設(shè)法讓函數(shù)的總執(zhí)行時(shí)間足夠長,從而使得人工測試誤差小到可以容許的程度。為此,將設(shè)計(jì)1中標(biāo)記⑦所在行的10 000改為10 000 000,此時(shí)的程序稱為設(shè)計(jì)Ⅰ。在設(shè)計(jì)Ⅰ的基礎(chǔ)上進(jìn)行上述修改,由設(shè)計(jì)2得到設(shè)計(jì)Ⅱ,以此類推,直到得到設(shè)計(jì)Ⅶ。另外注意,人工只能直接測試整個(gè)程序即main()函數(shù)的總執(zhí)行時(shí)間。

    為了進(jìn)行比較,先利用測試工具按照上述方法測試main()函數(shù)的總執(zhí)行時(shí)間。不同的是僅測試1次且不再計(jì)算平均值及標(biāo)準(zhǔn)偏差。這是因?yàn)榇藭r(shí)完成一次測試所需的時(shí)間很長,例如對于設(shè)計(jì)Ⅶ測試一次耗時(shí)長達(dá)十幾分鐘,主要影響因素是測試工具本身需要時(shí)間。測試結(jié)果如表3所示。

    表3 設(shè)計(jì)Ⅰ~Ⅶ中main()函數(shù)的總執(zhí)行時(shí)間 s

    再利用一款蘋果手機(jī)上的秒表功能進(jìn)行人工測試,對于每個(gè)設(shè)計(jì)測試10次,然后計(jì)算平均值及標(biāo)準(zhǔn)偏差,結(jié)果在表3中同時(shí)給出。為方便操作,利用工具欄的快捷按鈕啟動(dòng)程序的同時(shí)讓秒表開始計(jì)時(shí),出現(xiàn)Press any key to continue后停止計(jì)時(shí)。另外發(fā)現(xiàn),每當(dāng)程序修改后啟動(dòng)運(yùn)行時(shí),前幾次往往明顯偏慢,需要跳過。

    由于main()函數(shù)的部分執(zhí)行時(shí)間很短(參見后面實(shí)驗(yàn)結(jié)果),即使將其總執(zhí)行時(shí)間視為func()函數(shù)的總執(zhí)行時(shí)間誤差也不是很大。根據(jù)表3中的數(shù)據(jù)可知:采用測試工具時(shí)調(diào)用次數(shù)變?yōu)橐郧暗?000倍,相應(yīng)的總執(zhí)行時(shí)間也大約為以前的1000倍,這符合預(yù)期,不算很大的偏差主要是數(shù)據(jù)波動(dòng)性的影響,main()函數(shù)部分執(zhí)行時(shí)間的影響并不大;人工測試時(shí),對于Release版,無論是內(nèi)聯(lián)的還是非內(nèi)聯(lián)的,自定義構(gòu)造函數(shù)對執(zhí)行時(shí)間的貢獻(xiàn)與自定義析構(gòu)函數(shù)相差不多。這是對所作假設(shè)的支持。

    3.4 測試工具的可信度問題

    對實(shí)驗(yàn)數(shù)據(jù)的進(jìn)一步分析發(fā)現(xiàn),即使所作假設(shè)成立,測試工具所給數(shù)據(jù)的可信度也值得懷疑。根據(jù)測試工具所給數(shù)據(jù):設(shè)計(jì)Ⅰ~Ⅶ中main()函數(shù)總執(zhí)行時(shí)間之比與設(shè)計(jì)1~7中func()函數(shù)總執(zhí)行時(shí)間之比基本一樣,在Debug和Release版下分別約為1252550252550,124080404080;如果認(rèn)為所作假設(shè)成立,Release版下的比值大約為1404080404080;對于相同設(shè)計(jì),Debug版的總執(zhí)行時(shí)間不超過Release版的2倍。

    然而根據(jù)人工測試數(shù)據(jù):設(shè)計(jì)Ⅰ~Ⅶ中main()函數(shù)總執(zhí)行時(shí)間之比在Debug和Release版下卻大約皆為155105510;對于相同設(shè)計(jì),Debug版的總執(zhí)行時(shí)間大約為Release版的5倍。將數(shù)據(jù)的波動(dòng)性、main()函數(shù)的部分執(zhí)行時(shí)間、測試工具運(yùn)行所需的時(shí)間以及人工測試時(shí)的反應(yīng)速度等因素之影響加在一起,都不足以造成與測試工具所給數(shù)據(jù)之間如此大的差別。雖然這不否定所作假設(shè),但它確實(shí)可能是VC 6.0提供的測試工具內(nèi)部的又一個(gè)Bug,使得它在特定條件下給的結(jié)果不可信,必須進(jìn)行人工測試才能夠得到可信的結(jié)果。

    4 獲取高可信度的測試數(shù)據(jù)

    4.1 獲取任意函數(shù)執(zhí)行時(shí)間的方法

    人工獲取任意函數(shù)執(zhí)行時(shí)間的方法只能是間接的:程序整體完成后,測試main()函數(shù)的總執(zhí)行時(shí)間T1(亦即它的執(zhí)行時(shí)間,因沒有通過循環(huán)多次調(diào)用它);然后將對被測試函數(shù)的調(diào)用注釋掉,再次測試main()函數(shù)(其中可能包含對其他函數(shù)的必要調(diào)用)的總執(zhí)行時(shí)間T2;于是,被測試函數(shù)的總執(zhí)行時(shí)間T=T1-T2,執(zhí)行時(shí)間等于T除以調(diào)用次數(shù)。若T1比較小,減小其測試誤差的方法如前所述。若T2比較小則可以通過調(diào)用“耗時(shí)函數(shù)”來減小其測試誤差。這種耗時(shí)函數(shù)本身沒有意義,但是總執(zhí)行時(shí)間比較長,而且在測試T1和T2時(shí)不變。

    4.2 實(shí)驗(yàn)結(jié)果

    在設(shè)計(jì)Ⅰ的基礎(chǔ)上,將標(biāo)記⑧所在行前面的注釋符號刪除以添加對耗時(shí)函數(shù)consume()的調(diào)用,此時(shí)的程序稱為設(shè)計(jì)ⅰ。在設(shè)計(jì)ⅰ的基礎(chǔ)上進(jìn)行上述修改,由設(shè)計(jì)2得到設(shè)計(jì)ⅱ,以此類推,直到得到設(shè)計(jì)ⅶ,再將標(biāo)記⑨所在行對func()函數(shù)的調(diào)用(注意不包括后面的兩個(gè)右花括號)注釋掉,此時(shí)的程序稱為設(shè)計(jì)ⅷ。然后按照上述方法人工測試并計(jì)算平均值及標(biāo)準(zhǔn)偏差,結(jié)果如表4所示。

    表4 設(shè)計(jì)ⅰ~ⅷ中main()函數(shù)的總執(zhí)行時(shí)間 s

    將表4中設(shè)計(jì)ⅰ~ⅶ的T1減去設(shè)計(jì)ⅷ的T2,得到設(shè)計(jì)ⅰ~ⅶ中func()函數(shù)的總執(zhí)行時(shí)間Tⅰ~Tⅶ,如表5所示。

    表5 設(shè)計(jì)ⅰ~ⅶ中func()函數(shù)的總執(zhí)行時(shí)間 s

    將表5中的結(jié)果與表3中的人工測試結(jié)果進(jìn)行比較可知,main()函數(shù)的部分執(zhí)行時(shí)間很短,如果不添加對耗時(shí)函數(shù)的調(diào)用,人工直接測試將非常困難。但它的影響還是有的,將其影響剔除后可以提高測試結(jié)果的可信度。

    4.3 關(guān)于操作系統(tǒng)多任務(wù)特性的影響

    若按照本文提出的方法測試函數(shù)的執(zhí)行時(shí)間,其中將包含程序運(yùn)行過程中被其他任務(wù)中斷所消耗的時(shí)間。文獻(xiàn)[7]認(rèn)為不應(yīng)該包含它,但是本文認(rèn)為恰好應(yīng)該包含它,因?yàn)樵谶@樣的操作系統(tǒng)中被中斷是不可避免的,只有包含它才能反映實(shí)際情況。

    5 結(jié)語

    本文通過實(shí)驗(yàn)證明了VC 6.0提供的函數(shù)執(zhí)行時(shí)間測試工具對于使用了矢量形式之new和delete運(yùn)算符的函數(shù)存在問題:在Release版下當(dāng)僅有內(nèi)聯(lián)自定義構(gòu)造函數(shù)時(shí),沒有統(tǒng)計(jì)自定義構(gòu)造函數(shù)的執(zhí)行時(shí)間;無論Debug版還是Release版,其所給數(shù)據(jù)的可信度都太低。此時(shí),通過人工測試調(diào)用和不調(diào)用被測試函數(shù)時(shí)main()函數(shù)的總執(zhí)行時(shí)間,再取二者之差,并采取適當(dāng)?shù)拇胧┤缍啻窝h(huán)調(diào)用、添加調(diào)用耗時(shí)函數(shù)等減小測試誤差,可以得到較高可信度的測試數(shù)據(jù)。或許還有更多的類似情況尚未發(fā)現(xiàn),相信皆可以利用這種方法解決。

    猜你喜歡
    運(yùn)算符測試工具調(diào)用
    邊緣智力兒童及其智力測試工具的研究進(jìn)展
    老祖?zhèn)魇诨具\(yùn)算符
    核電項(xiàng)目物項(xiàng)調(diào)用管理的應(yīng)用研究
    LabWindows/CVI下基于ActiveX技術(shù)的Excel調(diào)用
    Http并發(fā)連接測試工具
    基于系統(tǒng)調(diào)用的惡意軟件檢測技術(shù)研究
    福祿克推出先進(jìn)的連接式測試工具系統(tǒng)
    C++運(yùn)算符重載剖析
    利用RFC技術(shù)實(shí)現(xiàn)SAP系統(tǒng)接口通信
    表達(dá)式求值及符號推導(dǎo)
    龙里县| 桐庐县| 于田县| 东宁县| 白玉县| 民勤县| 酉阳| 民权县| 塔城市| 霍城县| 开远市| 梧州市| 海兴县| 武穴市| 新干县| 如皋市| 东山县| 元氏县| 汉中市| 左贡县| 龙泉市| 江城| 辉南县| 正蓝旗| 胶州市| 乌拉特后旗| 阿坝县| 开封县| 九龙坡区| 内黄县| 宣武区| 丰城市| 济源市| 洪洞县| 建昌县| 西贡区| 大港区| 林西县| 五原县| 寿光市| 福泉市|