LINUX时钟系列-04-从CPU主频到系统时间

LINUX时钟系列-04-从CPU主频到系统时间

首先我们从一个实验开始:

#define _GNU_SOURCE

#include <sched.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> 
#include <stdint.h>
#include <time.h>
#include <sys/time.h>

// gcc -o rdtsc rdtsc.c -lpthread -std=c99

uint64_t get_tsc()
{
    uint64_t a, d;
    __asm__ volatile("rdtsc" : "=a"(a), "=d"(d));
    return (d << 32) | a;
}

void bind_cpu(int cpuid)
{
    cpu_set_t cpuset;

    CPU_ZERO(&cpuset);
    CPU_SET(cpuid, &cpuset);

    pthread_t tid = pthread_self();
    
    pthread_setaffinity_np(tid, sizeof(cpuset), &cpuset);
}

#define     CPU_NUM             16

uint64_t    cpuid_tsc[CPU_NUM];

int         epoch               = 0;

void* thread_func(void* arg) 
{
    int cpuid = *((int*)arg);

    bind_cpu(cpuid);
    
    int old = epoch;
    while(1)
    {
        if (old == epoch)
            continue;
        
        old = epoch;
        
        uint64_t tsc = get_tsc();
        uint64_t diff = tsc - cpuid_tsc[cpuid];

        printf("cpuid=%2d, tsc=%llu, diff=%llu\n", cpuid, tsc, diff);
        
        cpuid_tsc[cpuid] = tsc;
    }

    return NULL;
}

int main()
{
    // 启动线程
    int cpuids[CPU_NUM];
    for (int i = 0; i < CPU_NUM; ++i)
    {
        pthread_t tid;
        cpuids[i] = i;
        pthread_create(&tid, NULL, thread_func, &cpuids[i]);
    }
    // 初始化tsc
    sleep(1);
    for (int i = 0; i < CPU_NUM; ++i)
        cpuid_tsc[i] = get_tsc();
    // 测试
    while(1)
    {
        sleep(1);
        printf("\n");
        ++epoch;
    }

    return 0;
}

先在一个16核的机器上运行一下:

运行结果如下:

再换一台72核的机器:

运行结果如下:

观察这两台机器的运行结果,我们发现了三点:

1.绑定在不同CPU核心上的程序,同一时刻读取到的tsc的值都差不多(即使他们位于两颗CPU上!)

2.tsc的值基本上按照CPU的标称频率增加

3.tsc的值跟机器的启动时间有关(uptime)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注