Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 函数指针上的分支预测_C++_Function Pointers_Branch Prediction - Fatal编程技术网

C++ 函数指针上的分支预测

C++ 函数指针上的分支预测,c++,function-pointers,branch-prediction,C++,Function Pointers,Branch Prediction,我有一个循环在一次又一次地运行。该循环内的逻辑取决于程序所处的模式。为了提高性能,我认为可以初始化函数指针数组functionPtr[],这样就可以调用运行正确逻辑的functionPtrmode。循环将在许多循环中保持相同的模式(前面的数字未知,但有数千个)。该程序仅在intel x64计算机上运行,不需要可移植性 我希望CPU能够利用分支预测,但因为我的分支不是有条件的(在汇编级别上),但分支的位置确实取决于一个变量(functionPtr+mode)。CPU是否会尝试计算functionP

我有一个循环在一次又一次地运行。该循环内的逻辑取决于程序所处的模式。为了提高性能,我认为可以初始化函数指针数组functionPtr[],这样就可以调用运行正确逻辑的functionPtrmode。循环将在许多循环中保持相同的模式(前面的数字未知,但有数千个)。该程序仅在intel x64计算机上运行,不需要可移植性


我希望CPU能够利用分支预测,但因为我的分支不是有条件的(在汇编级别上),但分支的位置确实取决于一个变量(functionPtr+mode)。CPU是否会尝试计算functionPtr+模式,并在管道中开始引入这些指令

分支预测适用于实际分支,在分支计算之前,我们不知道这些分支,分支计算告诉我们下一步将执行哪条指令。但由于在您的代码中,下一条指令是已知的,这取决于我们所处的模式,所以不需要任何预测,它们也不会在管道中等待


考虑到在模式更改和指令选项之间有足够的时间,管道每次都能成功地获取正确的指令,而无需任何额外的努力。

是的,最近的处理器可以(至少类似于)对间接跳转进行分支预测

从奔腾(英特尔第一个进行分支预测)到第一个奔腾IV,所有用于间接分支的都是分支目标缓冲区(BTB)。这意味着,当(并且仅当)目标与前一个目标完全相同时,他们才能正确地“预测”此类分支——这听起来似乎适合您的情况


从奔腾M/Prescott(最后一款奔腾IV)开始,英特尔改进了间接跳转的分支预测,使用了两级自适应预测器。如果我正确地理解了您的问题(即,您的循环将在许多连续迭代中以相同的目标执行,而这正是您所关心的),即使是BTB也足以满足您的目的。如果(例如)在连续数字的最低有效位上进行分支,那么两级预测器将变得更有用,因此,在一次迭代中跳转到一个目标,在下一次迭代中跳转到另一个目标,这是一种可预测的模式。对于这样的模式,BTB本身总是会错误地预测分支,但当前处理器中的两级预测器会正确地预测(在前两次迭代之后,因此可以检测到模式)。

来自Intel的微体系结构,AMD和VIA CPU——汇编程序员和编译器制造商的优化指南

第3.7节(对于砂桥,其他处理器在其他章节中) 间接跳转和呼叫的模式识别 间接跳转和间接调用(但不是返回)使用与分支指令相同的两级预测器进行预测


指向函数的指针是间接调用。< /p>与分支预测无关,但应该是好的——即使对于间接函数调用,也不应该有流水线停滞。我看到您正在使用C++。你不能创建两个从同一接口继承的类,然后根据模式实例化正确的类吗?如果只有少数情况,你可以将循环中的函数作为模板参数。在运行时选择(例如switch语句),一个包含循环的模板函数。请注意,这会增加代码大小。@Vincent,我认为这也有同样的问题,如果您有foo[mode].run(),那么您仍然有一个指向foo[mode]的指针要计算,还有一个函数要调用。无论如何,在我的例子中,run()调用中所需的信息会修改下一次run()调用中使用的变量,即使是对于不同的模式,因此将其保留在一个类中是有意义的。@Neil,当模式不可预测地在整个循环中切换时,这听起来似乎不起作用。间接分支仍然需要预测。当给定的分支每次都相同时,这是一个简单的预测,但它仍然使用BTB(分支目标缓冲区)中的条目。来自内存/寄存器的数据在解码时不可用,更不用说在解码前的提取时了,因此即使数据最近没有改变,仍然需要进行预测。除非您使用自修改机器代码重写相关的分支指令,否则目标在需要它的CPU部分并不容易获得。