我读了乔·阿姆斯特朗的'Programming Erlang',并且'n核机器'理论的'n倍快“。在Erlang中进行多核编程的有效方法是使用大量进程(线程)。
我是一名C ++程序员,所以我很好奇在C ++中创建大量线程和在Erlang中创建大量进程之间的区别。我知道在C / C ++中处理线程并不容易。我也知道锁定/解锁会使系统变慢。但它不是不可能,对吧?
那么..为什么Erlang是一种支持多种语言的语言?是因为它很容易编程吗?
我正在为MMORPG制作一款在线游戏服务器,这就是我对Erlang作为替代服务器语言感兴趣的原因。
(我已经阅读了this个问题,但我认为这不是我正在寻找的问题。)
答案 0 :(得分:25)
归结为线程与进程。
操作系统是专门设计的,因此每个“用户”都认为他们自己拥有整个计算机 - 这就是为什么你以用户wwwrun 运行apache的原因。
程序员作为程序员,开始超载这种范式,首先是每个运行多个“工作”的人类用户。由于操作系统是为多个用户设计的,因此该体系结构的上限扩展限制反映了登录用户的上限扩展限制 - 这就是为什么apache将开始在4,000-8,000个用户死亡的原因。
流程是一个成熟的范例(我的流程不会让你崩溃)。当我们开始看到线程的引入时,事情开始变得非常不同。在这里,我们有一些程序具有外部阻塞活动(等待磁盘,等待io,等待内存),希望能够一方面等待,另一方面工作,线程允许您这样做并克服两个问题:
由于操作系统无法处理,因此无法获得足够的进程
每个流程都很昂贵,因为通过设计,它为“用户”提供了操作系统的全部功能
线程的问题在于它们打破了进程设计的分离。我的线程可以丢弃你的线程 - 错误传播。
Erlang的不同之处在于许多方面。 Joe Armstrong的PhD Thesis被称为在存在软件错误的情况下制作可靠的分布式系统。
可靠性意味着流程优于线程。问题是操作系统进程太“昂贵”,因为它们是为人类设计的(你拥有机器)而不是并发的程序单元。在Erlang VM中,VM具有多用户系统的全部功能(它在操作系统进程中运行),并且每个Erlang进程具有小得多的并发功率 - 如果它想要使用'大机器'它与VM进行对话,并为此做好准备。因此Erlang进程比操作进程(和线程)便宜得多。你只是产卵,产卵,产卵。开箱即用的Erlang VM以2 ** 8个进程开始,但你可以将其提高到数百万(如果你有足够的RAM)。
另外,正如Joe在博士论文第一部分的第一部分所说,要拥有可靠的软件,你需要从两台计算机开始。使用Erlang / OTP,在写入时间,您不知道您的软件将运行在哪台计算机上。 Erlang / OTP集群在运行时将分配您的计算工作。所以Erlang进程是本机分布式的,就像spawn()(用于fork()的Erlang)和重启语义一样。
因为Erlang有自己的进程,所以它有自己的调度程序和自己的代码加载器/二进制格式(可以解释Erlang,也可以编译为本机二进制文件)。这样就可以获得一小组额外的好处 - 在你编写Erlang / OTP应用程序之前,它已经可以热插拔其二进制文件等等。
因此,确保您可以使用C ++编写多线程应用程序 - 但是您有责任防止错误传播并构建系统稳定性。
当然,您可以在C中构建可靠的软件 - 看看Erlang(VM是用C编写的)这就是您想要的原因吗?在过去,公司编写了自己的“操作系统”,您现在可以编写自己的操作系统,但为什么要这样做呢?有数百万行强大的测试代码“做到了”,就像在Erlang / OTP系统中有150万行强大的测试代码“做到了”。
使用Erlang是关于使用其他人编写的内容,并且只构建使您的公司有效的位。
答案 1 :(得分:15)
不,这并非不可能,但Erlang确实让它变得更容易。关键是不在进程之间共享状态。 Erlang凭借其作为一种功能语言实现了这一目标。该函数应该没有副作用,也不应该访问任何变量状态(除了在堆栈上传递的参数)。使用这些属性,可以将系统中任何函数的计算移动到具有单独存储空间的另一个处理器,Erlang将为您执行此操作。 Erlang只需要复制函数的参数和内存空间之间的结果(注意:这不适用于所有类型的应用程序......需要在非常大的输入状态下运行的函数可能会提供性能复制该状态时的问题。)
在C ++应用程序中天真地使用线程可能会有不同的处理器(在多核系统中)尝试同时访问同一个共享内存。然后,系统必须做大量工作以确保与每个核心关联的本地缓存保持一致。这是您可以遭受巨大性能命中的地方。由于这个原因,当你有多个内核时,我们的应用程序会降低性能。事实上,我甚至会说你最好设计你的应用程序只使用你需要进行异步I / O的线程,但是你需要让进程做真正的工作而不是阻塞I / O,使用完整的流程。通过使用完整进程,您可以保证每个进程都有自己的内存空间,并且没有两个线程会同时使用相同的内存(当然,您需要在这些进程之间建立一种良好的通信方式)。有了这样的系统以及管理状态和分发处理的规则,你可以获得与Erlang提供的类似的结果,但是你必须做很多Erlang已经为你做的基础设施工作。
答案 2 :(得分:3)
上下文切换非常昂贵。在Erlang中没有。 锁使传统程序开始考虑下一个要执行的线程。这也非常昂贵。
答案 3 :(得分:2)
Gordon Guthrie的answer很棒。哪个更大的区别是个人偏好。从我的角度来看,Erlang的更大区别在于可靠性和偶然的可扩展性。在Erlang中,您可以自然地设计并发流程而不会出现大的性能问题,这将是可扩展的可扩展性。大信息中存在陷阱,但在大多数情况下,您的设计将优雅并且表现良好而无需特别小心。当您的设计优雅时,您可以减少错误,更易于管理,顺便说一句,您可以轻松分配和扩展,结果将是可靠的。
简而言之,在Erlang中,您可以以不同于C ++的方式设计程序,因为您可以在没有大的性能问题的情况下完成它,并且无需大量工作即可保证良好的可伸缩性和可靠性。没有人是完美的,但对于有趣的大量任务,Erlang是最好的选择。
编辑:关于Erlang和C ++之间差异的好presentation - Erlang 2.5x更高的顶级性能,3倍的延迟和18倍的SLOC - 我认为摩托罗拉的开发人员在C ++方面经验丰富写好软件。
答案 4 :(得分:1)
嗯,具有只能设置一次的变量的语言的本质以及它是一种函数式语言的事实会自动使得具有大量并行性的程序被编写并以“正确的方式”执行多核。
除了这两个事实之外,我对erlang了解不多,所以也可能还有别的东西。但这并不是说你不能使C ++程序具有可扩展性,但你可能会经历很多事情来实现性能,可扩展性和稳定性,如果用erlang编写,这将是免费的。