为什么 R 在使用 str 后进行修改时复制?

GKi*_*GKi 34 r

我想知道为什么 R 在使用str.

我创建一个matrix. 我可以改变它dim,一个元素甚至全部。没有复制。但是当str在 Matrix 上的下一个修改操作期间调用R 正在制作副本时。为什么会这样?

m <- matrix(1:12, 3)
tracemem(m)
#[1] "<0x559df861af28>"
dim(m) <- 4:3
m[1,1] <- 0L
m[] <- 12:1
str(m)
# int [1:4, 1:3] 12 11 10 9 8 7 6 5 4 3 ...
dim(m) <- 3:4  #Here after str a copy is made
#tracemem[0x559df861af28 -> 0x559df838e4a8]:
dim(m) <- 3:4
str(m)
# int [1:3, 1:4] 12 11 10 9 8 7 6 5 4 3 ...
dim(m) <- 3:4 #Here again after str a copy
#tracemem[0x559df838e4a8 -> 0x559df82c9d78]:
Run Code Online (Sandbox Code Playgroud)

我也想知道为什么在有任务回调时会复制一份。

TCB <- addTaskCallback(function(...) TRUE)
m <- matrix(1:12, nrow = 3)
tracemem(m)
#[1] "<0x559dfa79def8>"
dim(m) <- 4:3  #Copy on modification
#tracemem[0x559dfa79def8 -> 0x559dfa8998e8]:
removeTaskCallback(TCB)
#[1] TRUE
dim(m) <- 4:3  #No copy
Run Code Online (Sandbox Code Playgroud)

会话信息()

R version 4.0.3 (2020-10-10)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Debian GNU/Linux 10 (buster)

Matrix products: default
BLAS:   /usr/local/lib/R/lib/libRblas.so
LAPACK: /usr/local/lib/R/lib/libRlapack.so

locale:
 [1] LC_CTYPE=de_AT.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=de_AT.UTF-8        LC_COLLATE=de_AT.UTF-8    
 [5] LC_MONETARY=de_AT.UTF-8    LC_MESSAGES=de_AT.UTF-8   
 [7] LC_PAPER=de_AT.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=de_AT.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] compiler_4.0.3
Run Code Online (Sandbox Code Playgroud)

这是修改属性时是否有办法防止修改时复制的后续问题.

我开始 RR --vanilla有一个干净的会话。

GKi*_*GKi 6

我已经按照@sam-mason 在评论中的建议在R-help上问了这个问题。

Luke Tierney 的回答解决了这个问题str

从 R 4.0.0 开始,在某些情况下可以在内部减少引用计数,因此在这种情况下避免复制。尝试检测可以删除计数的所有情况的成本太高了,但在这种情况下我们可以做得更好。事实证明,pos.to.env 的内部结构不必要地创建了对调用环境的额外引用(此处是对exists() 的调用)。这已在 r79528 中修复。谢谢。

并与Task Callback

事实证明,处理回调调用的方式存在一些问题。这已在 R-devel 中的 r79541 中进行了修订。这个例子将不再需要在 R-devel 中重复。

谢谢你的报告。