您会为CPU绑定的应用程序推荐什么语言/平台?

时间:2008-10-11 21:28:42

标签: c++ performance algorithm

我正在开发非交互式cpu绑定应用程序,它只进行计算,几乎没有IO。目前它的工作时间太长,而我正在努力改进算法,我也认为它可以为改变语言或平台带来任何好处。目前,在使用英特尔C ++编译器编译的Windows上,它是C ++(没有OOP,因此它几乎是C)。可以切换到ASM帮助和多少?可以切换到Linux和GCC帮助吗?

22 个答案:

答案 0 :(得分:15)

只是要彻底:首先要做的是收集个人资料数据,第二件事就是考虑你的算法。我相信你知道这一点,但他们必须在任何性能编程讨论中加入#include。

直接了解您的问题“可以切换到ASM帮助吗?”答案是“如果你不知道答案,那么可能不会。”除非您非常熟悉CPU架构及其细节,否则您的代码不可能比优化的C / C ++编译器好得多。

接下来要说明的是,代码中的显着加速(除了算法改进之外)几乎肯定会来自并行性,而不是线性增长。桌面计算机现在可以在一项任务中投入4或8个核心,这比稍微好一点的代码生成器具有更多的性能潜力。由于您对C / C ++感到满意,OpenMP几乎是不费吹灰之力的。它很容易用来并行化你的循环(显然,你必须观察循环携带的依赖,但它绝对是“最简单的并行可能工作”)。

尽管如此,代码生成质量确实在C / C ++编译器之间有所不同。英特尔C ++编译器因其优化质量而备受推崇,并且不仅完全支持OpenMP,还支持其他技术,如线程构建模块。

关于哪些编程语言甚至可能比C ++更好的问题,答案将是“积极推动/促进并行和并发编程概念的编程语言”。在这方面,Erlang是球的美女,而且现在是一种“热门”语言,大多数对性能编程感兴趣的人都至少要注意它,所以如果你想提高你在这方面的技能,你可能会想看看。

答案 1 :(得分:14)

它始终是算法,很少是语言。这是我的线索:“我正在努力改进算法”。

调整可能还不够。

考虑对算法进行根本性更改。你必须消除处理,而不是让处理更快。罪魁祸首通常是“搜索” - 循环查找数据。找到消除搜索的方法。如果你无法消除它,用某种树搜索或某种哈希映射替换线性搜索。

答案 2 :(得分:6)

切换到ASM不会有太大帮助,除非你非常擅长和/或有一个特定的关键路径例程,你知道你可以做得更好。正如几位人士所说,现代编译器在大多数情况下利用缓存等优势更好。比任何人都可以手工做的。

我建议:

  • 尝试使用其他编译器和/或不同的优化选项
  • 运行代码覆盖率/分析实用程序,找出关键路径的位置,并在代码中优化代码

C ++应该能够为您提供非常接近代码的最佳性能,因此我不建议您切换语言。根据应用程序的不同,您可以使用多个线程在多代码/处理器系统上获得更好的性能,作为另一种建议。

答案 3 :(得分:4)

虽然只是切换到asm不会带来任何好处,因为英特尔C ++编译器可能比您更好地优化,您可以尝试以下选项之一:

  • 尝试一种将代码并行化的编译器,如VectorC编译器。
  • 尝试通过大量使用MMX,3DNow!,SSE或任何适合您需求(以及您的CPU)的方式切换到asm。这将比纯粹的asm带来更多的好处。
  • 您还可以尝试GPGPU,即在GPU而不是CPU上执行算法的大部分。根据您的算法,它可以大大加快。

编辑:我也是第二种配置文件方法。我推荐AQTime,它支持英特尔C ++编译器。

答案 4 :(得分:3)

就个人而言,我会看一些语言,它们可以让你最容易地利用并行性,除非它是一个完全不可并行的情况。能够锁定一些额外的核心并获得(如果可能的话)接近线性的改进可能比挤出额外的几个百分点的效率更具成本效益。

在并行化方面,我认为函数式语言通常被认为是最好的方法,或者你可以看看OpenMP for C / C ++。 (就个人而言,作为托管语言的人,我会看Java / .NET的库,但我完全理解并非所有人都有相同的偏好!)

答案 5 :(得分:3)

尝试使用Fortran 77 - 在计算方面,仍然没有什么能胜过编程语言的祖父。此外,尝试使用OpenMP来利用多个核心。

答案 6 :(得分:3)

与C ++可以为您做的相比,手动优化您的ASM代码很少具有成本效益。

如果您已经从传统的算法视图中对算法做了任何事情,并且您也消除了过度行为,那么您可能是SOL,或者您可以考虑从硬件角度优化您的程序图。

例如,每当你在堆上跟踪指针时,由于缓存未命中,可能是分页等,都会支付巨额费用,这些都会影响分支预测。大多数程序员(甚至是C大师)倾向于从功能角度看CPU,而不是幕后发生的事情。有时重新组织内存,例如通过“展平”或手动分配内存以适合同一页面,可以获得极高的加速。只是通过展平我的结构,我设法在图形遍历上获得2倍的加速。

这些不是编译器将为您做的事情,因为它们基于您对程序的高级理解。

答案 7 :(得分:2)

正如lobrien所说,你没有给我们任何信息来告诉你手动优化的ASM代码是否有帮助......这意味着答案可能是“尚未”。

您是否使用分析器运行代码?

您是否知道代码是否由于内存限制或处理器限制而变慢?

您使用的是所有可用内核吗?

您是否已确定任何不使用O(1)的算法?你能把他们送到O(1)吗?如果没有,为什么不呢?

如果您已完成所有这些操作,那么您对程序运行环境的控制程度如何? (如果您考虑切换操作系统,可能会很多)您可以禁用其他进程,优先处理您的进程吗?如何找到具有更快处理器,更多内核或更多内存的计算机(取决于您受限制的内容)

不断。

如果你已经完成了所有这些以及更多,你肯定可以达到你认为的那个点,“我想知道这里的这几行代码是否可以优于我所用的程序集。现在看着调试器?“那时你可以具体询问。

祝你好运!你正在解决一个有趣的问题。

答案 8 :(得分:1)

首先,确定是否可以像S.Lott建议的那样更改算法。

假设算法选择正确,您可能会查看内存访问模式,如果您正在处理大量数据。对于目前很多数字运算应用程序来说,它们受内存总线的约束,而不是ALU。我最近优化了一些形式的代码:

// Assume N is a big number
for (int i=0; i<N; i++) {
  myArray[i] = dosomething(i);
}
for (int i=0; i<N; i++) {
  myArray[i] = somethingElse(myArray[i]);
}
...

并将其转换为:

for (int i=0; i<N; i++) {
  double tmp = dosomething(i);
  tmp = somethingElse(tmp);
  ...
  myArray[i] = tmp;
}
...

在这种特殊情况下,这产生了大约2倍的加速。

答案 9 :(得分:1)

正如Oregonghost已经暗示的那样 - VectorC编译器可能有所帮助。它并没有真正并行化代码,而是可以使用它来利用扩展的命令集,如mmx或sse。我将它用于软件渲染引擎中最关键的时间部分,它在大多数处理器上的速度提高了约150%-200%。

答案 10 :(得分:0)

CrowdProcess有大约2000名工作人员可以用来计算算法。 API非常简单,我们一直在观察接近工人数量的加速比。你也可以编写Javascript,它可以让你比C ++或ASM更高效。

因此,如果你处于C ++或ASM之间,我会说你应该首先使用你所有的CPU内核,如果还不够,那么CrowdProcess应该是一个有趣的平台。

免责声明:我制作了CrowdProcess。

答案 11 :(得分:0)

的Linux

如果将其剥离到实际需要的部分,切换到Linux会有所帮助。

答案 12 :(得分:0)

答案 13 :(得分:0)

如果您觉得已经优化了代码,那么就没有任何改进,请增加CPU。这可以在不同的平台上完成。我开发的是Appistry。一些链接:

http://www.appistry.com/resource-library/index.html

您可以从这里免费下载该产品:

http://www.appistry.com/developers/

我为Appistry工作,我们已经完成了许多安装工作,这些任务通过在10台或100台机器上传播工作而受到限制。

希望这有帮助, -Brett

答案 14 :(得分:0)

First get the lead out.然后,如果它没有去ASM那么快,那就这样吧。但是想到你必须去ASM假设你知道是什么让它变慢了,我敢打赌你猜的是一个甜甜圈。

答案 15 :(得分:0)

“CPU限制”的2个明显答案是: 1.使用更多CPU(核心) 2.使用别的东西。

使用2个线程而不是1个线程将花费的时间减少多达50%。相比之下,C ++到ASM很少给你5%(对于新手ASM程序员来说,通常是-5%!)。一些问题可以很好地扩展,并且可能受益于8或16个核心。这种硬件仍然是主流,所以看看你的问题是否属于那个类别。

另一个解决方案是在任务中投入更多专用硬件。这可能是你CPU的矢量单元 - 考虑到Windows = x86 / x64,这将是SSE的一种风格。另一种矢量硬件是现代GPU。 GPU也有自己的内存总线,速度非常快。

答案 16 :(得分:0)

对于现代处理器,学习ASM需要很长时间。此外,对于所有不同版本的SSE,您的代码最终会依赖于处理器。

我做了很多CPU限制工作,并且发现intel的C ++编译器和g ++之间的区别通常不是很大(最多15%左右),并且Mac OS之间没有可衡量的差异X,Windows和Linux。

您必须手动优化代码并改进算法。没有“魔仙尘”可以使我现有的代码更快,我害怕。

如果你还没有,并且你关心性能,你必须通过一个好的分析器来运行你的代码(就个人而言,我喜欢Linux上的kcachegrind&amp; valgrind,或者Mac OS X上的Shark。我不知道是什么对于Windows我很害怕。)

根据我过去的经验,您很有可能会发现某些方法占用了95%的CPU时间,而一些简单的更改或添加缓存将大大提高您的性能。在类似的说明中,如果某种方法仅花费1%的CPU时间,那么任何优化都不会为您带来任何好处。

答案 17 :(得分:0)

我建议你重新考虑一下你的算法,或者更好的方法。另一方面,您尝试计算的内容可能需要大量的计算时间。您是否考虑过将其分发以便可以在某种群集中运行?如果您想通过为inner loops引入Assembler来专注于纯代码优化,那么通常这会非常有益(如果您知道自己在做什么)。

答案 18 :(得分:0)

如果您在intel编译器上坚持使用C ++,请查看compiler intrinsics(完整参考here)。我知道VC ++有similar functionality,我相信你可以用gcc做同样的事情。这些可以让您充分利用CPU内置的并行性。您可以使用MMX,SSE和SSE2指令在一定程度上提高性能。就像其他人所说的那样,你最好先看看算法。

答案 19 :(得分:0)

有时您可以找到具有所关注算法优化实现的库。很多时候他们会为你做多线程。

例如,从LINPACK切换到LAPACK,使用良好的BLAS库,使LU分解/求解速度提高了10倍。

答案 20 :(得分:0)

对于另一种方法,您可以查看Distributed Computing,这听起来可能符合您的需求。

答案 21 :(得分:-1)

很难生成比天真的C或C ++代码更快的ASM代码。在大多数情况下,如果你的工作做得非常好,你可能获得的收益不会超过几个百分点,并且获得10%的加速被认为是非常成功的,但在大多数情况下,这是不可能的。

编译器能够理解如何有效地编译。您应该进行分析以确定优化的位置。