《七週七併發模型》作者Paul Butcher:用併發計算實現最大效率(圖靈訪談)

盼盼姐發表於2015-05-28

Paul Butcher是一位資深程式設計師,涉獵廣泛,從微控制器編碼到高階宣告式程式設計無所不精,現在他開辦了獨立諮詢公司Ten Tenths。他曾任SwiftKey的首席軟體架構師,並先後擔任Texperts和Smartner的CTO。他從1989年開始攻讀博士學位,在平行計算和分散式計算的領域深造,當時他便深信併發程式設計將成為主流。二十年後,他的觀點終於得以驗證——整個世界都在討論多核以及如何發揮其優勢。Paul Butcher的著作《七週七併發模型》延續了《七週七語言》的寫作風格,通過七個精選的模型幫助讀者瞭解併發領域的輪廓。除《七週七併發模型》外,Paul還著有在亞馬遜獲得全五星好評的《軟體除錯修煉之道》

《七週七併發模型》作者Paul Butcher:用併發計算實現最大效率(圖靈訪談)

問:你在很久以前就成為了一位程式設計師,是什麼激發了你學習並行和分散式計算的興趣?

確實是很久以前了——我的第一個程式是在第一代可程式設計計算器上編寫的,那時我才10歲。

激發我興趣的是程式語言。當我在1989年攻讀博士的時候,我想找一個存在待解決難題的領域,所以我決定研究並行和分散式計算的語言。這是一個很有趣的領域,我的選擇沒有錯,但是我錯誤地估計了該領域成為主流所需要的時間。

在獲得博士學位之後,我很幸運有機會能在一個大型的共享記憶體多執行緒系統上工作(一個並行PostScript直譯器),這裡的工作為我解決執行緒和鎖這樣的困難問題提供了一個很好的基礎。

問:和傳統序列模型比較,併發模型有哪些優勢?應用併發模型的最佳場景是什麼?

我們必須要接受非序列(並行或併發)程式設計,這樣才能有效地使用當今的多核處理器。但是併發不僅在利用多核上有用武之地(當然,必須要使用正確),併發還會讓軟體變得更具響應性,它比序列軟體更易寫,也更好理解。

或許併發最有魅力的地方在於它的容錯性。序列軟體永遠不可能像併發軟體那樣具有彈性(比如,當你執行序列程式碼的硬體裝置失效了會怎樣?)

問:是否有可能對比不同併發模型的效能?

評量兩種程式語言的基準是很困難的,所以評量兩種併發模型的基準也是很困難的。效能所依賴的因素很多(硬體架構,所執行的演算法的本質,通訊在網路上進行還是在本地執行的程式間進行,等等)所以要想得到概括的結論幾乎是不可能的。

不同的方法肯定有不同的“有效點”。比如,如果你在搞數值計算,在GPGPU上執行資料平行程式碼就會得到奇佳的效能。如果你的資料是太位元組級別的,那麼Lambda架構就是最棒的。

如果要說多用途程式設計的話,在我心中關於方式的選擇其實無關於效能,我更看重的是這種方式是否契合我的思維模型,是否能提供我所需要的裝置。再比如說,如果你需要對於分佈和容錯的支援,角色(Actors)差不多就是這種情況下唯一的選擇了。

問:多個邏輯上的併發程式執行時,哪種方式能實現最大的效率,獨立執行還是序列執行?

就像上一個問題中所說的那樣,這個答案取決於你所處的具體環境。如果你所說的“最大效率”意味著利用多核,那麼從定義上說序列執行的效率是比較低的,因為它只能利用一個核。

所以我猜你想問的是在單核上的效率。總體來說,併發確實會帶來一些開銷,但是今天我們已經有了優化充分的執行時間,所以開銷其實是很小的。Erlang的程式,Go的goroutines,Clojure的core.async,以及其他語言中相似的機制可以讓多個邏輯上的併發程式的執行效率相當高。

除了非常少的幾個特殊領域之外,我們已經過了因為效率而放棄併發的階段了。

問:Erlang和Go受到了CSP模型的影響,但是Process Algebra領域有三個分支:CSP,ACP和CCS。為什麼還沒有受ACP和CCS影響的新語言出現?

Go肯定是受CSP影響的語言。相比於CSP,Erlang和角色模型(Actor模型)之間的共同點更多(雖然角色模型和程式演算肯定是相互影響的)。

有趣的是,Erlang的設計者們在設計這個語言的時候從沒聽說過角色模型,我認為這一點就是這個問題的答案——在軟體領域,學界和業界之間的紐帶並不強,語言設計通常都由實用主義驅動,而非理論。

問:不同的語言有著不同的併發模型,而且交集比較少。如果不同的子系統要使用不同的併發模型,那麼這個系統很有可能要使用兩種以上的語言,那麼如何才能解決多語言除錯問題?比如有基於ErlangVM和JVM的子系統,兩個子系統之間的連線方式就是程式間通訊。在外部高併發的情況下,負載就匯聚到了兩個子系統的邊界上,這時有什麼好的解決方法?

這兩個問題都很難,沒有簡單的答案。哪怕在最好的情況下,多語言程式都是很具有挑戰性的,引入不同的併發模型只會讓情況更加複雜。

唯一的解決方案就是合理的高層設計。你需要用清晰的原則架構你的系統,比如用最大化內聚和最小化耦合的方式來減少子系統間的通訊,所以相比於子系統內部通訊,系統間通訊更少。

問:Erlang和Go都沒有完整的型別系統,所以資料的有效性處理比較麻煩,比如傳遞結構化的json資料時。關於如何在Channel傳遞結構化的資料,你是否有一些建議?

關於靜態型別和動態型別的爭論幾乎和程式設計一樣古老,而且這不僅僅是併發領域獨有的問題。

當我在使用動態型別的系統時(比如Erlang),我會用同一種方式來告訴自己,當我在做序列程式碼的時候併發程式碼是正確的,這個方法就是做很多測試。

問:Erlang比Scala古老,但最近Scala相關的技術很流行,效率也很高。Scala的Actor併發模型有可能取代Erlang嗎?

現在下結論還為時尚早。Scala的Akka確實讓人印象深刻,無論什麼時候我都會毫不猶豫地推薦它。但是Elixir(以Erlang VM為目標的新語言)很大程度上重新點燃了我對Erlang生態系統的興趣。我們非常幸運,可以從兩個很好的選擇中挑選。在可以預見的未來,相信兩種技術都會保持流行的態勢。

問:編寫併發/並行程式要比一般的序列程式困難得多,有沒有什麼方法可以降低這種難度? 有沒有哪些適合併發程式設計的思考模型可以推薦給讀者們?

可以肯定的是帶有執行緒和鎖的併發程式設計確實很難。比難更糟的是,你幾乎無法確定一個基於執行緒和鎖的程式是否正確。

但是如果你選擇了正確的工具,就會避免很多問題。在很多情況下,併發解決方案可以比相對應的序列解決方案更加簡單、更加容易。

或許我能給你的最好建議,就是儘量多地瞭解併發的不同方式,這樣你才能知道什麼是可用的。你的工具箱越大,就越有可能為你手頭的問題找到合適的工具。


更多精彩,加入圖靈訪談微信!

相關文章