这是一个对任何平台、语言或编译器都开放的天真的一般性问题。虽然我最好奇的是 Aarch64、C++、GCC。
当在依赖于 I/O 状态的程序流中编写不可避免的分支时(编译器无法预测),并且我知道一种状态比另一种状态更有可能,我如何向编译器表明这一点?
这是否更好
if(true == get(gpioVal))
unlikelyFunction();
else
likelyFunction();
Run Code Online (Sandbox Code Playgroud)
比这个?
if(true == get(gpioVal))
likelyFunction(); // performance critical, fill prefetch caches from this branch
else
unlikelyFunction(); // missed prediction not consequential on this branch
Run Code Online (Sandbox Code Playgroud)
如果通信协议使更有可能或临界值为真(高)或假(低),这是否有帮助?
我查看了关于分支目标预测器的维基文章;这有点令人困惑:
我认为当 CPU 决定下一步要获取哪些指令(进入 CPU 管道来执行)时,分支目标预测器就会发挥作用。
但这篇文章提到了这样的一些观点:
指令缓存获取指令块
扫描块中的指令以识别分支
那么,指令缓存(==我想象的 L1i)是否基于某些分支目标预测数据(预)取指令?...
或者只是这篇文章暗示了x86以外的东西......好吧,或者我误解了一些东西
考虑单个静态分支的以下实际结果序列.T表示分支被采用.N表示不采用分支.对于这个问题,假设这是程序中唯一的分支.
TTTNTNTTTNTNTTTNTN
假设使用一位分支历史的两级分支预测器 - 即一位BHR.由于程序中只有一个分支,因此BHR如何与分支PC连接以索引BHT并不重要.假设BHT使用一位计数器,并且再次将所有条目初始化为N.此序列中哪些分支将被错误预测?使用下表. alt text http://img641.imageshack.us/img641/7117/branch.jpg
现在我不是要问这个问题的答案,而不是这个问题的指南和指针.两级分支预测器的含义是什么?它是如何工作的?BHR和BHT代表什么?
因此,我理解流水线处理器的分支预测中使用的基本技术 - 例如2位饱和计数器,两级自适应预测器等.
这是我的问题:
1)分支目标预测:为什么这很重要,这里使用的机制是什么?当我想到一个分支时,我认为"bne r2,r3,LABEL"表示如果r2!= r3然后分支到LABEL,这意味着做PC(程序计数器)= PC + LABEL.在这里预测目标有什么神秘之处?你知道它将基于LABEL的编译值.我可能在某种程度上忽略了这一点.
2)为什么程序计数器值本身(例如0x4001000C)或至少其最后几位用作分支预测方案的一部分?我看到了一种方案,其中PC的最后4位连接到(4位)分支历史寄存器,并且该8位值用于访问模式历史表.我认为PC很随意!
感谢您帮助理解这些问题
这是一篇很好的文章,讨论了低级优化技术,并展示了一个例子,即作者将昂贵的部门转换为廉价的比较. https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920
对于那些不想点击的人,基本上他转换了这个:
uint32_t digits10(uint64_t v) {
uint32_t result = 0;
do {
++result;
v /= 10;
} while (v);
return result;
}
Run Code Online (Sandbox Code Playgroud)
进入:
uint32_t digits10(uint64_t v) {
uint32_t result = 1;
for (;;) {
if (v < 10) return result;
if (v < 100) return result + 1;
if (v < 1000) return result + 2;
if (v < 10000) return result + 3;
// Skip ahead by 4 orders of magnitude
v /= 10000U;
result += 4;
} …Run Code Online (Sandbox Code Playgroud) 要了解有关CPU和代码优化的更多信息,我已经开始研究汇编编程.我还阅读了一些聪明的优化,比如"分支预测",CPU可以加速自身.
我的问题可能看起来很愚蠢,因为我还不太清楚这个问题.
我有一个非常模糊的记忆,我在某处(在互联网上)读过这些goto语句会降低程序的性能,因为它不能很好地处理CPU中的分支预测.然而,这可能只是我编造的内容并没有真正阅读过.
我认为这可能是真的.
我希望这个例子(在伪C中)将澄清为什么我认为是这样的:
int function(...) {
VARIABLES DECLARED HERE
if (HERE IS A TEST) {
CODE HERE ...
} else if (ANOTHER TEST) {
CODE HERE ...
} else {
/*
Let us assume that the CPU was smart and predicted this path.
What about the jump to `label`?
Is it possible for the CPU to "pre-fetch" the instructions over there?
*/
goto label;
}
CODE HERE...
label:
CODE HERE...
}
Run Code Online (Sandbox Code Playgroud)
对我来说,这似乎是一项非常复杂的任务.那是因为那时CPU需要查找goto跳转的位置,以便能够在那里预取指令.
你对此有所了解吗?
我想测量 Mac OS X 上英特尔处理器的 Xcode 上的分支预测失败情况,其明显的目的是速度优化。
有没有办法对 XCode 的 Instruments 进行编程来实现这一目标?
我已经检查过了,遗憾的是 Xcode 文档中没有此信息。我怀疑这可以通过一些自定义设置来实现。
目的是识别优化问题,例如: 为什么处理排序数组比处理未排序数组更快?
我知道存在针对在 Linux 和 Windows 上运行的英特尔处理器的英特尔商业解决方案。在 OS X 上,您显然只能监控在 Linux 或 Windows 系统上运行的远程 Intel 处理器。
与商业工具相比,我更喜欢一种设置/编程 Xcode 和 Apple 工具的方法,以至少获得对此问题的最低限度的了解。
冒着重复的风险,也许我现在找不到类似的帖子:
我正在用 C++(具体来说是 C++20)编写。我有一个带有计数器的循环,每转一次都会进行计数。我们就这样称呼它吧counter。如果counter达到页面限制(我们称之为page_limit),程序应该继续下一页。所以它看起来像这样:
const size_t page_limit = 4942;
size_t counter = 0;
while (counter < foo) {
if (counter % page_limit == 0) {
// start new page
}
// some other code
counter += 1;
}
Run Code Online (Sandbox Code Playgroud)
现在我想知道,因为计数器变得相当高:如果我不让程序counter % page_limit每次都计算模数,而是创建另一个计数器,程序运行得会更快吗?它可能看起来像这样:
const size_t page_limit = 4942;
size_t counter = 0;
size_t page_counter = 4942;
while (counter < foo) {
if (page_counter == page_limit) {
// start new page
page_counter = 0;
} …Run Code Online (Sandbox Code Playgroud) c++ performance assembly micro-optimization branch-prediction
我需要运行一个带有 N 个布尔变量的函数,我想让它们 constexpr 以消除比较并从分支预测失败中保存代码。
我的意思是:
templateFunc<b1, b2, b3, b4 ...>(args...);
Run Code Online (Sandbox Code Playgroud)
由于 b1..bn 变量只是布尔变量并且可能只有 2 个状态,我可以这样写:
if (b1 && b2)
templateFunc<true, true>(args...);
else if (b1 && !b2)
templateFunc<true, false>(args...);
else if (!b1 && b2)
templateFunc<false, true>(args...);
else
templateFunc<false, false>(args...);
Run Code Online (Sandbox Code Playgroud)
问题很明显,我需要对 5 个变量进行 64 次调用。有什么解决方案吗?
c++ templates variadic-templates constexpr branch-prediction
我正在阅读有关分支预测的内容,我想知道分支预测器是否会"推测性地"执行任何类型的指令.特别是,我想知道它是否会与硬件进行通信.
我们假设您有类似这样的事情:
while (true) {
if (condition)
SendPacketOverNetwork()
DoSomethingElse()
}
Run Code Online (Sandbox Code Playgroud)
(在汇编级别,if之后的第一条指令引发中断,或与硬件通信).如果分支预测器恰好"猜错",在这种情况下会发生什么?如果这不可能发生,为什么?分支预测器将执行什么样的指令?我误解了分支预测器的作用吗?