获取机器当前CPU频率
struct perf_cpu_info
{
int tsc;
int index;
int mhz;
};
struct perf_cpu_info *cpu_list;
static unsigned long long native_read_tsc(void)
{
unsigned long long val;
asm volatile("rdtsc": "=A" (val));
return val;
}
unsigned int calibrate_tsc(void)
{
unsigned long long val;
unsigned long long val2;
long long diff = 0;
int error = 0,cnt = 0;
unsigned long long min_tsc = (unsigned long long) -1;
val = native_read_tsc();
do {
usleep(4950);
val2 =native_read_tsc();
diff = val2 - val;
if (diff > 0) {
min_tsc = min_tsc > diff?diff:min_tsc;
error = 0;
cnt ++;
}
if (error ++ > 6) return -1;
val = val2;
} while(cnt < 3);
return min_tsc / 5;
}
int aperfmperf_mhz(unsigned int cpu, unsigned int tsc)
{
unsigned long long aperf = 0, aperf2 = 0;
unsigned long long mperf = 0, mperf2 = 0;
if (rdmsr_on_cpu(MSR_IA32_MPERF, cpu, &mperf) != 0)
return -1;
if (rdmsr_on_cpu(MSR_IA32_APERF, cpu, &aperf) != 0)
return -1;
usleep(99950);
if (rdmsr_on_cpu(MSR_IA32_MPERF, cpu, &mperf2) != 0)
return -1;
if (rdmsr_on_cpu(MSR_IA32_APERF, cpu, &aperf2) != 0)
return -1;
aperf = aperf2 - aperf;
mperf = mperf2 - mperf;
return tsc * aperf / mperf / 1000;
}
void* threadFun(void* arg) //arg 传递线程标号(自己定义)
{
cpu_set_t mask; //CPU核的集合
cpu_set_t get; //获取在集合中的CPU
struct perf_cpu_info *perf = (struct perf_cpu_info *)arg;
CPU_ZERO(&mask);
CPU_SET(perf->index, &mask);
if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
{
printf("warning: could not set CPU affinity, continuing...\n");
}
perf->mhz = aperfmperf_mhz(perf->index, perf->tsc);
// printf("cpu[%d] %d Mhz\n", perf->index, perf->mhz);
return NULL;
}
int aperf_get_min_freq_mhz(int tsc)
{
int num=0;
int i;
num = sysconf(_SC_NPROCESSORS_CONF); //获取核数
pthread_t thread[num];
cpu_list = (struct perf_cpu_info*)malloc(num * sizeof (struct perf_cpu_info));
for(i=0;i<num;i++)
{
cpu_list[i].tsc = tsc;
cpu_list[i].index = i;
pthread_create(&thread[i],NULL,threadFun,(void*)&cpu_list[i]);
}
unsigned int min = (unsigned int)(-1);
for(i=0; i< num; i++)
{
pthread_join(thread[i],NULL);//等待所有的线程结束,线程为死循环所以CTRL+C结束
}
for(i=0; i< num; i++)
{
min = cpu_list[i].mhz < min ? cpu_list[i].mhz : min;
}
free(cpu_list);
return min;
}

该博客介绍了一个在Linux环境下,通过读取MSR寄存器和使用`perf_cpu_info`结构体来获取CPU当前频率的方法。涉及到的关键函数包括`native_read_tsc`、`calibrate_tsc`、`aperfmperf_mhz`和`aperf_get_min_freq_mhz`,通过多线程计算所有CPU核心的最小频率。
853

被折叠的 条评论
为什么被折叠?



