我有一个小功能,用于读取*nix中的TSC (时间戳计数器)。使用它似乎多少正确地报告了我的CPU频率。
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
uint64_t read_time_stamp_counter()
{
uint32_t my_edx;
uint32_t my_eax;
asm ("cpuid\n\t" /* Discourage out-of-order execution. */
"rdtsc\n\t"
"movl %%edx, %0\n\t"
"movl %%eax, %1"
:"=r"(my_edx), "=r"(my_eax)
:
: /* List of registers clobbered by both RDTSC and CPUID. */
"%eax", "%ebx", "%ecx", "%edx"
);
return (((uint64_t) my_edx) << 32) | my_eax;
}
int main(int argc, char** argv) {
uint64_t tmp;
uint64_t cycles;
uint64_t sleep_overhead;
tmp = read_time_stamp_counter();
sleep(1);
cycles = read_time_stamp_counter() - tmp;
tmp = read_time_stamp_counter();
sleep(0);
sleep_overhead = read_time_stamp_counter() - tmp;
printf("Sleep overhead: %llu cycles.\n", sleep_overhead);
cycles -= sleep_overhead;
printf("Cycles: %llu\n", cycles);
printf("Estimated frequency: %.3f GHz\n", cycles / 1e9);
return 0;
}目前的实现看起来不太好:应该有更好的方法。还有,它是否有可能使它更精确?
发布于 2016-12-30 02:41:52
从“如何获得正确答案”的角度来看,David的评论解释了为什么问OS是唯一值得信赖的解决方案--最好回答这个问题。
但这是代码评审,而不是堆栈溢出。从这一角度来看:
cpuid指令根据eax的输入值返回不同的数据。由于在执行asm之前从未设置过它,(可以想象)操作的长度在不同的调用之间可能会有所不同,从而扰乱了您的计算。
此外,mov语句也是不必要的:
asm ("cpuid\n\t"
"rdtsc"
: "=d"(my_edx), "=a"(my_eax)
: "a"(0)
: "%ebx", "%ecx");也许还值得将rdtscp作为cpuid + rdtsc的替代品。
https://codereview.stackexchange.com/questions/118359
复制相似问题