分支的缓存缺失惩罚
Cache miss penalty on branching
我想知道用2乘法代替分支是否更快(由于缓存丢失惩罚)?
以下是我的例子:
float dot = rib1.x*-dir.y + rib1.y*dir.x;
if(dot<0){
dir.x = -dir.x;
dir.y = -dir.y;
}
我试着用
来代替它float dot = rib1.x*-dir.y + rib1.y*dir.x;
int sgn = (dot < 0.0) - (0.0 < dot ); //returns -1 or 1 (no branching here, tested)
dir.x *= sgn;
dir.y *= sgn;
分支并不意味着缓存丢失:只有指令预取/流水线会受到干扰,因此您可能会在编译时用它阻塞一些SSE优化。
另一方面,如果只使用x86指令,推测执行将使处理器正确地开始执行最常用的分支。
另一方面,如果你在50%的时间里输入if,你处于最坏的情况:在这种情况下,我会尝试寻找SSE管道,并使用SSE优化执行,可能从这篇文章中得到一些提示,与你的第二块代码一致。
但是,对代码进行基准测试,检查生成的汇编程序,以便找到此优化的最佳解决方案,并获得适当的见解。并最终让我们更新:)
乘法的成本取决于几个因素,是使用32位还是64位浮点数,以及是否启用SSE。根据此来源,两次浮点乘法的成本为10个周期:http://www.agner.org/optimize/instruction_tables.pdf
分支的成本还取决于几个因素。根据经验,不要担心代码中的分支。分支预测器在CPU上的确切行为将定义性能,但在这种情况下,您可能应该期望分支最多是不可预测的,因此这很可能导致许多分支错误预测。根据此来源,分支错误预测的代价是10-30个周期:http://valgrind.org/docs/manual/cg-manual.html
最好的建议是进行分析和测试。我猜在现代的酷睿i7上,这两个乘法运算应该比分支if the range of input varies sufficiently as to cause sufficient branch mispredictions as to outweigh the cost of the additional multiplication
更快。
假设漏检率为50%,支路的成本平均为15个周期(30 * 0.5),float mul的成本为10个周期。
EDIT:添加链接,更新估计的指令成本。
- cmake更新缓存的变量
- 试图对缓存进行跨步测试,但程序并没有结束
- 缓存std::数组的选定元素,并在c++中自动保持其一致性
- 通过ccmake在cmake中缓存依赖选项
- 使用宏扩展的泛型:为什么指令缓存使用不当?
- 如何使缓存线程安全
- 存储指令是否会阻止缓存未命中的后续指令?
- 缓存局部性与函数调用
- Qt 网页程序集缓存
- 多线程减慢程序速度:无错误共享,无互斥锁,无缓存未命中,无小工作量
- std::shared_ptr vs std::make_shared:意外的缓存未命中和分支预测
- 多个 rocksdb 实例:使用单个共享缓存还是多个独立缓存?
- 无法链接 LRU 缓存C++
- 空函数的参数是否加载到缓存中?
- 是否可以检查变量是否位于 L1/L2/L3 缓存中
- dynamic_cast每次调用是否比具有空检查的缓存变量更昂贵?
- C++:如何在从给定缓存中排除数字的同时生成随机数
- 如果着色器中未使用绑定属性位置,是否会对其进行惩罚
- 如何对0,1,..中的k个随机数进行采样..,n-1,而不缓存到数组
- 分支的缓存缺失惩罚