生活随笔
收集整理的這篇文章主要介紹了
会员教程翻译:性能和时间
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
來自會員德魯伊: 在討論性能之前,先討論一個重要的話題:時間。為了理解代碼中的變化如何影響性能,我們需要一個排序的指標。有許多方法用于時間例程,一些比另一些合適。在本教程
“” 來自會員德魯伊:
在討論性能之前,先討論一個重要的話題:時間。為了理解代碼中的變化如何影響性能,我們需要一個排序的指標。有許多方法用于時間例程,一些比另一些合適。在本教程中我們將討論Mach Absolute Time。
為什么是Mach? 時間例程依賴于所需要測量的時間域。某些情況下使用諸如clock()或getrusage()函數來做些簡單的數學運算就足夠了。如果時間例程將用于實際的開發框架之外,可移植性就很重要了。我不使用這些。為什么? 對于我來說,調試代碼的典型問題是: 1) 我只需要在即時測試時使用時間例程 2) 我不喜歡依賴于多種函數來包含不同的時間域。它們的行為可能不一致 3) 有時我需要一個高精度定時器
歡迎了解mach_absolute_time mach_absolute_time是一個CPU/總線依賴函數,返回一個基于系統啟動后的時鐘”嘀嗒”數。它沒有很好的文檔定義,但這不應該成為使用它的障礙,因為在MAC OS X上可以確保它的行為,并且,它包含系統時鐘包含的所有時間區域。那是否應該在產品代碼中使用它呢?可能不應該。但是對于測試,它卻恰到好處。 使用mach_absolute_time時需要考慮兩個因素: 1) 如何獲取當前的Mach絕對時間 2) 如何將其轉換為有意義的數字
獲取mach_absolute_time 這非常簡單
#include?<stdint.h>??uint64_t?start?=mach_absolute_time();?uint64_t?stop?=mach_absolute_time();?? 這樣就可以了。我們通常獲取兩個值,以得到這兩個時間的時間差。
將mach_absolute_time時間差轉換為秒數 這稍微有點復雜,因為我們需要獲取mach_absolute_time所基于的系統時間基準。如下代碼:
#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;?}?? 這里最重要的是調用mach_timebase_info。我們傳遞一個結構體以返回時間基準值。最后,一旦我們獲取到系統的心跳,我們便能生成一個轉換因子。通常,轉換是通過分子(info.numer)除以分母(info.denom)。這里我乘了一個1e-9來獲取秒數。最后,我們獲取兩個時間的差值,并乘以轉換因子,便得到真實的時間差。 現在我們可能會想,為什么這比用clock好?看起來做了更多的事情。確實是有點,這便是為什么它在一個函數中。我們只需要傳遞我們的值到函數中并取得答案。
例子 讓我們寫個例子。下面是完整的代碼清單(包括mach函數)。可以使用gcc mach.c –o mach來編譯它:
#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;?}?? 我們在這里做了什么?在這個例子中,我們有一個適當大小的double數組,當中存放了一些數字,然后獲取這些數值的和的開方。為了測試,我們迭代了5次這個計算。每次迭代后我們打印花費的時間,并總結了計算所需的運行時間。在我的PowerMac G5(2.5)機器上,我獲得如下結果:
[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? 注意,在這里我沒有進行優化,因為編譯器有方法避開這樣的無腦循環。另外,這只是一個例子。如果是真正的代碼,我們會進行優化。 好了,這就是這個例子的兩個目的。 首先,我使用的數組大小比我的緩存大。我這樣做的目的是因為我們需要注意到數據溢出緩存的情況(正如這個例子一樣,至少在我的系統中是這樣。如果是在MacPro中,不會出現這種情況)。我們將在以后討論緩存的事宜。當然,這是一個做作的例子,但有一些東西可供思考。其次,你注意到在內存分配之前我寫了一句注釋,這是什么意思呢? 這在實際情況下是不需要關心的事情,因為內存總是在需要時已準備好使用。但當做一些小測試時來測試函數的性能時,它卻可能是會影響到測試結果的實際問題。 當動態分配內存時,第一次訪問內存管理時會將其清0(在OS X中不管使用哪種動態分配函數:malloc, calloc…所有內存在用戶使用前都會清0)。內存清零是一種安全預防措施(我們不需要遞交一些包含安全信息的內容,如解密密鑰) 清零過程產生一個副作用(被系統標記為零填充頁面故障)。所以為了讓我們的計時更精確些,我們在使用內存之前一次性填充數據,以確保我們不會獲取到零填充頁面故障的處理時間。 讓我們來測試一下,注釋下面這行代碼 for(i=0;i<size;i++) array =(double)i; 為: //for(i=0;i<size;i++) array =(double)i; 再次運行測試
[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? 注意第一次迭代的時間比后序的時間多了將近一倍。同時還需要注意所有的answer都是0。再次說明內存被清零了。如果我們從堆上獲取了內存,我們獲取到的是無意義的數值。 最后,但很重要的一點。不要依賴于內存的清零操作。很有可能獲取到的內存是從一個靜態分配區而來,那么可能會導致如下這樣的問題。 double array[3][3]; 在我的系統上的打印結果是: -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
轉載于:https://www.cnblogs.com/zsw-1993/archive/2013/06/08/4880030.html
總結
以上是生活随笔為你收集整理的会员教程翻译:性能和时间的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。