指定されたシード (常に指定されたシード) を持つ乱数の生成を必要とするアプリを実装できるように、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)