You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux x86/x64 GCC下__rdtsc用法及流水线刷新与__rdtscp疑问

在Linux x64平台用GCC做准确CPU周期测量的正确姿势

一、不用汇编时如何刷新流水线配合__rdtsc

要解决CPU乱序执行导致的TSC测量不准问题,核心是在调用__rdtsc前强制CPU完成所有前置指令、刷新流水线。GCC提供的内置__cpuid函数可以直接做到这一点——它对应x86的cpuid指令,属于强序列化指令,会让CPU暂停乱序执行逻辑,确保所有前置指令执行完毕后才继续后续操作。

使用时只需用临时变量承接__cpuid的输出即可(比如传入参数0,避免触发特殊CPU功能):

#include <cpuid.h>

// 序列化流水线,确保前置指令全部执行完成
void serialize_pipeline() {
    unsigned int eax, ebx, ecx, edx;
    __cpuid(0, eax, ebx, ecx, edx);
}

// 周期测量示例
void measure_cycles() {
    unsigned long long start, end;
    
    serialize_pipeline();
    start = __rdtsc();
    
    // 这里放入你需要测量的代码段
    for (int i = 0; i < 1000; i++);
    
    serialize_pipeline();
    end = __rdtsc();
    
    printf("消耗周期: %llu\n", end - start);
}

另外,也可以用GCC的__sync_synchronize()内置函数——它会生成mfence这类内存栅栏指令,同样能起到序列化流水线的效果,不过cpuid的序列化强度更高,更适合高精度周期测量场景。

二、__rdtscp能否替代「刷新操作+__rdtsc」?

答案是完全可以,但要明确它的特性:

  • __rdtscp对应x86的rdtscp指令,这条指令本身就带有序列化语义:它会确保在读取TSC计数器前,所有前置指令都已执行完成、所有内存操作都已提交到内存。也就是说,调用__rdtscp前不需要额外的cpuid或栅栏指令来刷新流水线。
  • 和「__cpuid+__rdtsc」的组合相比,__rdtscp的开销更小——cpuid指令的执行延迟比rdtscp高不少,用__rdtscp能降低测量自身带来的误差。
  • 注意:rdtscp只会序列化它之前的指令流,不会阻止后续指令提前执行,但这不影响周期测量的准确性——不管是测量代码段的起始还是结束时间,__rdtscp的序列化语义都能保证TSC读取时机的正确性。

用__rdtscp的测量示例:

void measure_with_rdtscp() {
    unsigned long long start, end;
    unsigned int aux; // rdtscp会返回一个辅助值,可直接忽略
    
    start = __rdtscp(&aux); // 自带序列化,无需前置刷新
    
    // 被测代码段
    for (int i = 0; i < 1000; i++);
    
    end = __rdtscp(&aux);
    
    printf("消耗周期: %llu\n", end - start);
}

需要注意:部分极老版本的GCC可能不支持__rdtscp,确保你的GCC版本在4.4及以上(现代Linux发行版基本都满足)。

内容的提问来源于stack exchange,提问作者doraemon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 02:05:33