还记得列表里面以前争吵过的进程vs线程的问题吗?
来自: http://program-think.blogspot.com/2009/02/multi-process-vs-multi-thread.html
就像莎士比亚的"To be, or not to be, that is the question"始终困扰着哈姆雷特,对于"进程还是线程?"这个问题,也经常困扰着那些进行软件架构设计的家伙。所以今天打算聊一下我对这个问题的体会。假如你还搞不清楚线程和进程的区别,请先找本操作系统原理的书好好拜读一下,再回来看帖。
由于这个问题很容易引发口水战,事先声明如下:多进程和多线程,无法一概而论地说谁比谁好。因此本帖主要描述特定场景(与我所负责的产品相关)下,进程和线程的权衡经验,仅供大伙儿参考。
由于特定场景是本帖讨论的前提,先说说我目前负责的产品的特点:业务逻辑比较复杂、业务数据量比较大、对数据实时处理的性能要求比较高、对健壮性和安全性要求比较高、要求跨平台(包括操作系统、数据库)、某些情况下需要分布部署。
上面说了一大堆,其实有不少的应用系统符合上述特点,比如:某些游戏服务器、某些金融方面的业务系统、某些电子商务系统等等。如果你正在从事的是类似的应用系统的设计,希望我下面介绍的经验对你有帮助。
★进程颗粒度问题
大伙儿应该明白,进程和线程都是处理并发(concurrency)的手段。对于上述这种比较复杂的系统,如果你企图全部用进程(见注1)或者全部用线程(见注2)来处理并发,估计会死得很难看。所以,关键问题就是如何在进程和线程之间进行平衡(也就是确定进程颗粒度的问题)。
我个人建议,尽量以业务逻辑的单元来划分进程。这样做的好处有如下几点:
1、避免扯皮
一般来说,某个固定业务逻辑的开发人员也是相对固定的。如果业务逻辑对应的某个进程崩溃了,测试人员容易快速定位肇事者,然后直接提交Bug给他/她。
反之,一个进程搞得太庞大,N多人掺和在里面,一旦进程崩溃了,相关编程人员之间很容易互相扯皮,不利于维护安定团结的局面;另外,由于测试人员经常搞不清楚Bug属于谁,经常给错Bug,也容易制造人民内部矛盾。
从上面可以看出来,相对细的进程颗粒度能够避免一些管理上的麻烦。由于XXX经常教导我们:"稳定压倒一切",所以该优点列第一条。
2、健壮性、容错性
一般来说,开发人员的水平参差不齐,优秀的毕竟是少数(具体参见"二八原理系列"的帖子)。所以难免会有菜鸟程序员搞出低级错误,而有些低级错误是致命的,会导致进程的崩溃。
如果你是以业务逻辑划分进程,一个业务逻辑的进程崩溃,对其它业务逻辑的影响不大(除非是该业务逻辑的依赖方);因此就不会出现"注2"提到的问题。
3、分布式
我常碰见的分布式部署需求,一般都是按照业务逻辑的维度来划分。比如系统中有一个认证模块,里面包含有敏感的用户认证信息。这时候客户就会要求把该模块单独部署在一台经过安全加固的主机中(以防阶级敌人搞破坏)。
如果是以业务逻辑为单位划分进程,要满足上述的部署需求就相对容易了(只要再配合恰当的进程间通讯机制,下面会提到)。
另外,支持分布式部署还可以顺带解决性能问题。比如某个业务逻辑模块特别消耗硬件资源(比如内存、CPU、硬盘、带宽),就可以把它拿出去单独放一台机器上跑。
4、跨编程语言
这个好处可能很多人容易忽略。一般来说,每个编程语言都有各自的优缺点。如果你通过业务逻辑划分进程,就可以根据不同的业务逻辑的特点来选择合适的编程语言。
比如:对于性能敏感的模块,我就使用C++搞定;而对于一些业务逻辑密集型的模块,则使用Java或Python开发。
★进程间通讯(以下简称IPC)问题
既然不可能把整个系统放入一个进程,那就必然会碰到IPC的问题。下面就来说一下该如何选择IPC。
各种操作系统里面,有很多稀奇古怪的IPC类型。由于要考虑跨平台,首先砍掉一批(关于IPC的跨平台问题,我在"跨平台开发"系列中会提到)。剩下的IPC类型中,能够进行数据传输的IPC就不多了,主要有如下几种:套接字(以下简称Socket)、共享内存、管道、文件。
其中Socket是我强烈推荐的IPC方式,理由如下:使用Socket可以天然地支持分布式部署;使用Socket可以比较容易地实现多种编程语言的混合(比如C++、Java、Python、Flex都支持Socket);使用Socket还可以省掉了一大坨"锁操作"的代码。
列位看官中,或许有人在担心Socket的性能问题,其实大可不必多虑。当两个进程在本机上进行Socket通讯时,由于可以使用localhost环回地址,数据不用经过物理网卡,操作系统内核还可以进行某些优化。这种情况下,Socket相对其它几种IPC机制,不会有太大的性能偏差。
最后再补充一下,Socket方式也可以有效防止扯皮问题。举个例子:张三写了一个进程A,李四写了一个进程B,进程A通过Socket方式发数据给进程B。突然有一天,两个进程的通讯出故障了。然后张三就说是李四接收数据出错;李四就说张三发送数据出错。这时候怎么办捏?很简单,随便找个Sniffer软件当场抓一下数据包并Dump出来看,问题就水落石出了。
★为啥还要线程?
上面说了这么多进程的好处,有同学要问了:"那线程有什么用捏?"总的来说,使用线程出于两方面的考虑:性能因素和编码方便。
1、性能因素
由于某些操作系统(比如Windows)中的进程比较重型,如果频繁创建进程或者创建大量进程,会导致操作系统的负载过高。举例如下:
假设你要开发一个类似Web Server的应用。你针对每一个客户端请求创建一个对应的进程用于进行数据交互(是不是想起了古老的CGI :-)。一旦这个系统扩容,用户的并发连接数一增加,你的应用立马死翘翘。
上面的例子表明,跨平台软件系统的进程数要保持相对稳定。如果你的进程数会随着某些环境因素呈线性增长,那就相当不妙了。而根据业务逻辑的单元划分进程,顺便能达到"进程数的相对稳定"的效果。
2、编码方面
由于业务逻辑内部的数据耦合比较紧密。如果业务逻辑内部的并发也用进程来实现,就会导致大量的IPC编码(任意两个进程之间只要有数据交互,就得写一坨IPC代码)。这会让相关的编程人员怨声载道。
写到这里,看看篇幅有点超,就此打住。大伙儿如有不同看法,请到评论中拍砖。
---------------------------------------------------
注1
所谓"全部用进程",就是所有的并发都使用进程实现(因此每个进程只有一个线程)。这种设计在某些平台上(比如Windows)会导致严重的性能问题。
注2
所谓"全部用线程",就是所有的并发都使用线程实现(因此整个系统只有一个进程)。这种设计的健壮性极差(一个致命错会导致整个系统崩溃),而且更别提分布部署了。
--
刘未鹏(pongba)
Blog | Mind Hacks
http://mindhacks.cn
TopLanguage
http://groups.google.com/group/pongba
还记得列表里面以前争吵过的进程vs线程的问题吗?
来自: http://program-think.blogspot.com/2009/02/multi-process-vs-multi-thread.html
就像莎士比亚的"To be, or not to be, that is the question"始终困扰着哈姆雷特,对于"进程还是线程?"这个问题,也经常困扰着那些进行软件架构设计的家伙。所以今天打算聊一下我对这个问题的体会。假如你还搞不清楚线程和进程的区别,请先找本操作系统原理的书好好拜读一下,再回来看帖。
由于这个问题很容易引发口水战,事先声明如下:多进程和多线程,无法一概而论地说谁比谁好。因此本帖主要描述特定场景(与我所负责的产品相关)下,进程和线程的权衡经验,仅供大伙儿参考。
由于特定场景是本帖讨论的前提,先说说我目前负责的产品的特点:业务逻辑比较复杂、业务数据量比较大、对数据实时处理的性能要求比较高、对健壮性和安全性要求比较高、要求跨平台(包括操作系统、数据库)、某些情况下需要分布部署。
上面说了一大堆,其实有不少的应用系统符合上述特点,比如:某些游戏服务器、某些金融方面的业务系统、某些电子商务系统等等。如果你正在从事的是类似的应用系统的设计,希望我下面介绍的经验对你有帮助。
★进程颗粒度问题
大伙儿应该明白,进程和线程都是处理并发(concurrency)的手段。对于上述这种比较复杂的系统,如果你企图全部用进程(见注1)或者全部用线程(见注2)来处理并发,估计会死得很难看。所以,关键问题就是如何在进程和线程之间进行平衡(也就是确定进程颗粒度的问题)。
我个人建议,尽量以业务逻辑的单元来划分进程。这样做的好处有如下几点:
1、避免扯皮
一般来说,某个固定业务逻辑的开发人员也是相对固定的。如果业务逻辑对应的某个进程崩溃了,测试人员容易快速定位肇事者,然后直接提交Bug给他/她。
反之,一个进程搞得太庞大,N多人掺和在里面,一旦进程崩溃了,相关编程人员之间很容易互相扯皮,不利于维护安定团结的局面;另外,由于测试人员经常搞不清楚Bug属于谁,经常给错Bug,也容易制造人民内部矛盾。
从上面可以看出来,相对细的进程颗粒度能够避免一些管理上的麻烦。由于XXX经常教导我们:"稳定压倒一切",所以该优点列第一条。
2、健壮性、容错性
一般来说,开发人员的水平参差不齐,优秀的毕竟是少数(具体参见"二八原理系列"的帖子)。所以难免会有菜鸟程序员搞出低级错误,而有些低级错误是致命的,会导致进程的崩溃。
如果你是以业务逻辑划分进程,一个业务逻辑的进程崩溃,对其它业务逻辑的影响不大(除非是该业务逻辑的依赖方);因此就不会出现"注2"提到的问题。
3、分布式
我常碰见的分布式部署需求,一般都是按照业务逻辑的维度来划分。比如系统中有一个认证模块,里面包含有敏感的用户认证信息。这时候客户就会要求把该模块单独部署在一台经过安全加固的主机中(以防阶级敌人搞破坏)。
如果是以业务逻辑为单位划分进程,要满足上述的部署需求就相对容易了(只要再配合恰当的进程间通讯机制,下面会提到)。
另外,支持分布式部署还可以顺带解决性能问题。比如某个业务逻辑模块特别消耗硬件资源(比如内存、CPU、硬盘、带宽),就可以把它拿出去单独放一台机器上跑。
4、跨编程语言
这个好处可能很多人容易忽略。一般来说,每个编程语言都有各自的优缺点。如果你通过业务逻辑划分进程,就可以根据不同的业务逻辑的特点来选择合适的编程语言。
比如:对于性能敏感的模块,我就使用C++搞定;而对于一些业务逻辑密集型的模块,则使用Java或Python开发。
★进程间通讯(以下简称IPC)问题
既然不可能把整个系统放入一个进程,那就必然会碰到IPC的问题。下面就来说一下该如何选择IPC。
各种操作系统里面,有很多稀奇古怪的IPC类型。由于要考虑跨平台,首先砍掉一批(关于IPC的跨平台问题,我在"跨平台开发"系列中会提到)。剩下的IPC类型中,能够进行数据传输的IPC就不多了,主要有如下几种:套接字(以下简称Socket)、共享内存、管道、文件。
其中Socket是我强烈推荐的IPC方式,理由如下:使用Socket可以天然地支持分布式部署;使用Socket可以比较容易地实现多种编程语言的混合(比如C++、Java、Python、Flex都支持Socket);使用Socket还可以省掉了一大坨"锁操作"的代码。
列位看官中,或许有人在担心Socket的性能问题,其实大可不必多虑。当两个进程在本机上进行Socket通讯时,由于可以使用localhost环回地址,数据不用经过物理网卡,操作系统内核还可以进行某些优化。这种情况下,Socket相对其它几种IPC机制,不会有太大的性能偏差。
最后再补充一下,Socket方式也可以有效防止扯皮问题。举个例子:张三写了一个进程A,李四写了一个进程B,进程A通过Socket方式发数据给进程B。突然有一天,两个进程的通讯出故障了。然后张三就说是李四接收数据出错;李四就说张三发送数据出错。这时候怎么办捏?很简单,随便找个Sniffer软件当场抓一下数据包并Dump出来看,问题就水落石出了。
恩,对这个话题很感兴趣。其实一开始看到"健壮"、"安全"、"分布部署"这些词的时候我就知道了,作者会使用进程来实现这些,而线程仅仅只是一种性能优化的手段。从我的角度来看,这时线程机制的作用就只是锦上添花而已,而进程机制则成为整个系统的支柱。对里面提到的两个问题的看法:1.使用线程进行性能优化的问题按照文中的描述,使用线程来做性能优化而不是使用进程来做性能优化,是因为一个新的用户session会使用一个新的进程来处理,这样用户多的时候性能就会成为一个问题,而线程比进程更加轻便,所以使用了线程来做优化。但是线程的轻便只是相对于进程而言的,如果真的是一个用户连接对应一个线程,那么这个系统的承载能力仍然非常有限。想起我以前开始做网络模块的时候,一开始看到的提供并发能力的方案就两种:多进程和多线程。当后来搞明白了select、poll和epoll的时候,越来越觉得使进程数或线程数与用户访问数直接相关是很糟糕的做法,因为你很难假设以后用户访问会不会增加以及增加到什么程度,而进程或线程则一直都是操作系统中昂贵的资源。所以文中举的那个用线程做性能优化的例子并不合适,那个问题我觉得还是用异步的方式会更好些。性能优化时,使用线程比进程更合适的情况我现在只能想到这一种:线程之间需要交换大量的数据,并且无法或难以使用共享内存来实现交换。2.使用线程来避免IPC时的繁琐操作的问题我觉得IPC并不必然是繁琐的,其实我觉得对于参与通信的进程来说IPC应该是透明的,这样逻辑功能直接的交互不仅不会导致"大量的IPC编码",甚至不会导致任何IPC编码。就简单的IPC来说,其实已经做到了透明,比如管道,对于管线上的一环来说,它只是读写stdio而已,并不需要做任何特殊的处理,可能一个进程开发的时候完全就是一个独立的程序而不是作为一个分布式系统的一部分,之后使用了netcat和管道就加入了一个分布式系统,而这个进程不需要为此做任何修改。我这段时间的尝试就是做出一个程序,它能够为其他进程提供透明的IPC服务,不仅能支持1对1的通信,而且能支持m对n的通信。以前做过的网络模块,不管怎么样设计,使用的时候仍然需要使用特定的头文件、库文件和函数调用,甚至会影响到使用它的程序的设计,这次这个东西的目标就是它的使用不会影响使用者自己的设计。
怎么看都是上erlang的好场合。
至少,erlang的超轻量级进程,单台pc轻松支持100万个进程,就已经让这个主题不值得讨论了。
Jeffrey Zhao
--------------------------------------------------
From: "taodm" <tao.do...@zte.com.cn>
Sent: Monday, February 23, 2009 9:10 AM
To: "TopLanguage" <pon...@googlegroups.com>
Subject: [TopLanguage] Re: 进程还是线程?这是个问题! by 编程随想
>
在2009-02-23,taodm <tao.do...@zte.com.cn> 写道: > >怎么看都是上erlang的好场合。 >至少,erlang的超轻量级进程,单台pc轻松支持100万个进程,就已经让这个主题不值得讨论了。
to sjinny
对于那个类CGI的例子,我只是故意举一个极端的情形来说明"不要让进程数随环境因素呈线性增长(当然更别提指数增长了)"
我原文中忘记提醒一下"也别让线程数随环境因素呈线性增长",我待会儿在Blog中补充一下。
其实我也比较认同pool的做法。
至于适合多线程的场合,除了你提到的:"线程之间需要交换大量的数据,并且无法或难以使用共享内存来实现交换。",我觉得还有其它情况也适合线程,举例如下:
例1
某进程主要负责某业务逻辑的处理,计算过程中需要不定期地从外部(比如DB、配置文件)载入某些数据参与业务逻辑处理。这时候可以用两个线程:一个主要进行处理,另一个阻塞等待某个外部的通知(比如信号量)。
例2
还有一种情况涉及到进程的反身逻辑。比如需要某个监控进程来监控其它进程的运行情况。这时候监控进程内部我倾向使用线程来监控其它进程。
ps, erlang 的多线程这么轻不会全是绿色的吧. 如果不是, 他怎么做到高效的m->n映射
2009/2/23 sjinny <sji...@163.com>:
我对透明的IPC机制也很感兴趣,不知道Program Thinker对这方面有没有什么看法?
如果公司里面有很成熟且方便易用的IPC库,可以比较透明地封装IPC相关操作,那线程在"方便编码"的某些优势就削弱了。或许就能够做到楼上说的"只定义数据格式, 不定义数据交换的方法"。
On Feb 22, 9:06 pm, pongba <pon...@gmail.com> wrote:
> *还记得列表里面以前争吵过的进程vs线程的问题吗?*
>
> 来自:http://program-think.blogspot.com/2009/02/multi-process-vs-multi-thre...
>
> 就像莎士比亚的"To be, or not to be, that is the
> question"始终困扰着哈姆雷特,对于"进程还是线程?"这个问题,也经常困扰着那些进行软件架构设计的家伙。所以今天打算聊一下我对这个问题的体
> 会。假如你还搞不清楚线程和进程的区别,请先找本操作系统原理的书好好拜读一下,再回来看帖。
> 由于这个问题很容易引发口水战,事先声明如下:多进程和多线程,无法一概而论地说谁比谁好。因此本帖主要描述*特定场景*
> (与我所负责的产品相关)下,进程和线程的权衡经验,仅供大伙儿参考。
> 由于特定场景是本帖讨论的前提,先说说我目前负责的产品的特点:业务逻辑比较复杂、业务数据量比较大、对数据*实时*
> 处理的性能要求比较高、对健壮性和安全性要求比较高、要求跨平台(包括操作系统、数据库)、某些情况下需要分布部署。
> 上面说了一大堆,其实有不少的应用系统符合上述特点,比如:某些游戏服务器、某些金融方面的业务系统、某些电子商务系统等等。如果你正在从事的是类似的应用系统-的设计,希望我下面介绍的经验对你有帮助。
>
> ★进程颗粒度问题
> 大伙儿应该明白,进程和线程都是处理并发(concurrency)的手段。对于上述这种比较复杂的系统,如果你企图全部用进程(见注1<http://program-think.blogspot.com/#comment1>
> )或者全部用线程(见注2 <http://program-think.blogspot.com/#comment2>
> )来处理并发,估计会死得很难看。所以,关键问题就是如何在进程和线程之间进行平衡(也就是确定进程颗粒度的问题)。
> 我个人建议,尽量*以业务逻辑的单元来划分进程*。这样做的好处有如下几点:
> 1、避免扯皮
> 一般来说,某个固定业务逻辑的开发人员也是相对固定的。如果业务逻辑对应的某个进程崩溃了,测试人员容易快速定位肇事者,然后直接提交Bug给他/她。
> 反之,一个进程搞得太庞大,N多人掺和在里面,一旦进程崩溃了,相关编程人员之间很容易互相扯皮,不利于维护安定团结的局面;另外,由于测试人员经常搞不清楚B-ug属于谁,经常给错Bug,也容易制造人民内部矛盾。
> 从上面可以看出来,*相对*细的进程颗粒度能够避免一些管理上的麻烦。由于XXX经常教导我们:"稳定压倒一切",所以该优点列第一条。
> 2、健壮性、容错性
> 一般来说,开发人员的水平参差不齐,优秀的毕竟是少数(具体参见"二八原理系列<http://program-think.blogspot.com/2009/02/80-20-principle-0-overview....>
> "的帖子)。所以难免会有菜鸟程序员搞出低级错误,而有些低级错误是致命的,会导致进程的崩溃。
> 如果你是以业务逻辑划分进程,一个业务逻辑的进程崩溃,对其它业务逻辑的影响不大(除非是该业务逻辑的依赖方);因此就不会出现"注2<http://program-think.blogspot.com/#comment2>
> "提到的问题。
不太同意进程比线程更健壮的说法,如果是用多进程的话一般都是流水线的设计,其中某个进程crash了,那么整个流水线就block在这个进程上了,就
算其他进程都正常,整个服务还是不能正常工作的。另外用了多进程的话,因为进程之间有依赖性,整个服务的启动、关闭、维护都会变得相对困难,更谈不上健
壮了。
采用多线程还是多进程主要还是取决与你的应用。多线程的优点在于线程之间可以共享内存,如果你的应用有大量状态需要共享,那么多线程就提供了高效且便利
的机制来存取这些状态,而用多进程的话如果要共享状态就会变得非常昂贵而可能严重的拖跨性能。
On Mar 2, 10:26 am, Program Thinker <program.th...@gmail.com> wrote:
> 楼上的同学
>
> 关于进程的流水线问题,其实不一定如你所说的这么悲观。
> 我举例如下:
>
> 数据采集 ==> DB ==> 数据分析 ==> DB ==> 数据展示
>
> 假设有这么一个业务流程,其中数据采集、数据分析、数据展示都用进程实现。
> 如果某个进程崩溃,只要由专门的*进程监控*模块把崩溃的进程重新启动,对于其它进程的影响很小。
> 另外,即使进程之间不是通过DB,而是通过诸如socket方式进行数据交互,只有有专门的进程监控机制,也很容易恢复过来。
>
> 关于多线程的优点,其实我原文中已经提到。
> 对于数据耦合比较紧密的情况,我认为线程会比较方便。
>
> 2009/3/1 qiaojie <qiao...@gmail.com>
>
> > 不太同意进程比线程更健壮的说法,如果是用多进程的话一般都是流水线的设计,其中某个进程crash了,那么整个流水线就block在这个进程上了,就
> > 算其他进程都正常,整个服务还是不能正常工作的。另外用了多进程的话,因为进程之间有依赖性,整个服务的启动、关闭、维护都会变得相对困难,更谈不上健
> > 壮了。
> > 采用多线程还是多进程主要还是取决与你的应用。多线程的优点在于线程之间可以共享内存,如果你的应用有大量状态需要共享,那么多线程就提供了高效且便利
> > 的机制来存取这些状态,而用多进程的话如果要共享状态就会变得非常昂贵而可能严重的拖跨性能。
>
> --
> ----------------
> 编程随想
> program.th...@gmail.comhttp://program-think.blogspot.com
进程的崩溃和重启动远没有想象的那么简单,也需要一套复杂的实现来保证。要不就不会有系统管理员这个职位存在。
进程优于线程的只有存取边界和跨机器部署,隐形的优势是防止程序员抻面条。想用个全局就用全局,全无顾虑。
说到场景恢复问题和线程监视问题倒是进程和线程都存在的。
On Mar 2, 11:55 am, Program Thinker <program.th...@gmail.com> wrote:
> 具体要看 "复杂的实现" 到底有多复杂。如果衡量下来,"复杂的实现" 产生的成本不太大,那用进程还是挺合算的(我以前做的系统就属于这种情况)。
> 毕竟进程的优势,楼上的同学也点出来了。而且有些优势(比如跨机器)线程在技术上无法取代。
>
> 另外,楼上的同学能否介绍一下,之前碰到的由于 "进程崩溃和重启动" 导致的复杂实现大概是什么样子的?
>
> 2009/3/2 Bennie <ZhaoYin...@gmail.com>
>
> > 进程的崩溃和重启动远没有想象的那么简单,也需要一套复杂的实现来保证。要不就不会有系统管理员这个职位存在。
> > 进程优于线程的只有存取边界和跨机器部署,隐形的优势是防止程序员抻面条。想用个全局就用全局,全无顾虑。
>
> --
> ----------------
> 编程随想
> program.th...@gmail.comhttp://program-think.blogspot.com
CUDA个人理解是一个很大的SIMD,不是线程的概念
线程的本质问题,参见这篇文章
http://www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.html
----------------------------------------------------------------------------------
Yours Sincerely
Kun
blog: www.forwind.cn
2009/3/1 qiaojie <qia...@gmail.com>:
共享内存的存储模型也不是新的概念,OpenMP就是一个可以在Cluster上做share memory programming的模型。
关于CUDA,虽然它能执行分支和跳转,但是所有线程必须必须执行同样的分支和跳转,如果线程处于不同的分支和跳转,他们会相互等待,对于大规模的数据并行这不是大问题,这也是为什么我认为它是一个SIMD的模型体现。但是对于细粒度的并行,比如instruction
level or task level的并行,CUDA就很难高效handle。
所以,我认为线程只是传统的串行计算机的模型,本质问题那篇paper也说了很多,现在有很多真正细粒度的programming
model,比如actor这种,我认为这些更加promising
erlang非业余 mryufeng.javaeye.com
我说的Bluegene就是scale到cluster形式的,超级计算机没有不这么用的吧?
OpenMP有for cluster的啊:http://www.hpcwire.com/features/17884424.html
To qiaojie:你确定?你看看这篇文章
http://www.touchdreams.net/blog/2009/02/26/cuda-thread-warp-and-simt/
我很早以前看过CUDA的正式论文,也记得是这样的。也可能是我记错了。你的说法的出处?
----------------------------------------------------------------------------------
Yours Sincerely
Kun
blog: www.forwind.cn
2009/3/2 jiang li <li.ji...@gmail.com>:
erlang语言把并发特性提升到了一个更好的层次,不过可能它的优势还是在于通讯方面。
On 3月3日, 上午9时34分, jiang li <li.jian...@gmail.com> wrote:
> "Intel is offering Cluster OpenMP*, which extends the OpenMP programming
> model to clusters"
> sorry,我不知道intel出了一个扩展版本。
> OpenMP的通信是基于共享内存的,一般cluster不具备这一点。Intel的这个版本将它扩展了,底层的实现应该是基于消息传递,然后模拟出共享内存的接口。所以对于开发人员好像还是在访问共享内存,但其实底层是消息传递机制。
>
> 2009/3/3 windstorm <likunarmstr...@gmail.com>
>
> > 我没觉得我理解错了。
>
> > 我说的Bluegene就是scale到cluster形式的,超级计算机没有不这么用的吧?
>
> > OpenMP有for cluster的啊:http://www.hpcwire.com/features/17884424.html
>
> > To qiaojie:你确定?你看看这篇文章
>
> >http://www.touchdreams.net/blog/2009/02/26/cuda-thread-warp-and-simt/
>
> > 我很早以前看过CUDA的正式论文,也记得是这样的。也可能是我记错了。你的说法的出处?
>
> > ----------------------------------------------------------------------------------
> > Yours Sincerely
> > Kun
>
> > blog:www.forwind.cn
>
> > 2009/3/2 jiang li <li.jian...@gmail.com>:
> > > 你们两个人的理解应该都有些问题。
> > > "A computer cluster is a group of linked computers, working together
> > closely
> > > so that in many respects they form a single
> > > computer.",所以cluster应该是很多台机器,而不是一台机器。
> > > 至于OpenMP,它应该是不能用于cluster的,因为一般意义的cluster是不共享内存的。cluster常用的是MPI。
>
> > > 2009/3/2 qiaojie <qiao...@gmail.com>
>
> > 你所说的cluster是超级计算机一类的大型计算机吧?上千万一台的东西对你来说居然都不算希罕玩意,你可以的.....反正我是没机会接触。共享内存当然不是什么新鲜概念,但是从理论到实用是要经过很长一段路要走的。
> > >> 在CUDA里面每个线程可以有不同的分支顺序而不会互相等待,不然的话分支程序的效率将一塌糊涂了,建议你再好好的看一下CUDA的架构。
>
> > 至于你所说的那篇文章,作者只是抱怨了一番多线程编程有多困难,但是却给不出更好的计算模型来(虽然他相信有),最多只是在多线程的基础上增加一些约束和抽象出一些更高层的概念来简化这些困难,但是本质上还是脱离不了多线程的。
>
> > >> 2009/3/2 windstorm <likunarmstr...@gmail.com>
>
> > >>> 传统的cluster不早就几千个线程了么,又不是什么稀罕的事情,看看IBM的深蓝不就是么。
>
> > >>> 共享内存的存储模型也不是新的概念,OpenMP就是一个可以在Cluster上做share memory programming的模型。
>
> > 关于CUDA,虽然它能执行分支和跳转,但是所有线程必须必须执行同样的分支和跳转,如果线程处于不同的分支和跳转,他们会相互等待,对于大规模的数据并行这不是大问题,这也是为什么我认为它是一个SIMD的模型体现。但是对于细粒度的并行,比如instruction
> > >>> level or task level的并行,CUDA就很难高效handle。
>
> > >>> 所以,我认为线程只是传统的串行计算机的模型,本质问题那篇paper也说了很多,现在有很多真正细粒度的programming
> > >>> model,比如actor这种,我认为这些更加promising
>
> > ----------------------------------------------------------------------------------
> > >>> Yours Sincerely
> > >>> Kun
>
> > >>> blog:www.forwind.cn
>
> > >>> 2009/3/1 qiaojie <qiao...@gmail.com>:
>
> > 线程和进程的本质区别在于存储模型。存储模型对于并行计算是非常重要的概念,决定了你可以做什么不可以做什么。只有多核出现之后,我们才有了可以共享内存的多个计算单元的硬件,多线程实现并行计算才会变得有价值,所以说是多核促成了多线程并行计算的发展,现在的CPU最多也就是4核8核,还显示不出什么威力,但如果像GPU那样同时运行上千个线程,那么威力就完全显示出来了。
>
> > 另外CUDA也不是SIMD,GPU内部虽然有SIMD单元用来执行向量操作,但是CUDA每个执行绪有自己的分支和跳转,这个不是SIMD的范畴。
>
> > >>> > 2009/3/2 windstorm <likunarmstr...@gmail.com>
>
> > >>> >> 没理解你说多线程和"多核"的"相互促进"的关系
>
> > >>> >> CUDA个人理解是一个很大的SIMD,不是线程的概念
>
> > >>> >> 线程的本质问题,参见这篇文章
>
> > >>> >>http://www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.html
>
> > ----------------------------------------------------------------------------------
> > >>> >> Yours Sincerely
> > >>> >> Kun
>
> > >>> >> blog:www.forwind.cn
>
> > >>> >> 2009/3/1 qiaojie <qiao...@gmail.com>:
> ...
>
> 阅读更多 >>
第一,同一个SM只能执行一个wrap,在一个时间段内。这就是相当于SIMD
第二,不同的SM之间不能cooperate。而且local memory不能share,share的level是global
memory,需要手工定义,根本就不是uniform shared memory。不过这点不是很确定。很早以前看得paper了。
当然你对SM的调度可以手工指定的,但这就不是shared memory的编程模式,和传统的thread概念就不一样了。
最后,我个人认为,CUDA就是对GPU的一种hack而已。就以前和别人交流的情况看,学术界没有听说把CUDA称为多线程平台的。你要这样认为也可以,但把CUDA作为多线程并行平台的例子,我个人认为不合适。
To jiang li:
对,也就是在cluster上搞虚拟内存地址。
另外wiki上对于cluster的概念定义太狭窄,一堆computer可以搞cluster,一堆CPU也可以以node的概念搞cluster,Bluegene一出来的paper就是发表在ICCC上面的
----------------------------------------------------------------------------------
Yours Sincerely
Kun
blog: www.forwind.cn
2009/3/2 qiaojie <qia...@gmail.com>:
我说的cluster就是一堆multiprocessor的组合,例如bluegene。只不过此时cluster的节点,通常偏向于CPU加内存,通过SAN链接起来的。当然人们也可以argue
CPU+内存就是computer了。所以这种概念很模糊。
而且“一堆机器通过LAN的方式组合到一起”肯定是不完善的概念,你可以看看这篇文章
http://ceng.usc.edu/smart/presentations/archives/AppendixE.ppt
我忘了以前看到概念的出处,貌似是Computer Architecture: A Quantitative Approach这本书的附录的介绍。
我不确定你能不能找到,IEEE上好像都是abstract。如果找不到原文给我说声,我传给你。
唉,CUDA这么深入人心,就是Nvidia在CUDA推出的时候,到处去世界各地演讲忽悠来的。当时各个大学都开始尝试用CUDA编程,然后炒火了。
你既然已经承认thread会有不确定性,假设thread带来的不确定性加上分层内存带来的限制,会导致多核编程一点都不scalable。而且我觉得CUDA就是SIMD的模型,没有人会当作并行多线程模型来研究它,至少我没见过。
就算退一万步说,线程会是发展方向,也不会是CUDA这种非标准线程模型,而是类似于Larrabee的这种模型。你去看看Larrabee的架构,哪个才叫“并行多线程”?
顺便加一句,Thread继续发展的最大道理也就是legacy code很多。
你要真觉得CUDA就是好,那就坚持吧,这种就是个人选择而已。但是你把CUDA当作promising的并行多线程平台......
Anyway,我没什么多说的
包括你说的OPENCL,实际上这个是apple提出来,接受这个OPENCL的组织也是multimedia的组织而已,也就是说,如果你认为以后的多核编程全是图像处理,数据并行,那说不定CUDA这种编程模型还是有用的。
但显然,这并不是实际情况,举个最简单的例子,一个http server,怎么用CUDA handle呢?
既然你举了Cell的例子,Cell的推出是为了sony的ps3,相对于wii和xbox360来讲,Cell投资最多,但出货量最少,所以不是说投钱最多的东西就是好东西。应该说,我个人理解,就是因为Cell这种复杂编程模型给application的开发带来很大的困难,换句话来说,一个公司想开发cell上的程序,必须高价雇佣像你这样喜欢并行复杂编程模型的程序员。
你讲的关于cache coherence的问题,除了用你所说的用local memory的办法来解决,还有诸如像transactional
memory的办法解决,而你所谓的这种“local memory”的办法,只能是一种临时的解决方案,因为会带来很高的编程复杂度。
如果你就是一个programmer的话,你现在没什么办法,只能适应别人的架构和模型,但是小心哦,过了N年之后公司可能把你fire掉,因为这种编程的架构,因为编程的人太少,会逐渐消失的。
大家都是外行,但你不能接触内行,不代表别人不能接触内行。工业界的人通常都有大量编程经验,so
what?建议你多看看学术界的动向比较好,体系结构方面ISCA和HPCA还是每年都开得,看看有几个人还在“多线程复杂并行平台”的问题上纠缠。你有时间问“你妈贵姓”,不如给那些TPC发mail探讨一些这些问题,我保证你会有新的思路和见解的,那帮TPC有不少就是你所谓的“神一般的人物”。
Anyway,我不想在这个问题上和你继续纠缠,除非你有新的idea。
----------------------------------------------------------------------------------
Yours Sincerely
Kun
blog: www.forwind.cn
2009/3/3 qiaojie <qia...@gmail.com>:
至于PS3的编程复杂性,感觉那纯属于软件设计的问题,如果没有CUDA,没有CG,
opengl和diretx,
直接面对GPU,恐怕GPU编程要比PS3还要麻烦...好在driver都替你做了。
其实CUDA的给我们的好处在于,你花上1W美金就可以搞到一台个人的超级计算机,
剩下的就发挥想象吧。。。
windstorm 写道:
我一开始的立意就是(33楼)
1 多线程和“多核”没有“相互促进”的关系(和一些人讨论的见解而已,不认同的人可以不认同)
2 CUDA个人理解是一个很大的SIMD,不是线程的概念(这个争议应该不大吧?)
所以我赞同你的话。唯一需要提到的是,
“其实CUDA的给我们的好处在于,你花上1W美金就可以搞到一台个人的超级计算机, 剩下的就发挥想象吧。。。”
当然是大家都可以想象的,就是编程起来太难了。
----------------------------------------------------------------------------------
Yours Sincerely
Kun
blog: www.forwind.cn
2009/3/3 avalon <aval...@gmail.com>:
我承认CUDA是一个很好SIMD的平台,所以在大规模图形图像或者数据并行处理方面有很大优势,这就是为什么我说CUDA就是GPU的一个hack而已。我说整个CUDA忽悠是有点过了,但至少CUDA的线程模型是忽悠,你想看什么是不忽悠,不是给你推荐了Larrabee么。
包括你说的OPENCL,实际上这个是apple提出来,接受这个OPENCL的组织也是multimedia的组织而已,也就是说,如果你认为以后的多核编程全是图像处理,数据并行,那说不定CUDA这种编程模型还是有用的。
但显然,这并不是实际情况,举个最简单的例子,一个http server,怎么用CUDA handle呢?
既然你举了Cell的例子,Cell的推出是为了sony的ps3,相对于wii和xbox360来讲,Cell投资最多,但出货量最少,所以不是说投钱最多的东西就是好东西。应该说,我个人理解,就是因为Cell这种复杂编程模型给application的开发带来很大的困难,换句话来说,一个公司想开发cell上的程序,必须高价雇佣像你这样喜欢并行复杂编程模型的程序员。
你讲的关于cache coherence的问题,除了用你所说的用local memory的办法来解决,还有诸如像transactional
memory的办法解决,而你所谓的这种“local memory”的办法,只能是一种临时的解决方案,因为会带来很高的编程复杂度。
如果你就是一个programmer的话,你现在没什么办法,只能适应别人的架构和模型,但是小心哦,过了N年之后公司可能把你fire掉,因为这种编程的架构,因为编程的人太少,会逐渐消失的。
大家都是外行,但你不能接触内行,不代表别人不能接触内行。工业界的人通常都有大量编程经验,so
what?建议你多看看学术界的动向比较好,体系结构方面ISCA和HPCA还是每年都开得,看看有几个人还在“多线程复杂并行平台”的问题上纠缠。你有时间问“你妈贵姓”,不如给那些TPC发mail探讨一些这些问题,我保证你会有新的思路和见解的,那帮TPC有不少就是你所谓的“神一般的人物”。
1 whereas SIMT instructions specify the execution and branching behavior
of a single thread. In contrast with SIMD vector machines, SIMT enables
programmers to write thread-level parallel code for independent,
scalar threads, as
well as data-parallel code for coordinated threads.
这不就是证明了我说的么。你当然可以specify the execution and branching behavior
of a single thread.
问题在于CUDA是怎么执行它的?然后我告诉你,
“如果线程处于不同的分支和跳转,他们会相互等待,对于大规模的数据并行这不是大问题,这也是为什么我认为它是一个SIMD的模型体现。但是对于细粒度的并行,比如instruction
level or task level的并行,CUDA就很难高效handle”
你给我argue
“同一时间里会有很多个wrap同时运行,而wrap之间的执行是独立的,不存在互相等待的问题”
我告诉你
“同一个SM只能执行一个wrap,在一个时间段内。这就是相当于SIMD
不同的SM之间不能cooperate。而且local memory不能share,share的level是global
memory,需要手工定义,根本就不是uniform shared memory。当然你对SM的调度可以手工指定的,但这就不是shared
memory的编程模式,和传统的thread概念就不一样了。”
这就叫线程不完备性,明白?
2 没有理由让Intel另起炉灶开发出一个新的API?你比我还要行,我只是批判一下CUDA而已,你连人家Intel的蓝图都规划了
看看这个吧
http://techresearch.intel.com/articles/Tera-Scale/1514.htm
3 http server确实不恰当,总的来说就是这种细粒度的每个thread做不同的branch的任务。你要真觉得CUDA好handle,OK,go on。
4 Local Memory会带来很高的编程复杂度不是我的yy,唉。也没听说过“Local
Memory其实是非常自然的解决方案”,我觉得是你自己的yy吧,我告诉你Local
Memory的问题是难以调度,特别要求程序员对底层硬件工作原理特别了解,这造成了人力成本急剧上升。如果你调度不好Local
Memory,说不好听的,就等死吧。
5 事实上是以CUDA/OpenCL为代表的计算平台,只是流处理的某种代表。流处理语言海了去了,Brook/+,CT,streamc,etc。CUDA只是宣传最为猛烈的而已。而且也就你把CUDA当作“多线程并行”计算平台的发展方向。
6 我暂时还不会混工业界,不用你担心我被fire。只是我实在想不出你迷信CUDA是“并行计算平台发展方向”的理由,也许你现在就是CUDA
programmer,也许还是高水平的,特佩服CUDA。但你这个“发展方向”实在有点信口开河。将来并行平台可能是application
specific的,也可能是有新的平台出来一统天下,但这个平台绝对不会是CUDA,而在流处理领域,没几个学术界大牛看好CUDA的。说了半天你还是没看Larrabee的架构吧?光这个架构看好程度就比CUDA大。
7 你要继续你的CUDA,没问题,个人选择而已,但别扣什么“平台发展方向”的帽子了。唱衰多线程并行平台的paper,你想要我可以给你找一箩筐。Edward
A. Lee的paper给你看了,你说人家空谈,他在体系领域的地位至少都是和你口中那些“神人”一个级别的。将来可能的并行平台模型,他也提出来了,不过不是这篇paper而已,你自己去看看他的主页
http://ptolemy.eecs.berkeley.edu/~eal/
8 如果你还想继续这种“发展方向”的争论,恕不奉陪。反正Post也摆在这里,希望得到信息的人自然会从中提取。
----------------------------------------------------------------------------------
Yours Sincerely
Kun
blog: www.forwind.cn
2009/3/3 qiaojie <qia...@gmail.com>:
对于CUDA线程,我的意见:
1 CUDA有没有线程? 有
2 CUDA是不是线程完备? 不是
3 CUDA这种手工指定的调度适合不适合细粒度大规模branch任务? 我认为不适合。别人可以自行判断。
----------------------------------------------------------------------------------
Yours Sincerely
Kun
blog: www.forwind.cn
2009/3/3 windstorm <likunar...@gmail.com>:
uan
如果我没有估计错,你应该就是GPGPU的programmer吧。
那就正常了,因为你所处理的数据就根本不用担心复杂调度的问题。Local memory这种设计就是CUDA这种应用数据的specific
design。你也没有接触过这种细粒度多branch的并行任务。
我给你举个例子,你就知道为什么CUDA不会是发展方向。你去看看Sun的Rock和Niagara
1/2,注意看架构的区别,你就知道为什么说CUDA是data specific design。你也就会明白为什么我说
“将来并行平台可能是application specific的,也可能是有新的平台出来一统天下,但这个平台绝对不会是CUDA”
http://en.wikipedia.org/wiki/UltraSPARC_T2
http://en.wikipedia.org/wiki/Rock_processor
相关paper可以在wiki的reference中找到
还有,Niagara和Larrabee的线程才叫完备性,这就是他们和CUDA能做的事情的区别之一。
对于Larrabee,我估计你到死也不愿意去看他的设计吧。你看了就知道为什么Intel不会在上面用OPENCL了。
http://www.spectrum.ieee.org/jan09/7129
----------------------------------------------------------------------------------
Yours Sincerely
Kun
blog: www.forwind.cn
o
我一开始就谈到了,并行平台发展,要不然你用全新的概念,比如actor这种,要不然你用现有的架构,但是specific
application。而CUDA的问题是过于specific application了,但是像Larrabee这种线程完全完备的,task
level也能处理很好。
Larrabee虽然没有正式推出,但是其优点在学术界早就开始探讨了,很多人就是拿CUDA作为反例。CUDA,以及其所采用的local
memory机制,一旦跳出这个领域,相较于其变成复杂性,真的就是一个死。Larrabee允许现有程序员不经过任何特殊training就上手编程,包括图形图像,科学计算,或者网络处理,各个领域。cell和CUDA谁能做到?
你可能觉得没什么,但是如果Larrabee真的和其资料显示的那样,至少在GPGPU方面,公司的倾向性会非常明显。你去哪里找那么多对底层和开发都精通的程序员?
Anyway,CUDA现在当然是有用的,我们这里用CUDA的lab也是一堆。只是在探讨“未来的发展趋势”的时候,我只能说,我自己,包括以前交流的人,没有把CUDA作为方向的。
其实说这些趋势都是虚的,让时间说话吧。
一种就是显示控制,比如erlang这种消息机制,一种就是隐式控制,比如共享内存。
那么,两者有什么区别呢?对于显式控制的语言,它的缺点在于编起来比较麻烦,好处在于性能会比较好。对于隐式控制的语言则刚好相反,你根本不用去care这些东西,但性能就会有牺牲。
这是productivity和efficiency的trade off。
至于Lee谈到的Bug问题,我个人理解和消息机制或者共享内存没啥关系,这是多线程并行计算故有的问题,你用erlang也可能遇到这种情况。
再深入的我就没法解释了,因为我对erlang本身不是很了解。但如果你还有更深入的问题,可以提出来,TP说不定有了解的,实在不行我可以拿来问问我朋友的老板,他是编程语言界大牛。
我其实对这个话题很感兴趣的,可惜一直没时间去看。
----------------------------------------------------------------------------------
Yours Sincerely
Kun
blog: www.forwind.cn
2009/3/4 jiang li <li.ji...@gmail.com>:
是这样的,我对erlang不是很了解,但是对于并行编程来说,最本质的问题就是它会出现共享的情况。这是任何编程语言都无法避免的,所以你的trick就在于,怎么去处理这种共享的情况。
一种就是显示控制,比如erlang这种消息机制,一种就是隐式控制,比如共享内存。
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
当然,显式还是隐式没有一个标准说法,我的理解是错的也是可能的。不要过于当真:)
----------------------------------------------------------------------------------
Yours Sincerely
Kun
2009/3/4 Rockins Chen <ybc...@gmail.com>:
“你妈贵姓”出自周星驰《大话西游》,用来表示提起一个很无聊很没有意义的话题。并非骂人。Rockins Chen大约是误会了
发件人: pon...@googlegroups.com [mailto:pon...@googlegroups.com] 代表 qiaojie
发送时间: 星期四 2009年03月05日 上午 10:38
收件人: pon...@googlegroups.com
主题: [TopLanguage] Re: 进程还是线程?这是个问题! by 编程随想
我觉得问题到不是哈佛架构还是冯氏架构,这两种架构对软件层的影响不是很大。FP类的语言虽然在软件上很完美,而且天生具有并行执行的能力,但在性能上却一直没法跟命令式语言比,特别是no side effect的约束条件是非常强的约束,连变量赋值这样的操作都是不允许的,而具有side effect的函数都必须串行化执行,这样本身会造成编程困难,在性能上也是需要置疑的。并行计算本身就是为了解决性能问题而出现的,如果语言本身有性能问题,那很可能会得不偿失。所以,我认为像erlang这样的语言可能未必是将来并行计算的主流方向,erlang更像是分布式时代的产物。
你误解了我的意思,我的意思是说FP语言本身不可能避免串行化,FP语言对有无side effect的函数做了严格的区分,将no side effect的函数并行化,而有side effect的函数都必须串行化执行,这样才能保证程序的正确性。但是其实有些具有side effect的函数是可以并行化的,如果过分严格的串行化,就可能导致性能问题。
语言的性能对于并行计算来说的话是非常重要的,因为各种因素使得性能跟执行核数之间不是线性关系,假设FP语言比命令式语言慢了10倍,不可能通过增加10倍的核数来弥补,可能需要多的多的核或者根本弥补不过来。那么这种并行算法就是完全失效的。
目前为止,我曾经参与过的一个最复杂的分布式并行系统是基于ICE的网络游戏服务器Wish,是ICE开发小组成员亲自开发的服务器系统(当年是作为ICE的主打产品来宣传的)。这个项目最终以失败告终,当然失败有很多其他的原因,这里具体不多说了。我只简单说说一下服务器的问题。Wish服务器的程序员本身在分布式领域有很多年的开发经验,应该说从代码的质量来看还是相当高的,但是事后看服务器的架构设计基本上是完全失败的。Wish里的每一个功能模块都是一个独立的服务,可以任意部署到一个进程或者多个进程里,从表面上看这个设计具有很高的伸缩性,(当时的wish小组是搞了88台服务器的集群),但是实际上通过我们做的一些简单的profile,就明显的发现很多服务的性能不能随着服务器的增加而显著提升,很多服务部署到一个进程里反而性能更好(因为减小了通讯成本)。而由分布式编程带来的复杂性则使得开发变得尤其的困难,很多困难是没有做过的人想不到的,比方说部署及维护上的繁杂,关闭重启一下服务器需要很长时间,跟踪调试彻底失效(因为很容易的,一个方法调用就跑到另外一个进程里去没法跟踪了),编程上更是受到诸多限制导致很多不必要的复杂性。事后我也进行过一些总结,首先就是并行计算,并行只是提高性能的手段而不是目的,在并行化之前要非常仔细的考察性能问题,否则很有可能得不偿失。
顺便说说题外话:我认为逻辑上紧密的东西物理上也应该紧密,否则不容易理解,性能低下,可扩展性也差。我的blog 有一个关于模块化的讨论就是这个方面。
稍微来个具体的实例分析就能看出你的设计有多么的不靠谱首先战斗计算的开销非常小,一般都是些简单的加减运算,几乎不耗什么CPU,反倒是把数据序列化通过网络传输再反序列化的开销要大很多,把战斗计算分离出来是典型的吃肥走瘦。而位置管理则是一个计算密集型服务,算法复杂度为m * n,如果角色多的话最容易出现瓶颈。你把不该并行的并行了,需要并行的却没有并行化。需不需要并行计算以及怎么分割任务跟耦合度是没有关系的,很多时候就是要把某个高度内聚的模块分割开来并行计算,比方说碰撞检测和物理模拟是个计算密集型模块,现在有不少物理引擎已经可以做到并行化计算,甚至放到GPU里计算。
2009/3/7 sjinny <sji...@163.com>
其实是云风的blog上描述的……当然也许我描述得并不精确。对于火球法术来说可以这样:1.A给服务器发命令要攻击B,接入进程根据配置表把相关的数据打包路由给战斗进程2.战斗进程收到命令后,根据战斗逻辑进行预判,如果允许攻击,则记录下这个行为,并向位置进程发命令,要求创建一个火球的实体进行运动模拟,并订阅火球与其他实体发生碰撞的事件,并且可以说明这个火球一旦碰撞到特定类型的实体就会自动消失3.位置进程会对火球和其他实体的运动进行模拟,并且会给其他客户端进行运动同步,当发生碰撞时就通知这个事件的订阅者(这里是战斗进程),并且会有超时的功能(或者说是实体有生命期)4.战斗进程收到火球碰撞的事件或者超时事件,那么就会取出关于这个对象的战斗记录:火球法术。然后根据事件判断要做些什么,如果是要修改对象属性,那么就可以发消息给对象管理器去修改属性。属性修改可能只是一个值或者一个增量,也可能是一个公式id加参数。对于共享状态,要么尽量减少它,要么就要有一定的通信手段,比如:1.事件的订阅/发布机制2.在产生请求时能够根据配置把对方所需的数据与命令一起发送过去3.显式查询4.可能还有其他办法如果两个进程之间需要共享的东西太多,特别是需要实时共享的东西太多,那么说明两个进程耦合太大,需要从设计的层面进行考虑。当然,这方面我也不是很在行,不过这是我学习的方向。我*猜测*越复杂的东西伸缩性越难保证……只是猜测……不过wish最终是因为性能不足导致部署成本太高,还是有其他商业上的原因?
这里的正确性是指共享数据的逻辑一致性,举例来讲,如果运行到一半的时候,进程被系统管理员误操作给kill了,你怎么保证在DB中的数据是处于一个一
致的,可以继续供其它进程来使用的。当你重启进程的时候,怎么样区分可以重用的,或者需要丢弃的数据?
使用多进程,将一个逻辑上完整的应用的各个内部的组成部分都暴露在了OS层面上,导致了更多可能受到OS影响而出错的点。这一点是削弱了健壮性的。更不
用说极大地提高了使用和维护上的成本。
而顶楼提到的多线程之前的干扰,完全可以通过一个通用的线程抽象层来加以减轻,也就是说由一个统一的模块来负责创建和启动线程,并在最外层加上
error handling,这样已经可以解决很大程度上减少影响。至于对共享数据操作导致的互相干扰,用IPC也一样会有。
至于,跨机器的部署这样的需求,是需要项目开始之前就要充分考虑的,跨machine boundary的RPC的效率和LPC不是一个量级的。很难想
像一个完全没有考虑过跨机器部署的需求的应用,只是因为用了多进程,就会可以很容易地部署到多个机器上去。
我觉得这个问题本来就是各有利弊,其实没啥好讨论的,很多时候是OS决定了的。在Windows平台上,还是多线程优先。
On 3月2日, 上午11时02分, Bennie <ZhaoYin...@gmail.com> wrote:
> 进程的崩溃和重启动远没有想象的那么简单,也需要一套复杂的实现来保证。要不就不会有系统管理员这个职位存在。
> 进程优于线程的只有存取边界和跨机器部署,隐形的优势是防止程序员抻面条。想用个全局就用全局,全无顾虑。
>
同意楼上的同学。我不知道楼主有没有真正试过用“数据采集 ==> DB ==> 数据分析 ==> DB ==> 数据展示”来做一个健壮的项目。
用内存以外的东西来当作两个进程之前通信的方式是挺危险,且不论性能的问题,也很难保证它的正确性的。
这里的正确性是指共享数据的逻辑一致性,举例来讲,如果运行到一半的时候,进程被系统管理员误操作给kill了,你怎么保证在DB中的数据是处于一个一致的,可以继续供其它进程来使用的。当你重启进程的时候,怎么样区分可以重用的,或者需要丢弃的数据?
使用多进程,将一个逻辑上完整的应用的各个内部的组成部分都暴露在了OS层面上,导致了更多可能受到OS影响而出错的点。这一点是削弱了健壮性的。更不用说极大地提高了使用和维护上的成本。
而顶楼提到的多线程之前的干扰,完全可以通过一个通用的线程抽象层来加以减轻,也就是说由一个统一的模块来负责创建和启动线程,并在最外层加上 error handling,这样已经可以解决很大程度上减少影响。至于对共享数据操作导致的互相干扰,用IPC也一样会有。
至于,跨机器的部署这样的需求,是需要项目开始之前就要充分考虑的,跨machine boundary的RPC的效率和LPC不是一个量级的。很难想
像一个完全没有考虑过跨机器部署的需求的应用,只是因为用了多进程,就会可以很容易地部署到多个机器上去。
我觉得这个问题本来就是各有利弊,其实没啥好讨论的,很多时候是OS决定了的。在Windows平台上,还是多线程优先。
On 3月2日, 上午11时02分, Bennie <ZhaoYin...@gmail.com> wrote:
- Show quoted text -
> 进程的崩溃和重启动远没有想象的那么简单,也需要一套复杂的实现来保证。要不就不会有系统管理员这个职位存在。
> 进程优于线程的只有存取边界和跨机器部署,隐形的优势是防止程序员抻面条。想用个全局就用全局,全无顾虑。
>
我在原文特地写了如下一段话,但还是没有躲过数量众多的口水 :-)对于楼上的Hush同学,我做了逐条的回答。
由于这个问题很容易引发口水战,事先声明如下:多进程和多线程,无法一概而论地说谁比谁好。因此本帖主要描述特定场景(与我所负责的产品相关)下,进程和线程的权衡经验,仅供大伙儿参考。
2009/3/8 Hush <just...@gmail.com>同意楼上的同学。我不知道楼主有没有真正试过用“数据采集 ==> DB ==> 数据分析 ==> DB ==> 数据展示”来做一个健壮的项目。
用内存以外的东西来当作两个进程之前通信的方式是挺危险,且不论性能的问题,也很难保证它的正确性的。
我设计的产品,有采用上述DB方式的例子。不敢说非常健壮,至少还过得去吧 :-)
Hush同学认为:“用内存以外的东西来当作两个进程之前通信的方式是挺危险”。个人感觉似乎过于武断。
这里的正确性是指共享数据的逻辑一致性,举例来讲,如果运行到一半的时候,进程被系统管理员误操作给kill了,你怎么保证在DB中的数据是处于一个一致的,可以继续供其它进程来使用的。当你重启进程的时候,怎么样区分可以重用的,或者需要丢弃的数据?
我如果使用DB作为进程间的数据耦合方式,一般通过事务来保证一致性。
如果有某同学有更好的方法,希望能分享给大伙儿。
2) 使用什么样的OS,往往是由客户,或者应用的类型决定的。包括使用什么语言之类的,我们能做的是在这样的限制条件下,选一个比较优的。
再一次申明,我并没有觉得多线程比多进程好,反之亦然,讨论这个,不如讨论分别适合在什么场景上比较有意义
On 3月8日, 下午9时34分, sjinny <sji...@163.com> wrote:
> 我觉得"进程被系统管理员误操作给kill了"跟管理员误操作把咖啡撒进了机柜是一样的概率......进程管理是不能随随便便地操作的,linux的root用户删文-件都要有额外确认的......
> 你所说的意外宕机导致数据的一致性被破坏的问题,对线程和进程是同样的问题。
> 进程内的线程同样会受os影响,我也想象不出有什么东西有本事脱离os的影响的......
> "由一个统一的模块来负责创建和启动线程,并在最外层加上error handling"。如果一个线程出现bug,比如内存访问越界,结果修改了另一个模块的数据,那么这种手段能解决或防止这个问题吗?只有带有内存保护的进程才-能解决这个问题。
> "至于对共享数据操作导致的互相干扰,用IPC也一样会有。"你可以具体说说是哪些干扰"用IPC也一样会有"。
> 多进程的方案当然是要在设计阶段就做考虑的,线程也一样:一个一开始就没有考虑多线程的设计,要在半路改成多线程还要确保正确性和健壮性,我觉得也是超高难度的-任务,除非原来的模块设计非常好,耦合非常低,不过这样改成多进程也不难。
> os也是要做选择的,到底是根据os选择并发模型,还是根据并发模型选择os就是鸡生蛋、蛋生鸡的问题了。
-