更好地同步基准测试

时间:2018-01-29 04:46:19

标签: c linux caching synchronization interrupt

我试图对我添加到内核的一些中断功能进行基准测试。目前,我只想测量从一个核心发送中断到另一个核心接收中断所需的时间。我大致做了以下几点:

volatile bool wait = true;

...

//Sending core:
void run_benchmark() {
    //clear pipeline and record time A with rdtsc
    for (int i = 0; i < 10000; i++) {
        send_interrupt();
        while (wait);
        wait = true;
    }
    //record time B with rdtsc
    //benchmark = (B - A) / 10000
}

...

//Receiving core:
void handle_interrupt(...) {
    wait = false;
    ...
}

我还减去基准测试中的其他开销,例如记录时间的成本等。我发送中断10,000次以获得稳定的值。

我对这种方法的主要关注是接收核心和发送核心都会出现缓存未命中,因为它们都将wait设置为不同的值。鉴于中断传输速度已经很快,这些缓存未命中可能会对我记录的基准测试产生重大影响。

有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

在较新的英特尔平台上,所有内核的TSC应在Linux下同步。所以我认为你不需要这种同步(see corresponding thread in the Intel developer zone).

为什么不简单地在接收CPU上获取TSC值?然后,您可以等待发送CPU,直到时间B的变量包含合理的值。

答案 1 :(得分:0)

是的,每个核心上的两个L1缓存都会闪烁,因为每个核心都会使对方的缓存行无效。

我不知道你是如何实现send_interrupt()的,但如果是通过使用某个共享变量,那么你还需要考虑这种通信存在缓存驱逐,这会导致测量值出现一些延迟

关于测量执行时间,我最近在工作,这是我用来测量时钟滴答的代码:

uint64_t rdtscp(uint64_t *chip, uint64_t *core)
{
    uint32_t a, d, c;

    __asm__ volatile("rdtscp" : "=a" (a),"=d" (d), "=c" (c));
    *chip = (c & 0xFFF000) >> 12;
    *core = c & 0xFFF;

    return ((uint64_t) a) | (((uint64_t) d) << 32);
}

基本上,RDTSCP在NUMA架构中共享相同芯片组的所有内核上同步,rdtscp指令使用三个不同的CPU寄存器来形成64位时间戳,这就是为什么它需要这三个函数中的变量。

尽管如此,您可以从此指令中获取其他有用信息,例如核心ID和芯片ID。

因此,您可以使用此时间戳来衡量代码所用的时间。

其他可能有用的事情是将您的流程固定到特定的CPU核心,因为它可能被安排到不同的核心,因此它也会导致任务迁移等等。

P.S。:其分辨率为CPU时钟周期。