标签 Gopher 下的文章

也谈并发与并行

在一般人的眼中,“并行”就是并行,即你干你的,我干我的,两个“并行”的执行过程可能是两条毫无瓜葛的平行线,也可能是有交叉,但瞬即分开的两条线。不 过在程序员的世界里,有关“并行”的概念却有两个单词:Concurrency和Parallelism,对应的比较主流的中文翻译为并发 (Concurrency)和并行(Parallelism)。

之前一直使用C、Python进行Coding,对Concrrency和Parallelism的异同并不十分关心,也未求甚解。但switch to golang后,尤其是学习2012年Rob Pike的一个talk slide:“Concurrency is not Parallelism(译作:并发不是并行)"后,感觉之前对于“并行”的理解还未到火候。

golang的Author们对文档还是非常看重的。按照目前golang的age来说,其文档的充分性相对于其他语言已经是相对较好的了。golang 的 author们还时不时放出一些blog、talk和slide,以帮助大家编写出more idiomatic的golang程序。Rob Pike的“并发不是并行”就是golang官方站点上的一个talk slide(中文版在这里 )。

Rob Pike是Golang大神,这里先列出他在talk中对于并发与并行的学术阐释和理解:

【Concurrency并发】
Programming as the composition of independently executing processes. (Processes in the general sense, not Linux processes. Famously hard to define.)
将相互独立的执行过程综合到一起的编程技术。(这里是指通常意义上的执行过程,而不是Linux进程。很难定义。)

Concurrency is about dealing with lots of things at once.
并发是指同时处理很多事情。

Concurrency is about structure.
并发关乎结构。

Concurrency provides a way to structure a solution to solve a problem that may (but not necessarily) be parallelizable.
并发提供了一种方式让我们能够设计一种方案将问题(非必须的)并行的解决。

Concurrency is a way to structure a program by breaking it into pieces that can be executed independently.
并发是一种将一个程序分解成小片段独立执行的程序设计方法。

【Parallelism并行】
Programming as the simultaneous execution of (possibly related) computations.
同时执行(通常是相关的)计算任务的编程技术。

Parallelism is about doing lots of things at once.
并行是指同时能完成很多事情。

Parallelism is about execution.
并行关乎执行。

【小结】
They are Not the same, but related.
它们不相同,但相关。

怎么样?看上上面的论述是不是一头雾水啊。Rob Pike也觉得这些概念以及描述过于抽象,于是给了一个具体的“地鼠推车运书”的例子,不过当你看完这个例子后,可能会变得更加糊涂,至少我有这种感觉-地鼠凌乱综合症^_^。这是因为这个例子隐含的结合了Go语言goroutine调度的三个概念:P(虚拟processor上下文)、M(内核线程)和G(Goroutine对象)。如果仅仅从理解并行和并发的差异来说,我们可以抛开go语言,用生活中的例子感觉更适合些。

下面我们就来一个例子来说说明一下并发与并行,从一个程序的设计演进角度来阐述。

问题:说的是一个Gopher早起后的生活,Gopher早起后,有三个任务(或者称为三件事情)要完成:洗漱、早餐、着装。我们来设计一个程序,帮助Gopher高效正确的完成这三件事。

如果你是程序员,要完成这个场景,你可能会这么设计你的程序:

program1:

最简单的思路:这个gopher一件一件事情去完成:

main:
    call 洗漱
    call 早餐
    call 着装

这里我们把Gopher看做是一颗cpu,它按程序逻辑,顺序执行洗漱、早餐和着装三件事。即如下图那样:

现在我们玩个克隆游戏,我们clone出一个与这个Gopher一模一样的Gopher,且两个gopher之间存在着某种超宇宙联系,一个Gopher行为的结果都能反应到另外一个gopher上。我们让这两个Gopher一起来做这三件事情,看看是否能够提速。

遗憾的是,两个Gopher都要从洗漱做起。一个Gopher占用了卫生间开始洗漱,另外一个Gopher只能等着,而没法去做早餐或是着装。当那个 Gopher完成洗漱,后面的这个Gopher由于超联系也同步完成了洗漱,进入下一个环节:早餐。过程还是一样的,只能一个Gopher在餐厅准备早 餐。也就是说这两个Gopher没有一起做事,而是一个做,一个赋闲。因此我们看到两个Gopher并没有加快事情完成的步伐,从过程上来看,即便有更多 的Gopher,也依旧无法提速。我们需要对程序做些改造。

注:首尾相连的红线的总长度 = 完成时间。

program2:

main:
    pthread_create(洗漱)
    pthread_create(早餐)
    pthread_create(着装)

    waitAll

Gopher来执行一遍新程序。由于建立了三个逻辑执行体,因此Gopher在三个执行体间切换,从Gopher的角度去看,Gopher的执行路径如下图:


Program2-1

Gopher不再像上面Program1那样顺序执行了,而是在三个活动间切换,但总时长依旧没有下降。

为了验证该程序在多Gopher下是否有效率提升,我们再玩一次克隆游戏,这次clone出另外两个Gopher,三个Gopher一起来执行该程序,一个可能的执行路径见下图:


Program2-2

每个Gopher绑定一个逻辑执行体,整体完成的总时长下降为原来的三分之一。这次三个Gopher都没有赋闲,真正做到你干你的,我干我的,一起做。

program3:

虽然在program2中,多个Gopher一起工作提升了效率,但那是极限么,还能提高么?我们试想一下三个活动:洗漱、早餐和着装的难易不同,耗时不 同。一个可能的结果是Gopher1完成了洗漱,但Gopher2才准备了一半早餐,Gopher3刚选完上衣。这时Gopher1便开始空闲,无法帮助 Gopher2和Gopher3继续提高效率。我们再试试重新组合一下要完成的任务,让每个Gopher都能执行不同的活动环节。

main:
        c chan job
        for i = 0; i < 3; i++  {
            go gopherworker(c)
        }

        for j := range jobs {
            c <- j
        }
        … …

gopherworker(c chan job):
      for {
         select {
         case <-c:
         … …
      }

以下是一个可能的执行路径图:

到了这里,不知道你是否通过上面程序演进的过程悟道些什么,例子里我通篇没有提到并发或并行。

但从例子可以看出,并发和并行是两个阶段的事情。并发在程序的设计和实现阶段,并行在程序的执行阶段。

在Program1之前,我们只有问题,并无方案。

Program1方案让我们可以解决问题,但从Program1的执行结果来看,Program1并不能并行执行。原因是在设计和实现阶段程序就是按照顺序思路进行的,这就好比底子没打好,在平房的地基上永远不能盖50层的大楼。

Program2-1方案的执行结果与Program1相同,但Program2在设计和实现阶段采用的理念却与Program1完全不同,如果说 Program1打的是平房的地基,那么Program2打的就是大厦的地基,虽然Program2-1上依旧盖的是平房(单Gopher执行)。但 Program2-2显然就是在这样的地基上盖的摩天大楼了(多Gopher执行)。Program2的结构使得Program2在多Gopher下提升 了效率,实现了运行时并行。

Program3更进一步,在设计和实现阶段就本着充分高效的利用多个Gopher的理念,并最终实现了执行阶段的并行。

因此我们在编程语言层面更多谈并发,Golang对外宣传时永远用的是支持并发,而不是支持并行。设计实现阶段好比打地基,不同水准的地基决定了你在这个地基上面是只能盖平房,还是盖高层,还是能盖摩天大楼。

我们再回过头来重温Rob Pike大神关于两者的阐述:“并发关乎结构,并行关乎执行”,是不是感觉意味深长啊,大神就是大神,一句话就能抓住本质。

go 1.5之前默认情况下,Go程序都是不能并行的,因为Go将GOMAXPROCS默认设置为1,这样你仅仅能利用一个内核线程。Go 1.5及以后GOMAXPROCS被默认设置为所运行机器的CPU核数,如果你的机器是多核的,你的Go程序就有可能在运行期是并行的,前提是你在设计程 序时就充分运用了并发的设计理念,否则就会像Program1那样,即便有1w颗CPU,你也只能利用上一颗。

Go,5周年

2014年11月10日(美国当地时间),Golang官方博客 放出了Andrew Gerrand的一篇博文《Half a decade with Go》来纪念Go语言发布五周年。文章按时间顺序简要描述了Golang这五年来发展的 点点滴滴,并让全世界Gopher看到了Go可期的光明未来。考虑到这篇文章在墙外,不便于国内Gopher阅读,这里给出中文翻译版,希望能给中国大陆 的Gophers带来些帮助!

五年前,我们启动了Go语言项目。我们准备发布第一版时的一幕仿佛就发生在昨天似的:我们的官方站点用的是一种可爱的黄色色调,我们将Go语言称为一门 “系统编程语言”,你需要使用分号作为语句结束标志,使用Makefile来构建你的代码。我们不知道Go语言是否能被大家接受。人们会分享我们的目标和 愿景吗?人们会发现Go语言有用吗?

起初,我们的发布引起了一阵关注。Google发布了一门新的编程语言,每个人都渴望探究它一番。一些程序员因为Go相对保守的功能特性集合而选择了放 弃,Go给他们的第一印象就是:没有什么新鲜玩意儿!但另外一小群程序员则看到了这个为软件工程师量身定做的生态系统的开端。这少数人将组成Go语言社区 的核心。

第一版发布后,我们花了些时间向社区传达Go语言背后的目标和设计理念。Rob Pike在官方的《Go at Google: Language Design in the Service of Software Engineering》一文中对此进行了生动地表达,并 在其个人博客文章《Less is exponentially more》中做了进一步的阐述。Andrew Gerrand的《Code that grows with grace》(Slides在这里)和《Go for Gophers》(Slides在这里)对Go的设计哲学又给出了更有深度和技术性的说明。

随着时间的推移,积少成多。这个项目的转折点出现在2012年3月Go 1发布时。Go 1为程序员们提供了可以信赖的稳定的语言和标准库。到2014年,Go项目拥有了上百的核心贡献者,其生态圈中拥有了数不尽的第三方库和工具 ,并由成千上万的开发者维护着。正在发展壮大的社区拥有许多极具热情的成员(或者就如我们所称呼 的:Gophers)。今天,就我们目前的统计分析,Go社区的成长速度远远超出了我们的预期。

Gophers们在哪里可以得到这些呢?全世界目前有很多有关Go语言的“大事”发生。今年我们看到了几个专门的Go技术大会:在丹佛和巴黎举行的首次 GopherCondotGo大 会。FOSDEM的Go DevRoom以及在东京举行的一年两次的GoCon。每次会上来自全球各地的Gophers们都踊跃地展示他们开发的Go项目。对于Go语言开发组来 说,我们很高兴能满足这些分享我们愿景和兴奋的程序员的需求。

在世界各地,还有数十个社区驱动运行的“Go用户组”。如果你还没有造访过你当地的用户组,可以考虑去尝试一下。如果你当地尚没有这类用户组,也许你可以考虑发起一个

今天,Go在云端找到了用武之地。Go出现在了工业向云计算转型的时刻。并且我们兴奋地看到Go正在快速成为这个运动的一个重要组成部分。简单、高效、内 置并发原语和现代的标准库让Go语言尤其适合云端软件开发(毕竟它就是为此而设计的)。一些重量级的开源云项目,诸如Docker和Kubernetes 都是用Go语言实现的,一些运作基础设置的公司,诸如Google、CloudFlare、Canonical、Digital Ocean、Github、Heroku以及微软也都在使用Go语言开发一些重量级的项目。

那么将来会怎样呢?我们认为2015年将是Go语言大爆发的一年。

Go 1.4,除了其新增的特性和bug修正外,它为实现一个新的低延迟垃圾收集器以及支 持在移动终端上运行Go奠定了基础。 预计Go1.4将在2014年12月1日正式发布。我们期望在Go 1.5中能出现新GC的身影,Go 1.5预计在2015年6月1日发布,它将使Go适合更加广泛的应用开发。我们迫不及待的想看到哪些领域的开发者会接受它。

接下来会有更多的Go大事发生。11月15日,GothamGo将在纽约如期举行。2014年1月31日到 2月1日,布鲁塞尔将举行另一次Go DevRoot at FOSDEM。2015年2月19日到21日,在印度班加罗尔将举行GopherCon India大会。最初的GopherCon将在2015年7月份回到丹佛。2015年11月 dotGo大会将再次来到巴黎。

Go团队将向届时到场的所有gophers表示衷心的感谢。为Go语言的下一个五年!

为了庆祝Go诞生5周年,在未来的一个月里,Gopher Academy将会发布一系列由知名Go users撰写的文章,务必要去看看哦。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



Statcounter View My Stats