问题
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