如何編寫高效的 R 語言程序?

在計算機條件限制的條件下,用什麼方法可使R程序跑的更快


第一步:很明顯的可以向量化和矩陣化的loop,改變矩陣或者向量的大小,都是比較耗時的,這些可以在R內部通過矩陣化,正確估計矩陣的dim來解決。

比較簡單的函數:基本程序本身寫好之後,用Rprof做profiling,找到最耗時間的環節,用inline和Rcpp包把最耗時間的部分重新寫一次(有一天我用一個二十行的C++函數換掉了一個which,程序的運行速度快了十倍這種事我會亂說嗎)。

可以並行的計算做並行處理。

使用ff包處理大的數據表格。

用sparse matrix處理大矩陣。

當然,使用正確的演算法也很重要。

啊,對了,有一本叫做the R inferno的書,作者是Patrick Burns,列舉了R語言編程中容易出現的各種小麻煩和解決方法,向大家推薦一下。


我很久以前寫的兩篇blog:

1. 給R代碼加速 | f(Program,Poet)=Programet

裡面介紹了幾個具體的例子,希望能從例子中介紹幾個讓R程序比較快的思考方法。例如盡量使用向量化運算,預先分配內存等。比較零散,

2. 同時通過OpenBLAS和mclapply加速R運算

這是關於怎麼單機並行R代碼的嘗試。如果設計很多的向量運算,簡單地配置好OpenBLAS能事半功倍。

另外附送一個大牛阿穩在2013年R會上的演講幻燈片:http://cos.name/wp-content/uploads/2013/05/%E7%AC%AC%E5%85%AD%E5%B1%8AR%E4%BC%9A%E8%AE%AE-%E9%98%BF%E7%A8%B3.pdf

前半部分的討論非常切題。


謝邀。

  1. 多用apply functions,少用loop
  2. 多用已建的東西,少寫自己的碼
  3. 如project大型,可考慮建包,用object-oriented programming


R語言編程藝術.pdf_免費高速下載

看14-16章


1. 熟悉 R 編程的特性,向量化,多用自帶的函數

2. 拿Fortran或C++寫再用R調用

3. 用 compiler 包編譯函數再調用

4. parallel 和其他的並行計算包

5. Revolution R Open, 編譯 R 時鏈接了一些計算庫

3、5 沒試過,我一般的順序是1,4,2,大部分別人的問題1就能解決,自己的問題經常用2。


程序員出身的人,一般第一次用R時都會感慨,怎麼這麼碎啊,一個功能有十八種函數,一個函數有十八種用法,這哪是門語言啊,這根本就是坨零碎嘛。

如果你也有這種感慨,那你需要思考一個問題,R的靈魂是什麼?

是程序嗎?是邏輯嗎?是演算法嗎?

都不是,R的靈魂是數據!

你可以這樣來理解,用R得到結果的過程,就是雕琢數據的過程,一切都圍繞數據。這兒用斧子砍幾下,那兒用刀子劃幾道,直到成型了,再琢磨怎麼上色怎麼添彩,或者就這麼粗曠著。

那些精彩的包,無一不是如此思想,當正確的包作用到正確的數據時,那種郎情妾意,真真的是共舞到醉。

好了,現在給你一坨數據,你打算把它塑造成啥?塑造時,你還缺什麼工具?


lapply 效率很低,詳情看這篇:Parallel computing in R

我最深有體會的一點是這是一個不停嘗試的過程。

每次涉及到必須寫loop的情況,就加個proc.time(),然後調試代碼,比較iteration 的時間。

我支持針對情況寫自己的碼,有些時候會比內置的好很多,一些矩陣運算有它自己的特性(比如對稱矩陣),這種最好自己寫,然後benchmark不停改。


http://arxiv.org/abs/1503.00855v1

Hadley Wickham補充的:

http://civilstat.com/.../very-gentle-resource-for.../...


(待完善)

  1. 多用*apply系列函數,對for循環趕盡殺絕,具體使用方法和範圍可參考:R Grouping functions: sapply vs. lapply vs. apply. vs. tapply vs. by vs. aggregate;
  2. Rcpp,參考書籍:《Seamless.R.and.C++.Integration.with.Rcpp》;
  3. 單機並行,理論來說你的機器有幾個核,效率會相應提升幾倍,實際上對操作大數據,或者針對長時間的運算效果才明顯,對於小數據,會有阻礙作用;

  • 參考書籍:
    《parallel computation for data science》,《R in a nutshell》26章,《R語言編程藝術》第16章;
  • 參考文檔: Using the foreach package,getting started parallel parallel R

  • 可用的包:snow,multicore(僅Linux中可用), foreach, Rmpi(操作系統級別,一般用於集群),parallel(合併了snow和multicore),segue(適合集群),doMC(Unix) ;doparallel與foreach結合;

4.考慮集群,如sparkR,RHadoop(還未嘗試過)。

  • 對sparkR功能的講解視頻:youtube.com 的頁面

  • sparkR的github官網:SparkR by amplab-extras
  • 操作入門:SparkR (R on Spark)
  • RHadoop安裝配置可參考書籍《R的極客理想——工具篇》


Julia 的作者之一John Myles White 在他的博文 The Relationship between Vectorized and Devectorized Code 中提到,在R下, 最糟糕的情況是R Devectorized Code, 常用的情況是R Vectorized Code, 最佳情況是C Devectorized Code. JMW認為 「R』s vectorized code is simply a thin wrapper around completely devectorized C code.」

-------------------------------------------------------------------------------------------------------------------------------------------

p.s. 我只是搬運一下人家的結論,輕拍。


我是新手,不過也有一些感悟。

少用循環,尤其是多重循環;

如果不得不用循環,甚至是多重循環,可以考慮先把數據量限制一下,取出其中的子集做操作。


多用內置函數,少用loop。


補充一下,關於並行運算這個頁面總結的比較齊全,包括多核多線程,GPU並行等等

CRAN Task View: High-Performance and Parallel Computing with R


最近的一點體驗:

多使用apply,不過目前使用的最多的倒不是apply而是mclapply 以及plyr包裡面的llply, alply這些了。

雖然我覺得目前看下來成熟的幾個並行包都或多或少有點小不爽。。。但是總體來說還是可以加速的。。foreach這東西求方家能細說一下。。。

Rcpp還是一定要用的,比如RcppEigen,RcppArmadillo 是比較常用的包。另外前陣子出了RcppParallel。

OOP的問題拿來做數據處理確實方便。但是,實際生活中遇到各種S3,S4 object還是略微不爽。。

順便請教一下。我想使用Rcpp + CUDA的話,有沒有什麼比較成熟的方案?

Fortran 是好的選擇。。但是有時候看見 Fortran 代碼真是想。。。


推薦閱讀:

十一歲的兒童學編程該如何開始,有什麼合適的入門書?
編程語言有韻律嗎?
有人質疑PL研究,比如program slicing的價值。如何解釋?
英語和數學不好的學渣能學計算機嗎?

TAG:編程語言 | 統計學 | 統計軟體 | R編程語言 |