Почему withr :: with_seed и R.utils :: withSeed генерируют разные результаты при использовании в асинхронном коде?

Я пытаюсь изучить асинхронное программирование с использованием R, чтобы я мог реализовать приложение, которое требует генерации случайных чисел с указанными начальными числами ( всегда с указанными начальными числами ). Я использовал для этого, но знаю, что он тоже существует, поэтому подумал, что могу это проверить.

Я знаю, что генерация случайных чисел - сложная задача, поэтому я пытался запустить простые примеры, чтобы попытаться понять, как все работает. Мне нужно:

  • ... чтобы всегда получать одни и те же случайные числа при использовании одного и того же семени
  • ... чтобы получить одни и те же случайные числа с одним и тем же семенем, независимо от того, использую ли я асинхронный фреймворк (чтобы я мог запустить код вне обещания и получить тот же ответ)

В приведенном ниже коде я определяю две функции для генерации случайных чисел, устанавливая начальное число с помощью или.

  • Эти две функции дают мне одинаковый ответ, когда выполняются вне обещания.
  • Эти две функции дают разные ответы при запуске внутри обещания.
  • В версия дает один и тот же ответ внутри или вне обещания.
  • Версия дает разные ответы внутри или вне обещания.

Однако ответы кажутся одинаковыми для нескольких прогонов.

У меня вопрос: почему? Это ошибка в , или я что-то недопонимаю?


Код

      
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)

1 ответ

В future package устанавливает тип RNG по умолчанию на L'Ecuyer-CMRG, тогда как R по умолчанию использует Mersenne-Twister. withr::with_seed сбрасывает тип ГСЧ на "default" (например, Mersenne-Twister), если это явно не указано в .rng_kind аргумент. R.utils::withSeed, с другой стороны, по умолчанию ничего не делает с типом ГСЧ, но тип ГСЧ можно указать с помощью ... список аргументов, переданный в set.seed. В вашем примере s0_R можно изменить следующим образом, чтобы получить одинаковые результаты внутри и за пределами обещания.

      s0_R = function(seed = 1, n = 1){
  R.utils::withSeed(expr = {
    rnorm(n)
  }, seed = seed, kind = "default")
}
Другие вопросы по тегам