Questions tagged «compiler-optimization»

编译器优化涉及调整编译器以减少运行时或对象大小,或两者兼而有之。这可以通过使用编译器参数(即CFLAGS,LDFLAGS),编译器插件(例如DEHYDRA)或直接对编译器进行修改(例如修改源代码)来实现。

13
如何制作不会被优化的无限空循环?
C11标准似乎暗示不应优化具有恒定控制表达式的迭代语句。我从这个答案中获取建议,该答案特别引用了标准草案的6.8.5节: 该实现可以假定其控制表达式不是常量表达式...的迭代语句终止。 在该答案中,它提到while(1) ;不应对循环进行优化。 那么...为什么Clang / LLVM优化了下面的循环(与编译cc -O2 -std=c11 test.c -o test)? #include <stdio.h> static void die() { while(1) ; } int main() { printf("begin\n"); die(); printf("unreachable\n"); } 在我的机器上,此打印输出begin,然后在一条非法指令(ud2位于后面的陷阱die())中崩溃。在godbolt上,我们可以看到调用之后什么也没有产生puts。 让Clang在下面输出无限循环是一件非常困难的任务-O2-虽然我可以重复测试一个volatile变量,但该变量涉及不需要的内存读取。如果我做这样的事情: #include <stdio.h> static void die() { while(1) ; } int main() { printf("begin\n"); volatile int x = 1; if(x) die(); …

3
使用此指针会在热循环中引起奇怪的反优化
最近,我遇到了一个奇怪的取消优化(或者说错过了优化机会)。 考虑使用此函数可以有效地将3位整数的数组拆包为8位整数。它在每次循环迭代中解压缩16个整数: void unpack3bit(uint8_t* target, char* source, int size) { while(size > 0){ uint64_t t = *reinterpret_cast<uint64_t*>(source); target[0] = t & 0x7; target[1] = (t >> 3) & 0x7; target[2] = (t >> 6) & 0x7; target[3] = (t >> 9) & 0x7; target[4] = (t >> 12) & 0x7; …

11
函数过早返回的效率
作为一个缺乏经验的程序员,我经常遇到这种情况,尤其是对于我要优化的一个雄心勃勃,速度密集的项目,我感到特别奇怪。对于主要的类C语言(C,objC,C ++,Java,C#等)及其常用的编译器,这两个函数是否会同样高效地运行?编译后的代码有什么区别吗? void foo1(bool flag) { if (flag) { //Do stuff return; } //Do different stuff } void foo2(bool flag) { if (flag) { //Do stuff } else { //Do different stuff } } 基本上来说,提早break或return提早有过直接的效率红利/罚金吗?堆栈框架如何参与?是否有优化的特殊情况?是否有任何因素(例如内联或“内容”的大小)会对此产生重大影响? 我一直支持通过次要优化来提高可读性(我在参数验证中经常看到foo1),但是这种情况经常出现,因此我想一劳永逸地抛开所有烦恼。 而且我知道过早优化的陷阱...呃,那是一些痛苦的回忆。 编辑:我接受了一个答案,但是EJP的答案非常简洁地解释了为什么使用a return几乎可以忽略不计(在汇编中,return到函数末尾创建一个“分支”,这非常快。分支会更改PC寄存器和可能还会影响缓存和管道,这是很小的。)特别是在这种情况下,它实际上没有任何区别,因为if/else和和都return创建了到函数末尾的相同分支。

3
lang优化级别
海合会,手动解释什么-O3,-Os等转化为在特定的优化参数方面(-funswitch-loops,-fcompare-elim,等) 我正在为clang寻找相同的信息。 我在网上看过,man clang并且只提供一般信息(-O2优化多于-O1,-Os针对速度进行了优化,…),还在此处查看Stack Overflow并发现了这一点,但是在引用的源文件中没有发现任何相关信息。 编辑:我找到了答案,但是我仍然很感兴趣是否有人链接到用户手册,该手册记录了所有优化过程以及所选择的过程。目前,我仅找到此通行证列表,但在优化级别上却一无所获。-Ox


3
为什么代码会积极尝试阻止尾调用优化?
问题的标题可能有点奇怪,但据我所知,根本没有什么可以反对尾部调用优化。但是,在浏览开源项目时,我已经遇到了一些主动尝试阻止编译器进行尾部调用优化的功能,例如CFRunLoopRef的实现,其中充斥着此类黑客。例如: static void __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__() __attribute__((noinline)); static void __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(CFRunLoopObserverCallBack func, CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) { if (func) { func(observer, activity, info); } getpid(); // thwart tail-call optimization } 我很想知道为什么这看起来如此重要,并且在任何情况下我作为普通开发人员都应该牢记这一点吗?例如。尾部调用优化存在常见的陷阱吗?



5
为什么“ while(i ++ <n){}”比“ while(++ i <n){}”显着慢
显然,在装有HotSpot JDK 1.7.0_45(并将所有编译器/ VM选项设置为默认值)的Windows 8笔记本电脑上,以下循环 final int n = Integer.MAX_VALUE; int i = 0; while (++i &lt; n) { } 比以下速度至少快两个数量级(〜10 ms与〜5000 ms): final int n = Integer.MAX_VALUE; int i = 0; while (i++ &lt; n) { } 我在编写循环以评估另一个不相关的性能问题时碰巧注意到了这个问题。之间的差异++i &lt; n和i++ &lt; n是巨大的,足以显著影响结果。 如果我们查看字节码,则较快版本的循环主体为: iinc iload ldc if_icmplt 对于较慢的版本: iload …

7
是否可以告诉分支预测变量跟随分支的可能性有多大?
为了清楚起见,我在这里不打算进行任何形式的可移植性,因此任何将我与特定机器绑定在一起的解决方案都可以。 基本上,我有一条if语句,它将在99%的时间中将其评估为true,并试图提高性能的最后一个时钟,我是否可以发出某种编译器命令(使用GCC 4.1.2和x86 ISA,如果重要)告诉分支预测器它应该为该分支缓存?

3
添加字符时,编译器停止优化未使用的字符串
我很好奇为什么下面的代码: #include &lt;string&gt; int main() { std::string a = "ABCDEFGHIJKLMNO"; } 当使用编译时,将-O3产生以下代码: main: # @main xor eax, eax ret (我完全理解不需要多余的,a因此编译器可以从生成的代码中完全忽略它) 但是以下程序: #include &lt;string&gt; int main() { std::string a = "ABCDEFGHIJKLMNOP"; // &lt;-- !!! One Extra P } 产量: main: # @main push rbx sub rsp, 48 lea rbx, [rsp + …

22
编译器优化会引入错误吗?
今天,我与我的一个朋友进行了讨论,我们就“编译器优化”进行了两个小时的辩论。 我捍卫了这样的观点,有时,编译器优化可能会引入错误或至少会带来不良行为。 我的朋友完全不同意,说“编译器是由聪明的人建造的,可以做聪明的事情”,因此永远不会出错。 他一点也不说服我,但是我不得不承认我缺乏现实生活中的例子来加强我的观点。 谁在这里?如果是的话,您是否有现实生活中的示例,其中编译器优化在结果软件中产生了错误?如果我误会了,我应该停止编程并学习钓鱼吗?

8
超越-O3 / -Ofast的G ++优化
问题 我们有一个需要优化的中型程序来执行模拟任务。我们已经尽最大努力优化了源代码,以达到编程技能的极限,包括使用Gprof和Valgrind进行性能分析。 最终完成后,我们可能希望在多个系统上运行该程序几个月。因此,我们非常有兴趣将优化推向极限。 所有系统都将在相对较新的硬件(Intel i5或i7)上运行Debian / Linux。 问题 除了-O3 / -Ofast,使用最新版本的g ++可能有哪些优化选项? 我们也对代价高昂的次要优化感兴趣,从长远来看,这将有回报。 我们现在使用的 现在,我们使用以下g ++优化选项: -Ofast:最高“标准”优化级别。所包含的内容-ffast-math在我们的计算中不会造成任何问题,因此尽管不符合标准,我们还是决定使用它。 -march=native:启用所有特定于CPU的指令的使用。 -flto 以便跨不同的编译单元优化链接时间。

2
为什么使用三元运算符返回字符串与返回等效的if / else块会产生截然不同的代码?
我在使用Compiler Explorer时,偶然发现使用三元运算符时会发生以下有趣的行为: std::string get_string(bool b) { return b ? "Hello" : "Stack-overflow"; } 编译器为此生成的代码(带有-O3的Clang干线)是这样的: get_string[abi:cxx11](bool): # @get_string[abi:cxx11](bool) push r15 push r14 push rbx mov rbx, rdi mov ecx, offset .L.str mov eax, offset .L.str.1 test esi, esi cmovne rax, rcx add rdi, 16 #&lt; Why is the compiler storing the …

5
这是JVM错误还是“预期行为”?
我注意到了一些意外的行为(相对于我的个人期望而言是意外的),我想知道是否是JVM中存在错误,或者这可能是一种边缘情况,在这种情况下我不了解某些确切的细节应该发生。假设我们自己在main方法中具有以下代码: int i; int count = 0; for(i=0; i &lt; Integer.MAX_VALUE; i+=2){ count++; } System.out.println(i++); 天真的期望是这样会印刷Integer.MAX_VALUE-1,最大的甚至可以代表int。但是,我认为整数算术应该在Java中“翻转”,因此将1加到会Integer.MAX_VALUE导致Integer.MIN_VALUE。由于Integer.MIN_VALUE仍然小于Integer.MAX_VALUE,因此循环将循环遍历负数甚至整数。最终它将回到0,并且此过程应作为无限循环重复进行。 当我实际运行此代码时,会得到不确定的结果。打印的结果往往大约为一百万,但是确切的值却有所不同。因此,当我认为循环应该是无限循环时,循环不仅终止了,而且似乎随机终止了。这是怎么回事? 我的猜测是,这要么是JVM中的错误,要么是正在进行许多时髦的优化,从而产生了预期的行为。哪有

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.