通过代码移动优化C代码

时间:2018-08-16 05:30:51

标签: c optimization

optimizeMe   (const char* string0, const char* string1)
{
    int i0; 
    int i1  = strlen(string1) - 1;
    int count = 0;

    for (i0 = 0; i0 < strlen(string0); i0++)    
    {
        if (toupper(string0[i0]) == toupper(string1[i1])) 
            count++;
        count++;
        if ((i0%32)==0) 
            i1--;
    }
    return(count / 8);
}

我知道我可以通过使用寄存器gcc -o2,降低强度i0%32=0x10000和通用表达式count/8 = count >> 3等来优化此代码;
但是,如何通过代码移动来优化它们?专门用于if语句和il--
任何提示表示赞赏!

1 个答案:

答案 0 :(得分:0)

正如伦丁在评论中指出的那样,这些都是过早的优化。它们为时过早,因为您显然只是在猜测,而没有使用探查器在具有实际瓶颈的真实程序上测试您的理论。

它们也是 micro 的优化,并且自80年代以来,由于在技术上的重大突破,我们实际上并不需要在C中进行 micro 的优化。例如,我们要做令人惊奇的事情,例如实时模拟三维领域。

gcc已支持您可能感兴趣的各种功能,例如死代码消除,代码提升(在某些情况下甚至进入编译时)和配置文件引导的优化。我认为我们理所当然我们拥有一个编译器,它可以通过代码的寂寞来静态推断出代码无法访问的事实;对于机器而言,这是相当复杂的优化。

通过在测试时进行概要分析,然后重新编译,将探查器数据反馈到编译器中,编译器获得有关如何重新排列分支以更好地进行预测的信息。这是配置文件引导的优化,并且是半自动化的。我不知道《德军总部3D》的作者会为这种技术做些什么...

说到探查器,如果我建议您在一些现实的用例(即具有活跃开发和庞大社区的实际程序)中对它们进行测试:

  

使用register

     

力量降低i%32=0x10000

     

count/8 = count >> 3

最后的优化isn't even correct for you(请参阅练习5),顺便说一下,这可能是时候提一下我们套件中的其他调试工具了。我强烈建议您检出ASan(和其他UBSans),这样可能会节省您调试时间小时

最好使用size_t,因为that's what strlen returns首先,size_t可以更方便地与strlen一起使用,而且速度可能也更快(由于事实size_t没有符号位,因此在编写for (size_t x = 0; x < y; x++))之类的东西时没有潜在的符号处理开销……

...,或者,如果您想向编译器提供特定于体系结构的提示(可能没有配置文件引导的优化,或者您不需要手动进行此操作),也可以使用{{ 3}}或其他并非真正适合该任务的东西,但仍比int更合适。

我收集到,您必须从某个地方获取输入,否则您的程序是“纯净的”,从(功能上)意义上讲,它没有副作用,根本不会改变用户与系统交互的方式(在那方面)在这种情况下,您的编译器甚至可能会将所有逻辑都提升到编译时评估中)...您是否考虑过调整您所使用的任何文件和/或流(即stdinstdout)的缓冲区大小重新使用?您应该能够使用uint_fast32_t来执行此操作...如果一次打开许多流,则可能希望尝试选择较小的流缓冲区大小,以将所有内容保留在缓存中。我喜欢从1的缓冲区大小开始,然后从那里继续前进,这样一来,您将准确地看到系统瓶颈在哪里...如果您要展开循环gcc会很高兴地自动进行(如果有好处的话 ))...

如果您使用的是真正原始的编译器(虽然分析器实际上可能会引导您直接进行最重要的优化,但您没有用,但优化您作为开发人员的时间) ,您也许可以建议编译器为这些行发出非分支代码:

// consider `count += (toupper((unsigned char) string[i0]) == toupper((unsigned char) string1[i1]));`?
if (toupper(string0[i0]) == toupper(string1[i1])) 
    count++;

强制进行强制转换是防止setvbuf的必要...您绝对需要确保传递给<ctype.h>函数的唯一值是unsigned char值或{ {1}}。

EOF