6

メモ化を使用して、特定の高価な操作の結果をキャッシュし、何度も計算されないようにしたいと考えています。

memoiseR.cacheの両方が私のニーズに合っています。ただし、キャッシングは呼び出し間で堅牢ではないことがわかりました。

私が見ている問題を示す例を次に示します。

library(memoise)

# Memoisation works: b() is called only once
a <- function(x) runif(1)
replicate(5, a())
b <- memoise(a)
replicate(5, b())

# Memoisation fails: mfn() is called every single time
ProtoTester <- proto(
  calc = function(.) {
    fn <- function() print(runif(1))
    mfn <- memoise(fn)
    invisible(mfn())
  }      
)
replicate(5, ProtoTester$calc())

回答に基づいて更新

この質問は、永続的キャッシングと非永続的キャッシングのどちらが使用されているかによって、異なる回答になる可能性があります。非永続的なキャッシュ ( などmemoise) では、単一の割り当てが必要な場合があり、以下の回答が適切な方法です。永続的なキャッシュ ( などR.cache) はセッション全体で機能し、複数の割り当てに対して堅牢である必要があります。上記のアプローチはR.cache. 複数の割り当てにもかかわらず、fnは で 1 回だけ呼び出されR.cacheます。で 2 回呼び出されmemoiseます。

> ProtoTester <- proto(
+     calc = function(.) {
+         fn <- function() print(runif(1))
+         invisible(memoizedCall(fn))
+     }      
+ )
> replicate(5, ProtoTester$calc())
[1] 0.977563
[1] 0.1279641
[1] 0.01358866
[1] 0.9993092
[1] 0.3114813
[1] 0.97756303 0.12796408 0.01358866 0.99930922 0.31148128
> ProtoTester <- proto(
+     calc = function(.) {
+         fn <- function() print(runif(1))
+         invisible(memoizedCall(fn))
+     }      
+ )
> replicate(5, ProtoTester$calc())
[1] 0.97756303 0.12796408 0.01358866 0.99930922 0.31148128

問題があると思った理由は、 に関数としてメソッドをR.cache渡していたからです。メソッドは、困難な方法で環境にバインドされます。この場合、関数をアンバインド (インスタンス化されたメソッドから単純な関数に取得) してから、最初の引数としてオブジェクトを手動で渡す必要があります。次の例は、これがどのように機能するかを示しています ( と は両方ともオブジェクトです:protomemoizedCallprotoR.cacheReportReport$loaderproto

# This will not memoize the call
memoizedCall(Report$loader$download_report)

# This works as intended
memoizedCall(with(Report$loader, download_report), Report$loader)

環境にバインドされた通常の関数では機能するが、インスタンス化されたメソッドR.cacheでは失敗する理由を知りたいです。proto

4

2 に答える 2

5

コードでは、関数が呼び出されるたびに、関数が新たにメモ化されます。次のように機能するはずです。定義されたときに一度だけメモ化されます。

ProtoTester <- proto(
  calc = {
    fn <- function() print(runif(1))
    mfn <- memoise(fn)
    function(.) mfn()
  }
)
replicate(5, ProtoTester$calc())
于 2012-07-06T07:45:02.540 に答える
3

別の解決策は、内部(現在の R セッションの環境で一時的、またはディスク ストレージで永続的) キャッシュ エンジンを持つ (私の)パンダー パッケージevalsからの評価に使用することです。コードに基づく短い例:

library(pander)
ProtoTester <- proto(
  calc = function(.) {
    fn <- function() runif(1)
    mfn <- evals('fn()')[[1]]$result
    invisible(mfn)
  }      
)

evalsキャッシュをオフにしてオンにして実行すると、次のようになります。

> evals.option('cache', FALSE)
> replicate(5, ProtoTester$calc())
[1] 0.7152186 0.4529955 0.4160411 0.1166872 0.8776698

> evals.option('cache', TRUE)
> evals.option('cache.time', 0)
> replicate(5, ProtoTester$calc())
[1] 0.7716874 0.7716874 0.7716874 0.7716874 0.7716874

S3 メソッドに関する警告を軽減するために、evals.option関数 si はすぐに名前が変更されることに注意してください。evalsOptionR CMD check

于 2012-07-06T08:01:44.990 に答える