2009-11-03 148 views
4

我有一个非常大的程序,我一直在visual studio下编译(v6然后迁移到2008)。我需要可执行文件尽可能快地运行。该程序花费大部分时间处理各种大小的整数,并且做的IO很少。生成最快的可执行文件

显然我会选择最大优化,但似乎有很多事情可以完成,但它们并不在优化的标题下,这仍然会影响可执行文件的速度。例如,选择__fastcall调用约定或将结构成员对齐设置为大数。

所以我的问题是:是否有其他编译器/链接器选项我应该用来使程序更快,而不是从“属性”对话框的“优化”页面进行控制。

编辑:我已经广泛使用探查器。

+0

你有没有尝试其他的编译器?我听说英特尔C++编译器有时会生成更快的代码。也许值得一试。 – MP24 2009-11-04 12:09:30

+0

大约一年前,我确实尝试了intel编译器,它生成的代码与microsoft的速度大致相同...虽然可能我不知道如何设置所有选项以获得最大速度。如果我听说很多关于它快得多的报道,或者有人说“你用X标志试过了吗?这会让它跑得更快”或者其他一些,我会再试一次。 – Mick 2009-11-04 13:30:15

+0

它需要在特定的CPU /平台上更快吗?或者尽可能快地跨越多个平台(虽然接受总是存在折衷)? – Kylotan 2009-11-04 13:44:38

回答

5

1)使用__restrict降低别名。

2)通过使用__pure帮助编译器消除常见的子表达式消除/死代码。

3)对SSE/SIMD的介绍可以找到herehere。互联网并不完全满足关于这个话题的文章,但这足够了。有关内部函数的参考列表,您可以搜索MSDN以查找“编译器内在函数”。

4)对于'宏并行',你可以试试OpenMP。它是用于简单任务并行化的编译器标准 - 本质上,您使用一些#pragma告诉编译器某些代码段可重入,并且编译器自动为您创建线程。

5)我第二次interjay的观点是,PGO可以很有帮助。不像#3,#4,它几乎毫不费力地在添加

12

要考虑的另一个优化选项是优化大小。由于更好的缓存局部性,有时候大小优化的代码可以比速度优化的代码运行得更快。

此外,除了优化操作之外,在剖析器下运行代码并查看瓶颈位置。花费在一个好的分析器上的时间可以在性能上获得重大的回报(特别是如果给出代码的缓存友好性的反馈)。

最终,你可能永远不会知道“尽可能快”是什么。你最终需要解决“这对我们的目的来说足够快”。

+1

+3(如果可能的话)100%同意每个点。你打我评论它的大小方面。许多人在优化时不会考虑这一点。 – Marcin 2009-11-03 15:34:33

+1

+1 - 由于内存访问时间的高度差异,现在的一般建议是全局优化大小,优化速度只是真正的瓶颈。一个长到适合代码缓存的循环可能会使你受到10倍的影响,这是一个针对大小而不是速度进行了优化的瓶颈,会在'1.alittle'周围受到伤害' – peterchen 2009-11-03 15:57:32

+0

不会为速度和大小设置同等优先级好主意呢? – henle 2009-11-04 13:41:54

3

忘记微观优化,例如您所描述的内容。通过一个探查器运行你的应用程序(至少在某些版本中有一个包含在Visual Studio中)。分析器会告诉你你的应用程序在哪里花费时间。

微优化很少会给您带来超过几个百分点的性能提升。为了获得巨大的提升,您需要确定代码中使用低效算法和/或数据结构的区域。关注这些,例如通过更改算法。分析器将帮助识别这些问题区域。

8

Profile-guided optimization可能会导致很大的加速。我的应用程序运行速度比正常优化版本快大约30%。基本上,您只需运行一次应用程序,然后让Visual Studio对其进行配置,然后再根据收集的数据再次进行优化。

1

我同意每个人都说过关于分析。但是你提到“各种大小的整数”。如果你使用不匹配的整数进行大量算术,那么当计算表达式时,可能会浪费大量时间来改变大小,例如缩写整数。

我会再投入一件事。可能最重要的优化是选择和实施最佳算法。

1

您有三种方法可以加速你的应用程序:

  1. 更好的算法 - 你没有指定的算法或数据类型(是有一个上限整数大小?)还是什么输出你想。

  2. 宏并行 - 将任务拆分为块,并将每个块分配给一个单独的CPU,因此,在一个双核CPU上,将整数集分为两组,每个CPU分配一半。这取决于您使用的算法 - 并非所有算法都可以像这样处理。

  3. 微并联 - 这就像上面的,但使用SIMD。您也可以将它与第2点相结合。

+0

我认为编译器在进行最大化优化时已经尽可能地使用了SIMD指令。没有? – Mick 2009-11-03 16:01:14

+0

这取决于。像总结整数数组这样的简单东西可能会被优化到SIMD中,如果你有编译器选项的话。如果这是一个更复杂的算法,可能性可能会降低。唯一的办法是查看编译器生成的代码。 – Skizz 2009-11-03 16:06:06

+0

不一定。虽然大多数编译器可以做一些自动矢量化,但考虑到自动矢量化并不是一件容易的事情,这种支持在本质上有点基本。所以我不会依赖编译器能够模拟更多然后最明显的情况 – Grizzly 2009-11-03 16:07:11

5

你问哪个编译器选项可以帮助你加快你的程序,但这里是一些通用的优化技巧:

1)确保你的算法适合这项工作。如果你编写O(shit squared)算法,那么编译器选项的大量操作都不会帮助你。

2)编译器选项没有硬性规定。有时优化速度,有时优化大小,并确保你的时间差异!

3)了解您正在使用的平台。了解该CPU的高速缓存如何操作,并编写专门利用硬件的代码。确保你没有在任何地方跟随指针来访问会导致缓存溢出的数据。了解可用的SIMD操作并使用内部函数而不是写入程序集。如果编译器肯定不会生成正确的代码(即以不良方式写入未缓存的内存),则只编写程序集。确保在不会别名的指针上使用__restrict。有些平台更喜欢你通过值传递向量变量,而不是通过引用,因为它们可以坐在寄存器中 - 我可以继续这样做,但这应该足以让你指向正确的方向!

希望这有助于

-Tom

2

你应该总是满足您的算法,并依靠编译器的优化,让你在大多数情况下,显著改善之前优化这一点。

此外,你可以抛出硬件的问题。你的电脑可能已经有了大部分未使用的必要硬件:GPU!改进某些类型的计算昂贵的处理的性能的一种方式是在GPU上执行它。这是硬件特定的,但NVIDIA提供的API完全是:CUDA。使用GPU可能会比使用CPU有更大的改进。

2

检查您正在使用哪种/精度模式。每个代码都会生成完全不同的代码,您需要根据应用中需要的准确性进行选择。我们的代码需要精度(几何,图形代码),但我们仍然使用/ fp:fast(C/C++ - >代码生成选项)。

还要确保您有/ arch:SSE2,假设您的部署涵盖了所有支持SSE2的处理器。这会导致性能差异很大,因为编译将使用很少的周期。博客中包含的细节很好SomeAssemblyRequired

由于您已经分析,我建议循环展开,如果它没有发生。我已经看到VS2008没有更频繁地使用它(模板,参考文献等)。

在热点中使用__forceinline(如果适用)。

更改您的代码的热点使用SSE2等作为您的应用程序似乎是计算密集型。

0

你说这个程序非常大。这告诉我它可能在层次结构中有许多类。

我对这种程序的经验是,虽然你可能假设基本结构是正确的,为了获得更好的速度,你需要担心低级优化,很可能是那里的好机会是不是低级别的优化的大机会

除非程序已经被大幅调整,否则中间堆栈操作的形式可能会有不同的加速空间。这些通常非常无辜,并且永远不会引起你的注意。它们不是“改进算法”的情况。他们通常是恰好处于关键路径上的“优秀设计”案例。

  • 不幸的是,你不能依靠分析器来找到这些东西,因为它们不是为了寻找它们而设计的。

This is an example of what I'm talking about.

相关问题