我在R中有大对象,几乎不适合我的16GB内存(data.table
数据库>> 4M记录,> 400变量。
我希望有一个哈希函数,用于确认加载到R中的数据库没有被修改。
一种快速的方法是使用先前存储的哈希计算数据库的哈希值。
问题是digest::digest
函数复制(序列化)数据,并且只有在序列化所有数据之后,它才会计算散列。对我的硬件来说太迟了......: - (
有没有人知道解决这个问题的方法?
有一个不好的人解决方案:将对象保存到文件中,并计算文件的哈希值。但它引入了大量不必要的开销(我必须确保硬盘上还有一个备用副本,并且需要跟踪所有可能无法自动删除的文件)
答案 0 :(得分:0)
我们的问题跟踪器中已经描述了类似的问题: https://github.com/eddelbuettel/digest/issues/33
当前版本的digest
可以读取文件来计算哈希值。
因此,至少在Linux上,我们可以使用一个命名管道,它将由摘要包读取(在一个线程中),另一方面,数据将由另一个线程写入。
以下代码片段显示了我们如何通过首先以1:5然后6:10提供消化器来计算10个数字的MD5哈希值。
library(parallel)
library(digest)
x <- as.character(1:10) # input
fname <- "mystream.fifo" # choose name for your named pipe
close(fifo(fname, "w")) # creates your pipe if does not exist
producer <- mcparallel({
mystream <- file(fname, "w")
writeLines(x[1:5], mystream)
writeLines(x[6:10], mystream)
close(mystream) # sends signal to the consumer (digester)
})
digester <- mcparallel({
digest(fname, file = TRUE, algo = "md5") # just reads the stream till signalled
})
# runs both processes in parallel
mccollect(list(producer, digester))
unlink(fname) # named pipe removed
更新: Henrik Bengtsson提供了基于期货的修改示例:
library("future")
plan(multiprocess)
x <- as.character(1:10) # input
fname <- "mystream.fifo" # choose name for your named pipe
close(fifo(fname, open="wb")) # creates your pipe if does not exists
producer %<-% {
mystream <- file(fname, open="wb")
writeBin(x[1:5], endian="little", con=mystream)
writeBin(x[6:10], endian="little", con=mystream)
close(mystream) # sends signal to the consumer (digester)
}
# just reads the stream till signalled
md5 <- digest::digest(fname, file = TRUE, algo = "md5")
print(md5)
## [1] "25867862802a623c16928216e2501a39"
# Note: Identical on Linux and Windows
答案 1 :(得分:0)
在紧跟nicola的评论之后,这是专栏观点的基准。似乎并没有太大帮助,至少对于这种规模的人来说,没有帮助。 long_iris
是150行,library(microbenchmark)
#iris
nrow(iris)
microbenchmark(
whole = digest::digest(iris),
cols = digest::digest(lapply(iris, digest::digest))
)
#long iris
long_iris = do.call(bind_rows, replicate(20e3, iris, simplify = F))
nrow(long_iris)
microbenchmark(
whole = digest::digest(long_iris),
cols = digest::digest(lapply(long_iris, digest::digest))
)
是3M(3,000,000)。
#normal
Unit: milliseconds
expr min lq mean median uq max neval cld
whole 12.6 13.6 14.4 14.0 14.6 24.9 100 b
cols 12.5 12.8 13.3 13.1 13.5 23.0 100 a
#long
Unit: milliseconds
expr min lq mean median uq max neval cld
whole 296 306 317 311 316 470 100 b
cols 261 276 290 282 291 429 100 a
结果:
CANVAS