VS C++:树状 if/else 结构的代码生成需要很长时间

VS C++: Code generation of tree-like if/else structure takes very long

本文关键字:代码生成 长时间 结构 else C++ 树状 if VS      更新时间:2023-10-16

我有一个(公认的大(if/else条件结构:

if ( a > 0 )
{
    if ( b > 0 )
    {
        ...
    }
}else
{
   ...
}

结构为树状,深度为9(共512个节点(。

更糟糕的是,有 500 个需要编译......

但是,代码生成似乎需要很长时间。我停用了优化(调试模式(,所以在我的 opitit 中,它应该不需要那么长时间来生成......

您知道如何提高代码生成速度吗?

更新:

该代码只是一个由几棵树组成的随机森林分类器。所以,是的,我可以把它放在不同的结构中,但最快的代码执行将是硬编码的 if 条件。

更新 2:

我仔细查看了输出,似乎问题出在链接过程上。你能解释一下,为什么,或者如何改进吗?

更新 3:

这是我的链接器命令:

/OUT:"C:ProjectFolderMyFile.exe" 
/MANIFEST /LTCG /NXCOMPAT   
/PDB:"C:ProjectFolder\installx64ReleaseMyFile.pdb" 
/DYNAMICBASE "ThirdPartyLibrary1.lib" "ThirsPartyLibrary2.lib" 
"kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" 
/DEBUG /MACHINE:X64 /OPT:REF /INCREMENTAL:NO 
/PGD:"C:ProjectFolder\installx64ReleaseMyFile.pgd" 
/SUBSYSTEM:CONSOLE 
/MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"C:ProjectFolder\buildx64ReleaseMyFile.exe.intermediate.manifest" 
/OPT:ICF /ERRORREPORT:PROMPT /NOLOGO 
/LIBPATH:"D:3rdx64lib1" /LIBPATH:"D:3rdx64lib2" /TLBID:1 

更新 4:

仅供参考,目前,链接过程需要655MB的RAM,正在缓慢上升...

回复:Do you have an idea how to improve the speed of the code generation?

如果你真的需要以 512 种方式分支你的代码(我不确定你是否这样做(,你可以构造一个整数值,其中最低的 9 位中的每一个都反映条件(a > 0)(b > 0) 等。然后有一个 512 个案例的开关,从 0 到 511。

[添加示例代码]

这是我要做的:

int mask(0);
if(a > 0) mask |= 0x01;
if(b > 0) mask |= 0x02;
if(c > 0) mask |= 0x04;
...
if(h > 0) mask |= 0x80;
if(i > 0) mask |= 0x100;
switch(mask)
{
case 0x01: // only (a>0) was true
  ...
break;
....
case 0x77: // all but (i>0) were true
  ...
break;
}

你已经知道这一点,但我要再说一遍:你不应该有一个包含 if/else 块的打包树到深度 9。 你甚至不应该有一个这样的结构,更不用说其中的 500 个了。 无论你从这个设计中得到什么,你都应该仔细寻找其他方法来获得它。

你确定这些结构是罪魁祸首吗? C++ 编译时间可能令人惊讶。 它们是否在许多位置包含的头文件中?

无论如何,因为这是一件非常不寻常的事情,所以您的编译器没有经过优化以有效地编译它,因此您的编译速度很慢。 如果你可以用 gcc 或 clang 来编译,那么这可能会有所帮助,但更有可能的是你的问题没有解决方案,如前所述:如果你想让你的编译速度更快,那么你必须停止做你正在做的奇怪事情,做一些更像正常C++的事情。

根据最新的it's the linker that seems to take forever澄清...如果这是启用了全程序优化的发布/优化版本,请务必注意使用全程序优化的快速提示中的注意事项:

  • 从命令行或通过生成文件生成时,需要将/LTCG 开关添加到链接命令行,以告知链接器希望看到使用/GL 编译的一个或多个对象文件。如果不这样做,则会浪费一些生成时间,因为链接器在到达使用/GL 编译的模块时必须重新开始。如果通过 IDE 生成,则此内容位于"链接器优化"页上的项目配置设置中。

  • 使用/GL 可减少编译时间,但链接时间会增加,因为在链接期间将工作移至。整体构建时间可能会增加一点,但应该不会增加很多。

这是我所做的:

我目前保留 if-else 语句,如果在某个时候我需要速度。

现在,我创建了一个树的参数化版本(见下文(。

然后代码如下所示(对于具有 16 个节点的树,每个节点两个参数(:

// "sample" denotes the thing that I want to classify.
// nodeFunction evaluates to a true/false statement the detemines the next leaf
double decisionTree( sample )
{
    const bool isTerminalNode[ 15 ] = {false, false, true, true, false, ...};
    const double parameters[ 15 ][ 2 ] = {{1.0, 2.0}, {1.5, 7.5}, {1.7, 7.7}, ...};
    const double returnValues[ 31 ] = {-1.0, -1.0, 1.5, 3.7, ...};
    int nCurrentIdx = 0;
    while( !isTerminalNode[ nCurrentIdx ] )
    {
        if ( nodeFunction( parameters[ nCurrentIdx ], sample ) )
            nCurrentIdx = nCurrentIdx * 2 + 1; // go left
        else
            nCurrentIdx = (nCurrentIdx + 1) * 2; // go right
    }
    return returnValues[ nCurrentIdx ];
}

树结构如下所示:

          0
       /     
      1       2
    /      /   
   3    4  5     6
  ...  ... ... ... ... etc