日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

[笔记]提升R的性能和突破内存限制的技巧

發(fā)布時(shí)間:2023/12/9 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [笔记]提升R的性能和突破内存限制的技巧 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文為雪晴數(shù)據(jù)網(wǎng)《R語(yǔ)言大規(guī)模數(shù)據(jù)分析實(shí)戰(zhàn)》 http://www.xueqing.tv/course/56 的課程學(xué)習(xí)筆記。

該課程目前更新到“第2章 Microsoft R Server簡(jiǎn)介”的微軟數(shù)據(jù)科學(xué)家介紹MRS,后續(xù)教學(xué)主要是關(guān)于MRS的內(nèi)容,再另外學(xué)習(xí),所以本文只學(xué)習(xí)“第1章 提升R的性能和突破內(nèi)存限制的技巧”

1. 課程介紹

1.1 課程目錄

第一章 突破R內(nèi)存瓶頸的一些小技巧

  • 升級(jí)硬件和軟件

  • 減少數(shù)據(jù)復(fù)制

  • 利用整數(shù)的優(yōu)勢(shì)

  • 有效地存儲(chǔ)數(shù)據(jù)

  • 在轉(zhuǎn)換數(shù)據(jù)的時(shí)候避免循環(huán)

  • 在關(guān)鍵函數(shù)里使用C、C++或Fortran

  • 盡可能地使用面向行的數(shù)據(jù)轉(zhuǎn)換

  • 排序之前要三思

  • 使用bigmemory家族的包

  • 借助數(shù)據(jù)庫(kù)

  • 使用Revolution R Enterprise(簡(jiǎn)稱RRE)

第二章 RRE的簡(jiǎn)介

  • RRE學(xué)術(shù)版的下載與安裝

  • RRE的功能介紹

  • 導(dǎo)入數(shù)據(jù)的函數(shù)

  • 概括數(shù)據(jù)的函數(shù)

  • RRE可視化功能

  • RRE所支持的算法介紹

第三章 用RRE做數(shù)據(jù)探索

  • 導(dǎo)入數(shù)據(jù)

  • 用rxGetVarInfo()函數(shù)查看數(shù)據(jù)的基本特征

  • 用rxSummary()函數(shù)計(jì)算數(shù)據(jù)的描述統(tǒng)計(jì)量

  • 用rxHistogram()分析數(shù)據(jù)的分布

  • 用rxLinePlot()可視化分析兩個(gè)變量之間的關(guān)系

  • 用rxCrossTabs()分析變量間的關(guān)系

  • 用with rxCube()分析變量間的關(guān)系

第四章 用RRE做數(shù)據(jù)整理

  • 數(shù)據(jù)融合

  • 用rxDataStep()做數(shù)據(jù)變換

  • 用dplyrXdf包整理數(shù)據(jù)

第五章 用RRE做數(shù)據(jù)挖掘(案例實(shí)戰(zhàn))

  • 數(shù)據(jù)準(zhǔn)備

  • 導(dǎo)入數(shù)據(jù)

  • 數(shù)據(jù)探索

  • 線性回歸

  • 邏輯回歸

  • K-means聚類

  • 決策樹分類

1.2 課程視頻目錄

第1章:提升R的性能和突破內(nèi)存限制的技巧

  • 如何提升R的性能

  • 并行計(jì)算

第2章:Microsoft R Server簡(jiǎn)介

  • 微軟數(shù)據(jù)科學(xué)家介紹MRS

2. 第1章:提升R的性能和突破內(nèi)存限制的技巧

2.1 如何提升R的性能

這一節(jié)先介紹提高R性能的幾種方法,然后重點(diǎn)介紹如何利用R的內(nèi)部機(jī)制來(lái)提升性能。

2.1.1 性能提升的方法

a.1 系統(tǒng)升級(jí)

  • 升級(jí)硬件

  • 使用64位操作系統(tǒng)

  • 利用GPU

  • 租用云計(jì)算服務(wù)器

a.2 開發(fā)層面的優(yōu)化

  • 算法
    降低算法復(fù)雜度

  • 調(diào)用C/C++或者Fortran
    關(guān)鍵的、耗時(shí)的計(jì)算步驟

  • 緩沖技術(shù)
    減少重復(fù)計(jì)算

a.3 使用層面的優(yōu)化

  • 充分利用R的內(nèi)存機(jī)制——R的基礎(chǔ)優(yōu)化

  • 增強(qiáng)R的矩陣運(yùn)算——加速BLAS

  • 并行計(jì)算

  • 大規(guī)模數(shù)據(jù)的處理——圖片內(nèi)存限制

  • 使用Revolution R Enterprise(RRE)

下列介紹通過(guò)充分利用R的內(nèi)部機(jī)制優(yōu)化性能

2.1.2 向量化

向量化的代碼,不要用循環(huán)!

  • 利用矩陣運(yùn)算

  • 利用內(nèi)置的向量化函數(shù),比如exp、sin、rowMeans、rowSums、colSums、ifelse等

  • 利用Vectorize函數(shù)將非向量化的函數(shù)改裝為向量化的函數(shù)

  • *apply函數(shù)族:apply、lapply、sapply、tapply、mapply等

  • plyr和dplyr包
    Rstudio發(fā)布的data wrangling cheat sheet

##利用矩陣運(yùn)算 n <- 100000 x1 <- 1:n x2 <- 1:n y <- vector() system.time(for(i in 1:n){y[i] <- x1[i] + x2[i]} ) system.time(y <- x1 + x2)## 利用向量化運(yùn)算 ## 內(nèi)置的向量化函數(shù) v <- 1:100000 result <- rep(1:100000) system.time(for(i in 1:100000){result[i] <- sin(v[i])} ) system.time(result <- sin(v))## 利用rowMeans、rowSums、colSums、colMeans等函數(shù)對(duì)矩陣或數(shù)據(jù)庫(kù)做整體處理 colSums(iris[,1:4])

利用R內(nèi)置的向量化函數(shù),自定義向量化函數(shù),只要在函數(shù)定義時(shí)每個(gè)運(yùn)算是向量化的。但是在函數(shù)定義時(shí)用了邏輯判斷語(yǔ)句,就會(huì)破壞的向量化特征。

func <- function(x){if(x %% 2 == 0){ret <- TRUE}else{ret <- FALSE}return(ret) } func(34) func(c(1,2,3,4)) ## Warning message: ## In if (x%%2 == 0) { : ## the condition has length > 1 and only the first element will be used ## 在函數(shù)的定義中有if語(yǔ)句,不能接受向量作為判斷的條件,否則判斷第一個(gè)元素。## 利用ifelse函數(shù)做向量化的判斷 myfunc <- function(x){ifelse(x %% 2 == 0,TRUE,FALSE) } myfunc(c(1,2,3,4))##利用Vectorize函數(shù)將非向量化的函數(shù)改裝為向量化的函數(shù) funcv <- Vectorize(func) funcv(c(1,2,3,4))##利用sapply函數(shù)向量化運(yùn)算 sapply(c(1,2,3,4),func)

2.1.3 預(yù)先給對(duì)象分配內(nèi)存

R為解釋性語(yǔ)言,也是動(dòng)態(tài)語(yǔ)言,如果不事先指定對(duì)象的類型和長(zhǎng)度,在運(yùn)算過(guò)程會(huì)動(dòng)態(tài)分配內(nèi)存,提高靈活性,但降低了效率。

盡量減少cbind、rbind的使用

## 求出10000個(gè)斐波那契數(shù) x <- c(1,1) i <- 2 system.time(while(i<10000){new <- x[i] + x[i-1]x <- cbind(x,new)i <- i + 1} )## 指定類型和長(zhǎng)度 x <- vector(mode="numeric",100000) x[1] <- 1 x[2] <- 1 system.time(while(i<10000){i <- i + 1x[i] <- x[i-1] + x[i-2]} )

2.1.4 避免內(nèi)存拷貝

假設(shè)我們有許多彼此不相關(guān)的向量,但因?yàn)橐恍┢渌脑?#xff0c;我們希望將每個(gè)向量的第三個(gè)元素設(shè)為8,既然它們是互不相關(guān)的,甚至可能具有不同的長(zhǎng)度,我們也許會(huì)考慮將它們放在一個(gè)列表中:

m <- 5000 n <- 1000 z <- list() for(i in 1:m) z[[i]] <- sample(1:10, n, replace = T) system.time(for(i in 1:m) z[[i]][3] <- 8)## 把這些向量一起放到矩陣中 z <- matrix(sample(1:10, m * n, replace = T),nrow = m) system.time(z[,3] <- 8)

2.1.5 刪除臨時(shí)對(duì)象和不再用的對(duì)象

  • rm()刪除對(duì)象
    rm(object)刪除指定對(duì)象,rm(list = ls())可以刪除內(nèi)存中的所有對(duì)象

  • gc()內(nèi)存垃圾回收
    使用rm(object)刪除變量,要使用gc()做垃圾回收,否則內(nèi)存是不會(huì)自動(dòng)釋放的。invisible(gc())不顯示垃圾回收的結(jié)果

2.1.6 分析內(nèi)存的函數(shù)

  • ls()列出特定環(huán)境中的對(duì)象

  • object.size()返回R對(duì)象的大小(近似的)

  • memory.profile()分析cons單元的使用情況

  • memory.size()監(jiān)測(cè)全部?jī)?nèi)存的使用情況(僅Windows下可用)
    memory.size(max=T)返回歷史占用過(guò)的最大內(nèi)存;memory.size(max=F)返回目前占用的內(nèi)存。未做垃圾清理時(shí),已使用內(nèi)存和已分配內(nèi)存同步增加,但在垃圾清理后rm(list=ls());gc(),已使用內(nèi)存會(huì)減少,而已分配給R的內(nèi)存不會(huì)改變。

  • memory.limit()系統(tǒng)可分配的內(nèi)存上限(僅Windows下可用)
    memory.limit(newLimit)更改到一個(gè)新的上限。 注意,在32位的R中,封頂上限為4G,你無(wú)法在一個(gè)程序上使用超過(guò)4G (數(shù)位上限)。這種時(shí)候,可以考慮使用64位的版本。

2.2 并行計(jì)算

本節(jié)主要介紹parallel包,后續(xù)介紹R與Hadoop的結(jié)合

2.2.1 parallel包

parallel包實(shí)際上整合了之前已經(jīng)比較成熟的snow包和multicore包,multicore無(wú)法在windows下運(yùn)行。

## 一個(gè)簡(jiǎn)單的例子 system.time(for(i in 1:4){Sys.sleep(2)}) ## 或者用lapply改寫成: system.time(lapply(1:4, function(i) Sys.sleep(2))) ## 設(shè)置并行環(huán)境 library(parallel) ## 檢測(cè)系統(tǒng)可用的核數(shù) detectCores() ## 默認(rèn)返回的結(jié)構(gòu)邏輯的核數(shù),需修改logical=FALSE,返回物理核數(shù) detectCores(logical=FALSE) ## 建立2核的集群 cl <- makeCluster(2)## 不使用并行計(jì)算 system.time(lapply(1:4, function(i) Sys.sleep(2)))## 使用parallel包,運(yùn)行時(shí)間減半 ## 在非windows系統(tǒng)下,使用mclapply函數(shù) system.time(mclapply(1:4, function(i) Sys.sleep(2),mc.cores=2) ) ## 在windows系統(tǒng)下,使用parlapply函數(shù) system.time(parlapply(cl, 1:4 function(i) Sys.sleep(2)) )##關(guān)閉集群 stopCluster(cl)

2.2.2 foreach和doParallel包

使用parallel包進(jìn)行并行運(yùn)算時(shí),需改寫原來(lái)的程序,且改寫較多。

foreach包是一個(gè)并行計(jì)算的框架:循環(huán)控制+并行執(zhí)行。foreach相當(dāng)于for的延伸,在循環(huán)的過(guò)程中它能夠選擇不同的并行后段進(jìn)行執(zhí)行。在非并行運(yùn)算過(guò)程中代替for。改寫為并行運(yùn)算,改寫很少。

## 一個(gè)簡(jiǎn)單的例子 ## 不并行的版本 library(foreach) foreach(i=1:4) %do% sqrt(i) ## .combine則表示運(yùn)算結(jié)果的整合方式,.combine='c'運(yùn)算結(jié)果為向量 foreach(i=1:4,.combine='c') %do% sqrt(i) system.time(foreach(i=1:4) %do% sqrt(i)) ## 并行的版本,需要把%do%改為%dopar% system.time(foreach(i=1:4) %dopar% sqrt(i)) ## 并行計(jì)算失敗!

用foreach做并行計(jì)算必須跟并行后端(parallel backend)配合使用

doParallel包時(shí)foreach包執(zhí)行并行計(jì)算時(shí)的后端接口程序。

CRAN上還有以下的并行計(jì)算后端包:

  • doMPI與Rmpi包配合使用

  • doRedis與rredis包配合使用

  • doMC提供parallel包的多核計(jì)算接口

  • doSNOW提供現(xiàn)已廢棄的SNOW包的接口

library(foreach) ## 注冊(cè)并行后端 library(doParallel) cl <- makeCluster(2) registerDoParallel(cl) ## 使用doParallel包做foreach的并行后端 system.time(foreach(1:4) %dopar% Sys.sleep(2))system.time(for(i in 1:400){sqrt(i)}) system.time(lapply(1:400, function(i) sqrt(i))) system.time(foreach(i=1:400) %do% sqrt(i)) system.time(foreach(i=1:400) %dopar% sqrt(i)) system.time(foreach(i=1:400,.combine='c') %dopar% sqrt(i)) ## foreach和doParallel并行計(jì)算速度比不并行計(jì)算還慢很多## 關(guān)閉集群 stopCluster(cl)

案例

library(parallel) cl <- makeCluster(2) fun <- function(x){return(x+1) } ## 不并行計(jì)算效果 system.time(res <- lapply(1:5000000, fun) ) ## parallel并行計(jì)算效果 system.time(res <- mclapply(1:5000000, fun, mc.cores=2) ) ## foreach并行計(jì)算效果 library(foreach) library(doParallel) registerDoParallel(cl) system.time(res <- foreach(x=1:5000000,.combine='cbind') %dopar%fun(x) )## 關(guān)閉集群 stopCluster(cl)

parallel并行計(jì)算速度比不并行計(jì)算速度稍微快點(diǎn),而foreach并行計(jì)算速度比不并行計(jì)算還慢很多很多,不知道是什么原因

不知何故,在Mac OSX 下采用doParallel速度特別慢, 比不用并行還慢,于是又嘗試了doMC

library(doMC) ## 設(shè)置并行核數(shù), 并注冊(cè)并行 registerDoMC(2) ## 開始計(jì)算 system.time(foreach(i=1:4) %dopar% sqrt(i))## 比較不并行計(jì)算和doParallel并行計(jì)算 system.time(foreach(i=1:4) %do% sqrt(i)) cl <- makeCluster(2) registerDoParallel(cl) system.time(foreach(i=1:4) %dopar% sqrt(i))

doMC比doParallel還慢!

Getting Started with doParallel and foreach的解釋如下:

With small tasks, the overhead of scheduling the task and returning the result can be greater than the time to execute the task itself, resulting in poor performance. In addition, this example doesn’t make use of the vector capabilities of sqrt, which it must to get decent performance. This is just a test and a pedagogical example, not a benchmark.

對(duì)于小任務(wù),調(diào)度任務(wù)并返回結(jié)果的開銷可能比執(zhí)行任務(wù)本身還耗時(shí),導(dǎo)致表現(xiàn)不佳。

下列為實(shí)際的例子

x <- iris[which(iris[,5] != "setosa"), c(1,5)] trials <- 10000 ptime <- system.time({r <- foreach(icount(trials), .combine=cbind) %dopar% {ind <- sample(100, 100, replace=TRUE)result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))coefficients(result1)} })stime <- system.time({r <- foreach(icount(trials), .combine=cbind) %do% {ind <- sample(100, 100, replace=TRUE)result1 <- glm(x[ind,2]~x[ind,1], family=binomial(logit))coefficients(result1)} }) ptime stime

3. 參考資料

  • 有沒有高人能使得R迅速釋放占的內(nèi)存 http://cos.name/cn/topic/139522/

  • 也談提高R語(yǔ)言的運(yùn)算效率 http://cos.name/2009/12/impro...

  • R語(yǔ)言并行計(jì)算的原理和案例 http://www.tbk.ren/article/63...

  • R高性能包介紹與并行運(yùn)算 http://www.idatacamp.com/2015...

  • R語(yǔ)言 并行處理 http://cangfengzhe.github.io/...

  • Getting Started with doParallel and foreach https://cran.r-project.org/we...

  • parallel http://stat.ethz.ch/R-manual/...

總結(jié)

以上是生活随笔為你收集整理的[笔记]提升R的性能和突破内存限制的技巧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。