Лучший способ управлять большими наборами комбинаций в R

Я надеюсь получить совет по управлению большими наборами комбинаций в R.

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

# fake data
B <- matrix (data=runif(1600, 1.0, 5.0),ncol=40,nrow=40)
diag(B) <- diag(B) - 1 # diagonals are when plants are crossed to themselves and suffer inbreeding depression

Я делаю это, находя среднее значение подмножества матрицы ("perse.hybrid"), содержащей различные комбинации родителей:

SubsetWright <- function (perse.hybrid, subset) {
  return (mean(perse.hybrid[subset,subset]))
}

В идеале я хотел бы найти значения потомства для всех комбинаций 40 родителей, но немного более реалистично я хотел бы найти значения для комбинации от 2 до 11 родителей. Это около 3,5 миллиардов комбинаций.

Я работал над ускорением этого, а также над управлением памятью. Чтобы ускорить его, я настроил его на параллельный запуск задач в кластере Amazon EC2 (обычно это 3 машины m4.10xlarge). Чтобы решить проблему с памятью, я попытался сохранить данные в big.matrix. Тем не менее, я, кажется, натыкаюсь на combn. Обычно, когда я добираюсь до 40, выбираю 8, он вылетает. Смотря htop, я считаю, что это из-за использования памяти.

Я начинающий пользователь R и не совсем понимаю, как в R управляется память. Кажется, я мог бы получить эти ограничения, если бы каким-то образом разделил функцию combn, что могло бы позволить мне запускать ее параллельно и избежать пределы памяти. Или, возможно, есть способ заполнить big.matrix всеми комбинациями без использования combn. У кого-нибудь есть какие-либо стратегии, чтобы предложить? Код ниже. Большое спасибо!

#' Test all combinations of parents to find set of offspring with highest estimated mean.
#'
#' @param perse.hybrid  A matrix of offspring values, with row[i]=col[j]=parent ID 
#' @param min The minimum number of parents to test combinations of
#' @param max The maximum number of parents to test combinations of
#' @param rows Number of rows of top combinations to return, default is to return all rows
#' @param cl cluster to use
#' @return A big.matrix with parent combinations and predicted average offspring values 
TestSyn <- function (perse.hybrid, min, max, rows="all", cl) {

      clusterExport(cl, list("SubsetWright"))

      total <- sum(apply(X=array(min:max),MARGIN=1,FUN=choose,n=nrow(perse.hybrid)))
      n <- nrow(perse.hybrid)
      start <- 1
      stop <- choose(n,min)

      syn.data <- big.matrix(nrow=total,ncol=max+1)

      for (i in min:max)
      {

        #add inbred numbers to syn.data. This seems to be what crashes when i gets large (>7)
        inbreds <- t(combnPrim(1:n,i))
        syn.data[start:stop,1:i] <- inbreds

        #add sythetic values to syn.data
        syn.data[start:stop,max+1]  <- parApply(cl=cl,X=inbreds,MARGIN=1,FUN=SubsetWright,perse.hybrid=perse.hybrid)

                     start <- stop + 1
                     stop <- start + choose(n,i+1) - 1

      }

      # sort by offspring average
      mpermute(x=syn.data,cols=max+1,decreasing=TRUE)

      if (rows == "all") rows <- nrow(syn.data)

      return (syn.data[1:rows,])
    }

РЕДАКТИРОВАТЬ:

При дальнейшем изучении кажется, что комбинаторика может быть частью решения. Сообщение Stackoverflow здесь: Создание очень большого матрица комбинаций строк с помощью combn() и пакета bigmemory

Я проведу некоторое тестирование, чтобы увидеть, держится ли это с большими числами.


person Jared Zystro    schedule 18.09.2015    source источник
comment
Я думаю, вы столкнулись с двумя проблемами: скоростью и передачей R по значению (по сравнению с передачей по ссылке), обе из которых можно решить с помощью (например) Rcpp (CRAN и собственный сайт). Хотя это C++, Дирк, Ромен и компания приложили значительные усилия (и успех, IMO) для преодоления разрыва между R-программистами.   -  person r2evans    schedule 19.09.2015
comment
Что-то еще, что вы, возможно, захотите рассмотреть, я позаимствую у python: генераторы. Вместо того, чтобы создавать огромный список комбинаций, прежде чем что-либо делать, создавайте их по мере необходимости. Это немного расширяет ваш код, но принесет дивиденды в подобных ситуациях.   -  person r2evans    schedule 19.09.2015