Hadley的新pryr包显示变量的地址非常适合分析.我发现无论何时将变量传递给函数,无论该函数做什么,都会创建该变量的副本.此外,如果函数体将变量传递给另一个函数,则会生成另一个副本.这是一个明显的例子
n = 100000
p = 100
bar = function(X) {
print(pryr::address(X))
}
foo = function(X) {
print(pryr::address(X))
bar(X)
}
X = matrix(rnorm(n*p), n, p)
print(pryr::address(X))
foo(X)
Run Code Online (Sandbox Code Playgroud)
哪个生成
> X = matrix(rnorm(n*p), n, p)
> print(pryr::address(X))
[1] "0x7f5f6ce0f010"
> foo(X)
[1] "0x92f6d70"
[1] "0x92f3650"
Run Code Online (Sandbox Code Playgroud)
尽管功能没有做任何事情,地址每次都会改变.我对这种行为感到困惑,因为我听说R描述为写入时的副本 - 因此可以传递变量,但只有当函数想要写入该变量时才会生成副本.这些函数调用发生了什么?
为了获得最佳的R开发,最好不要编写多个小函数,而是将内容保存在一个函数中?我也发现了一些关于Reference Classes的讨论,但我看到很少有R开发人员使用它.是否有另一种有效的方法来传递我错过的变量?
我不完全确定,但地址可能指向指向对象的指针的内存地址.以下面的例子为例.
library(pryr)
n <- 100000
p <- 500
X <- matrix(rep(1,n*p), n, p)
l <- list()
for(i in 1:10000) l[[i]] <- X
Run Code Online (Sandbox Code Playgroud)
此时,如果每个元素l都是副本X,则大小为l〜3.5Tb.显然情况并非如此,因为您的计算机已开始吸烟.然而地址却不同.
sapply(l[1:10], function(x) address(x))
# [1] "0x1062c14e0" "0x1062c0f10" "0x1062bebc8" "0x10641e790" "0x10641dc28" "0x10641c640" "0x10641a800" "0x1064199c0"
# [9] "0x106417380" "0x106411d40"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
125 次 |
| 最近记录: |