哪種函數式語言更適合多核的並行和並發編程?


當然是Haskell了。簡要地列舉一下:

======基礎篇======

1. GHC的threaded runtime原生支持多個OS線程運行Haskell程序。沒有GIL(Global Interpreter Lock),保證了並行Haskell程序能真正利用多核。

2. GHC runtime提供輕量級線程的支持,通過OS線程池運行Haskell線程。另外,Haskell線程中調用的所有同步I/O操作都通過runtime的I/O manager透明地轉成非同步I/O操作,底層使用epoll/kqueue實現。因此並發Haskell程序可以開發效率/運行效率兼得(隨意開多線程、隨意使用偽同步I/O,避免callback hell等非同步程序的陷阱)

3. GHC runtime內建STM機制,通過stm: Software Transactional Memory提供STM介面。寫需要維護共享狀態的多線程Haskell程序時,使用STM可以顯著簡化實現,同時避免deadlock等lock-based多線程程序的常見困擾。

4. GHC runtime提供了sparks機制,sparks可以理解為比Haskell線程更加輕量級的微線程,不涉及I/O,只處理純運算。sparks機制下,通過Control.Parallel提供par組合子,適合實現細粒度的並行計算。

======應用篇======

1. 輕量級線程

Control.Concurrent - 創建輕量級線程的介面。

Control.Concurrent.MVar - MVar,線程間共享變數。MVar a相當於裝有a類型元素的箱子,可以put和get,其中對空箱子get和滿箱子put都會阻塞。MVar是最基礎的並發數據結構,基於MVar,很容易開發出Mutex、Semaphore、Channel等常見的並發設施。從介面不難看出,MVar也有deadlock的風險。

stm: Software Transactional Memory - STM介面。這裡提供TVar a,作為使用STM的線程之間的共享變數,但是Haskell通過類型系統提供了安全保證,一次STM事務允許的操作只有讀寫TVar,禁止執行任意IO操作。一般而言,提倡使用STM實現並發程序,以簡化實現、避免死鎖。

Control.Concurrent.Async - 封裝了線程的Future庫,將任意IO action轉成非同步操作。另外還有Concurrently這個簡化版的「There is no fork」並發模型,官網的常式如下:

(page1, page2, page3)
&<- runConcurrently $ (,,) &<$&> Concurrently (getURL "url1")
&<*&> Concurrently (getURL "url2")
&<*&> Concurrently (getURL "url3")

這裡的getURL類型是String -&> IO Page,是一個同步的IO介面,通過Concurrently的Applicative instance,無需手動創建Thread/Async或者管理callback,即可完成同步轉非同步和收集多個非同步操作結果。

2. 數據流並行

parallel: Parallel programming library - par組合子,以及基於其提供的Eval monad。這裡的Eval monad通過rpar和rseq來啟動並行計算和收集結果,但是暴露給程序員的,只不過是一個strict identity monad,看不見創建線程的過程。而傳遞需要並行求值的表達式,也無需手動包裝成一個thunk,直接利用Haskell的lazy-by-default屬性,把計算耗時的表達式傳給rpar和rseq就可以了。

monad-par: A library for parallel programming based on a monad - 另一個用於純的並行計算的Par monad。Par monad類似於前面的輕量級線程,提供了IVar這種一次性變數傳遞計算結果;可以spawn出計算,通過IVar傳回結果,最後通過runPar啟動整個並行計算pipeline,獲得最終結果。一個很贊的地方在於,寫Par monad程序,可以寫成「先從IVar拿結果,再把需要的值放進IVar」這種因果顛倒的模式,調度器可以從IVar的依賴關係按照正確的拓撲序進行計算。

3. 數組並行

repa :: Stackage Server - 支持並行計算的數組庫,底層通過線程池進行計算,支持調用任意Haskell函數。

accelerate :: Stackage Server - 支持異構計算的DSL,需要按照一套受限的語言定義計算,然後可以在多個後端上執行計算,包括CUDA等。

======缺點======

GHC runtime與語言特性的配合,使得Haskell在單機共享內存這一情形下開發和運行效率均令人滿意。然而構建分散式系統時,仍然缺乏跨機器的、透明的actor實現,需要手動管理不同runtime間的消息傳遞;另外,Haskell與現有的big data生態圈互動較少。(有個叫Frege的JVM上的Haskell方言,可以沾沾JVM的光,沒用過不評價)另外,即使在單機這一前提下,Haskell的科學計算輪子太少。用函數式語言構建並行/並發系統,建議重應用、輕語言,優先利用已有輪子。

======後記======

首推Simon Marlow的Parallel and Concurrent Programming in Haskell一書,深入淺出,不容錯過。

文獻方面,近的有Facebook在ICFP14上發的There is no fork,裡面的Haxl庫除了用Applicative functor抽象非同步計算以外,還有自動緩存等機制,限於篇幅不展開了。遠的可以翻翻ReadingList,看其中講concurrent runtime和stm的幾篇文章。不過,Data Parallel Haskell現在完全處於棄坑狀態,實在是可惜,畢竟nested data parallelism是比repa這種flat data parallelism更強、更好用的並行模型。


超算都是使用 F90/C++ 配合 MPI 和/或 OpenMP。

你的問題涉及到異構計算,呃,還是 intel 那個(你買了天河 2 的配額么),haskell 之類對異構計算支持很差,能用的也就 C++ 了吧……


如果你只是需要並發計算的話可以嘗試Haskell,僅需一個par函數。或者F#,僅需在普通語句外面加一個async{}。


高性能計算中,多核並行編程正統選擇:

C++/Fortran + OpenMP

C++/Fortran + MPI

C++/Fortran + MPI + OpenMP

其次:

Matlab的Parallel Computing Toolbox

Matlab Parallel Computing Toolbox配合C++(Matlab主要負責調度)

普通的科學計算(對性能沒「極致」要求),Python(用Multiprocessing)、Julia、Haskell等等隨便玩玩。

非要用函數式語言的話,Mathematics、Haskell可以試試。

而並發編程的概念更廣,可選的語言、模型、框架很多,除了上面的,Erlang、Scala Akka、Ocaml Async,Clojure atom/ref/agent。。


同意 @姚培森 如果你是專業搞並行,不是學著玩玩的話,Fortran/C/C++加上MPI/openmp,才是正統的選擇。cuda/opencl也可以加進去。至於專門的函數式語言,只能說目前市場有限。我認識的人裡面,我不知道他們中任何一個人在用這類東西。

為什麼要選一個「正統」的選擇呢?現成的庫多,優化方案成熟,文檔充足。這些也是fortran從f77,f90一直到現在,甚至在f90之前連動態內存分配都不支持的情況下,一直統治高性能計算的原因。


只聽過Erlang擅長這個,但沒學過


函數式語言裡面最適合併發和並行的是erlang和haskell

haskell在並行和並發上都非常優秀。在並行上至少有3種模式(ghc官方支持,非ghc團隊的就更多了),還能使用gpu;在並發上有輕量級actor,軟體事務內存,分散式編程庫(山寨erlang的otp)

erlang非常適合併發,但它的核心目標並不是並發,而是高可用性和軟實時,其actor模型是為高可用性服務的。erlang沒有專門的並行計算模型,是用並發來實現並行

其他函數式語言比如racket也有並發和並行功能,但是功能性上遠遠不如haskell和erlang


真正的高性能計算目前只能說是一個歷史遺留情況下的妥協的情況。你要知道花在各個演算法上的人力物力都是要錢的,這些東西明明跑得好好的,突然說要換一個語言,換一個並行模型來弄,那之前花的錢怎麼辦,之前那些人怎麼繼續吃飯啊。這些都是現實問題,其他什麼牛,什麼優雅,都推到後面去……真心這樣。

至於建議嘛,我推薦 @姚培森 的答案~


http://www.erlang.org


不考慮GPU嗎?


單台電腦屬於共享內存模式,不知道你的業務需求如何,試試openmp和c++配合使用吧


fortran coarray 可以參考


Julia 大法好好好!

速度快,解釋性,原生搞並行。MIT計算化學組位科學計算量身打造


推薦閱讀:

coursera上有沒有關於分散式系統,並行計算,linux內核,多線程編程的課程?
人腦的並行計算能力有多強?
並行計算在 Quant 中是如何應用的?

TAG:編程語言 | 並行計算 | 多核編程 |