R與平行計算

2021-10-04 14:07:33 字數 4235 閱讀 4657

本文在creative commons許可證下發布

什麼是平行計算?

平行計算,準確地說應該包括高效能計算機和並行軟體兩個方面。不過,近年來隨著個人pc機,廉價機群,以及各種加速卡(nvidia gpu, intel xeon phi, fpga)的快速發展,現在個人電腦已經完全可以和過去的高效能計算機相媲美了。 相比於計算機硬體的迅速發展,並行軟體的發展多少有些滯後,試想你現在使用的哪些軟體是支援並行化? 軟體的並行化需要更多的研發支援,以及對大量序列演算法和現有軟體的並行化,這部分工作被稱之為**現代化(code modernization)。聽起來相當高大上的工作,然而在實際中大量的錯誤修正(bugfix),底層資料結構重寫,軟體框架的更改,以及**並行化之後帶來的執行不確定性和跨平台等問題極大地增加了軟體的開發維護成本和執行風險,這也使得這項工作在實際中並沒有想象中的那麼吸引人。

r為什麼需要平行計算?

那麼言歸正傳,讓我們回到r本身。r作為當前最流行的統計軟體之一,具有非常多的優點,比如豐富的統計模型與資料處理工具,以及強大的視覺化能力。但隨著資料量的日漸增大,r的記憶體使用方式和計算模式限制了r處理大規模資料的能力。從記憶體角度來看,r採用的是記憶體計算模式(in-memory),被處理的資料需要預取到主存(ram)中。其優點是計算效率高、速度快,但缺點是這樣一來能處理的問題規模就非常有限(小於ram的大小)。另一方面,r的核心(r core)是乙個單執行緒的程式。因此,在現代的多核處理器上,r無法有效地利用所有的計算核心。

怎麼破?平行計算!

平行計算技術正是為了在實際應用中解決單機記憶體容量和單核計算能力無法滿足計算需求的問題而提出的。因此,平行計算技術將非常有力地擴充r的使用範圍和場景。最新版本的r已經將parallel包設為了預設安裝包。可見r核心開發組也對平行計算非常重視了。

r使用者:如何使用平行計算?

從使用者的使用方式來劃分,r中的平行計算模式大致可以分為隱式和顯示兩種。下面我將用具體例項給大家做乙個簡單介紹。

隱式平行計算

隱式計算對使用者隱藏了大部分細節,使用者不需要知道具體資料分配方式 ,演算法的實現或者底層的硬體資源分配。系統會根據當前的硬體資源來自動啟動計算核心。顯然,這種模式對於大多數使用者來說是最喜聞樂見的。我們可以在完全不改變原有計算模式以及**的情況下獲得更高的效能。常見的隱式並行方式包括:

1、 使用平行計算庫,如openblas,intel mkl,nvidia cublas

這類並行庫通常是由硬體製造商提供並基於對應的硬體進行了深度優化,其效能遠超r自帶的blas庫,所以建議在編譯r的時候選擇乙個高效能庫或者在執行時通過ld_preload來指定載入庫。

2、使用r中的多執行緒函式

openmp是一種基於共享記憶體的多執行緒庫,主要用於單節點上應用程式加速。最新的r在編譯時就已經開啟了openmp選項,這意味著一些計算可以在多執行緒的模式下執行。比如r中的dist函式就 是乙個多執行緒實現的函式,通過設定執行緒數目來使用當前機器上的多個計算核心,下面我們用乙個簡單的例子來感受下平行計算的效率,此**需在linux系統下執行。

#comparison of single thread and multiple threads run

for(i in 6:11)

顯示平行計算

# not vectorized function

solve.quad.eq <- function(a, b, c)

# generate data 

len <- 1e6

a <- runif(len, -10, 10)

a[sample(len, 100,replace=true)] <- 0

b <- runif(len, -10, 10)

c <- runif(len, -10, 10)

# serial code

system.time(

)# parallel

library(parallel)

# multicores on linux

system.time(

)#cluster on windows

cores <- detectcores(logical = false)

cl <- makecluster(cores)

clusterexport(cl, c('solve.quad.eq', 'a', 'b', 'c'))

system.time(

)stopcluster(cl)

for# serial code

res2.s <- matrix(0, nrow=len, ncol = 2)

system.time(

for(i in 1:len)

)對於for迴圈的並行化,我們可以使用foreach包裡的%dopar% 操作將計算分配到多個計算核心。foreach包提供了乙個軟體層的資料對映方法,但不包括計算組的建立。因此,我們需要doparallel或者domc包來建立計算組。計算組的建立和之前基本一樣,當計算組建立之後,我們需要使用registerdoparallel來設定foreach後端的計算方式。 這裡我們從資料分配方式入手,我們希望給每個r工作程序分配一段連續的計算任務,即將1:len的資料均勻分配給每個r工作程序。假設我們有兩個工作程序,那麼程序1處理1到len/2的資料,程序2處理len/2+1到len的資料。所以在下面的程式中,我們將向量均勻分配到了計算組,每個程序計算chunk.size大小的聯絡任務。並且在程序內建立了矩陣來儲存結果,最終foreach函式根據.combine指的的rbind函式將結果合併。

# foreach

library(foreach)

library(doparallel)

# real physical cores in the computer

cores <- detectcores(logical=f)

cl <- makecluster(cores)

registerdoparallel(cl, cores=cores)

# split data by ourselves

chunk.size <- len/cores

system.time(

res2.p <- foreach(i=1:cores, .combine='rbind') %dopar%

# return local results

res}

)stopimplicitcluster()

stopcluster(cl)

最後,我們在linux平台下使用4個執行緒進行測試,以上幾個版本的並行實現均可達到3倍以上的加速比。

r並行化的挑戰與展望

挑戰:

在實際中,平行計算的問題並沒有這麼簡單。要並行化r以及整個生態環境的挑戰仍然巨大。

1、r是乙個分散的,非商業化的軟體

r並不是由乙個緊湊的組織或者公司開發的,其大部分包是由使用者自己開發的。這就意味著很難在軟體架構和設計上來統一調整和部署。

2、r的底層設計仍是單執行緒,上層應用包依賴性很強

r最初是以單執行緒模式來設計的,意味著許多基礎資料結構並不是執行緒安全的。所以,在上層並行演算法實現時,很多資料結構需要重寫或者調整,這也將破壞r本來的一些設計模式。另一方面,在r中,包的依賴性很強,我們假設使用b包,b包呼叫了a包。如果b包首先實現了多執行緒,但是在一段時間之後a包也做了並行化。那麼這時候就很有可能出現混合並行的情況,程式就非常有可能出現各種奇怪的錯誤(bug),效能也會大幅度降低。

展望:

個人比較看好雲計算平台

隨著雲計算的興起,猜想會興起資料分析即服務(daas:data analyst as a services)的浪潮。 各大服務商會從底層的硬體部署,資料庫優化到上層的演算法優化都提供了相應的並行化措施,比如微軟近期推出了一系列r在雲上的產品,比如微軟新推出的sql server與它整合的r server。因此,未來更多的並行化工作將會對使用者透明,r使用者看到的還是原來的r,然而真正的計算已經部署到雲端了。

R語言平行計算程式設計

r語言並行程式設計例項,將資料集rcuters 21578的50個文件賦值100,000次,得到包含500萬個文件的資料庫,查詢正規表示式。tm軟體包是r語言中為文字挖掘提供處理的package,提供資料匯入 語料庫處理 預處理 元資料管理 建立term document矩陣等功能。平行計算 lib...

python平行計算 python平行計算

0.基礎並行 發 multiprocessing threading 1.concurrent 2.併發 asynico 3.ipython下的平行計算 使用ipyparallel庫的ipython提供了前所未有的能力,將科學python的探索能力與幾乎即時訪問多個計算核心相結合。系統可以直觀地與本...

R語言snow包平行計算

this post was kindly contributed by 資料科學與r語言 go there to comment and to read the full post.在資料探勘和機器學習領域有許多的演算法需要強大的計算能力,如果對大資料進行運算操作,那麼其工作量之大使單個cpu核心難...