什么是更快 - Java或C#(或旧的C)?

Rex*_*ung 26 .net c c# java performance

我目前正在决定建立一个科学计算产品的平台,并决定使用Core2 Quad CPU上的英特尔编译器的C#,Java或普通C.它主要是整数运算.

到目前为止,我的基准测试显示Java和C相互之间的差距很大,而.NET/C#的速度约为5% - 但是我的一些同事声称,如果给定足够的时间,那么具有正确优化的.NET将会击败这两者让JIT做它的工作.

我总是认为JIT会在应用程序启动后的几分钟内完成它的工作(在我的情况下可能只需几秒钟,因为它主要是紧环),所以我不确定是否相信它们

任何人都可以了解情况吗?.NET会打败Java吗?(或者我最好只是坚持使用C?).

代码是高度多线程的,数据集的大小是几TB.

在这种情况下,Haskell/Erlang等不是选项,因为有大量现有的遗留C代码将被移植到新系统,而将C移植到Java/C#比Haskell或Erlang简单得多.(当然,除非这些提供了显着的加速).

编辑:我们正在考虑转向C#或Java,因为理论上它们可能更快.我们可以减少每一个处理时间,每年为我们节省数万美元.在这一点上,我们只是试图评估C,Java或c#是否会更快.

Dan*_*ker 67

问题中的关键信息是:

我们可以减少每一个处理时间,每年为我们节省数万美元

因此,您需要考虑削减每个百分比的成本.如果这种优化工作每年花费数万美元,那么就不值得做.你可以通过解雇程序员来节省更多.

拥有合适的技能(现在这种技能比较罕见,因此更加昂贵),您可以手工编写汇编程序以获得最快的代码.使用稍微不那么罕见(和昂贵)的技能,你可以用一些非常难看的C代码做得很好.等等.你从中挤出的性能越多,你在开发工作中花费的成本就越高,并且会有越来越多的努力回报.如果从中获得的利润保持在"每年数万美元",那么就会有一个不再值得努力的地步.事实上,我会猜测你已经在那时,因为"每年数万美元"在一个薪水的范围内,并且可能不足以购买手工优化复杂程序所需的技能.

我猜想如果你的代码已经用C语言编写,那么将它全部重写为另一种语言的直接翻译的努力将是90%的浪费.它很可能只是因为你不会利用平台的功能而变得更慢,而是反对它们,例如尝试使用Java就好像它是C.

同样在您现有的代码中,会有一些部分对运行时间(它们经常运行)和其他完全不相关的部分(它们很少运行)做出重要贡献.因此,如果您对加速程序有一些想法,那么浪费时间将其应用于不影响运行时间的程序部分是没有经济意义的.

因此,使用分析器查找热点,并查看现有代码中浪费的时间.

当我注意到代码的引用为"多线程"时更新

在这种情况下,如果您专注于消除瓶颈,以便您的程序可以在大量核心上很好地扩展,那么它每年将自动变得更快,其速度将使您可以进行的任何其他优化相形见绌.明年的这个时候,四核将是台式机的标准配置.在那之后的一年,8个核心将变得更便宜(我在一年前购买了一个核心几千美元),我预测到那时32核心机器的成本将低于开发者.

  • +1关注问题的经济学 (5认同)
  • 我同意较少的话.此外,我认为如果可能的话,你可以通过利用gpu来节省更多的钱,如果它是一个很酷/很大的项目,你可以从英特尔获得帮助 (2认同)
  • 目前尚不清楚32核机器上是否有足够的带宽可以在所有内核上进行数据密集型计算.查看分布式内存扩展(如MapReduce或MPI)也是值得的.这可以让他扩展到数千个内核*现在*.见下文. (2认同)

Mar*_*ell 31

对不起,这不是一个简单的问题.这将取决于一个很多关于究竟发生了什么事情.C#当然不会懈怠,你很难说"java更快"或"C#更快".C是一个非常不同的野兽...它可能有更快的速度 - 如果你做对了; 但在大多数情况下它会大致相同,但要写得更难.

这也取决于你是如何做到的 - 锁定策略,如何进行并行化,主代码体等.

重新JIT - 你可以使用NGEN来平整这个,但是是的; 如果你要使用相同的代码,它应该很早就被JIT.

C#/ Java(通过C)的一个非常有用的特性是它们有可能更好地利用本地CPU(优化等),而不必担心它.

另外 - 使用.NET,可以考虑"并行扩展"(将在4.0中捆绑),这样可以提供更强大的线程故事(与没有PFX的.NET相比).


Tod*_*lin 13

不要担心语言; 并行!

如果你有一个高度多线程,数据密集的科学代码,那么我认为担心语言不是最重要的问题.我认为您应该专注于使应用程序并行,特别是使其扩展到单个节点.这将使您获得比仅切换语言更多的性能.

只要您被限制在一个节点上,您就会因应用程序的计算能力和带宽而匮乏.在即将推出的多核机器上,目前尚不清楚您是否拥有在所有内核上进行数据密集型计算所需的带宽.您可以执行计算密集型工作(如GPU所做的那样),但如果您需要将大量数据流式传输到每个核心,则可能无法提供所有核心.

我认为你应该考虑两个选择:

  1. MapReduce
    您的问题听起来像Hadoop之类的很好的匹配,Hadoop专为数据密集型工作而设计.

    Hadoop已经扩展到Linux上的10,000个节点,你可以将你的工作分流到其他人(例如亚马逊,微软)或你自己的计算云.它是用Java编写的,因此就移植而言,您可以从Java中调用现有的C代码,也可以将整个内容移植到Java.

  2. MPI
    如果您不想打扰移植到MapReduce,或者由于某种原因您的并行范例不适合MapReduce模型,您可以考虑调整您的应用程序以使用MPI.这也允许您扩展到(可能数千个)核心.MPI是计算密集型分布式内存应用程序的事实标准,我相信有Java绑定,但大多数人使用MPI与C,C++和Fortran.因此,您可以将代码保存在C中,并专注于并行化性能密集型部分.如果您有兴趣,请查看OpenMPI的初学者.


Dar*_*ark 11

老实说,我对这些基准感到惊讶.

在计算密集型产品中,我会在C上下大赌注以更快地执行.您可能会编写像筛子那样泄漏内存的代码,并且具有与线程相关的有趣缺陷,但它应该更快.

我认为Java或C#会更快的唯一原因是测试的运行时间很短.如果很少或没有GC发生,你将避免实际释放内存的开销.如果进程是迭代的或并行的,那么尝试坚持使用GC.Collect,只要你认为你已经完成了一堆对象(在将事物设置为null或以其他方式删除引用之后).

另外,如果你正在处理数TB的数据,我的意见是你用C得到的确定性内存分配会好得多.如果你在分配堆时大致接近释放将保持很大程度上未分段.使用GC环境,您可能会在运行时间长于预期后使用更多内存来结束您的程序,这仅仅是因为碎片.

对我来说,这听起来像C语言是适当语言的那种项目,但需要对内存分配/释放进行一些额外的关注.我敢打赌,如果在完整的数据集上运行,C#或Java将会失败.

  • 你的先入之见已经过时了.现代垃圾收集器非常擅长优化释放,特别是当它接近分配时.它们甚至可以超越C风格的malloc/free. (5认同)
  • 可能是,我所知道的是,如果我在一个带C#的循环中分配一个可变大小的缓冲区(大约8K)并且不进行GC.Collect我死了.快速.即使每次迭代都释放缓冲区.LOH ftl. (2认同)

Ric*_*ard 9

很久以前,Raymond ChenRico Mariani有一系列博客文章逐步优化文件加载到字典工具中.虽然.NET早期更快(即易于快速),但C/Win32方法最终显着更快 - 但相当复杂(例如使用自定义分配器).

最后答案更快将在很大程度上取决于你愿意花费多少时间从每个方法的每微秒开始.这种努力(假设您正确地执行,由真实的分析器数据指导)将比语言/平台的选择产生更大的差异.


第一个和最后一个性能博客条目:

(最后一个链接给出了结果和一些分析的总体摘要.)


Tof*_*eer 5

它将在很大程度上取决于你正在做什么.我有Java代码胜过C代码.我的Java代码比C++代码要慢得多(我不做C#/ .NET,所以不能说那些).

所以,这取决于你在做什么,我相信你能找到比语言Y更快的语言X.

您是否尝试通过分析器运行C#代码以查看它花费最多时间(与Java和C相同).也许你需要做一些不同的事情.

Java HotSpot VM比.NET更成熟(至少可以追溯到1994年),因此它可能归结为两者的代码生成能力.


Ski*_*izz 5

你说"代码是多线程的",这意味着算法是可并行的.此外,您保存"数据集大小为几TB".

优化就是找到并消除瓶颈.

明显的瓶颈是数据集的带宽.考虑到数据的大小,我猜测数据是保存在服务器而不是台式机上.您还没有提供您正在使用的算法的任何细节.算法所花费的时间是否大于读取/写入数据/结果所花费的时间?算法是否适用于总数据的子集?

我将假设该算法适用于数据块而不是整个数据集.

您有两种情况需要考虑:

  1. 与获取数据相比,该算法需要更多时间来处理数据.在这种情况下,您需要优化算法.

  2. 该算法处理数据所花费的时间少于获取数据所需的时间.在这种情况下,您需要增加算法和数据之间的带宽.

在第一种情况下,您需要一个能够编写良好汇编代码的开发人员,以充分利用您正在使用的处理器,如果可用的话,可以利用SIMD,GPU和多核.无论你做什么,不要只是增加线程数,因为一旦线程数超过内核数量,你的代码就会变慢!这是由于切换线程上下文的额外开销.另一种选择是使用像分布式处理系统这样的SETI(组织中有多少台PC用于管理目的 - 想想所有备用处理能力!).C#/ Java,如bh213所提到的,可能比使用SIMD等编写良好的C/C++慢一个数量级.但这是当今的利基技能.

在后一种情况下,在受带宽限制的情况下,您需要改进将数据连接到处理器的网络.在这里,请确保您使用的是最新的以太网设备 - 各地1Gbps(PC卡,交换机,路由器等).不要使用无线,因为速度较慢.如果有很多其他流量,请考虑与"办公室"网络并行的专用网络.考虑将数据存储得更靠近客户端 - 每五个客户端使用一个直接连接到每个客户端的专用服务器,它反映来自服务器的数据.

如果节省几个百分点的处理时间可以节省"数万美元",那么请认真考虑聘请一名顾问,实际上是两个 - 一个软件,一个网络.他们应该轻松地为所节省的费用付出代价.我相信这里有很多人都有资格提供帮助.

但是,如果降低成本是最终目标,那么考虑谷歌的方法 - 编写使CPU保持在100%以下的代码.这通过减少冷却直接和间接地节省能量,因此成本更低.你需要更多的回报,所以它再次是C/C++ - Java/C#有更多的开销,开销=更多的CPU工作=更多的能量/热量=更多的成本.

因此,总而言之,在节省资金方面,它比你要选择的语言要多得多.