Tag: 编译器优化

C / C ++在最短的执行时间内提供任何保证吗?

为什么编译器似乎对没有任何作用的循环有礼貌,而不是消除它们? C标准是否需要循环才能花费一些时间? 例如下面的代码: void foo(void) { while(1) { for(int k = 0; k < 1000000000; ++k); printf("Foo\n"); } } 比这个运行速度慢: void foo(void) { while(1) { for(int k = 0; k < 1000; ++k); printf("Foo\n"); } } 即使有-O3优化级别。 我希望删除允许的空循环,从而在两个代码上获得相同的速度。 “花费的时间”是一个应该由编译器保存的副作用吗?

多余的演员是否得到优化?

我正在更新一些旧的代码,并发现了几个实例,其中每次需要调用其某个属性或方法时,同一个对象将被重复投射。 例: if (recDate != null && recDate > ((System.Windows.Forms.DateTimePicker)ctrl).MinDate) { ((System.Windows.Forms.DateTimePicker)ctrl).CustomFormat = "MM/dd/yyyy"; ((System.Windows.Forms.DateTimePicker)ctrl).Value = recDate; } else { (System.Windows.Forms.DateTimePicker)ctrl).CustomFormat = " "; } ((System.Windows.Forms.DateTimePicker)ctrl).Format = DateTimePickerFormat.Custom; 我的意图是解决这个怪物,但考虑到我有限的时间,我不想打扰任何不影响function或性能的东西。 所以我想知道的是,这些冗余演员是由编译器优化了吗? 我试图通过使用ildasm来简化自己的例子,但是不熟悉IL,我只是更加困惑。 UPDATE 到目前为止,共识似乎是这样的:a)不是,演员阵容不是最优化的,但b)虽然可能会有一些小的performance受到打击,但这不太可能是重要的,c)无论如何我应该考虑修复。 如果我有时间的话,我已经决定解决这些问题了。 同时,我也不会担心。 感谢大家!

错误只发生在编译优化启用

我遇到了代码中的一个错误,只有在代码是在启用优化的情况下才会生成。 我制作了一个控制台应用程序,用于复制testing逻辑(下面的代码)。 你会看到,启用优化时,在执行这个无效逻辑之后,“value”变为null: if ((value == null || value == new string[0]) == false) 修复很简单,在违规代码下面注释掉。 但是……我更担心的是,我可能碰到过汇编程序中的一个错误,或者其他人可能会解释为什么value被设置为null。 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace memory_testing { class Program { sta tic void Main(string[] args) { while(true) { Console.Write("Press any key to start…"); Console.ReadKey(); Console.WriteLine(); PrintManagerUser c = new PrintManagerUser(); c.MyProperty = new string[1]; } […]

为什么GCC不能优化删除C ++中的空指针呢?

考虑一个简单的程序: int main() { int* ptr = nullptr; delete ptr; } 使用GCC(7.2),在结果程序中有一个关于operator delete的call指令。 使用Clang和Intel编译器,不存在这样的指令,空指针删除被完全优化(在所有情况下都是-O2 )。 你可以在这里testing: https : //godbolt.org/g/JmdoJi 。 我不知道这样的优化是否可以用GCC打开? (我更广泛的动机源于自定义swap与可移动types的std::swap的问题,在第二种情况下删除空指针可能代表性能损失;请参阅https://stackoverflow.com/a/45689282/580083细节。) UPDATE 为了澄清我的问题的动机:如果我使用只是delete ptr; if (ptr)在一个移动赋值操作符和某个类的析构函数中没有if (ptr) guard,那么std::swap与该类的对象产生3个与GCC的call指令。 这可能是一个相当大的性能损失,例如,sorting这样的对象数组时。 而且,我可以写if (ptr) delete ptr; 无处不在,但是,不知道这是否也不是一个性能损失,因为deleteexpression式也需要检查ptr 。 但是,在这里,我想,编译器只会生成一个单一的检查。 另外,我真的很喜欢没有防范的情况下调用delete的可能性,这对我来说是一个惊喜,它可能会产生不同的(性能)结果。 UPDATE 我只做了一个简单的基准testing,即sorting对象,在移动赋值运算符和析构函数中调用delete 。 来源在这里: https : //godbolt.org/g/7zGUvo 在至强E2680v3上使用GCC 7.1和-O2标志测量std::sort运行时间: 链接的代码中有一个错误,它比较指针,而不是指向值。 更正的结果如下: 没有防守: 17.6 [s] 40.8 [s] , […]

为什么编译器不会将浮点数* 2优化为指数增量?

我经常注意到gcc把乘法转换成可执行文件的转换。 乘以一个int和一个float可能会发生类似的情况。 例如, 2 * f可以简单地将f的指数递增1,从而节省一些周期。 做编译器,也许如果有人要求他们这样做的话(比如通过-ffast-math ),一般来说,这样做吗? 编译器是否足够聪明可以做到这一点,或者我需要使用scalb*()或ldexp()/frexp()函数族自己来做这scalb*()吗?

JIT不会优化涉及Integer.MAX_VALUE的循环

在写另一个问题的答案时,我注意到一个奇怪的边界情况下JIT优化。 以下程序不是 “Microbenchmark”, 并非旨在可靠地衡量执行时间(正如在其他问题的答案中指出的那样)。 它只是作为一个MCVE来重现这个问题: class MissedLoopOptimization { public static void main(String args[]) { for (int j=0; j<3; j++) { for (int i=0; i<5; i++) { long before = System.nanoTime(); runWithMaxValue(); long after = System.nanoTime(); System.out.println("With MAX_VALUE : "+(after-before)/1e6); } for (int i=0; i<5; i++) { long before = System.nanoTime(); runWithMaxValueMinusOne(); long after = System.nanoTime(); […]

这是一个编译器优化错误,还是一个未定义的行为?

在这段代码中我们无法解释一个烦人的错误: unsigned char bitmap[K_BITMAP_SIZE] = {0} ; SetBit(bitmap, K_18); // Sets the bit #18 to 1 for(size_t i = 0; i < K_END; ++i) { if(TestBit(bitmap, i)) // true for 18 { size_t i2 = getData(i); // for 18, will return 15 SetBit(bitmap, i2); // BUG: IS SUPPOSED TO set the bit #15 to 1 […]

如何在gcc中禁用编译器优化?

我正在学习汇编语言。 我已经search并find了如何反汇编一个.c文件,但我认为它会产生一些优化版本的程序。 有没有什么办法,我可以看到我的C文件对应的确切汇编代码。

C#编译器是否将lambdaexpression式视为公共或私有方法?

在内部,编译器应该将lambdaexpression式转换为方法。 在这种情况下,这些方法是私有的还是公共的(或其他),是否有可能改变这种情况?

为什么Clang优化这个代码?

代码的目的是find代表0到1之间的值的32位浮点位模式的总数。在我看来,这应该工作,但由于某种原因,从铿的组装输出基本上是return 0; 。 我用Clang 3.3和Clang 3.4.1编译,使用-std=c++1y -Wall -Wextra -pedantic -O2和-std=c++1y -Wall -Wextra -pedantic -O3 铿锵3.4使用-O2和-O3优化了所有的东西。 铿锵3.3只会优化-O3的所有function。 通过“优化一切”我的意思是这是程序的汇编输出: main: # @main xorl %eax, %eax ret #include <limits> #include <cstring> #include <cstdint> template <class TO, class FROM> inline TO punning_cast(const FROM &input) { TO out; std::memcpy(&out, &input, sizeof(TO)); return out; } int main() { uint32_t i = […]