生活随笔
收集整理的這篇文章主要介紹了
会员教程翻译:性能和时间
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
來(lái)自會(huì)員德魯伊: 在討論性能之前,先討論一個(gè)重要的話題:時(shí)間。為了理解代碼中的變化如何影響性能,我們需要一個(gè)排序的指標(biāo)。有許多方法用于時(shí)間例程,一些比另一些合適。在本教程
“” 來(lái)自會(huì)員德魯伊:
在討論性能之前,先討論一個(gè)重要的話題:時(shí)間。為了理解代碼中的變化如何影響性能,我們需要一個(gè)排序的指標(biāo)。有許多方法用于時(shí)間例程,一些比另一些合適。在本教程中我們將討論Mach Absolute Time。
為什么是Mach? 時(shí)間例程依賴于所需要測(cè)量的時(shí)間域。某些情況下使用諸如clock()或getrusage()函數(shù)來(lái)做些簡(jiǎn)單的數(shù)學(xué)運(yùn)算就足夠了。如果時(shí)間例程將用于實(shí)際的開(kāi)發(fā)框架之外,可移植性就很重要了。我不使用這些。為什么? 對(duì)于我來(lái)說(shuō),調(diào)試代碼的典型問(wèn)題是: 1) 我只需要在即時(shí)測(cè)試時(shí)使用時(shí)間例程 2) 我不喜歡依賴于多種函數(shù)來(lái)包含不同的時(shí)間域。它們的行為可能不一致 3) 有時(shí)我需要一個(gè)高精度定時(shí)器
歡迎了解mach_absolute_time mach_absolute_time是一個(gè)CPU/總線依賴函數(shù),返回一個(gè)基于系統(tǒng)啟動(dòng)后的時(shí)鐘”嘀嗒”數(shù)。它沒(méi)有很好的文檔定義,但這不應(yīng)該成為使用它的障礙,因?yàn)樵贛AC OS X上可以確保它的行為,并且,它包含系統(tǒng)時(shí)鐘包含的所有時(shí)間區(qū)域。那是否應(yīng)該在產(chǎn)品代碼中使用它呢?可能不應(yīng)該。但是對(duì)于測(cè)試,它卻恰到好處。 使用mach_absolute_time時(shí)需要考慮兩個(gè)因素: 1) 如何獲取當(dāng)前的Mach絕對(duì)時(shí)間 2) 如何將其轉(zhuǎn)換為有意義的數(shù)字
獲取mach_absolute_time 這非常簡(jiǎn)單
#include?<stdint.h>??uint64_t?start?=mach_absolute_time();?uint64_t?stop?=mach_absolute_time();?? 這樣就可以了。我們通常獲取兩個(gè)值,以得到這兩個(gè)時(shí)間的時(shí)間差。
將mach_absolute_time時(shí)間差轉(zhuǎn)換為秒數(shù) 這稍微有點(diǎn)復(fù)雜,因?yàn)槲覀冃枰@取mach_absolute_time所基于的系統(tǒng)時(shí)間基準(zhǔn)。如下代碼:
#include?<stdint.h>?#include<mach/mach_time.h>???double?subtractTimes(?uint64_tendTime,?uint64_t?startTime?)?{?uint64_t?difference?=?endTime?-?startTime;?static?double?conversion?=?0.0;?if(?conversion?==?0.0?)?{?mach_timebase_info_data_t?info;?kern_return_t?err?=mach_timebase_info(?&info?);??if(?err?==?0??)?conversion=?1e-9?*?(double)?info.numer?/?(double)?info.denom;?}?return?conversion?*?(double)difference;?}?? 這里最重要的是調(diào)用mach_timebase_info。我們傳遞一個(gè)結(jié)構(gòu)體以返回時(shí)間基準(zhǔn)值。最后,一旦我們獲取到系統(tǒng)的心跳,我們便能生成一個(gè)轉(zhuǎn)換因子。通常,轉(zhuǎn)換是通過(guò)分子(info.numer)除以分母(info.denom)。這里我乘了一個(gè)1e-9來(lái)獲取秒數(shù)。最后,我們獲取兩個(gè)時(shí)間的差值,并乘以轉(zhuǎn)換因子,便得到真實(shí)的時(shí)間差。 現(xiàn)在我們可能會(huì)想,為什么這比用clock好?看起來(lái)做了更多的事情。確實(shí)是有點(diǎn),這便是為什么它在一個(gè)函數(shù)中。我們只需要傳遞我們的值到函數(shù)中并取得答案。
例子 讓我們寫(xiě)個(gè)例子。下面是完整的代碼清單(包括mach函數(shù))。可以使用gcc mach.c –o mach來(lái)編譯它:
#include?<stdio.h>?#include?<stdlib.h>?#include?<stdint.h>?#include?<math.h>?#include<mach/mach_time.h>???double?subtractTimes(?uint64_tendTime,?uint64_t?startTime?)?{?uint64_t?difference?=?endTime?-startTime;?static?double?conversion?=?0.0;?if(?conversion?==?0.0?)?{?????????mach_timebase_info_data_tinfo;?????????kern_return_terr?=?mach_timebase_info(?&info?);????????????????????????if(err?==?0??)????????????????????????conversion=?1e-9?*?(double)?info.numer?/?(double)?info.denom;?????}??????????return?conversion?*?(double)difference;?}??int?main()?{?inti,?j,?count;?uint64_t?start,stop;?doublecurrent?=?0.0;?doubleanswer?=?0.0;?doubleelapsed?=?0.0;?intdim1?=?256;?intdim2?=?256;?intsize?=?4*dim1*dim2;??double?*array?=(double*)malloc(size*sizeof(double));????????for(i=0;i<size;i++)array?=?(double)i;?count=?5;??????for(i=0;i<count;i++)?{???????????????start?=?mach_absolute_time();???????????????????????????????????for(j=0;j<size;j++){?answer+=?sqrt(array[j]);?}?stop?=mach_absolute_time();?current=?subtractTimes(stop,start);?printf("Timefor?iteration:?%1.12lf?for?answer:?%1.12lf\n",current,?answer);?elapsed+=?current;?}????????printf("\nTotaltime?in?seconds?=?%1.12lf?for?answer:?%1.12lf\n",elapsed/count,answer);?free(array);?return?0;?}?? 我們?cè)谶@里做了什么?在這個(gè)例子中,我們有一個(gè)適當(dāng)大小的double數(shù)組,當(dāng)中存放了一些數(shù)字,然后獲取這些數(shù)值的和的開(kāi)方。為了測(cè)試,我們迭代了5次這個(gè)計(jì)算。每次迭代后我們打印花費(fèi)的時(shí)間,并總結(jié)了計(jì)算所需的運(yùn)行時(shí)間。在我的PowerMac G5(2.5)機(jī)器上,我獲得如下結(jié)果:
[bigmac:~/misc]?macresearch%?gcc?mach.c?-omach?[bigmac:~/misc]?macresearch%./mach??Time?for?iteration:?0.006717496412for?answer:?89478229.125529855490?Time?for?iteration:?0.007274204955for?answer:?178956458.251062750816?Time?for?iteration:?0.006669191332for?answer:?268434687.376589745283?Time?for?iteration:?0.006953711252for?answer:?357912916.502135872841?Time?for?iteration:?0.007582157340for?answer:?447391145.627681851387??Average?time?in?seconds?=0.007039352258?for?answer:?447391145.627681851387? 注意,在這里我沒(méi)有進(jìn)行優(yōu)化,因?yàn)榫幾g器有方法避開(kāi)這樣的無(wú)腦循環(huán)。另外,這只是一個(gè)例子。如果是真正的代碼,我們會(huì)進(jìn)行優(yōu)化。 好了,這就是這個(gè)例子的兩個(gè)目的。 首先,我使用的數(shù)組大小比我的緩存大。我這樣做的目的是因?yàn)槲覀冃枰⒁獾綌?shù)據(jù)溢出緩存的情況(正如這個(gè)例子一樣,至少在我的系統(tǒng)中是這樣。如果是在MacPro中,不會(huì)出現(xiàn)這種情況)。我們將在以后討論緩存的事宜。當(dāng)然,這是一個(gè)做作的例子,但有一些東西可供思考。其次,你注意到在內(nèi)存分配之前我寫(xiě)了一句注釋,這是什么意思呢? 這在實(shí)際情況下是不需要關(guān)心的事情,因?yàn)閮?nèi)存總是在需要時(shí)已準(zhǔn)備好使用。但當(dāng)做一些小測(cè)試時(shí)來(lái)測(cè)試函數(shù)的性能時(shí),它卻可能是會(huì)影響到測(cè)試結(jié)果的實(shí)際問(wèn)題。 當(dāng)動(dòng)態(tài)分配內(nèi)存時(shí),第一次訪問(wèn)內(nèi)存管理時(shí)會(huì)將其清0(在OS X中不管使用哪種動(dòng)態(tài)分配函數(shù):malloc, calloc…所有內(nèi)存在用戶使用前都會(huì)清0)。內(nèi)存清零是一種安全預(yù)防措施(我們不需要遞交一些包含安全信息的內(nèi)容,如解密密鑰) 清零過(guò)程產(chǎn)生一個(gè)副作用(被系統(tǒng)標(biāo)記為零填充頁(yè)面故障)。所以為了讓我們的計(jì)時(shí)更精確些,我們?cè)谑褂脙?nèi)存之前一次性填充數(shù)據(jù),以確保我們不會(huì)獲取到零填充頁(yè)面故障的處理時(shí)間。 讓我們來(lái)測(cè)試一下,注釋下面這行代碼 for(i=0;i<size;i++) array =(double)i; 為: //for(i=0;i<size;i++) array =(double)i; 再次運(yùn)行測(cè)試
[bigmac:~/misc]?macresearch%?./mach?Time?for?iteration:?0.009478866798for?answer:?0.000000000000?Time?for?iteration:?0.004756880234for?answer:?0.000000000000?Time?for?iteration:?0.004927868215for?answer:?0.000000000000?Time?for?iteration:?0.005227029674for?answer:?0.000000000000?Time?for?iteration:?0.004891864428for?answer:?0.000000000000??Average?time?in?seconds?=0.005856501870?for?answer:?0.000000000000? 注意第一次迭代的時(shí)間比后序的時(shí)間多了將近一倍。同時(shí)還需要注意所有的answer都是0。再次說(shuō)明內(nèi)存被清零了。如果我們從堆上獲取了內(nèi)存,我們獲取到的是無(wú)意義的數(shù)值。 最后,但很重要的一點(diǎn)。不要依賴于內(nèi)存的清零操作。很有可能獲取到的內(nèi)存是從一個(gè)靜態(tài)分配區(qū)而來(lái),那么可能會(huì)導(dǎo)致如下這樣的問(wèn)題。 double array[3][3]; 在我的系統(tǒng)上的打印結(jié)果是: -1.99844 -1.29321e-231 -1.99844 -3.30953e-232 -5.31401e+303 0 1.79209e-313 3.3146e-314 0 所以需要特別注意。 原帖地址:http://www.cocoachina.com/bbs/read.php?tid=143473
轉(zhuǎn)載于:https://www.cnblogs.com/zsw-1993/archive/2013/06/08/4880030.html
總結(jié)
以上是生活随笔為你收集整理的会员教程翻译:性能和时间的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。