这种方法是否对分支的预测产生了影响

Does this approach positvely impact branch prediction?

本文关键字:产生了 影响 分支 方法 是否      更新时间:2023-10-16

我一直在尝试制作一种回调函数,在此过程中,我意识到我喜欢的回调功能也可能会改变CPU处理引擎盖下的分支预测的方式。我知道过度优化是人们应该避免的事情,尤其是早期,但这是一种非常适合我使用的方法,并且避免缓存失误的效果将是一个整齐的奖励。

我不了解CPU架构足以亲自回答这一点,所以我很好奇是否有人知道这是否会影响分支机构的处理方式,并且是否以有益的方式进行了分支机构的预测。

我的初始解决方案看起来像这样:(请注意较大的块(

enum _myenum { t1, t2, t3 }myenum; //enumerator and switch 
switch (myenum){
case t1: 
    { /*a block*/ }
    break;
case t2: 
    { /*another block*/ }
    break;
case t3: 
    { /*yet another block*/ }
    break;
default: break;
}

和适合我使用的解决方案:

enum _myenum { t1, t2, t3 }myenum; //same enum
//a map of lambdas/functions
std::map<_myenum, std::function<void()>>lambda_map{ 
    { t1, [&]() {/*a block*/} },
    { t2, [&]() {/*another block*/ }},
    { t3, [&]() {/*yet another block*/ }}
}; 
lambda_map[myenum](); //to run the callback

我将在其中运行lambda_map[myenum]();而不是更难的轨道开关函数。

但是Lambda-Pointer地图是否会从潜在的缓存中保存CPU?就像我所收集的那样,不必预测语句或通过开关案例运行,而是基于集合myenum变量跳到特定功能,应该做到这一点,对吗?或至少以某种方式影响它。

我很好奇lambda_map[enum]();是否可以在分支机构预测和避免缓存失误上更好,而不是通过可能的情况列表的开关语句。

我将在哪里运行lambda_mapmyenum;而不是更困难的轨道开关功能。

这可能是误导您的原因。开关语句不一定比某些类似地图的结构"更难跟踪"。实际上,由于编译器的优化,它很可能会作为跳台实现,这是一系列跳跃指令,类似于您想象的第二个解决方案。

在您的情况下,使用std::map几乎可以保证会因为间接而变慢(并且与之相处的高速缓存(,并且因为它使用二进制搜索来找到一个值。您想要的是功能指针的数组(std::array((使用std::function或Lambdas(,使用枚举器作为索引。如果数组不可行(由于密钥的性质(,则可以使用hashmap(std::unordered_map(。

在性能方面,无法分析,无法分析,功能障碍方法是否击败了编译器优化的开关。

话虽如此,我经常发现自己编写了阵列或哈希图(功能与否(,而不是Switch语句,因为个人偏好范围从样式(块嵌套,位置,...(到实际可维护性。也是因为我不喜欢开关语句的结构。将最后一部分撒上一粒盐:我敢肯定有些人喜欢类似开关的结构并鄙视替代方案。