今天我正在使用 Programming Erlang 一书进行线程练习,并搜索其他解决方案进行比较。我发现语言枪战与benchmark完全相同。我的印象是,这是一个Erlang应该很快的领域,但事实证明C和C ++再次位居榜首。我怀疑C / C ++程序没有遵循“将令牌从线程传递给线程”的规则。在阅读它们之后,似乎它们都操纵了一些与Erlang代码不同的共享内存和全局变量,但我可能是错的。
我的问题是:他们是在做同样的事情,还是C / C ++代码在概念上与Erlang代码不同(并且更快)?
还有一个问题:当解决方案非常相似时,为什么Haskell比Erlang更快?
答案 0 :(得分:9)
C版本正在使用LWP,我认为它是一个用户空间线程库。这种“不公平”在多大程度上引起争论:我会考虑一下它是否支持真正的先发制人并发,因为你可以在线程中进行阻塞系统调用而不会阻塞所有其他线程(你可以在Haskell中这样做,你能在Erlang吗?)。
Haskell的线程比Erlang稍微轻一些,因为据我所知,Erlang线程带有本地堆(在标准实现中),而Haskell线程都共享同一堆。
答案 1 :(得分:6)
最终,现代机器上的消息传递是使用某种形式的共享内存来传递消息(以及锁或原子指令)。因此,所有C和C ++实现实际上都在将消息传递的实现直接内联到其代码中。在C中使用快速消息传递库的类似基准测试,也是针对Haskell和Erlang的基准测试,可以在本文中找到:http://www.cs.kent.ac.uk/pubs/2009/2928/index.html(第5.1节)
各种方法的速度实际上取决于所涉及的并发运行时系统。 Haskell在这个领域做了很多很好的工作,使得它领先于Erlang。当然,测量微基准测试的速度往往是错误的,并且遗漏了重要的因素,如代码的可读性。要记住的一个问题可能是:你会很乐意维持枪战中的哪些解决方案?
答案 2 :(得分:5)
我认为我不会称之为作弊。多线程和多个进程之间的主要根本区别在于多个线程共享一个地址空间。因此,在我看来,指定多个线程(而不是多个进程)似乎默认了利用共享地址空间的权限(至少在没有一些非常具体的“传递”定义的情况下禁止这样做)。
它归结为:Erlang实际上没有线程,因为它具有异步通信的进程。这些过程在很大程度上(有意地)彼此隔离。一方面,这使得开发变得相当容易 - 特别是,一个过程只能通过特定的,明确定义的通信渠道影响另一个过程。在幕后,它使用了许多技巧(几乎可以肯定包括共享内存)来优化其流程,并利用特定实现/情况下的可能性(例如在单个共享地址空间中运行的所有进程)。尽管如此,不得不隐藏所有技巧,这使得它不像C版本那样有效,其中“技巧”都是明确的并且完全暴露出来。
我会用现实的比喻来解释这种差异。将线程/进程视为人。 Erlang强制建立专业的工作关系,通信都记录在备忘录中。 C和C ++版本更像是丈夫和妻子,可能会与一个单词进行交流,这对任何其他人都没有任何意义,甚至只是一瞥。
后者在工作时非常有效 - 但它对于微妙的误解会更加开放,如果两者有争执,你可能不想在同一个房间里。对于经理来说,即使他们的最高效率不是很高,处于纯粹职业关系的人也会更容易管理。
答案 3 :(得分:4)
当解决方案非常相似时,为什么Haskell比Erlang更快?
Haskell GHC是一种编译的本机代码优化语言实现,具有非常快的线程。它通常比Erlang / HIPE快得多。 Erlang没有对轻量级线程的垄断: - )
答案 4 :(得分:4)
我会回答另一个问题:如何在引擎盖下实现Erlang运行时?
有可能用C语言或类似的系统语言实现(我怀疑他们是在汇编中完成的)。或者至少,他们表达的概念可以在C中有效地表达。
现在,为什么你觉得奇怪的是,考虑到Erlang增加了自己的复杂性/间接性,优化的C版本(枪战肯定不显示平均级别代码)会击败Erlang版本?
无论何种类型的基准测试,C实现总是有可能击败另一种语言中最优秀的程序...构建在C之上,只是因为你采用它生成的C版本然后删除你的位不需要。
另一方面:
有时“更快”只是不值得花费。
答案 5 :(得分:2)
不遵守规则
鉴于有多少真正完全不同的编程并发方法,我确实发现它很难具有足够的包容性,可以引入不同的语言实现,但仍保留一些模糊的可比性。
现在看看使用different run time configuration测量的相同程序的性能,并注意重要程度 -
SMP quad core
1.0 C GNU gcc #3 4.16 4.17 16,952 607 100% 0% 1% 0%
4.2 Haskell GHC 17.99 17.42 4,020 307 100% 1% 1% 1%
7.5 Erlang HiPE 31.12 31.13 10,504 273 0% 0% 0% 100%
No SMP one core
1.0 C GNU gcc #3 4.16 4.16 16,952 607 1% 0% 0% 100%
1.4 Haskell GHC 5.89 5.89 3,204 307 0% 0% 0% 100%
2.6 Erlang HiPE 10.64 10.63 9,276 273 0% 0% 0% 100%
答案 6 :(得分:1)
该基准测试中需要注意的一点是,只有一个令牌可以传递。这意味着在实践中它只是一个单线程程序从内存读取和写入。
我希望结果在多处理器机器上出现不同(或使其成为一个集群),其中线程/进程必须以某种随机顺序传递M个令牌。
嗯。同时为基准测试解决方案的开发人员提供相同的小时数来完成他们的解决方案。然后我希望Erlang能够脱颖而出(至少接近顶端)。