從奔騰(penium)系列開始,intel
x86 處理器中增加了乙個64位的時間戳暫存器(tsc),每個經過乙個時鐘週期,該暫存器加1;機器重啟時,該暫存器將清空。
現在的處理器其主頻都在1g以上,也就是說其時鐘週期是納秒級的(1秒/1000000000=1納秒)。
那該暫存器會不會溢位呢?我們可以計算一下,假設機器的主頻是3gmhz,
也就是說1秒鐘包含3,000,000,000個時鐘週期,每個時鐘週期為0.33333納秒,則64位暫存器溢位所需要的時間為:
2^64 / 3000000000 ≈
6148914691 秒 ≈71168天 ≈ 195年
因此tsc溢位基本是不可能的了。
rdtsc 是一條機器指令用於讀取該時間戳暫存器中的值。
下面的程式就是通過在c語言呼叫rdtsc來得到時鐘週期:
#include
#include
__int64
__declspec(naked) read_time_stamp_counter()
__asm
cpuid; __asm rdtsc;
__asm ret;
int main()
{ float ticks_1, ticks_2;
unsigned int i,j=0;
unsigned int loop = 4000000000;
ticks_1 = (float)read_time_stamp_counter();
for(i=0;i
j++;
j++;
ticks_2
= (float)read_time_stamp_counter();
printf("\ntotal
ticks is : %f\n", ticks_2-ticks_1);
printf("\ntotal ticks per loop is : %f\n",
(ticks_2-ticks_1)/loop);
printf("\ntotal time is %f seconds\n", (ticks_2 -
ticks_1)/3300000000);
return 1;
說明:(1)
子函式read_time_stamp_counter()並沒有明確的指定返回值,為什麼程式中仍然可以得到正確的值?原因在於指令rdtsc將時間戳的放在edx:eax中,而這與c語言子函式的返回值的存放位址是一致的(參見
(2) 子函式read_time_stamp_counter()的定義中加入__deslspec(naked),
是避免編譯器在編譯該函式時新增其他的語句,通過下面的c**的反彙編可以看到__deslspec(naked)的作用:
(3) 執行程式的計算機的cpu是3.3ghz。
(4) 程式的執行結果如下, 從中可以看出,
每個迴圈所耗費的時鐘週期是12左右,(注意時鐘週期不同於指令週期,指令週期是指執行一條指令所花費的時間,可以用時鐘週期表示,一般乙個指令週期等於1個或多個時鐘週期);根據時鐘週期總數和cpu的主頻,我們可以計算出整個迴圈所花費的時間大約是14.83秒。
C 中的高精度計時方法(納秒級別計時)
queryperformancecounter獲得cpu執行計數值 精確的時間計量方法在某些應用程式中是非常重要的。常用的 windows api 方法 gettickcount 返回系統啟動後經過的毫秒數。另一方面,gettickcount 函式僅有 1ms 的分辨精度,很不精確。故而,我們要另外...
c納秒級計時器 C 11 計時器!真香
在我們寫程式過程中,有時候需要測試我們的程式語句執行時間的耗時,當前也是有很多的庫提供我們去使用,一直沒有良好的跨平台的庫可以提供出來 而且一般這種 也是由我們程式設計師自己呼叫系統的庫來進行,但是往往會出現精度不足和不支援跨平台等問題 他來了。他來了。他踩著七彩祥雲來了 他 就是c 11中引進bo...
C語言如何利用陣列儲存「變數」
背景解決方法 說明眾所周知,陣列僅能儲存常量資料,包括數字常量 字元常量 字串常量。但在實際應用中,可能會遇到需要按需修改陣列中資料值的需求,此時又應該如何解決呢?通過一段時間的測試驗證,解決了專案中的該需求,於是便產生了本篇文章,也是本人的第一篇技術部落格。如果有不足或錯誤之處,還望讀者可以不吝賜...