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

本文为雪晴数据网《R语言大规模数据分析实战》 http://www.xueqing.tv/course/56 的课程学习笔记。

该课程目前更新到“第2章 Microsoft R Server简介”的微软数据科学家介绍MRS,后续教学主要是关于MRS的内容,再另外学习,所以本文只学习“第1章 提升R的性能和突破内存限制的技巧”

1. 课程介绍

1.1 课程目录

第一章 突破R内存瓶颈的一些小技巧

  • 升级硬件和软件

  • 减少数据复制

  • 利用整数的优势

  • 有效地存储数据

  • 在转换数据的时候避免循环

  • 在关键函数里使用C、C++或Fortran

  • 尽可能地使用面向行的数据转换

  • 排序之前要三思

  • 使用bigmemory家族的包

  • 借助数据库

  • 使用Revolution R Enterprise(简称RRE)

第二章 RRE的简介

  • RRE学术版的下载与安装

  • RRE的功能介绍

  • 导入数据的函数

  • 概括数据的函数

  • RRE可视化功能

  • RRE所支持的算法介绍

第三章 用RRE做数据探索

  • 导入数据

  • 用rxGetVarInfo()函数查看数据的基本特征

  • 用rxSummary()函数计算数据的描述统计量

  • 用rxHistogram()分析数据的分布

  • 用rxLinePlot()可视化分析两个变量之间的关系

  • 用rxCrossTabs()分析变量间的关系

  • 用with rxCube()分析变量间的关系

第四章 用RRE做数据整理

  • 数据融合

  • 用rxDataStep()做数据变换

  • 用dplyrXdf包整理数据

第五章 用RRE做数据挖掘(案例实战)

  • 数据准备

  • 导入数据

  • 数据探索

  • 线性回归

  • 逻辑回归

  • K-means聚类

  • 决策树分类

1.2 课程视频目录

第1章:提升R的性能和突破内存限制的技巧

  • 如何提升R的性能

  • 并行计算

第2章:Microsoft R Server简介

  • 微软数据科学家介绍MRS

2. 第1章:提升R的性能和突破内存限制的技巧

2.1 如何提升R的性能

这一节先介绍提高R性能的几种方法,然后重点介绍如何利用R的内部机制来提升性能。

2.1.1 性能提升的方法

a.1 系统升级

  • 升级硬件

  • 使用64位操作系统

  • 利用GPU

  • 租用云计算服务器

a.2 开发层面的优化

  • 算法
    降低算法复杂度

  • 调用C/C++或者Fortran
    关键的、耗时的计算步骤

  • 缓冲技术
    减少重复计算

a.3 使用层面的优化

  • 充分利用R的内存机制——R的基础优化

  • 增强R的矩阵运算——加速BLAS

  • 并行计算

  • 大规模数据的处理——图片内存限制

  • 使用Revolution R Enterprise(RRE)

下列介绍通过充分利用R的内部机制优化性能

2.1.2 向量化

向量化的代码,不要用循环!

  • 利用矩阵运算

  • 利用内置的向量化函数,比如exp、sin、rowMeans、rowSums、colSums、ifelse等

  • 利用Vectorize函数将非向量化的函数改装为向量化的函数

  • *apply函数族:apply、lapply、sapply、tapply、mapply等

  • plyr和dplyr包
    Rstudio发布的data wrangling cheat sheet

##利用矩阵运算
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)## 利用向量化运算
## 内置的向量化函数
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等函数对矩阵或数据库做整体处理
colSums(iris[,1:4])

利用R内置的向量化函数,自定义向量化函数,只要在函数定义时每个运算是向量化的。但是在函数定义时用了逻辑判断语句,就会破坏的向量化特征。

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
## 在函数的定义中有if语句,不能接受向量作为判断的条件,否则判断第一个元素。## 利用ifelse函数做向量化的判断
myfunc <- function(x){ifelse(x %% 2 == 0,TRUE,FALSE)
}
myfunc(c(1,2,3,4))##利用Vectorize函数将非向量化的函数改装为向量化的函数
funcv <- Vectorize(func)
funcv(c(1,2,3,4))##利用sapply函数向量化运算
sapply(c(1,2,3,4),func)

2.1.3 预先给对象分配内存

R为解释性语言,也是动态语言,如果不事先指定对象的类型和长度,在运算过程会动态分配内存,提高灵活性,但降低了效率。

尽量减少cbind、rbind的使用

## 求出10000个斐波那契数
x <- c(1,1)
i <- 2
system.time(while(i<10000){new <- x[i] + x[i-1]x <- cbind(x,new)i <- i + 1}
)## 指定类型和长度
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 避免内存拷贝

假设我们有许多彼此不相关的向量,但因为一些其他的原因,我们希望将每个向量的第三个元素设为8,既然它们是互不相关的,甚至可能具有不同的长度,我们也许会考虑将它们放在一个列表中:

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 删除临时对象和不再用的对象

  • rm()删除对象
    rm(object)删除指定对象,rm(list = ls())可以删除内存中的所有对象

  • gc()内存垃圾回收
    使用rm(object)删除变量,要使用gc()做垃圾回收,否则内存是不会自动释放的。invisible(gc())不显示垃圾回收的结果

2.1.6 分析内存的函数

  • ls()列出特定环境中的对象

  • object.size()返回R对象的大小(近似的)

  • memory.profile()分析cons单元的使用情况

  • memory.size()监测全部内存的使用情况(仅Windows下可用)
    memory.size(max=T)返回历史占用过的最大内存;memory.size(max=F)返回目前占用的内存。未做垃圾清理时,已使用内存和已分配内存同步增加,但在垃圾清理后rm(list=ls());gc(),已使用内存会减少,而已分配给R的内存不会改变。

  • memory.limit()系统可分配的内存上限(仅Windows下可用)
    memory.limit(newLimit)更改到一个新的上限。 注意,在32位的R中,封顶上限为4G,你无法在一个程序上使用超过4G (数位上限)。这种时候,可以考虑使用64位的版本。

2.2 并行计算

本节主要介绍parallel包,后续介绍R与Hadoop的结合

2.2.1 parallel包

parallel包实际上整合了之前已经比较成熟的snow包和multicore包,multicore无法在windows下运行。

## 一个简单的例子
system.time(for(i in 1:4){Sys.sleep(2)})
## 或者用lapply改写成:
system.time(lapply(1:4, function(i) Sys.sleep(2)))
## 设置并行环境
library(parallel)
## 检测系统可用的核数
detectCores()
## 默认返回的结构逻辑的核数,需修改logical=FALSE,返回物理核数
detectCores(logical=FALSE)
## 建立2核的集群
cl <- makeCluster(2)## 不使用并行计算
system.time(lapply(1:4, function(i) Sys.sleep(2)))## 使用parallel包,运行时间减半
## 在非windows系统下,使用mclapply函数
system.time(mclapply(1:4, function(i) Sys.sleep(2),mc.cores=2)
)
## 在windows系统下,使用parlapply函数
system.time(parlapply(cl, 1:4 function(i) Sys.sleep(2))
)##关闭集群
stopCluster(cl)

2.2.2 foreach和doParallel包

使用parallel包进行并行运算时,需改写原来的程序,且改写较多。

foreach包是一个并行计算的框架:循环控制+并行执行。foreach相当于for的延伸,在循环的过程中它能够选择不同的并行后段进行执行。在非并行运算过程中代替for。改写为并行运算,改写很少。

## 一个简单的例子
## 不并行的版本
library(foreach)
foreach(i=1:4) %do% sqrt(i)
## .combine则表示运算结果的整合方式,.combine='c'运算结果为向量
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))
## 并行计算失败!

用foreach做并行计算必须跟并行后端(parallel backend)配合使用

doParallel包时foreach包执行并行计算时的后端接口程序。

CRAN上还有以下的并行计算后端包:

  • doMPI与Rmpi包配合使用

  • doRedis与rredis包配合使用

  • doMC提供parallel包的多核计算接口

  • doSNOW提供现已废弃的SNOW包的接口

library(foreach)
## 注册并行后端
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并行计算速度比不并行计算还慢很多## 关闭集群
stopCluster(cl)

案例

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

parallel并行计算速度比不并行计算速度稍微快点,而foreach并行计算速度比不并行计算还慢很多很多,不知道是什么原因

不知何故,在Mac OSX 下采用doParallel速度特别慢, 比不用并行还慢,于是又尝试了doMC

library(doMC)
## 设置并行核数, 并注册并行
registerDoMC(2)
## 开始计算
system.time(foreach(i=1:4) %dopar% sqrt(i))## 比较不并行计算和doParallel并行计算
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.

对于小任务,调度任务并返回结果的开销可能比执行任务本身还耗时,导致表现不佳。

下列为实际的例子

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迅速释放占的内存 http://cos.name/cn/topic/139522/

  • 也谈提高R语言的运算效率 http://cos.name/2009/12/impro...

  • R语言并行计算的原理和案例 http://www.tbk.ren/article/63...

  • R高性能包介绍与并行运算 http://www.idatacamp.com/2015...

  • R语言 并行处理 http://cangfengzhe.github.io/...

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/284194.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WTM:ASP.NET Core快速开发利器!

不少程序员朋友应该都有这个想法&#xff0c;接接私活&#xff0c;赚赚外快&#xff0c;但是从零开发一套系统并不容易&#xff0c;今天给大家推荐一款开箱即用的通用后台管理系统。一个能够让程序猿快速开发的炒鸡脚手架&#xff0c;采用.NET Core开源框架&#xff01;github地…

【CloudCompare教程】002:点云绘制模式详解

文章目录 1. 按高程着色2. 按索引着色3. 按渐变着色1. 按高程着色 在内容列表中选中点云图层,点击【编辑】→【标量领域】→【将坐标导出到SF】。 勾选Z,点击OK。 高程着色效果: 2. 按索引着色 点击【编辑】→【标量领域】→【添加点指数为SF】。 索引着色效果:

《首席产品官》成海清 著 图书目录 思维导图

原文档地址&#xff1a;《首席产品官》成海清

「每天一道面试题」如何理解方法的重载与覆盖?

方法重载在同一个Java 类中&#xff08;包含父类&#xff09;&#xff0c;如果出现了方法名称相同&#xff0c;而参数列表不同的情况就叫做重载。方法的重载的规则&#xff1a;&#xff08;1&#xff09;&#xff1a;方法名称必须相同&#xff08;2&#xff09;&#xff1a;参数…

day63-webservice 01.cxf介绍

CXF功能就比较强了。CXF支持soap1.2。CXF和Spring整合的非常密切。它的配置文件基本就是Spring的配置文件了。CXF是要部署在服务器才能用的。CXF得放到Web容器里面去发布。CXF就可以整合咱们的Web容器。 cxf-2.4.0解压出来之后 apache-cxf-2.4.2是核心包,apache-cxf-2.4.4-src是…

Java中的static关键字解析

static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字&#xff0c;也是各大公司的面试官喜欢在面试时问到的知识点之一。下面就先讲述一下static关键字的用法和平常容易误解的地方&#xff0c;最后列举了一些面试笔试中常见的关于static的考题。以下是…

微信公众号授权登录后报redirect_uri参数错误的问题

在进行微信公众号二次开发的时候&#xff0c;需要通过授权码模式来进行微信授权。比如&#xff0c;在进行登录的时候&#xff0c;用户点击了登录按钮&#xff0c;然后弹出一个授权框&#xff0c;用户点击同意后&#xff0c;就可以获取用户的OpenId等信息了。这篇文章主要分享下…

【GlobalMapper精品教程】022:根据一个字段属性值批量计算另一个字段属性值(地类名称求地类编码)

项目中通常需要根据一个字段属性值的不同,批量计算另一个字段属性值(如根据地类名称求地类编码),根据权属地物名称给权属地物编码批量赋值等,本文讲解在属性表中根据代码批量实现方法。 参考阅读: 【ArcGIS风暴】ArcGIS 10.2字段计算器(Field Calculator)批量条件赋值用…

[转]【读书笔记】《俞军产品方法论》——产品经理的枕边书

作者简介 俞军&#xff0c;1997年毕业于同济大学化学系。曾任百度产品副总裁、首席产品架构师&#xff0c;网名“搜索引擎9238”&#xff0c;有“百度贴吧之父”之称。滴滴前高级产品副总裁。 内容简介 摘抄语录 我的产品潜力和优势大约只来自三方面&#xff1a;第一&#xff0…

linux批量分发必会面试题,通过邮件反馈结果。

请准备三台linux机器为别为A,B,C,要求实现以下内容1、用自己的名字用户完成一把钥匙开多把锁&#xff08;A&#xff0c;钥匙&#xff0c;B,C锁&#xff09;的免密码登录部署场景该题在生产环境中的用途为&#xff1b;批量分发数据&#xff0c;批量发布程序代码&#xff0c;批量…

【GlobalMapper精品教程】023:Excel数据通过相同字段连接到属性表中(气温降水连接到气象台站)

globalmapper中也可以将Excel数据通过相同字段连接到属性表中。本文讲解将气温降水连接到气象台站点图层中。 文章目录 一、加载气象台站数据二、挂接气温降水数据一、加载气象台站数据 globalmapper中根据坐标生成点的方法,前面的文章有所说明: 【GlobalMapper精品教程】0…

记一次 .NET 某智慧物流WCS系统CPU爆高分析

一&#xff1a;背景 1. 讲故事哈哈&#xff0c;再次见到物流类软件&#xff0c;上个月有位朋友找到我&#xff0c;说他的程序出现了 CPU 爆高&#xff0c;让我帮忙看下什么原因&#xff0c;由于那段时间在苦心研究 C&#xff0c;分析和经验分享也就懈怠了&#xff0c;今天就给大…

采用Atlas+Keepalived实现MySQL读写分离、读负载均衡【转载】

文章 原始出处 &#xff1a;http://sofar.blog.51cto.com/353572/1601552 一、基础介绍 1、背景描述 目前我们的高可用DB的代理层采用的是360开源的Atlas&#xff0c;从上线以来&#xff0c;已稳定运行2个多月。无论是从性能上&#xff0c;还是稳定性上&#xff0c;相比其他开…

vscode搭建go开发环境

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、安装goLang二.配置环境变量三、vscode安装插件四.安装golang依赖五.新建go文件前言 能用golang就用golang..这配置很麻烦 提示&#xff1a;以下是本篇文章正…

【GlobalMapper精品教程】024:批量高效实现多种数据格式互转的方法

globalmapper批量高效实现多种数据格式互转的方法。 文章目录一、批量格式转换二、格式转换形式举例一、批量格式转换 选择原文件类型&#xff1a; 选择文件类型&#xff1a; 在源文件列表中添加需要转换的文件或者文件夹&#xff0c;指定目标文件目录&#xff0c;文件名称和投…

基于 WeihanLi.Npoi 实现excel导入时纯汉字的日期转换

基于 WeihanLi.Npoi 实现excel导入时纯汉字的日期转换Intro前段时间有位小伙伴在 Github 上提了一个 “不能识别纯汉字的日期格式” issue二〇二二年一月一日 格式的日期单元格识别不出来会变成&#xff0c;0001/1/1 0:00:00 如何让它能够识别出来呢&#xff0c;基于 InputForm…

十个模型,总结产品经理沟通方法论

编辑导语&#xff1a;毫不夸张地说沟通占据了产品经理日常工作内容的40%&#xff0c;高效沟通往往能让事情事半功倍。本文作者结合沟通方法与具体沟通情景讲解了如何高效沟通&#xff0c;一起来看看吧&#xff01; 目录 一、为什么要学会沟通 二、沟通模型 1. PREP原则&…

【Globalmapper中文入门到精通系列实验图文教程】(附配套实验数据持续更新)

【Globalmapper中文版入门到精通系列实验图文教程】&#xff08;附配套实验数据持续更新&#xff09; 文章目录一、专栏简介二、文章目录三、数据目录四、传送门一、专栏简介 本专栏为GlobalMapper中文入门实战精品教程&#xff0c;内容主要涉及&#xff1a;Globalmapper23软件…

【GlobalMapper精品教程】025:影像数据集的建立与巧妙使用

GlobalMapper影像数据集类似于金字塔,作用是提高大量影像的加载与显示速度,还可批量进行一系列设置。本文的配套数据为data025.rar。 文章目录 1. 建立影像数据集2. 影像数据集的使用1. 建立影像数据集 (1)点击【文件】→【创建新地图目录】。 (2)选择影像数据集存放路径…

使用xUnit为.net core程序进行单元测试(3)

第1部分: http://www.cnblogs.com/cgzl/p/8283610.html 第2部分: http://www.cnblogs.com/cgzl/p/8287588.html 请使用这个项目作为练习的开始: https://pan.baidu.com/s/1ggcGkGb 测试的分组 打开Game.Tests里面的BossEnemyShould.cs, 为HaveCorrectPower方法添加一个Trait属性…