用R語言修改一個工具包,做並行計算上的優化應該怎麼入手?
主要先熟悉了下R語言和並行計算的概念,選了幾個模型。因為是一次project,並不太考慮性能優化。(目前本科寫出來感覺就很不錯了)
但是看了一坨源代碼,自己的打算是從一個個Function上進行考慮。有沒有相關資料或者學習經驗?
R在2.14版本之後,內置了parallel包,整合了之前已經比較成熟的snow包和multicore包,強化了並行計算能力,parallel包的思路是將輸入數據分割、計算、整合結果,只不過運算被分配到了不同的cpu來。
可以參考這個文檔: http://stat.ethz.ch/R-manual/R-devel/library/parallel/doc/parallel.pdf
R開源社區還有一個foreach包,也是並行計算相關的,看了看例子,貌似很方便,接收輸入參數和一個運算函數,combine,doParallel.
可以參考這個文檔: http://cran.r-project.org/web/packages/foreach/vignettes/foreach.pdf還有一些R並行計算方面的文檔和優化方案,你可以參考下:
http://cran.r-project.org/web/views/HighPerformanceComputing.html
http://cran.r-project.org/web/packages/doParallel/vignettes/gettingstartedParallel.pdf剛好前段時間用R完成了一個project 。涉及到的計算任務從原理上來看是可以並行的,也就是說每個任務之間沒有相互依賴和先後順序關係。其實在2.1.4之前R做並行計算和其他的語言一樣是比較麻煩的。後來將一些穩定高質量的並行包,例如parallel,snow,doMC的收錄,大大簡化了並行計算的難度。同時利用foreach包,可以像書寫普通的循環一樣,自動調用多線程。但是說到優化,從我自己的實踐經驗來看,可以從三方面入手。首先,合理的分割任務,任務的分割尺度不能太大,這樣如果中途需要結束並行計算,會很困難,而且如果中途結束任務,任務的完成度會不是很理想。但是也不能太細,這樣任務反覆的調用多線程,也會影響效率。其次,當任務分割到合理的尺度的時候,每個元任務效率的優化就和多線程並行無關了。這樣如果需要提高效率,並且在R語言邏輯上不能大幅提高效率的時候,Rcpp出馬的時候了。
最後,關於結果的輸出問題。在R語言的並行包中,需要考慮最終的輸出結果的合併與否,以及結果的合併形式。自己的經驗是,如果計算任務不是太大,可以使用合併計算結果的參數,一般在foreach函數中有.combine參數,可以選擇結果合併的形式。但是如果計算任務很重,建議在循環內部將每個線程的結果輸出到文本,這樣,當中途結束並行計算,已經算過的任務在下次就可以不用重複了。
至於從源代碼方面優化,估計免不了要和open mpi 和mpi打交道吧。R的task view 的high performance computing頁面有很多的內容。但是R打包這些包的目的就是為了將並行任務簡化,關注於計算內容本身。首先嘗試一下RRO revolution R Open, Revolution R 是一家高性能R的軟體廠商,最近被微軟收購了,準備把他們的產品用到Azure雲里。RRO是 Revolution R的開源版本,採用Intel的MKL包(Math Kernel Library)對R進行了加速,目前RRO的版本以3.2.2版R為基礎,代碼完全兼容。具體見How the MKL speeds up Revolution R Open
我也是最近才開始用RRO,個人感覺,在高維的代數運算上,在完全不修改代碼的情況下,RRO比普通R提速30-40%,如果自己做了分散式,比如我的一些模型用foreach+doparallel做了一下修改,RRO在此基礎上還能再提高30-40%的速度。
目前已經把默認的R path改成了RRO,就不做實際的測試了。有興趣的可以用這段代碼先在自己的R環境里跑一遍,然後下載安裝RRO後再跑一遍。
# Set MKL threads if Revolution R Open or Revolution R Enterprise is available
if(require("RevoUtilsMath")){
setMKLthreads(4)
}
# Initialization
set.seed (1)
m &<- 10000
n &<- 5000
A &<- matrix (runif (m*n),m,n)
# Matrix multiply
system.time (B &<- crossprod(A))
# Cholesky Factorization
system.time (C &<- chol(B))
# Singular Value Deomposition
m &<- 10000
n &<- 2000
A &<- matrix (runif (m*n),m,n)
system.time (S &<- svd (A,nu=0,nv=0))
# Principal Components Analysis
m &<- 10000
n &<- 2000
A &<- matrix (runif (m*n),m,n)
system.time (P &<- prcomp(A))
# Linear Discriminant Analysis
library("MASS")
g &<- 5
k &<- round (m/2)
A &<- data.frame (A, fac=sample (LETTERS[1:g],m,replace=TRUE))
train &<- sample(1:m, k)
system.time (L &<- lda(fac ~., data=A, prior=rep(1,g)/g, subset=train))
來源:https://gist.github.com/andrie/24c9672f1ea39af89c66
單純補充一下,首先要評估哪一部分需要並行,哪一部分不能,實際上不是所有計算並行的效率一定好,MATLAB 在這方面做得很好,可以參考。其次估算計算規模,對cpu 的要求,對內存的要求和對存儲的要求,然後再確定軟硬體架構。另外樓上兩位大牛沒有提到GPU計算,有一些人提供了R的GPU計算的包,也可以考慮。
推薦閱讀:
※普通用戶沒有root許可權,如何在自己的home目錄安裝Perl模塊?
※Ubuntu 系統下有哪些整理硬碟的工具?
※如何正確為 Noto Sans CJK 配置 fontconfig 使中文不會被顯示為日文字型?
※Mir 和 Wayland 等 X11 替代品,相比 X11 有哪些具體的優點?