简体   繁体   English

c ++尝试通过替换测试来优化代码

[英]c++ attempt to optimize code by replacing tests

I am looking at code that someone else wrote, and it has a lot of debug sections, of type 我正在查看别人写的代码,它有很多类型的调试部分

if(0) { code }

or if(1) { code } 或者if(1) { code }

or if(false) { code } if(false) { code }

There is even 甚至有

#if(0)
#endif

(which did not turn gray though - I thought that it should) (虽然没有变灰 - 我认为应该)

I was wondering, if I replace these with some #if 0 (or #ifdef _DEBUG ), is it possible to optimize the code ? 我想知道,如果用一些#if 0 (或#ifdef _DEBUG )替换它们,是否可以优化代码? - or - it will not make any difference ? - 或 - 它不会有任何区别?

I think that it may help, since I have seen code that is within these sections being grayed out - and I thought that this code is removed from the Release executable... Therefore making it faster. 我认为它可能会有所帮助,因为我看到这些部分中的代码被灰显 - 我认为这个代码已从Release可执行文件中删除...因此使其更快。 Is that true ? 真的吗 ?

The code that I am thinking of is inside functions that could be called lots of times... 我正在考虑的代码是可以多次调用的函数内部...

Edit: The code I am referring to is being run millions of times. 编辑:我所指的代码正在运行数百万次。 I am aware that the contents of the if(0) will be ignored... 我知道if(0)的内容将被忽略...

I am also aware of the benefit of being able to easily debug an issue, by switching a test from 0 to 1... 通过将测试从0切换到1,我也意识到能够轻松调试问题的好处......

My question was, the fact that I am adding millions of millions of times the test if(0) does not add overhead... I am trying to figure out what are all the things that could make this code take fewer hours. 我的问题是,如果(0)不增加开销,我将增加数百万次测试的事实......我试图弄清楚什么是可以使这段代码花费更少时间的所有事情。

If expressions placed inside those IFs are constant and determinable at the time of compilation , then you may be almost sure that the compiler has already removed them off the code for you. 如果置于这些IF中的表达式在编译时常量且可确定的 ,那么您可能几乎可以确定编译器已经为您删除了代码。

Of course, if you compile in Debug-Mode, and/or if you have optimization-level set to zero, then the compiler may skip that and leave those tests - but with plain zero/one/true/false values it is highly unlikely. 当然,如果你在Debug-Mode中编译,和/或如果你将优化级别设置为零,那么编译器可能会跳过它并离开那些测试 - 但是使用普通的零/一/真/假值,这是极不可能的。

For a compile-time constant branches, you may be sure that the compiler removed the dead ones. 对于编译时常量分支,您可以确定编译器删除了死分支。

It is able to remove even complex-looking cases like: 它甚至可以删除复杂外观,例如:

const int x = 5;

if( 3 * x * x < 10 ) // ~ 75 < 10
{
    doBlah(); // skipped
}

However, without that 'const' marker at X, the expression's value may be not determinable at the compile time, and it may 'leak' into the actual final product. 但是,如果没有X上的'const'标记,表达式的值可能无法在编译时确定,并且可能会“泄漏”到实际的最终产品中。

Also, the value of expression in following code is not necesarily compile-time constant: 此外,以下代码中的表达式值不一定是编译时常量:

const int x = aFunction();

if( 3 * x * x < 10 ) // ~ 75 < 10
{
    doBlah(); // skipped
}

X is a constant, but it is initialized with value from a function. X是常量,但它是用函数的值初始化的。 X will most probably be not determinable at the time of compilation. X很可能在编译时无法确定。 In runtime the function could return any value*) so the compiler must assume that X is unknown. 在运行时,函数可以返回任何值*),因此编译器必须假定X是未知的。

Therefore, if you have possibility, then use preprocessor. 因此,如果您有可能,那么使用预处理器。 In trivial cases that won't do much, because the compiler already knew that. 在无关紧要的情况下,因为编译器已经知道了。 But cases are not always trivial, and you will notice the change vrey often. 但案件并非总是微不足道,你会经常注意到这种变化。 When optimizer fails to deduce the values, it leaves the code, even if it is dead. 当优化器无法推导出值时,它会离开代码,即使它已经死了。 Preprocessor on the other hand is guaranteed to remove disabled sections, before they get compiled and optimized. 另一方面,预处理器可以在编译和优化之前删除已禁用的部分。 Also, using preprocessor to do that at least will speed up the compilation: the compiler/optimizer will not have to traceconstants/calculate/checkbranches etc. 此外,使用预处理器至少可以加快编译速度:编译器/优化器不需要traceconstants / calculate / checkbranches等。

*) it is possible to write a method/function which return value will actually be determinable at the compilation and optimization phases: if the function is simple and if it gets inlined, its result value might be optimized out along with some branches.. But even if you can somewhat rely on removing the if-0 clauses, you cannot rely on the inlining as much.. *)可以编写一个方法/函数,其返回值实际上可以在编译和优化阶段确定:如果函数很简单并且如果它被内联,它的结果值可能会与一些分支一起优化。但是即使你可以在某种程度上依赖于删除if-0子句,你也不能依赖于内联..

If you have code inside an if (0) block, the code generated by the compiler will be the same as if that block wasn't there on any reasonable compiler. 如果你在if (0)块中有代码,那么编译器生成的代码将与在任何合理的编译器上没有该块的代码相同。 The code will still be checked for compile-time errors. 仍将检查代码是否存在编译时错误。 (Assuming you don't have any jump labels inside it or something weird like that.) (假设你里面没有任何跳转标签或类似的东西。)

If you have code inside an if (1) block, the code generated by the compiler will be the same as if the code was just inside braces. 如果你有一个if (1)块内的代码,编译器生成的代码将与代码只是在大括号内相同。 It's a common way to give a block of code its own scope so that local variables are destructed where desired. 这是为代码块提供自己的范围的常用方法,以便在需要时破坏局部变量。

If you ifdef out code, then the compiler ignores it completely. 如果您ifdef出来的代码,那么编译器完全忽略它。 The code can be completely nonsense, contain syntax errors, or whatever and the compiler will not care. 代码可以是完全无意义的,包含语法错误,或者编译器不关心的任何内容。

Typically, #if 0 is used to remove code whilst still keeping it around - for example to easily compare to options, I sometimes do: 通常, #if 0用于删除代码,同时仍然保留它 - 例如,为了方便地与选项进行比较,我有时会这样做:

#if 1
   some sort of code 
#else
   some other code
#endif

That way, I can quickly switch between the two alternatives. 这样,我可以快速切换两种选择。

In this case, the preprocessor will just leave one of the two options in the code. 在这种情况下,预处理器将只留下代码中的两个选项之一。

The constructs of if(0) or if(1) is similar - the compiler will pretty much remove the if, and in the case of 0 also remove the rest of the if-statement. if(0)if(1)的构造类似 - 编译器将几乎删除if,并且在0的情况下也删除if语句的其余部分。

I think it's rather sloppy to leave this sort of stuff in "completed" code, but it's very useful for debugging/development. 我认为将这类内容留在“已完成”的代码中相当草率,但它对于调试/开发非常有用。

Say for example you are trying a new method for doing something that is much faster: 比如说你正在尝试一种新方法来做更快的事情:

if (1) 
{
   fast_function();
}
else
{
    slower_function();
}

Now, in one of your testcases, the result shows an error. 现在,在您的一个测试用例中,结果显示错误。 So you want to quickly go back to slower_funcion and see if the result is the same or not. 所以你想快速回到slower_funcion ,看看结果是否相同。 If it's the same, then you have to look at what else has changed since it last passed. 如果它是相同的,那么你必须看看自上次通过以来还有哪些变化。 If it's OK with slower_function, you go back and look at why fast_function() is not working as it should in this case. 如果使用slow_function就可以了,那么你回过头来看看为什么fast_function()在这种情况下不能正常工作。

It's true (depending on your build settings and preprocessor). 这是真的(取决于您的构建设置和预处理器)。

Putting debug code in #ifdef _DEBUG (or similar) is a standard way to keep these completely out of your release builds. 将调试代码放在#ifdef _DEBUG (或类似的)中是一种标准方法,可以将这些完全保留在发布版本之外。 Usually the debug build #define s it, and the release build does not. 通常调试构建#define是它,而版本构建则没有。

Usually, though, a compiler should also remove code such as if (0) , if given the proper optimization flags, but this puts extra work on the compiler, and on the programmer (now you have to go change them all!). 但是,通常情况下,如果给出了正确的优化标志,编译器也应该删除if (0)代码,但这会给编译器以及程序员带来额外的工作(现在你必须全部改变它们!)。 I'd definitely leave this to the preprocessor. 我肯定会把它留给预处理器。

You're correct. 你说的没错。 If you compile with #define DEBUG 0 then you will be actually removing all the #if DEBUG blocks at compile time. 如果使用#define DEBUG 0进行编译,那么实际上您将在编译时删除所有#if DEBUG块。 Hence, there will be lot less code, and it will run faster. 因此,代码将会少得多,而且运行速度会更快。

Just make sure you release your code after making #define DEBUG 0 at release time. 只需确保在发布时制作#define DEBUG 0后释放代码。

A good optimizing compiler(GCC, MSVC) will remove if(0) and if(1) from code completely... the translation to machine code will NOT test for these conditions... 一个好的优化编译器(GCC,MSVC)将从代码中完全删除if(0)if(1) ......对机器代码的转换将不会测试这些条件......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM