我想在0到7的範圍內通過增加參數來計算一個函數的開銷。如何估算硬件開銷和軟件開銷。如何在c編程中使用rdtsc來估計for循環的開銷
回答
首先要做的是disassembly
,在Linux上你可以從objdump
獲得幫助。 objdump
將幫助您查看代碼是如何生成的。如果你對這些傳遞的參數沒有做任何處理,那麼這只是從堆棧中獲取參數並將它們保存在寄存器中的區別。由於這些操作將花費很少的CPU週期,因此,很難提供時序信息,但在CPU週期方面更容易。
你的問題不是很好擺出。但是,執行rdtsc
指令最可靠的方法是使用內聯彙編來調用它,這是所有C編譯器完全支持的。由C標準規定的任何定時功能將隨實施而變化。英特爾有一個非常好的白皮書,介紹實現rdtsc
東西here的最佳方式。主要問題是無序執行,這可能超出了您的問題範圍。
我發現的最好的實現是在this repo,我已經適應了我自己的使用。這組基本的宏,假設你有一個兼容的處理器,將會給你〜每個調用開銷的32個時鐘週期(你需要爲你自己的處理器做測試):
#include <cpuid.h>
#include <stdint.h>
/*** Low level interface ***/
/* there may be some unnecessary clobbering here*/
#define _setClockStart(HIs,LOs) { \
asm volatile ("CPUID \n\t" \
"RDTSC \n\t" \
"mov %%edx, %0 \n\t" \
"mov %%eax, %1 \n\t": \
"=r" (HIs), "=r" (LOs):: \
"%rax", "%rbx", "%rcx", "%rdx"); \
}
#define _setClockEnd(HIe,LOe) { \
asm volatile ("RDTSCP \n\t" \
"mov %%edx, %0 \n\t" \
"mov %%eax, %1 \n \t" \
"CPUID \n \t": "=r" (HIe), "=r" (LOe):: \
"%rax", "%rbx", "%rcx", "%rdx"); \
}
#define _setClockBit(HIs,LOs,s,HIe,LOe,e) { \
s=LOs | ((uint64_t)HIs << 32); \
e=LOe | ((uint64_t)HIe << 32); \
}
/*** High level interface ***/
typedef struct {
volatile uint32_t hiStart;
volatile uint32_t loStart;
volatile uint32_t hiEnd;
volatile uint32_t loEnd;
volatile uint64_t tStart;
volatile uint64_t tEnd;
/*tend-tstart*/
uint64_t tDur;
} timer_st;
#define startTimer(ts) \
{ \
_setClockStart(ts.hiStart,ts.loStart); \
}
#define endTimer(ts) \
{ \
_setClockEnd(ts.hiEnd,ts.loEnd); \
_setClockBit(ts.hiStart,ts.loStart,ts.tStart, \
ts.hiEnd,ts.loEnd,ts.tEnd); \
ts.tDur=ts.tEnd-ts.tStart; \
}
#define lapTimer(ts) \
{ \
ts.hiStart=ts.hiEnd; \
ts.loStart=ts.loEnd; \
}
然後像這樣的東西
#include <stdio.h>
#include <math.h>
#include "macros.h" /* Macros for calling rdtsc above */
#define SAMPLE_SIZE 100000
int main()
{
timer_st ts;
register double mean=0;
register double variance=0;
int i;
/* "Warmup" */
for(i=1;i<SAMPLE_SIZE;i++)
{
startTimer(ts);
endTimer(ts);
}
/* Data collection */
for(i=1;i<SAMPLE_SIZE;i++)
{
startTimer(ts);
endTimer(ts);
mean+=ts.tDur;
}
mean/=SAMPLE_SIZE;
fprintf(stdout,"SampleSize: %d\nMeanOverhead: %f\n", SAMPLE_SIZE,mean);
return 0;
}
把它在我的Broadwell微架構的芯片,我得到這個輸出
SampleSize: 100000
MeanOverhead: 28.946490
29時鐘分辨率的時鐘分辨率是相當不錯的。人們通常使用的任何庫函數(如gettimeofday
)都不具備時鐘級精度和200-300的開銷。
我不確定你的意思是「硬件開銷」與「軟件開銷」,但對於上面的實現,沒有函數調用來執行rdtsc
調用之間的時間或中間代碼。所以我想軟件開銷是零。
'rdtsc'本質上是芯片專用的,並且僅限於(某些)英特爾CPU。編譯器通常支持'asm',但是使用的符號有所不同 - 然而,它不是由C標準規定的(例如,'asm'不是標準C-ISO/IEC 9899:2011中的關鍵字)。標準的C(或POSIX)定時功能在各種平臺和CPU類型中更加可靠,並且性能可靠 - 儘管(比編譯器直接訪問「rdtsc」指令更慢)。 –
- 1. 使用C++ for循環估計pi
- 2. 如何評估C編程中for循環的表達式?
- 3. C編程for循環和計數器
- 4. 「for」循環來自Kochan的「Objective-C編程」中的程序7.6的循環
- 5. 如何在php中使用for循環來編號?
- 6. 使用For循環來在Oracle過程
- 7. 如何在此腳本的for循環中使用for循環?
- 8. 如何使用C++循環外的For循環中的變量?
- 9. C編程:for循環和中斷
- 10. 在c編程中使用for循環寫入文件
- 11. C++來的Objective-C,使用const int的在for循環中
- 12. C#中使用for循環
- 13. 如何寫一個for循環來計算在R中使用數學方程?
- 14. 如何在C編程中運行多個for循環?
- 15. 如何使用Python評估for循環中的表達式?
- 16. For循環在python編程?
- 17. 在for循環中使用C的fwrite
- 18. 在For循環中使用計數器?
- 19. 「循環」for循環在C
- 20. 如何計算for循環
- 21. For循環使用Go編程語言
- 22. 如何在python中編寫for循環
- 23. 如何在gremlin中編寫for循環?
- 24. 如何使用for循環來計數變量?
- 25. c編程輸入字符for循環
- 26. For循環IF語句C編程
- 27. 在目標c中使用For循環?
- 28. 計數for循環C++中的次數
- 29. 嵌套for循環中的C++計算
- 30. C編程,存儲來自for循環的數據
'gettimeofday'在任何POSIX系統上都能很好地工作。 'rdtsc'指令只存在於x86架構上,並且在所有這些指令上都不起作用,所以我建議避免它。 –
@BenVoigt'clock_gettime'現在正在取代'gettimeofday'。我不確定何時,但手冊頁說它將來會被刪除。 – tijko
@tijko:有'gettimeofday()'的平臺沒有'clock_gettime()' - Mac OS X(10.11.4)就是這樣。目前,'gettimeofday()'比'clock_gettime()'更具可移植性。 –