gpt4 book ai didi

c++ - RDTSC 开销的差异

转载 作者:IT老高 更新时间:2023-10-28 23:01:03 32 4
gpt4 key购买 nike

当我在一些原始图像处理操作中尝试使用 SIMD 指令内在函数时,我正在构建一个微基准来衡量性能变化。但是,编写有用的微基准很困难,所以我想首先了解(并尽可能消除)尽可能多的变化和错误来源。

我必须考虑的一个因素是测量代码本身的开销。我正在使用 RDTSC 进行测量,并且正在使用以下代码来查找测量开销:

extern inline unsigned long long __attribute__((always_inline)) rdtsc64() {
unsigned int hi, lo;
__asm__ __volatile__(
"xorl %%eax, %%eax\n\t"
"cpuid\n\t"
"rdtsc"
: "=a"(lo), "=d"(hi)
: /* no inputs */
: "rbx", "rcx");
return ((unsigned long long)hi << 32ull) | (unsigned long long)lo;
}

unsigned int find_rdtsc_overhead() {
const int trials = 1000000;

std::vector<unsigned long long> times;
times.resize(trials, 0.0);

for (int i = 0; i < trials; ++i) {
unsigned long long t_begin = rdtsc64();
unsigned long long t_end = rdtsc64();
times[i] = (t_end - t_begin);
}

// print frequencies of cycle counts
}

运行此代码时,我得到如下输出:

Frequency of occurrence (for 1000000 trials):
234 cycles (counted 28 times)
243 cycles (counted 875703 times)
252 cycles (counted 124194 times)
261 cycles (counted 37 times)
270 cycles (counted 2 times)
693 cycles (counted 1 times)
1611 cycles (counted 1 times)
1665 cycles (counted 1 times)
... (a bunch of larger times each only seen once)

我的问题是:

  1. 以上代码产生的循环计数双峰分布的可能原因是什么?
  2. 为什么最快的时间(234 个周期)只出现少数几次 - 什么极不寻常的情况可以减少计数?

更多信息

平台:

  • Linux 2.6.32 (Ubuntu 10.04)
  • g++ 4.4.3
  • 酷睿 2 双核 (E6600);这具有恒定速率 TSC。

SpeedStep 已关闭(处理器设置为性能模式并以 2.4GHz 运行);如果在“按需”模式下运行,我会在 243 和 252 个周期处获得两个峰值,在 360 和 369 个周期处有两个(可能是对应的)峰值。

我正在使用 sched_setaffinity 将进程锁定到一个核心。如果我依次在每个内核上运行测试(即锁定到内核 0 并运行,然后锁定到内核 1 并运行),我得到两个内核的相似结果,除了 234 个周期的最快时间往往会稍微出现核心 1 上的次数少于核心 0 上的次数。

编译命令为:

g++ -Wall -mssse3 -mtune=core2 -O3 -o test.bin test.cpp

GCC 为核心循环生成的代码是:

.L105:
#APP
# 27 "test.cpp" 1
xorl %eax, %eax
cpuid
rdtsc
# 0 "" 2
#NO_APP
movl %edx, %ebp
movl %eax, %edi
#APP
# 27 "test.cpp" 1
xorl %eax, %eax
cpuid
rdtsc
# 0 "" 2
#NO_APP
salq $32, %rdx
salq $32, %rbp
mov %eax, %eax
mov %edi, %edi
orq %rax, %rdx
orq %rdi, %rbp
subq %rbp, %rdx
movq %rdx, (%r8,%rsi)
addq $8, %rsi
cmpq $8000000, %rsi
jne .L105

最佳答案

RDTSC 可能由于多种原因返回不一致的结果:

  • 在某些 CPU(尤其是某些较旧的 Opterons)上,TSC 在内核之间不同步。听起来您已经使用 sched_setaffinity 处理了这个问题——很好!
  • 如果在您的代码运行时触发操作系统计时器中断,则会在代码运行时引入延迟。没有实际的方法可以避免这种情况。扔掉异常高的值。
  • CPU 中的流水线伪影有时会使您在紧密循环中的任一方向上偏离几个周期。完全有可能在非整数时钟周期内运行一些循环。
  • 缓存!根据 CPU 缓存的变幻莫测,内存操作(如写入 times[])的速度可能会有所不同。在这种情况下,您很幸运,所使用的 std::vector 实现只是一个平面数组;即便如此,这种写法也会把事情搞砸。这可能是这段代码最重要的因素。

对于 Core2 微体系结构的专家,我还不足以确切说明为什么您会获得这种双峰分布,或者您的代码如何运行得更快 28 倍,但这可能与上述原因之一有关.

关于c++ - RDTSC 开销的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6432669/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com