典型的现代 CPU 的分支预测缓冲区有多大?

owa*_*agh 5 c++ cpu performance branch-prediction

我正在处理的应用程序有大量的 if 语句,其特点是在任何一次执行中,90% 的时间只有一个分支被执行。

现在,我可以通过执行以下操作来测试分支预测对特定 CPU 的单个 if 语句的影响:-

#include <iostream>
#include <stdlib.h>

using namespace std;

int main() {
  int a;
  cin>>a;
  srand(a);
  int b;

  long count=0;

  for (int i=0; i<10000; i++) {
    for (int j=0; j<65535; j++) {
      b = rand() % 30 + 1;
      if (b > 15) // This can be changed to get statistics for different %-ages
        count += (b+10);
    }
  }

  cout << count <<"\n";
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,有没有一种方法可以在给定 CPU 的实际大型应用程序中使用多个 if 语句来测试分支预测的可扩展性和影响?

基本上,我希望能够弄清楚分支错误预测对各种 CPU 造成的损失及其对应用程序的影响。

Lou*_*cci 4

您需要考虑分支的复杂性,编译器可能会使用特定于体系结构的操作代码(例如 CMOV(比较和移动))删除分支。

您的简单示例代码

if (b > 15)
    count += (b+10);
Run Code Online (Sandbox Code Playgroud)

这是编译成机器语言的代码

;; assembly x86 FASM/NASM syntax

;; WITH branching
MOV ebx, [b] ;; b
MOV ecx, [count] ;; count
CMP ebx, 15 ;; if condition to set flags
JLE .skip ;; { branch/jump over the if body when less than or equal
LEA eax, [ecx + ebx + 10] ;; count + b+10
MOV [count], eax ;; store count
.skip: ;; } label after the if block

;; WITHOUT branching
MOV ebx, [b] ;; b
MOV ecx, [count] ;; count
LEA eax, [ecx + ebx + 10] ;; pre-calc avoiding the need to branch
CMP ebx, 15 ;; if condition to set flags
CMOVLE eax, ecx ;; make eax equal to ecx (current count) when less than or equal
            ;; avoiding the branch/jump
MOV [count], eax ;; store count
Run Code Online (Sandbox Code Playgroud)

因此,除非您知道优化编译器如何优化代码,否则分析分支预测会有点困难。如果您正在检查机器代码输出并知道有很多 J[condition] 语句,那么使用注释中提到的代码分析工具就足够了。尝试在不使用正确的架构调试寄存器的情况下进行自己的分支预测测试将导致我上面演示的情况。