Параллельная обработка — Foraech и для цикла в R

#r #for-loop #foreach #parallel-processing

Вопрос:

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

«»»

 library("foreach")
library("doParallel")
lambdas=seq(0.01,7, by = 0.01)

cl <- makeCluster(2) # create a cluster with 2 cores
registerDoParallel(cl) # register the cluster
nlambdas <-foreach(i = 1:1, .inorder=FALSE ,.combine = 'cbind', .multicombine=TRUE, .packages = "quantreg") %dopar% {
  first<-rep()
  second<-rep()
  third<-rep()
  fourth<-rep()
  for (m in 1:700) {
    for (j in 1:700) {
      for (n in 1:700) {
        for (k in 1:700) {
          first<-rbind(first,lambdas[m])
          second<-rbind(second,lambdas[j])
          third<-rbind(third,lambdas[n])
          fourth<-rbind(fourth,lambdas[k])
        }      
      }
    }
  }
  lambda_total<-cbind(first,second,third,fourth)
}

stopCluster(cl)
 

«»»

Комментарии:

1. rbind копирует каждый объект и добавляет к нему. Это один из наименее эффективных способов решения этой проблемы. На этом этапе я бы посоветовал прочитать R inferno .

2. Похоже , ваш код очень похож на as.matrix(expand.grid(lambdas, lambdas, lambdas, lambdas))[,4:1] , так что, возможно, это хорошее место для начала. Однако результатом вашего примера будет матрица с 240 100 000 000 строк и четырьмя столбцами, которая вполне может оказаться за пределами возможностей вашего компьютера для создания. Возможно, вам придется сделать шаг назад и подумать о другом подходе к проблеме

3. Спасибо вам обоим.

4. @Miff Я воспользовался вашей рекомендацией, еще раз спасибо. Я работаю на ПК с 64 ГБ оперативной памяти и могу создать матрицу всего 200^4 x 4. Я установил «лямбды» как lambdas=seq(0.01,2, by = 0.01) res=as.matrix(expand.grid(lambdas,lambdas,lambdas,lambdas))[,4:1] . Когда я пытаюсь использовать лямбды=seq(0,01,3, by = 0,01) Это выдает ошибку. Так есть ли какой-нибудь способ сделать это с помощью расщепления?

Ответ №1:

Вам не нужна параллельная обработка, вам просто нужен алгоритм со сложностью менее (O**4) и медленной операцией для составления этой матрицы.

Одна и та же матрица может быть легко построена путем многократной сортировки четырех векторов. Однако в вашем случае, когда 700**4= 2,4 e 11 элементов, это может занять некоторое время.

Я иллюстрирую алгоритм только 7 различными значениями в векторе lambdas (и всего 2401 элементом).

 nsteps = 7
lambdas = seq(0.01,7,(7/nsteps))

h = rep(lambdas,nsteps**3)
i = rep(lambdas,nsteps**3)
j = rep(lambdas,nsteps**3)
k = rep(lambdas,nsteps**3)

ordering = order(k)

k = k[ordering]
k = k[ordering]
k = k[ordering]
k = k[ordering]

j = j[ordering]
j = j[ordering]
j = j[ordering]

i = i[ordering]
i = i[ordering]

h = h[ordering]

lambdas.total = cbind(first=h,second=i,third=j,fourth=k)
 

Если ваша память достаточно велика, чтобы справиться с заказом вектора длиной>10**10, вы можете сделать это за 700 шагов для лямбды в кратчайшие сроки.
Нет необходимости в каких-либо петлях for.

Комментарии:

1. Большое вам спасибо!

2. Дорогой Мартин, моя память недостаточно велика. Есть ли способ, которым я могу сделать это отдельно и объединить позже, чтобы отдать тот же заказ?

3. Вряд ли. Но может быть, есть способ выполнить то, что вы хотите сделать, не создавая эту чудовищную матрицу.

4. Еще раз спасибо вам. Я пытаюсь найти лямбда-значения, которые удовлетворяют некоторым условиям. Если у меня есть лямбда.итого, я собираюсь запустить коды ниже. mylist_095<-rep() cl <- makeCluster(8) registerDoParallel(cl) res05 <-foreach(i = 1:240100000000, .inorder=FALSE ,.combine = 'cbind', .multicombine=TRUE, .packages = "quantreg") %dopar% { f <-rqss(Y~qss(x1,lambda = lambdas.total[i,1]) qss(x2,lambda = lambdas.total[i,2]) qss(x3,lambda = lambdas.total[i,3]) qss(x4,lambda = lambdas.total[i,4]), tau=0.05,data=data) sf<-summary(f) #if condition here mylist_005<-(f$lambdas)

5. Так что, я думаю, другого пути нет.