Is there a way to prevent copy-on-modify when modifying attributes?

僤鯓⒐⒋嵵緔 提交于 2020-12-05 11:53:07

问题


I am surprised that a copy of the matrix is made in the following code:

> (m <- matrix(1:12, nrow = 3))
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> tracemem(m)
[1] "<000001E2FC1E03D0>"
> str(m)
 int [1:3, 1:4] 1 2 3 4 5 6 7 8 9 10 ...
> attr(m, "dim") <- 4:3
tracemem[0x000001e2fc1e03d0 -> 0x000001e2fcb05008]: 
> m
     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12
> str(m)
 int [1:4, 1:3] 1 2 3 4 5 6 7 8 9 10 ...

Is it useful? Is it avoidable?


EDIT: I do not have the same results as GKi.

> sessionInfo()
R version 4.0.3 (2020-10-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19041)

Matrix products: default

locale:
[1] LC_COLLATE=French_France.1252  LC_CTYPE=French_France.1252    LC_MONETARY=French_France.1252
[4] LC_NUMERIC=C                   LC_TIME=French_France.1252    

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

loaded via a namespace (and not attached):
[1] compiler_4.0.3 tools_4.0.3   
> m <- matrix(1:12, nrow = 3)
> tracemem(m)
[1] "<000001F8DB2C7D90>"
> attr(m, "dim") <- c(4, 3)
tracemem[0x000001f8db2c7d90 -> 0x000001f8db2d93f0]: 

One difference is that I do not use BLAS library...


回答1:


I'm using R 3.6.3 and indeed a copy is made. To change an attribute without making a copy, you can use the setattr function of the data.table package:

library(data.table)

m <- matrix(1:12, nrow = 3)
.Internal(inspect(m))

setattr(m, "dim", c(4L,3L))
.Internal(inspect(m))



回答2:


In my case it is not making a copy of the data:

m <- matrix(1:12, nrow = 3)
.Internal(inspect(m))
#@250ff98 13 INTSXP g0c4 [REF(1),ATT] (len=12, tl=0) 1,2,3,4,5,...
#ATTRIB:
#  @38da270 02 LISTSXP g0c0 [REF(1)] 
#    TAG: @194d610 01 SYMSXP g0c0 [MARK,REF(1171),LCK,gp=0x4000] "dim" (has value)
#    @38c3d88 13 INTSXP g0c1 [REF(65535)] (len=2, tl=0) 3,4

attr(m, "dim") <- 4:3
.Internal(inspect(m))
#@250ff98 13 INTSXP g0c4 [REF(1),ATT] (len=12, tl=0) 1,2,3,4,5,...
#ATTRIB:
#  @38da270 02 LISTSXP g0c0 [REF(1)] 
#    TAG: @194d610 01 SYMSXP g0c0 [MARK,REF(1171),LCK,gp=0x4000] "dim" (has value)
#    @38d9978 13 INTSXP g0c0 [REF(65535)]  4 : 3 (expanded)

It was @250ff98 and is afterwards still there. It is only changing the dim from @38c3d88 to @38d9978.

sessionInfo()
#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=en_GB.UTF-8       LC_NUMERIC=C              
# [3] LC_TIME=en_GB.UTF-8        LC_COLLATE=en_GB.UTF-8    
# [5] LC_MONETARY=en_GB.UTF-8    LC_MESSAGES=en_GB.UTF-8   
# [7] LC_PAPER=en_GB.UTF-8       LC_NAME=C                 
# [9] LC_ADDRESS=C               LC_TELEPHONE=C            
#[11] LC_MEASUREMENT=en_GB.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 tools_4.0.3   

The same with tracemem.

m <- matrix(1:12, nrow = 3)
tracemem(m)
#[1] "<0x289ff98>"
attr(m, "dim") <- 4:3
tracemem(m)
#[1] "<0x289ff98>"

But if you make an str(m) in between it makes currently a copy:

m <- matrix(1:12, nrow = 3)
tracemem(m)
#[1] "<0x28a01c8>"
str(m)
# int [1:3, 1:4] 1 2 3 4 5 6 7 8 9 10 ...
attr(m, "dim") <- 4:3
#tracemem[0x28a01c8 -> 0x2895608]: 


来源:https://stackoverflow.com/questions/64695984/is-there-a-way-to-prevent-copy-on-modify-when-modifying-attributes

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!