R Knitr 为什么通过复制使缓存失效?
R Knitr Why is the cache invalidated by copying?
问题
似乎通过将相关文件(.rmd 脚本和缓存目录)复制到另一台计算机,knitr 缓存变得无效。
- 为什么会这样
- 我该如何解决这个问题?
详情
我在两台计算机上进行各种冗长的计算。我认为以下程序可行:
- 在机器 A 上编写报告的第一个版本。(包括一些冗长的计算)
- 将创建的文件,即脚本和缓存目录复制到机器B。
- 继续在机器 B 上编辑报告(无需重新计算,因为所有内容都已缓存)。
这不起作用,将文件复制到 B 后,“knit”会执行完整的重新计算。甚至在执行任何脚本编辑之前都是这种情况,即仅从 A 复制到 B 的行为似乎足以使缓存无效。
为什么要对 B 执行完整的重新计算?据我了解,缓存机制归结为创建和比较哈希。本来希望复制后hash不变。
还有什么我应该另外复制的吗?或者有什么其他方法可以使上述过程有效吗?
例子
任何简单的脚本都可以作为示例,例如下面的脚本:
```{r setup, include=FALSE}
knitr::opts_chunk$set(cache = TRUE)
```
Bla Bla
```{r test}
tmp = sort(runif(1e7))
```
我不知道为什么会发生这种情况的细节,但解决方法很简单:将值显式保存到文件,然后读回它们。您可以使用
saveRDS(x, "x.rds")
将变量x
保存到名为x.rds
的文件中,然后
x <- readRDS("x.rds")
重新读入。如果你想变得更有趣,你可以使用 file.exists("x.rds")
检查 x.rds
是否存在,然后进行完整计算,如果是 saveRDS
returns FALSE
,否则直接读取数据。
编辑添加:如果你真的想知道第一个问题的答案,一种可能的方法是将文件夹从第二台计算机复制回第一台,然后看看它是否在那里工作。如果不是,请对原始目录和两次复制的目录进行二进制比较,看看发生了什么变化。
如果确实有效,可能只是两台计算机上的 RNGkind()
设置不同:保存错误 sample.kind = "Rounding"
是很常见的。不确定缓存是否会使用它。或者可能是不同的包版本或 R 版本:当我更新时 knitr
缓存无效。
更多补充:
如果您想查看发生了什么变化,请在 digest::digest
函数上打开调试,然后调用 knitr::knit("src.Rmd")
。 digest()
为每个缓存块调用,并在其 object
参数中传递一个大列表。如果列表相同,它应该 return 相同的散列值,因此您需要保存这些对象,并在两台计算机之间进行比较。例如,对于上面的玩具示例,我将其传递为 object
:
list(eval = TRUE, echo = TRUE, results = "markup", tidy = FALSE,
tidy.opts = NULL, collapse = FALSE, prompt = FALSE, comment = "##",
highlight = TRUE, size = "normalsize", background = "#F7F7F7",
strip.white = TRUE, cache = 3, cache.path = "cache/", cache.vars = NULL,
cache.lazy = TRUE, dependson = NULL, autodep = FALSE, fig.keep = "high",
fig.show = "asis", fig.align = "default", fig.path = "figure/",
dev = "png", dev.args = NULL, dpi = 72, fig.ext = NULL, fig.width = 7,
fig.height = 7, fig.env = "figure", fig.cap = NULL, fig.scap = NULL,
fig.lp = "fig:", fig.subcap = NULL, fig.pos = "", out.width = NULL,
out.height = NULL, out.extra = NULL, fig.retina = 1, external = TRUE,
sanitize = FALSE, interval = 1, aniopts = "controls,loop",
warning = TRUE, error = TRUE, message = TRUE, render = NULL,
ref.label = NULL, child = NULL, engine = "R", split = FALSE,
purl = TRUE, label = "test", code = "tmp = sort(runif(1e7))",
75L)
问题
似乎通过将相关文件(.rmd 脚本和缓存目录)复制到另一台计算机,knitr 缓存变得无效。
- 为什么会这样
- 我该如何解决这个问题?
详情
我在两台计算机上进行各种冗长的计算。我认为以下程序可行:
- 在机器 A 上编写报告的第一个版本。(包括一些冗长的计算)
- 将创建的文件,即脚本和缓存目录复制到机器B。
- 继续在机器 B 上编辑报告(无需重新计算,因为所有内容都已缓存)。
这不起作用,将文件复制到 B 后,“knit”会执行完整的重新计算。甚至在执行任何脚本编辑之前都是这种情况,即仅从 A 复制到 B 的行为似乎足以使缓存无效。
为什么要对 B 执行完整的重新计算?据我了解,缓存机制归结为创建和比较哈希。本来希望复制后hash不变。
还有什么我应该另外复制的吗?或者有什么其他方法可以使上述过程有效吗?
例子
任何简单的脚本都可以作为示例,例如下面的脚本:
```{r setup, include=FALSE}
knitr::opts_chunk$set(cache = TRUE)
```
Bla Bla
```{r test}
tmp = sort(runif(1e7))
```
我不知道为什么会发生这种情况的细节,但解决方法很简单:将值显式保存到文件,然后读回它们。您可以使用
saveRDS(x, "x.rds")
将变量x
保存到名为x.rds
的文件中,然后
x <- readRDS("x.rds")
重新读入。如果你想变得更有趣,你可以使用 file.exists("x.rds")
检查 x.rds
是否存在,然后进行完整计算,如果是 saveRDS
returns FALSE
,否则直接读取数据。
编辑添加:如果你真的想知道第一个问题的答案,一种可能的方法是将文件夹从第二台计算机复制回第一台,然后看看它是否在那里工作。如果不是,请对原始目录和两次复制的目录进行二进制比较,看看发生了什么变化。
如果确实有效,可能只是两台计算机上的 RNGkind()
设置不同:保存错误 sample.kind = "Rounding"
是很常见的。不确定缓存是否会使用它。或者可能是不同的包版本或 R 版本:当我更新时 knitr
缓存无效。
更多补充:
如果您想查看发生了什么变化,请在 digest::digest
函数上打开调试,然后调用 knitr::knit("src.Rmd")
。 digest()
为每个缓存块调用,并在其 object
参数中传递一个大列表。如果列表相同,它应该 return 相同的散列值,因此您需要保存这些对象,并在两台计算机之间进行比较。例如,对于上面的玩具示例,我将其传递为 object
:
list(eval = TRUE, echo = TRUE, results = "markup", tidy = FALSE,
tidy.opts = NULL, collapse = FALSE, prompt = FALSE, comment = "##",
highlight = TRUE, size = "normalsize", background = "#F7F7F7",
strip.white = TRUE, cache = 3, cache.path = "cache/", cache.vars = NULL,
cache.lazy = TRUE, dependson = NULL, autodep = FALSE, fig.keep = "high",
fig.show = "asis", fig.align = "default", fig.path = "figure/",
dev = "png", dev.args = NULL, dpi = 72, fig.ext = NULL, fig.width = 7,
fig.height = 7, fig.env = "figure", fig.cap = NULL, fig.scap = NULL,
fig.lp = "fig:", fig.subcap = NULL, fig.pos = "", out.width = NULL,
out.height = NULL, out.extra = NULL, fig.retina = 1, external = TRUE,
sanitize = FALSE, interval = 1, aniopts = "controls,loop",
warning = TRUE, error = TRUE, message = TRUE, render = NULL,
ref.label = NULL, child = NULL, engine = "R", split = FALSE,
purl = TRUE, label = "test", code = "tmp = sort(runif(1e7))",
75L)