3

指定されたシード (常に指定されたシード) を持つ乱数の生成を必要とするアプリを実装できるように、R を使用して非同期プログラミングを学習しようとしています。私はこれを使ってきましたがR.utils::withSeed、それも存在することを知っているwithr::with_seedので、それをチェックしようと思いました.

乱数の生成が難しいことはわかっているので、簡単な例を実行して、物事がどのように機能するかを理解しようとしました。私は欲しい:

  • ...同じシードを使用する場合、常に同じ乱数を取得する
  • ...非同期フレームワークを使用しているかどうかに関係なく、同じシードで同じ乱数を取得するため (したがって、約束の外でコードを実行して同じ答えを得ることができるはずです)

以下のコードでは、乱数を生成する 2 つの関数を定義し、シードをwithr::with_seedまたはで設定しますR.utils::withSeed

  • これら 2 つの関数は、promise の外で実行すると同じ答えが得られます。
  • これら 2 つの関数は、promise 内で実行すると異なる答えを返します。
  • バージョンは、約束のwithr::with_seed内外で同じ答えを出します。
  • バージョンは、約束のR.utils::withSeed内外で異なる答えを出します。

ただし、答えは複数回の実行で一貫しているようです。

私の質問は:なぜですか?これは のバグR.utils::withSeedですか、それとも何か誤解していますか?


コード


library(future)
library(promises)

plan(multisession)


s0_R = function(seed = 1, n = 1){
  R.utils::withSeed(expr = {
    rnorm(n)
  }, seed = seed)
}

s0_w = function(seed = 1, n = 1){
  withr::with_seed(
     seed = seed,
     code = {
       rnorm(n)
     })
}


s_R = function(seed = 1, n = 1){
  future_promise(
    {
    Sys.sleep(5)
    s0_R(seed, n)
    }, 
    seed = TRUE
  )
} 

s_w = function(seed = 1, n = 1){
  future_promise(
    {
      Sys.sleep(5)
      s0_w(seed, n)
    }, 
    seed = TRUE
  )
} 

s0_R(123) %>%
  paste(" (R.utils::withSeed)\n") %>%
  cat()
# -0.560475646552213  (R.utils::withSeed)

s0_w(123) %>%
  paste(" (withr::with_seed)\n") %>%
  cat()
# -0.560475646552213  (withr::with_seed)

s_R(123) %...>%
  paste(" (async, R.utils::withSeed)\n") %...>%
  cat()

s_w(123) %...>%
  paste(" (async, withr::with_seed)\n") %...>%
  cat()

# Results occur later...
# -0.968592726552943  (async, R.utils::withSeed)
# -0.560475646552213  (async, withr::with_seed)
4

1 に答える 1