我想通过在0到7范围内增加参数来计算函数参数的开销。如何估算硬件开销和软件开销。
最佳答案
您的问题提出的并不十分正确。但是,执行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
调用之间的中间代码。因此,我认为软件开销为零。关于c - 如何在C编程中使用rdtsc估算for循环的开销,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36961657/