【问题标题】:Matrix doubles memory usage when replacing values矩阵在替换值时使内存使用量翻倍
【发布时间】:2014-07-07 18:29:53
【问题描述】:

如果我替换其中的值,为什么我的矩阵大小会翻倍?我可以阻止 R 这样做吗? 示例:

set.seed(42)
a <- matrix(rbinom(10000,2,0.45),ncol=10)
object.size(a)/1024/1024
# 0.038 Mb
# I want to have a mean smaller than 1 in every column
# Thus, swap 0's and 2' in every column where mean is bigger than 1
swapcol <- colMeans(a)>1
swapmat <- a[,swapcol]
tracemem(a)
# [1] "<0x7fe9d2f16f50>"
a[,swapcol][swapmat==2] <- 0
# tracemem[0x7fe9d2f16f50 -> 0x7fe9c2d98b90]: 
# tracemem[0x7fe9c2d98b90 -> 0x7fe9c2d2bf70]: 
a[,swapcol][swapmat==0] <- 2
# tracemem[0x7fe9c2d2bf70 -> 0x7fe9c2e1b460]: 
object.size(a)/1024/1024
# 0.076 Mb, memory occupation doubled

我知道矩阵可能会被复制以替换值,但为什么它会变大? (replace() 导致相同的行为)我阅读了 Hadley 书中关于 Memory usageR Documentation 的章节,但我仍然想知道为什么会这样。我想如果我想扩大矩阵,R 可能需要操作系统的更多空间,但为什么要两倍空间呢?对于大型矩阵,这甚至是正确的(具有相同的因素),使我的系统交换内存(因此与潜在的节省时间的效果相矛盾)。

感谢任何提示!

【问题讨论】:

  • 02 是浮点数(即双精度数)。您的矩阵包含整数。使用0L2L 强制R 将它们视为整数。
  • 谢谢!有效。然而有点出乎意料......我还有很多东西要学。如果您将其表述为非常简短的答案,我会接受。
  • 您也可能对typeof() 感兴趣,如typeof(swapmat)typeof(4); typeof(4L); typeof(1:4) 等。
  • @GavinSimpson -- 是的。在我看到你的答案之前发布。看到这两个并排(并再次想知道他们两个之间的区别是什么)确实激发了我不久前重新访问this fairly interesting answer
  • @Andarin R 必须对这些值做一些假设,因为我们在创建对象时不会在 R 中键入对象,这与其他一些语言不同。惯例是假设双精度数可能是因为对于统计数据,一个人可能会进行计算,要求他的数据在各种例程中都是双精度数。

标签: r memory-management matrix replace


【解决方案1】:

问题在于02不是 整数,而是 doubles 就 R 而言,当您将它们分配给矩阵 @987654323 @ 的元素,您强制 R 使用双精度存储修改后的 a,这会增加对象的内存大小。原始的a 使用整数存储,每个整数占用更少的内存。你可以通过storage.mode()看到这个:

set.seed(42)
a <- matrix(rbinom(10000,2,0.45),ncol=10)

> storage.mode(a)
[1] "integer"

swapcol <- colMeans(a)>1
swapmat <- a[,swapcol]
a[,swapcol][swapmat==2] <- 0
a[,swapcol][swapmat==0] <- 2

> storage.mode(a)
[1] "double"
> format(object.size(a), units = "Kb")
[1] "78.3 Kb"

要解决此问题,请将L 附加到您分配给a 的值;这是 R 的整数表示法。

set.seed(42)
a <- matrix(rbinom(10000,2,0.45),ncol=10)
swapcol <- colMeans(a)>1
swapmat <- a[,swapcol]
a[,swapcol][swapmat==2] <- 0L
a[,swapcol][swapmat==0] <- 2L

> storage.mode(a)
[1] "integer"
> format(object.size(a), units = "Kb")
[1] "39.3 Kb"

【讨论】:

  • 感谢您非常详尽的回答! (以及关于format(object.size)...的提示)我认为它的行为更像C,并且仅在必要时才转换为double(并且2是int),尽管我认为R将所有内容都视为@987654334 @。然而,我的二项式矩阵创建为int,但不是基本ints 的向量让我感到意外(例如typeof(rbinom(3,1,1))typeof(rep(1,3)))。
【解决方案2】:

将评论转换为答案:

02 是浮点数(即双精度数)。您的矩阵包含整数。使用 0L2L 强制 R 将它们视为整数:

set.seed(42)
> a <- matrix(rbinom(10000,2,0.45),ncol=10)
> object.size(a)/1024/1024
0.0383377075195312 bytes

> swapcol <- colMeans(a)>1
> swapmat <- a[,swapcol]
> tracemem(a)
[1] "<0x7fc50ec45e00>"
> a[,swapcol][swapmat==2] <- 0L
tracemem[0x7fc50ec45e00 -> 0x7fc50d839e00]: 

> a[,swapcol][swapmat==0] <- 2L
> object.size(a)/1024/1024
0.0383377075195312 bytes

大小相同!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-13
    • 1970-01-01
    • 2015-08-27
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 1970-01-01
    相关资源
    最近更新 更多