【问题标题】:Realistic examples of optimization through branch removal通过删除分支进行优化的实际示例
【发布时间】:2023-03-22 20:18:01
【问题描述】:
根据Intel,删除分支是优化 C 代码以用于紧密循环的最有效方法之一。但是,链接页面中的示例仅涵盖循环展开和将不变分支移动到循环之外。
是否有其他和不同的(之前和之后)分支移除以进行优化的示例?
【问题讨论】:
标签:
c
optimization
intel
branch-prediction
【解决方案1】:
如果消除分支是您的目标,那么您可能希望考虑数学或一些非便携式解决方案。
考虑以下示例:
if (a < b)
y = C;
else
y = D;
这可以重写为 ...
x = -(a < b); /* x = -1 if a < b, x = 0 if a >= b */
x &= (C - D); /* x = C - D if a < b, x = 0 if a >= b */
x += D; /* x = C if a < b, x = D if a >= b */
为了使上述工作有效,它假设您的处理器可以评估 a 而不会生成分支指令。它还会影响可读性。
值得吗?有时,但通常不会。如果分支或分支错误预测因为它不偏向一个分支或另一个分支而让您付出了很多代价,那么它可能是值得的。但可能不是。一如既往,个人资料。
如果这是您的目标,那么一点点数学/算术对消除分支大有帮助。虽然之前已经说过无数次了,但你可以做某事,并不代表你就应该这样做。
希望这会有所帮助。
【解决方案2】:
这是tutorial 有更多示例。除了这里的内容,我还可以考虑使用 switch 语句或sentinel values。我还发现这个other tutorial 有更晦涩的方法来避免 if 语句。
如果您正在进行优化,我强烈建议您使用诸如 callgrind/kcachegrind 之类的分析工具,并专注于您花费最多时间的代码部分。以某些方式优化代码可能会混淆代码或使其更难维护,根据我的经验,为了优化而优化是一个非常糟糕的主意。
使用分析器后,您可能会发现对于您的代码,使用更好的数据结构或避免某种算法可能是优化您的 C 代码的最有效方法,而不是分支删除。
我并不是要说教,我只是不同意删除分支是优化代码的最佳方式的前提。我知道这对现代处理器有很大帮助,但是任何优化工作的第一步应该是找到代码的慢部分,然后从那里开始。
【解决方案3】:
最佳的块排序可以产生相当大的差异,并出现在每段代码中。而且我不会轻易将英特尔给出的示例视为“不切实际”。