Knitr的缓存可以与指针对象一起使用吗?

发布于 2025-02-07 23:45:03 字数 1702 浏览 1 评论 0原文

我正在使用knitr来制作使用Terra软件包绘制地图的文档。这是我的最小.rmd文件:

```{r init, echo=FALSE}
library(knitr)
opts_chunk$set(cache=TRUE)
```

```{r maps}
library(terra)
r = rast(matrix(1:12,3,4))
plot(r)
```

```{r test2}
print(r)
plot(r)
```

第一次运行(通过rmarkDown :: Render(...)),这起作用,创建test_cache文件夹。第二次运行(没有更改)也可以正常运行。如果我对块2进行了较小的更改(例如添加注释)并运行我得到:

Quitting from lines 14-17 (cache.Rmd) 
Error in .External(list(name = "CppMethod__invoke_notvoid", address = <pointer: (nil)>,  : 
  NULL value passed as symbol address

我也从另一个RMD文件中获得了此内容,可能相关:

Quitting from lines 110-115 (work.Rmd) 
Error in x@ptr$readStart() : external pointer is not valid

清除缓存或使用Cache = false运行然后起作用,但是缓存的意义是什么。

我认为这是因为r是某种参考类,它通过通过rcpp分配的某些内存而存在,而Knitr仅在缓存参考,因此当它尝试读取缓存时版本,它获得了对内存的引用,该内存没有创建的对象,该对象与其中的参考有关。所以它失败了。

fwiw a terra栅格对象看起来像这样:

> str(r)
Formal class 'SpatRaster' [package "terra"] with 1 slot
  ..@ ptr:Reference class 'Rcpp_SpatRaster' [package "terra"] with 20 fields
  .. ..$ depth    : num 0
  .. ..$ extent   :Reference class 'Rcpp_SpatExtent' [package "terra"] with 2 fields

是否

> r@ptr
C++ object <0x55ce6fdf2bd0> of class 'SpatRaster' <0x55ce5a6750b0>

有一种方法可以使Knitr Cache与这些对象一起使用?我知道我只能将它们排除在缓存中,但是我的90%的文档正在使用此类对象,这就是我要使用缓存来加快速度的原因。但是,每当我遇到此错误时,我都必须停止,清除缓存,重新开始,我不知道该时间是否值得加速我使用缓存。


r 4.1.1与

> packageVersion("knitr")
[1] ‘1.34’
> packageVersion("rmarkdown")
[1] ‘2.11’
 

I'm using knitr to make a document that uses the terra package to draw maps. Here's my minimal .Rmd file:

```{r init, echo=FALSE}
library(knitr)
opts_chunk$set(cache=TRUE)
```

```{r maps}
library(terra)
r = rast(matrix(1:12,3,4))
plot(r)
```

```{r test2}
print(r)
plot(r)
```

First run (via rmarkdown::render(...)), this works, creates a test_cache folder. Running a second time (with no changes) it also runs fine. If I make a minor change to chunk 2 (eg add a comment) and run I get:

Quitting from lines 14-17 (cache.Rmd) 
Error in .External(list(name = "CppMethod__invoke_notvoid", address = <pointer: (nil)>,  : 
  NULL value passed as symbol address

I've also had this from another Rmd file, probably related:

Quitting from lines 110-115 (work.Rmd) 
Error in x@ptr$readStart() : external pointer is not valid

clearing the cache or running with cache=FALSE then works, but then what's the point of the cache.

I think its because r is some sort of reference class which exists via some memory allocated by Rcpp, and knitr is only caching a reference, so when it tries to read the cached version it gets a reference to memory which doesn't have the object that was created to go with the reference there. So it fails.

FWIW a terra raster object looks like this:

> str(r)
Formal class 'SpatRaster' [package "terra"] with 1 slot
  ..@ ptr:Reference class 'Rcpp_SpatRaster' [package "terra"] with 20 fields
  .. ..$ depth    : num 0
  .. ..$ extent   :Reference class 'Rcpp_SpatExtent' [package "terra"] with 2 fields

and

> r@ptr
C++ object <0x55ce6fdf2bd0> of class 'SpatRaster' <0x55ce5a6750b0>

Is there a way to make the knitr cache work with these objects? I know I could exclude just these from the cache but 90% of my document is working with these sorts of objects and that's the reason I want to use the cache to speed things up. But then every time I get this error I have to stop, clear the cache, start again, and I don't know if that time is worth the speedup I get with the cache.


R 4.1.1 with

> packageVersion("knitr")
[1] ‘1.34’
> packageVersion("rmarkdown")
[1] ‘2.11’
 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

全部不再 2025-02-14 23:45:03

例如,Terra做了一些允许序列化的工作:

library(terra)
f <- system.file("ex/elev.tif", package="terra")
r <- rast(f)

saveRDS(r, "test.rds")
readRDS("test.rds")
[1] "This is a PackedSpatRaster object. Use 'terra::rast()' to unpack it"

readRDS("test.rds") |> rast()
#class       : SpatRaster 
#dimensions  : 90, 95, 1  (nrow, ncol, nlyr)
#resolution  : 0.008333333, 0.008333333  (x, y)
#extent      : 5.741667, 6.533333, 49.44167, 50.19167  (xmin, xmax, ymin, ymax)
#coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#source      : memory 
#name        : elevation 
#min value   :       141 
#max value   :       547 

但是,似乎具有“保存”到RDATA文件的Knitr缓存;在这种情况下,将原始对象存储,在重新加载时,该对象是无效的。

我认为 May 可以通过一些巧妙的使用 hook function < /a>;但这将是如此涉及,以至于它将击败缓存的目的。

terra does some work to allow serialization, for example:

library(terra)
f <- system.file("ex/elev.tif", package="terra")
r <- rast(f)

saveRDS(r, "test.rds")
readRDS("test.rds")
[1] "This is a PackedSpatRaster object. Use 'terra::rast()' to unpack it"

readRDS("test.rds") |> rast()
#class       : SpatRaster 
#dimensions  : 90, 95, 1  (nrow, ncol, nlyr)
#resolution  : 0.008333333, 0.008333333  (x, y)
#extent      : 5.741667, 6.533333, 49.44167, 50.19167  (xmin, xmax, ymin, ymax)
#coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#source      : memory 
#name        : elevation 
#min value   :       141 
#max value   :       547 

But it seems that knitr caches with "save" to an RData file; in that case, the raw object is stored, which won't be valid when reloaded.

I think it may be possible to work around this with some clever use of hook functions; but that would be so involved that it would defeat the purpose of caching.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文