C++ If-else树优化
我正试图为以下问题找到一个好的解决方案: 我的输入是一组布尔变量C++ If-else树优化,c++,algorithm,optimization,code-generation,compiler-optimization,C++,Algorithm,Optimization,Code Generation,Compiler Optimization,我正试图为以下问题找到一个好的解决方案: 我的输入是一组布尔变量b0到bn和 一组if语句,在表达式(布尔变量的连词)为真的情况下调用某个函数 例如: 无效测试(布尔b0、布尔b1、布尔b2、布尔b3、布尔b4){ 如果(b0&&b1){action1();} 如果(b0&&b1&&b3){action2();} 如果(b0&&b1&&b4){action2();} 如果(b0&&b2){action3();} } 显然,为了减少比较次数,可以对代码进行优化 例如: 无效测试(布尔b0、布尔b
b0
到bn
和
一组if
语句,在表达式(布尔变量的连词)为真的情况下调用某个函数
例如:
无效测试(布尔b0、布尔b1、布尔b2、布尔b3、布尔b4){
如果(b0&&b1){action1();}
如果(b0&&b1&&b3){action2();}
如果(b0&&b1&&b4){action2();}
如果(b0&&b2){action3();}
}
显然,为了减少比较次数,可以对代码进行优化
例如:
无效测试(布尔b0、布尔b1、布尔b2、布尔b3、布尔b4){
if(b0){
如果(b1){
行动1();
如果(b3){action2();}
if(b4){action2();}
}
如果(b2){action3();}
}
}
是否有一种算法可以解决/优化此问题(甚至可能以最佳方式)?很明显,它可以表示为图形、表格等,但不知何故,我仍然找不到智能解决方案 更新:我想我没有很好地解释这个问题。将该问题视为具有多个输出的真值表。输入是布尔变量,输出是动作。所以这不仅仅是可以用KV-map或Quine-McCluskey算法解决的问题。我想这更复杂 上面示例的表格是(我省略了“无输出”的情况):
不要过早地优化 如果您正在考虑此类优化,您必须首先进行度量。确保此函数是生产代码中的热点。因此,
- 打开最高优化级别(-O3)
- 使用适当的工具查找热点,如perf或英特尔的vTune
尽管如此,我认为您的代码的第二个版本可以更流畅地阅读。不要过早地进行优化 如果您正在考虑此类优化,您必须首先进行度量。确保此函数是生产代码中的热点。因此,
- 打开最高优化级别(-O3)
- 使用适当的工具查找热点,如perf或英特尔的vTune
尽管如此,我认为您的代码的第二个版本可以更流利地阅读。我理解您的要求。有一些优化工具可用于帮助转换此类代码。但基本上,这是没有必要的 你的新代码也不是更好。它甚至有5个if语句。在性能方面,编译器的优化器会很小心。它将检测公共子表达式并优化它 这基本上也应该由软件开发人员/设计师完成。同行评审将检测该代码并修复语义问题 你当然知道布尔表达式可以通过Quine&McCluskey或其他方法最小化。但我知道这不是你的问题 Coverity/QAC/SonarCube的静态代码分析可以检测到它,但无法修复它。这需要手动完成 或者您需要评估源代码优化器,如
请查收。我理解你的要求。有一些优化工具可用于帮助转换此类代码。但基本上,这是没有必要的 你的新代码也不是更好。它甚至有5个if语句。在性能方面,编译器的优化器会很小心。它将检测公共子表达式并优化它 这基本上也应该由软件开发人员/设计师完成。同行评审将检测该代码并修复语义问题 你当然知道布尔表达式可以通过Quine&McCluskey或其他方法最小化。但我知道这不是你的问题 Coverity/QAC/SonarCube的静态代码分析可以检测到它,但无法修复它。这需要手动完成 或者您需要评估源代码优化器,如
请检查。一般来说,如果您需要处理一组布尔标志,请将它们合并到一个uint32中,这样您就可以非常轻松地测试它们
#include <cstdint>
enum Flags
{
kB0 = 1 << 0,
kB1 = 1 << 1,
kB2 = 1 << 2,
kB3 = 1 << 3,
kB4 = 1 << 4,
kB5 = 1 << 5,
};
inline bool testFlagsSet(uint32_t testFlags, uint32_t flags)
{
return (testFlags & flags) == testFlags;
}
void test(uint32_t flags) {
if(testFlagsSet(kB0 | kB1, flags)) { action1(); }
if(testFlagsSet(kB0 | kB1 | kB3, flags)) { action2(); }
if(testFlagsSet(kB0 | kB1 | kB4, flags)) { action3(); }
if(testFlagsSet(kB0 | kB2, flags)) { action4(); }
}
#包括
枚举标志
{
kB0=1一般来说,如果需要处理一组布尔标志,请将它们合并到一个uint32中,这将允许您相当轻松地测试它们
#include <cstdint>
enum Flags
{
kB0 = 1 << 0,
kB1 = 1 << 1,
kB2 = 1 << 2,
kB3 = 1 << 3,
kB4 = 1 << 4,
kB5 = 1 << 5,
};
inline bool testFlagsSet(uint32_t testFlags, uint32_t flags)
{
return (testFlags & flags) == testFlags;
}
void test(uint32_t flags) {
if(testFlagsSet(kB0 | kB1, flags)) { action1(); }
if(testFlagsSet(kB0 | kB1 | kB3, flags)) { action2(); }
if(testFlagsSet(kB0 | kB1 | kB4, flags)) { action3(); }
if(testFlagsSet(kB0 | kB2, flags)) { action4(); }
}
#包括
枚举标志
{
kB0=1您是否检查了生成的程序集以推断“此代码可以进行优化以最小化比较次数”?我没有注意到您的两个版本在以下方面有很大的差异:我相信它们的意思是返回操作,而不是仅仅运行操作并继续。@StoryTeller:谢谢您的评论。我想gcc、clang等在优化此类代码方面已经做得很好了。这更像是一个算法问题,即如何最大限度地减少比较次数@yukashimahuksay这不是关于是否返回某些内容。我感兴趣的是最小化比较的数量。我的意思是,您的代码是否只执行其中一个操作,或者可能执行其中几个操作。在后一种情况下,我认为您的代码甚至不会减少比较的数量。您是否检查了生成的程序集以进行推断“可以对该代码进行优化,以尽量减少比较次数“?我没有注意到您的两个版本在上有很大的差异,我相信它们的意思是返回操作,而不是仅仅运行操作并继续。@StoryTeller:谢谢您的评论。我想gcc、clang等在优化此类代码方面已经做得很好了。它更像是一种算法。”