在使用稀疏矩阵的脚本中,
在我的笔记本上,这大约需要7秒钟。 [顺便说一句,显然我没有重复执行同一操作10000次;更新的行和列每次都会改变,但确实会发生大量的更新操作。我之前这么做是为了模拟在真实脚本中执行的操作,并获得可以与更快的解决方案进行比较的可测时间。]
有什么想法/建议吗?
附言 我过去也遇到过类似的问题,但是是不同的情况;由于我的活动历史只能追溯到几个月前,所以找不回来了。
编辑 好的,我找到了如何检索所有旧帖子的方法,并发现我这里描述的问题并未被涉及。
编辑2 - 跟进/pseudospin的建议
也许这个例子有点误导人,因为通常我将有更高的i和 j 的最大值,所以从
需要使用我的真实数据进行测试...
因此,与GKi的结果一致,密集矩阵法远远是最快的方法,但代价是巨大的存储空间。
另一方面,最初使用的模拟数据对于方法给出了非常不同的结果,实际数据表明该方法在这4种方法中排名第二。 不幸的是,这看起来像一个进退两难的局面:为了进行快速编辑,我需要使用密集矩阵,但密集矩阵需要太多的内存,因此我需要使用稀疏矩阵,但是编辑速度慢 :( 也许我需要重新考虑pseudospin的原始建议,并使用矩阵每行的稀疏向量。为此,我需要找出如何通过间接引用(字符串)引用存储的R对象。
profvis
分析表明,稀疏矩阵元素的更新是该过程中最慢的步骤,慢1个数量级。我需要了解是否可以更好(尤其是更快),希望有人能指导我去哪里找或提供建议。这里是一些R
代码,可以重现我脚本的“关键”部分:require(Matrix)
m <- new("dgCMatrix", i = c(0L, 1L, 2L, 6L, 8L, 0L, 1L, 2L, 5L, 6L,
7L, 0L, 1L, 2L, 7L, 3L, 4L, 3L, 4L, 5L, 6L, 1L, 4L, 5L, 6L, 0L,
1L, 4L, 5L, 6L, 8L, 10L, 1L, 2L, 7L, 0L, 6L, 8L, 9L, 10L, 6L,
9L, 10L), p = c(0L, 5L, 11L, 15L, 17L, 21L, 25L, 32L, 35L, 38L,
40L, 43L), Dim = c(11L, 11L), Dimnames = list(c("1", "2", "3",
"4", "5", "6", "7", "8", "9", "10", "11"), c("1", "2", "3", "4",
"5", "6", "7", "8", "9", "10", "11")), x = c(2, 1, 1, 1, 1, 1,
3, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1,
1, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2), factors = list())
system.time(for (i in 1:10000) m[7,c(1,5,6,7)] <- c(0,0,1,0))
在我的笔记本上,这大约需要7秒钟。 [顺便说一句,显然我没有重复执行同一操作10000次;更新的行和列每次都会改变,但确实会发生大量的更新操作。我之前这么做是为了模拟在真实脚本中执行的操作,并获得可以与更快的解决方案进行比较的可测时间。]
有什么想法/建议吗?
附言 我过去也遇到过类似的问题,但是是不同的情况;由于我的活动历史只能追溯到几个月前,所以找不回来了。
编辑 好的,我找到了如何检索所有旧帖子的方法,并发现我这里描述的问题并未被涉及。
编辑2 - 跟进/pseudospin的建议
require(Matrix)
require(data.table)
m <- new("dgCMatrix", i = c(0L, 1L, 2L, 6L, 8L, 0L, 1L, 2L, 5L, 6L,
7L, 0L, 1L, 2L, 7L, 3L, 4L, 3L, 4L, 5L, 6L, 1L, 4L, 5L, 6L, 0L,
1L, 4L, 5L, 6L, 8L, 10L, 1L, 2L, 7L, 0L, 6L, 8L, 9L, 10L, 6L,
9L, 10L), p = c(0L, 5L, 11L, 15L, 17L, 21L, 25L, 32L, 35L, 38L,
40L, 43L), Dim = c(11L, 11L), Dimnames = list(c("1", "2", "3",
"4", "5", "6", "7", "8", "9", "10", "11"), c("1", "2", "3", "4",
"5", "6", "7", "8", "9", "10", "11")), x = c(2, 1, 1, 1, 1, 1,
3, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1,
1, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2), factors = list())
ms <- summary(m)
ms <- ms[order(ms$i,ms$j),]
msdt <- data.table(ms)
time_1 <- system.time(for (i in 1:5000) m[7,c(1,5,7,9)] <- c(0,0,1,0))
cat("\ntime_1 =", time_1)
time_2 <- system.time(for (i in 1:5000) ms[(ms$i == 7) & (ms$j %in% c(1,5,7,9)),"x"] <- c(0,0,1,0))
cat("\ntime_2 =", time_2)
time_3 <- system.time(for (i in 1:5000) msdt[(i == 7) & (j %in% c(1,5,7,9)),"x" := c(0,0,1,0)])
cat("\ntime_3 =", time_3)
这给出了:
time_1 = 2.86 0 2.86 NA NA
time_2 = 0.23 0 0.24 NA NA
time_3 = 1.2 0.02 1.22 NA NA
也许这个例子有点误导人,因为通常我将有更高的i和 j 的最大值,所以从
data.table
子集取数据可能比从 data.frame
子集取数据更有效率。需要使用我的真实数据进行测试...
编辑3 - 使用GKi建议的密集矩阵方法尝试真实数据测试
真实数据(太大无法粘贴在此):m
是一个稀疏的 5828 x 5828 的矩阵;其中 302986/33965584 = 0.9% 是填充的(因此是稀疏的)。它占用4.4 MB。对应的密集矩阵 dm = as.matrix(m)
占用272.5MB。
测试更新方法 sparseMatrix
(1), data.frame
(2), data.table
(3) 和密集矩阵 (4) 显示如下:
time_1 = 10.25 3.19 13.72 NA NA
time_2 = 41.32 10.94 52.52 NA NA
time_3 = 35.64 7.44 43.34 NA NA
time_4 = 0.05 0.03 0.08 NA NA
因此,与GKi的结果一致,密集矩阵法远远是最快的方法,但代价是巨大的存储空间。
另一方面,最初使用的模拟数据对于方法给出了非常不同的结果,实际数据表明该方法在这4种方法中排名第二。 不幸的是,这看起来像一个进退两难的局面:为了进行快速编辑,我需要使用密集矩阵,但密集矩阵需要太多的内存,因此我需要使用稀疏矩阵,但是编辑速度慢 :( 也许我需要重新考虑pseudospin的原始建议,并使用矩阵每行的稀疏向量。为此,我需要找出如何通过间接引用(字符串)引用存储的R对象。
data.table
实现可编辑的稀疏矩阵是否比Matrix
包更好。可能需要考虑实际项目来找出最佳方法,但是猜测,将行存储为单独的稀疏向量可能是高效的方法? - pseudospin