R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。
R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。
要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。
关于作者:
- 张丹(Conan), 程序员Java,R,PHP,Javascript
- weibo:@Conan_Z
- blog: http://blog.fens.me
- email: bsspirit@gmail.com
转载请注明出处:
http://blog.fens.me/r-cache-memoise/
前言
缓存技术在计算机系统中运用地非常广泛,特别是对于重复性计算,缓存能为我们节省大量的CPU时间,可能是99%。R语言以统计计算著名,但其中很多算法包都是在进行大量重复的计算。
优化正再进行,改变已经开始。以Hadley Wickham为代表的R语言领军人物,正在让R快起来!你感觉到了吗?!
目录
- memoise介绍
- memoise安装
- memoise的API介绍
- memoise使用
- memoise源代码分析
1. memoise介绍
memoise是一个简单的缓存包,主要用来减少重复计算,从而提升CPU性能。当你用相同的参数执行计算的时候,你会得到之前计算过的结果,而不是重算一遍。
缓存技术对于有并发访问的应用来说,是性价比最高的性能提升方案。
注:memoise包是“Hadley Wickham”大神的作品!
memoise的发布页:http://cran.r-project.org/web/packages/memoise/index.html
2. memoise安装
系统环境
- Win7 64bit
- R: 3.0.1 x86_64-w64-mingw32/x64 b4bit
memoise安装
~R
> install.packages("memoise")
trying URL 'http://mirror.bjtu.edu.cn/cran/bin/windows/contrib/3.0/memoise_0.1.zip'
Content type 'application/zip' length 10816 bytes (10 Kb)
opened URL
downloaded 10 Kb
package ‘memoise’ successfully unpacked and MD5 sums checked
memoise加载
> library(memoise)
3. memoise的API介绍
非常简单的API列表,只有2个函数。
- forget: 重置缓存函数
- memoize: 定义缓存函数
4. memoise使用
缓存测试
#定义缓存函数
> fun <- memoise(function(x) { Sys.sleep(1); runif(1) })
#第一次执行fun函数
> system.time(print(fun()))
[1] 0.05983416
用户 系统 流逝
0 0 1
#第二次执行fun函数
> system.time(print(fun()))
[1] 0.05983416
用户 系统 流逝
0 0 0
#重置缓存函数
> forget(fun)
[1] TRUE
#第三次执行fun函数
> system.time(print(fun()))
[1] 0.6001663
用户 系统 流逝
0 0 1
- 1. 定义缓存函数memoise
- 2. 第一次执行fun函数, 等待sleep(1)
- 3. 第二次执行fun函数, 无等待,直接从缓存中返回结果
- 4. 重置缓存函数forget
- 5. 第三次执行fun函数, 由于fun被重置,返回2,等待sleep(1)
5. memoise源代码分析
1). memoise函数
- 1. new_cache创建新的缓存空间,给f函数
- 2. 生成f函数的hash值,作为key
- 3. 返回缓存后的,f函数引入
memoise <- memoize <- function(f) {
cache <- new_cache()
memo_f <- function(...) {
hash <- digest(list(...))
if (cache$has_key(hash)) {
cache$get(hash)
} else {
res <- f(...)
cache$set(hash, res)
res
}
}
attr(memo_f, "memoised") <- TRUE
return(memo_f)
}
2). forget函数
- 1. 检查环境中,是否缓存了f函数
- 2. 如果有f函数的缓存,则清空f函数的缓存值
forget <- function(f) {
if (!is.function(f)) return(FALSE)
env <- environment(f)
if (!exists("cache", env, inherits = FALSE)) return(FALSE)
cache <- get("cache", env)
cache$reset()
TRUE
}
3). 私有函数:new_cache函数
- 1. 在new_cache函数里,定义cache对象,保存在env的环境中
- 2. 通过new_cache函数,构造list类型对象,包括reset,set,get,has_key,keys方法
- 3. 通过list对象,对cache对象进行访问操作
new_cache <- function() {
cache <- NULL
cache_reset <- function() {
cache <<- new.env(TRUE, emptyenv())
}
cache_set <- function(key, value) {
assign(key, value, env = cache)
}
cache_get <- function(key) {
get(key, env = cache, inherits = FALSE)
}
cache_has_key <- function(key) {
exists(key, env = cache, inherits = FALSE)
}
cache_reset()
list(
reset = cache_reset,
set = cache_set,
get = cache_get,
has_key = cache_has_key,
keys = function() ls(cache)
)
}
转载请注明出处:
http://blog.fens.me/r-cache-memoise/