【问题标题】:Branch prediction and multithreading分支预测和多线程
【发布时间】:2017-01-26 05:23:59
【问题描述】:

让我们假设一个简单的if 像这样:

if (something)
   // do_something
else
   // do_else

假设这条if-else 语句在不同的线程中并行执行,每个线程产生不同的结果,但在其生命周期中保持不变。例如,在线程 1 中,条件总是被评估为假,在线程 2 中,条件总是被评估为真;在线程 3 中也始终为真,依此类推。

分支预测是否考虑每个线程的执行上下文来进行统计?因为如果不是(我不这么认为,但很难通过测试来检查),CPU 将看到条件遵循随机模式并且根本不会预测。

【问题讨论】:

  • 定义线程。 CPU 显然不知道操作系统线程。但是现在大多数 CPU 都知道硬件线程。
  • 分支预测是一个以纳秒分辨率运行的处理器实现细节。线程执行以毫秒分辨率运行。这 6 个数量级的差异使这个问题变得无关紧要。
  • 基于多核异构的分支预测的研究与设计 - 摘要: 针对单靠处理器性能难以提升的问题通过提高单核频率,以及处理分支指令时超标量流水线停顿,本文介绍了采用B-Cache结构和C-Core处理器控制器的异构多核处理器架构。新架构避免了由于分支预测错误导致的流水线刷新,提高了多核处理器的整体效率。

标签: multithreading branch-prediction


【解决方案1】:

如果我们忽略 SMT(例如超线程),大多数架构的每个硬件线程都有一个分支预测器。 它与单个核心的获取单元紧密耦合。少数(AMD?)将一些分支预测信息存储在 L1/L2 I-cache 中,但主要针对下一次提取。

因此,如果您不在 SMT 上运行您的代码,那么您就是在天堂,每次都将获得 100% 的预测,但需要花费一些指令。

如果您在 SMT 上运行代码,您通常会发现您的生活是地狱,有 50% 以上的错误预测。

现在您可以轻松解决您的问题,您只需要使用更多代码,提前检查您的条件并调用包含 do_something 或 do_else 的代码分支。

如果你有一个循环调用你的函数,你有你的分支,你可以这样做:

如果(某事) do_something_loop(); 别的 do_else_loop();

void do_something_loop() { 对于(自动 x:myVec) 做一点事; }

这样做的缺点是您需要维护 2 个几乎相等的代码分支。

或者你可以在函数调用 branch_me() 中有你的分支,你可以创建一个模板函数,并且由于死代码消除的魔力,你不应该在循环中得到任何分支。

C++ 概念代码。

template<bool b_something>
void brancher() {
  // do things
  if (b_something)
    // do_something
  else
    // do_else
  }
  // do more things
}

void branch_user() {
  if (something) {
    for (auto x : myVec)
      brancher<true>();
  } else {
    for (auto x : myVec)
      brancher<false>();
  }
}

现在您只需要维护外部函数的 2 个分支,希望工作量更少。

【讨论】:

    猜你喜欢
    • 2015-11-24
    • 2014-04-25
    • 2014-03-03
    • 2016-09-14
    • 2019-12-13
    • 2016-07-01
    • 2011-02-01
    • 2019-08-20
    • 2012-07-02
    相关资源
    最近更新 更多