Размеры объектов увеличиваются после передачи их функциям - PullRequest
0 голосов
/ 09 ноября 2018

Я делаю несколько графиков из больших наборов данных. В этом коде размеры результирующих требуемых объектов графика очень малы, но увеличенное использование памяти намного больше.

Мои выводы на данный момент заключаются в том, что увеличение использования памяти, по-видимому, связано с несколькими объектами. В частности, значение объекта tab_ind не изменяется после процесса построения графика (проверяется с помощью функции identical()), но его размер значительно увеличивается после процесса (проверяется с помощью функции object.size()). Единственное, что я делаю с tab_ind во время процесса, это передаю его функциям в качестве аргументов.


Воспроизводимый пример

Размер симуляции можно контролировать, изменяя N. В конце прогона печатаются изменение размеров и проверка идентичности tab_ind.

library(data.table)
library(magrittr)
library(ggplot2)

N <- 6000

set.seed(runif(1, 0, .Machine$integer.max) %>% ceiling)

logit <- function(x) {return(log(x/(1-x)))}
invLogit <- function(x) {return(exp(x)/(1+exp(x)))}

tab_dat <- data.table(datasetID = seq(N), MIX_MIN_SUCCESS = sample(c(0, 1), N, replace = T), MIX_ALL = sample(c(0, 1), N, replace = T))
tab_dat[MIX_MIN_SUCCESS == 0, MIX_ALL := 0]
n <- sample(20:300, N, replace = T)
tab_ind <- data.table(
  datasetID = rep(seq(N), times = n),
  SIM_ADJ_PP1 = runif(sum(n), 0.00001, 0.99999),
  MIX_ADJ_PP1 = runif(sum(n), 0.00001, 0.99999)
)
tab_ind[, c("SIM_ADJ_LOGIT_PP1", "MIX_ADJ_LOGIT_PP1") := list(logit(SIM_ADJ_PP1), logit(MIX_ADJ_PP1))]

checkMem_gc <- function(status) {
  print(status)
  print(memory.size())
  gc()
  print(memory.size())
} 

## Individual bins for x and y
tab_by_bin_idxy <- function(dt, x, y, xNItv, yNItv, by = "quantile") {
  #Binning
  if (by == "even") {
    checkMem_gc("start x-y breaks")
    checkMem_gc("start x breaks")
    minN = dt[, min(get(x), na.rm = T)]
    checkMem_gc("after x min")
    maxN = dt[, max(get(x), na.rm = T)]
    checkMem_gc("after x max")
    xBreaks = seq(minN, maxN, length.out = xNItv + 1)
    checkMem_gc("after seq")
    checkMem_gc("after x breaks")
    yBreaks = dt[, seq(min(get(y), na.rm = T), max(get(y), na.rm = T), length.out = yNItv + 1)]
    checkMem_gc("after y breaks")
  } else if (by == "quantile") {
    xBreaks = dt[, quantile(get(x), seq(0, 1, length.out = xNItv + 1), names = F)]
    yBreaks = dt[, quantile(get(y), seq(0, 1, length.out = yNItv + 1), names = F)]
  } else {stop("type of 'by' not support")}
  checkMem_gc("after x-y breaks")
  xbinCode = dt[, .bincode(get(x), breaks = xBreaks, include.lowest = T)]
  checkMem_gc("after x binCode")
  xbinMid = sapply(seq(xNItv), function(i) {return(mean(xBreaks[c(i, i+1)]))})[xbinCode]
  checkMem_gc("after x binMid")
  ybinCode = dt[, .bincode(get(y), breaks = yBreaks, include.lowest = T)]
  checkMem_gc("after y binCode")
  ybinMid = sapply(seq(yNItv), function(i) {return(mean(yBreaks[c(i, i+1)]))})[ybinCode]
  checkMem_gc("after y binMid")
  #Creating table
  tab_match = CJ(xbinCode = seq(xNItv), ybinCode = seq(yNItv))
  checkMem_gc("after tab match")
  tab_plot = data.table(xbinCode, xbinMid, ybinCode, ybinMid)[
    tab_match, .(xbinMid = xbinMid[1], ybinMid = ybinMid[1], N = .N), keyby = .EACHI, on = c("xbinCode", "ybinCode")
    ]
  checkMem_gc("after tab plot")
  colnames(tab_plot)[colnames(tab_plot) == "xbinCode"] = paste0(x, "_binCode")
  colnames(tab_plot)[colnames(tab_plot) == "xbinMid"] = paste0(x, "_binMid")
  colnames(tab_plot)[colnames(tab_plot) == "ybinCode"] = paste0(y, "_binCode")
  colnames(tab_plot)[colnames(tab_plot) == "ybinMid"] = paste0(y, "_binMid")
  checkMem_gc("after col name")
  rm(list = c("xBreaks", "yBreaks", "xbinCode", "ybinCode", "xbinMid", "ybinMid", "tab_match"))
  checkMem_gc("after rm")
  #Returning table
  return(tab_plot)
}

tab_by_obin_x_str_y <- function(dt, x, y, width, Nbin, by = "even") {
  #Binning
  if (by == "even") {
    xLLim = dt[, seq(min(get(x), na.rm = T), max(get(x), na.rm = T) - width, length.out = Nbin)]
    xULim = dt[, seq(min(get(x), na.rm = T) + width, max(get(x), na.rm = T), length.out = Nbin)]
  } else if (by == "quantile") {
    xLLim = dt[, quantile(get(x), seq(0, 1 - width, length.out = Nbin), names = F)]
    xULim = dt[, quantile(get(x), seq(width, 1, length.out = Nbin), names = F)]
  } else {stop("type of 'by' not support")}
  xbinMid = (xLLim + xULim) / 2
  #summarizing y
  tab_out <- sapply(seq(Nbin), function(i) {
    dt[get(x) >= xLLim[i] & get(x) <= xULim[i], c(mean(get(y), na.rm = T), sd(get(y), na.rm = T),
                                                  quantile(get(y), c(0.025, 0.975), names = F))]
  }) %>% t %>% as.data.table %>% set_colnames(., c("mean", "sd", ".025p", ".975p")) %>%
    cbind(data.table(binCode = seq(Nbin), xLLim, xbinMid, xULim), .)
  tab_out[, c("mean_plus_1sd", "mean_minus_1sd") := list(mean + sd, mean - sd)]
  return(tab_out)
}

plotEnv <- new.env()
backupEnv <- new.env()

gc()
gc()
checkMem_gc("Starting memory size checking")
start.mem.size <- memory.size()
start_ObjSizes <- sapply(ls(), function(x) {object.size(get(x))})
start_tab_ind <- tab_ind
start_tab_ind_size <- object.size(tab_ind)
dummyEnv <- new.env()
with(dummyEnv, {
  ## Set function for analyses against SIM_PP1
  fcn_SIM_PP1 <- function(dt, newTab = T) {
    dat_prob = tab_by_bin_idxy(dt, x = "SIM_ADJ_PP1", y = "MIX_ADJ_PP1", xNItv = 50, yNItv = 50, by = "even")
    checkMem_gc("after tab prob")
    dat_logit = tab_by_bin_idxy(dt, x = "SIM_ADJ_LOGIT_PP1", y = "MIX_ADJ_LOGIT_PP1",
                                xNItv = 50, yNItv = 50, by = "even")
    checkMem_gc("after tab logit")

    if ((!newTab) && exists("summarytab_logit_SIM_ADJ_PP1", where = backupEnv) && 
        exists("summarytab_prob_SIM_ADJ_PP1", where = backupEnv)) {
      summarytab_logit = get("summarytab_logit_SIM_ADJ_PP1", envir = backupEnv)
      summarytab_prob = get("summarytab_prob_SIM_ADJ_PP1", envir = backupEnv)
    } else {
      summarytab_logit = tab_by_obin_x_str_y(dt, x = "SIM_ADJ_LOGIT_PP1", y = "MIX_ADJ_LOGIT_PP1",
                                             width = 0.05, Nbin = 1000, by = "even") 
      summarytab_prob = summarytab_logit[, .(
        binCode, invLogit(xLLim), invLogit(xbinMid), invLogit(xULim), invLogit(mean), sd,
        invLogit(`.025p`), invLogit(`.975p`), invLogit(mean_plus_1sd), invLogit(mean_minus_1sd)
      )] %>% set_colnames(colnames(summarytab_logit))
      assign("summarytab_logit_SIM_ADJ_PP1", summarytab_logit, envir = backupEnv)
      assign("summarytab_prob_SIM_ADJ_PP1", summarytab_prob, envir = backupEnv)
    }
    checkMem_gc("after summary tab")

    plot_prob <- ggplot(dat_prob, aes(x = SIM_ADJ_PP1_binMid)) +
      geom_vline(xintercept = 1, linetype = "dotted") +
      geom_hline(yintercept = 1, linetype = "dotted") +
      geom_abline(slope = 1, intercept = 0, size = 1.5, linetype = "dashed", alpha = 0.5) +
      geom_point(aes(y = MIX_ADJ_PP1_binMid, size = N), alpha = 0.5, na.rm = T) +
      geom_line(data = summarytab_prob, aes(x = xbinMid, y = mean), size = 1.25, color = "black", na.rm = T) +
      geom_line(data = summarytab_prob, aes(x = xbinMid, y = mean_plus_1sd), size = 1.25, color = "blue", na.rm = T, linetype = "dashed") +
      geom_line(data = summarytab_prob, aes(x = xbinMid, y = mean_minus_1sd), size = 1.25, color = "blue", na.rm = T, linetype = "dashed") +
      scale_size_continuous(range = c(0.5, 5)) +
      scale_x_continuous(name = "Simulated PP", breaks = seq(0, 1, 0.25),
                         labels = c("0%", "25%", "50%", "75%", "100%")) +
      scale_y_continuous(name = "Estimated PP", limits = c(0, 1), breaks = seq(0, 1, 0.25),
                         labels = c("0%", "25%", "50%", "75%", "100%")) +
      theme_classic() +
      theme(axis.title = element_text(size = 18),
            axis.text = element_text(size = 16))

    checkMem_gc("after plot prob")
    rm(dat_prob)
    rm(summarytab_prob)
    checkMem_gc("after removing dat_prob and summary_prob")

    plot_logit <- ggplot(dat_logit, aes(x = SIM_ADJ_LOGIT_PP1_binMid)) +
      geom_abline(slope = 1, intercept = 0, size = 1.5, linetype = "dashed", alpha = 0.5) +
      geom_point(aes(y = MIX_ADJ_LOGIT_PP1_binMid, size = N), alpha = 0.5, na.rm = T) +
      geom_line(data = summarytab_logit, aes(x = xbinMid, y = mean), size = 1.25, color = "black", na.rm = T) +
      geom_line(data = summarytab_logit, aes(x = xbinMid, y = mean_plus_1sd), size = 1.25, color = "blue", na.rm = T, linetype = "dashed") +
      geom_line(data = summarytab_logit, aes(x = xbinMid, y = mean_minus_1sd), size = 1.25, color = "blue", na.rm = T, linetype = "dashed") +
      scale_size_continuous(range = c(0.5, 5)) +
      scale_x_continuous(name = "Simulated LOGIT PP1",
                         breaks = c(0.00001, 0.001, 0.05, 0.5, 0.95, 0.999, 0.99999) %>% logit,
                         labels = c("0.001%", "0.1%", "5%", "50%", "95%", "99.9%", "99.999%")) +
      scale_y_continuous(name = "Estimated LOGIT PP1", limits = c(-12, 12),
                         breaks = c(0.00001, 0.001, 0.05, 0.5, 0.95, 0.999, 0.99999) %>% logit,
                         labels = c("0.001%", "0.1%", "5%", "50%", "95%", "99.9%", "99.999%")) +
      theme_classic() +
      theme(axis.title = element_text(size = 18),
            axis.text = element_text(size = 16))

    checkMem_gc("after plot logit")
    rm(summarytab_logit)
    rm(dat_logit)
    checkMem_gc("after removing dat_logit and summary_logit")

    return(list(plot_prob, plot_logit))
  }

  checkMem_gc("after defining function")

  ## Tabling

  tab_stat <- tab_ind[, c("MIX_MIN_SUCCESS", "MIX_ALL") := list(
    tab_dat[tab_ind[, datasetID], MIX_MIN_SUCCESS],
    tab_dat[tab_ind[, datasetID], MIX_ALL]
  )]
  checkMem_gc("after new tab_stat")

  tab_stat_MIN_SUCCESS <- tab_stat[MIX_MIN_SUCCESS == 1]
  checkMem_gc("after new new tab_stat_MIN_SUCCESS")

  tab_stat_MIX_ALL <- tab_stat[MIX_ALL == 1]
  checkMem_gc("after new tab_stat_MIX_ALL")

  # Generating ggplot objects
  print("--- start lst full ---")
  lst_full <- fcn_SIM_PP1(tab_stat, newTab = F)
  checkMem_gc("after lst full")
  rm(tab_stat)
  checkMem_gc("after rm tab_stat")

  print("--- start lst MIN_SUCCESS ---")
  lst_MIN_SUCCESS <- fcn_SIM_PP1(tab_stat_MIN_SUCCESS, newTab = F)
  checkMem_gc("after lst MIN_SUCCESS")
  rm(tab_stat_MIN_SUCCESS)
  checkMem_gc("after rm tab_MIN_SUCCESS")

  print("--- start lst MIX_ALL ---")
  lst_MIX_ALL <- fcn_SIM_PP1(tab_stat_MIX_ALL, newTab = F)
  checkMem_gc("after lst MIX_ALL")
  rm(tab_stat_MIX_ALL)
  checkMem_gc("after rm tab_stat_MIX_ALL")

  ## Start plotting
  print("--- Start plotting ---")
  assign("full_sp_MIX_ADJ_PP1_vs_SIM_ADJ_PP1", lst_full[[1]], envir = plotEnv)
  checkMem_gc("after assign1")
  assign("full_sp_MIX_ADJ_LOGIT_PP1_vs_SIM_ADJ_LOGIT_PP1", lst_full[[2]], envir = plotEnv)
  checkMem_gc("after assign2")
  rm(lst_full)
  checkMem_gc("after removing lst_full")
  assign("MIN_SUCCESS_sp_MIX_ADJ_PP1_vs_SIM_ADJ_PP1", lst_MIN_SUCCESS[[1]], envir = plotEnv)
  checkMem_gc("after assign3")
  assign("MIN_SUCCESS_sp_MIX_ADJ_LOGIT_PP1_vs_SIM_ADJ_LOGIT_PP1", lst_MIN_SUCCESS[[2]], envir = plotEnv)
  checkMem_gc("after assign4")
  rm(lst_MIN_SUCCESS)
  checkMem_gc("after removing lst_MIN_SUCCESS")
  assign("MIX_ALL_sp_MIX_ADJ_PP1_vs_SIM_ADJ_PP1", lst_MIX_ALL[[1]], envir = plotEnv)
  checkMem_gc("after assign5")
  assign("MIX_ALL_sp_MIX_ADJ_LOGIT_PP1_vs_SIM_ADJ_LOGIT_PP1", lst_MIX_ALL[[2]], envir = plotEnv)
  checkMem_gc("after assign6")
  rm(lst_MIX_ALL)
  checkMem_gc("after removing lst_MIX_ALL")
})

checkMem_gc("--- Finishing ---")
rm(dummyEnv)
gc()
checkMem_gc("After clean up")
final.mem.size <- memory.size()
end_ObjSizes <- sapply(ls(), function(x) {object.size(get(x))})
print("")
print("")
print("--- The sizes of all objects (under .GlobalEnv) BEFORE the graph plotting process ---")
print("--- (Before the process starts, all existing objects are stored under .GlobalEnv) ---")
print(start_ObjSizes)
print("")
print("--- The sizes of all objects (under .GlobalEnv) AFTER the graph plotting process ---")
print(end_ObjSizes)
print("--- I have not altered any existing objects under .GlobalEnv during the process, I only passed them to functions. And yet their sizes increase! ---")
print("--- Let's look at the object tab_ind, which shows the largest inflation in object size ---")
print("--- This is the size of tab_ind BEFORE the process: ---")
print(start_tab_ind_size)
print("--- This is the size of tab_ind AFTER the process: ---")
print(object.size(tab_ind))
print("--- But they are identical (checked using the function identical())! ---")
print(identical(start_tab_ind, tab_ind))
print("")

ОБНОВЛЕННЫЙ ВОСПРОИЗВОДИМЫЙ ПРИМЕР

Это обновленный, более простой воспроизводимый пример. Последний вывод заключается в том, что для создания копии объекта data.table вместо <- следует использовать <- data.table::copy(). Последний только создает указатель на одно и то же значение (т.е. по ссылке). Изменение значения нового указателя изменило бы размер объекта исходного указателя, поэтому размер объекта раздулся, когда я изменил новый указатель. Хотя я не уверен, является ли это единственным источником инфляции использования памяти.

library(data.table)
library(magrittr)
library(ggplot2)

N <- 6000

set.seed(runif(1, 0, .Machine$integer.max) %>% ceiling)

logit <- function(x) {return(log(x/(1-x)))}
invLogit <- function(x) {return(exp(x)/(1+exp(x)))}

tab_dat <- data.table(datasetID = seq(N), MIX_MIN_SUCCESS = sample(c(0, 1), N, replace = T), MIX_ALL = sample(c(0, 1), N, replace = T))
tab_dat[MIX_MIN_SUCCESS == 0, MIX_ALL := 0]
n <- sample(20:300, N, replace = T)
tab_ind <- data.table(
  datasetID = rep(seq(N), times = n),
  SIM_ADJ_PP1 = runif(sum(n), 0.00001, 0.99999),
  MIX_ADJ_PP1 = runif(sum(n), 0.00001, 0.99999)
)

## Individual bins for x and y
tab_by_bin_idxy <- function(dt, x, y, xNItv, yNItv, by = "quantile") {
  #Binning
  if (by == "even") {
    minN = dt[, min(get(x), na.rm = T)]
    maxN = dt[, max(get(x), na.rm = T)]
    xBreaks = seq(minN, maxN, length.out = xNItv + 1)
    yBreaks = dt[, seq(min(get(y), na.rm = T), max(get(y), na.rm = T), length.out = yNItv + 1)]
  } else if (by == "quantile") {
    xBreaks = dt[, quantile(get(x), seq(0, 1, length.out = xNItv + 1), names = F)]
    yBreaks = dt[, quantile(get(y), seq(0, 1, length.out = yNItv + 1), names = F)]
  }
  xbinCode = dt[, .bincode(get(x), breaks = xBreaks, include.lowest = T)]
  xbinMid = sapply(seq(xNItv), function(i) {return(mean(xBreaks[c(i, i+1)]))})[xbinCode]
  ybinCode = dt[, .bincode(get(y), breaks = yBreaks, include.lowest = T)]
  ybinMid = sapply(seq(yNItv), function(i) {return(mean(yBreaks[c(i, i+1)]))})[ybinCode]
  #Creating table
  tab_match = CJ(xbinCode = seq(xNItv), ybinCode = seq(yNItv))
  tab_plot = data.table(xbinCode, xbinMid, ybinCode, ybinMid)[
    tab_match, .(xbinMid = xbinMid[1], ybinMid = ybinMid[1], N = .N), keyby = .EACHI, on = c("xbinCode", "ybinCode")
    ]
  colnames(tab_plot)[colnames(tab_plot) == "xbinCode"] = paste0(x, "_binCode")
  colnames(tab_plot)[colnames(tab_plot) == "xbinMid"] = paste0(x, "_binMid")
  colnames(tab_plot)[colnames(tab_plot) == "ybinCode"] = paste0(y, "_binCode")
  colnames(tab_plot)[colnames(tab_plot) == "ybinMid"] = paste0(y, "_binMid")
  rm(list = c("xBreaks", "yBreaks", "xbinCode", "ybinCode", "xbinMid", "ybinMid", "tab_match"))
  #Returning table
  return(tab_plot)
}

plotEnv <- new.env()
backupEnv <- new.env()

gc()
gc(verbose = T)
start.mem.size <- memory.size()
start_ObjSizes <- sapply(ls(), function(x) {object.size(get(x))})
start_tab_ind <- copy(tab_ind)
start_tab_ind_size <- object.size(tab_ind)
dummyEnv <- new.env()
with(dummyEnv, {
  ## Set function for analyses against SIM_PP1
  fcn_SIM_PP1 <- function(dt, newTab = T) {
    dat_prob = tab_by_bin_idxy(dt, x = "SIM_ADJ_PP1", y = "MIX_ADJ_PP1", xNItv = 50, yNItv = 50, by = "even")

    plot_prob <- ggplot(dat_prob, aes(x = SIM_ADJ_PP1_binMid)) +
      geom_vline(xintercept = 1, linetype = "dotted") +
      geom_hline(yintercept = 1, linetype = "dotted") +
      geom_abline(slope = 1, intercept = 0, size = 1.5, linetype = "dashed", alpha = 0.5) +
      geom_point(aes(y = MIX_ADJ_PP1_binMid, size = N), alpha = 0.5, na.rm = T) +
      scale_size_continuous(range = c(0.5, 5)) +
      scale_x_continuous(name = "Simulated PP", breaks = seq(0, 1, 0.25),
                         labels = c("0%", "25%", "50%", "75%", "100%")) +
      scale_y_continuous(name = "Estimated PP", limits = c(0, 1), breaks = seq(0, 1, 0.25),
                         labels = c("0%", "25%", "50%", "75%", "100%")) +
      theme_classic() +
      theme(axis.title = element_text(size = 18),
            axis.text = element_text(size = 16))

    return(plot_prob)
  }

  ## Tabling
  tab_stat <- copy(tab_ind)
  tab_stat <- tab_stat[, c("MIX_MIN_SUCCESS", "MIX_ALL") := list(
    tab_dat[tab_stat[, datasetID], MIX_MIN_SUCCESS],
    tab_dat[tab_stat[, datasetID], MIX_ALL]
  )]

  tab_stat_MIN_SUCCESS <- tab_stat[MIX_MIN_SUCCESS == 1]

  tab_stat_MIX_ALL <- tab_stat[MIX_ALL == 1]

  # Generating ggplot objects
  lst_full <- fcn_SIM_PP1(tab_stat, newTab = F)
  lst_MIN_SUCCESS <- fcn_SIM_PP1(tab_stat_MIN_SUCCESS, newTab = F)
  lst_MIX_ALL <- fcn_SIM_PP1(tab_stat_MIX_ALL, newTab = F)

  ## Start plotting
  assign("full_sp_MIX_ADJ_PP1_vs_SIM_ADJ_PP1", lst_full, envir = plotEnv)
  assign("MIN_SUCCESS_sp_MIX_ADJ_PP1_vs_SIM_ADJ_PP1", lst_MIN_SUCCESS, envir = plotEnv)
  assign("MIX_ALL_sp_MIX_ADJ_PP1_vs_SIM_ADJ_PP1", lst_MIX_ALL, envir = plotEnv)
})

rm(dummyEnv)
rm(start_tab_ind)
gc(verbose = T)
final.mem.size <- memory.size()
end_ObjSizes <- sapply(ls(), function(x) {object.size(get(x))})

My sessionInfo() при запуске приведенного выше примера:

R version 3.5.0 (2018-04-23)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

Matrix products: default

locale:
  [1] LC_COLLATE=English_Hong Kong SAR.1252  LC_CTYPE=English_Hong Kong SAR.1252    LC_MONETARY=English_Hong Kong SAR.1252
[4] LC_NUMERIC=C                           LC_TIME=English_Hong Kong SAR.1252    

attached base packages:
  [1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
  [1] ggplot2_2.2.1     magrittr_1.5      data.table_1.11.4

loaded via a namespace (and not attached):
  [1] colorspace_1.3-2 scales_0.5.0     compiler_3.5.0   lazyeval_0.2.1   plyr_1.8.4       tools_3.5.0      pillar_1.2.3     gtable_0.2.0    
[9] tibble_1.4.2     yaml_2.1.19      Rcpp_0.12.18     grid_3.5.0       rlang_0.2.1      munsell_0.4.3   

1 Ответ

0 голосов
/ 12 ноября 2018

Мне кажется, вам нужно увеличить --min-vsize=. Зачем? Ошибка cannot allocate vector of size ... означает, что вам нужно увеличить --min-vsize=.

R Вызов командной строки:

R --min-vsize=400M

RStudio Invocation

Создайте или добавьте запись в файл .Renviron.

R_VSIZE=400M

Ссылка: дружественная конфигурация запуска R

Ключевые вопросы:

  • Вы используете 64-битную ОС? [Да / Нет]
  • Вы используете 64-битную версию R? [Да / Нет]

если вы ответите «Нет» на любой из этих вопросов, я бы порекомендовал вам обновить.

Фон

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

Для получения дополнительной информации о R Gotcha, я настоятельно рекомендую вам прочитать:

  • Патрик Бернс, электронная книга R Inferno

Деталь, стоящая за всем этим.

R поддерживает отдельные области для объектов фиксированного и переменного размера. Первый из них выделяется как массив cons-ячеек (программисты на Лиспе будут знать, что они есть, другие могут думать о них как о строительных блоках самого языка, разбирать деревья и т. Д.), А вторые выбрасываются в кучу. 'Vcells' по 8 байт каждый. Каждая ячейка cons занимает 28 байтов в 32-битной сборке R, (обычно) 56 байтов в 64-битной сборке.

Значения по умолчанию (в настоящее время) - это начальная настройка 350 КБ cons-ячеек и 6 МБ векторной кучи. Обратите внимание, что области фактически не выделяются изначально: скорее, эти значения являются размерами для запуска сборки мусора. Эти значения могут быть установлены с помощью параметров командной строки --min-nsize и --min-vsize (или, если они не используются, переменные среды R_NSIZE и R_VSIZE) при запуске R. После этого R будет увеличивать или уменьшать площади в зависимости от использования, никогда не опускаясь ниже начальных значений. Максимальный размер кучи вектора можно установить с помощью переменной окружения R_MAX_VSIZE.

Сколько времени R тратит в сборщике мусора, будет зависеть от этих начальных настроек и от компромисса, который менеджер памяти при заполнении памяти делает между сбором мусора для освобождения неиспользуемой памяти и ростом этих областей. Стратегия, используемая для роста, может быть указана путем установки переменной среды R_GC_MEM_GROW в целочисленное значение от 0 до 3. Эта переменная считывается при запуске. Более высокие значения увеличивают кучу более агрессивно, тем самым сокращая время сборки мусора, но используя больше памяти.

Ref: https://www.rdocumentation.org/packages/base/versions/3.5.1/topics/Memory

Windows

Ограничение адресного пространства составляет 2 ГБ под 32-битной Windows, если только по умолчанию операционной системы не было изменено разрешение на большее (до 3 Гбит). См. https://www.microsoft.com/whdc/system/platform/server/PAE/PAEmem.mspx и https://msdn.microsoft.com/en-us/library/bb613473(VS.85).aspx. В большинстве 64-разрядных версий Windows ограничение для 32-разрядной сборки R составляет 4 ГБ: для самых старых это 2 ГБ. Предел для 64-битной сборки R (установленной ОС) составляет 8 ТБ.

Обычно невозможно выделить до 2 Гбайт одному вектору в 32-битной сборке R даже в 64-битной Windows из-за предварительных выделений Windows в середине адресного пространства.

В Windows R накладывает ограничения на общее выделение памяти, доступное для одного сеанса, поскольку ОС не предоставляет этого способа: см. Memory.size и memory.limit.

...