Как использовать 8 ядер при работе тематической модели LDA в R - PullRequest
0 голосов
/ 08 ноября 2018

Я использую модель темы Latent Dirichlet в R, используя следующий код:

for(k in 2:30) {
    ldaOut <-LDA(dtm,k, method="Gibbs", 
                 control=list(nstart=nstart, seed = seed, best=best, 
                              burnin = burnin, iter = iter, thin=thin))
    assign(paste("ldaOut", k, sep = "_"), ldaOut)
}

DTM имеет 12 миллионов элементов, и каждый цикл занимает в среднем до двух часов. Между тем, R использует только 1 из 8 моих логических процессоров (у меня i7-2700K CPU @ 3,50 ГГц с 4 ядрами). Как я могу сделать так, чтобы R использовал всю вычислительную мощность, доступную, когда я запускаю одну тематическую модель LDA или при использовании цикла (как в этом коде)?

Спасибо

РЕДАКТИРОВАТЬ: следуя совету gc_, я использовал следующий код:

library(doParallel)

    n.cores <- detectCores(all.tests = T, logical = T) 
    cl <- makePSOCKcluster(n.cores) 

doParallel::registerDoParallel(cl)

burnin <- 4000 
iter <- 2000
thin <- 500 
seed <-list(2003,10,100,10005,765)
nstart <- 5 
best <- TRUE 

var.shared <- c("ldaOut", "dtm", "nstart", "seed", "best", "burnin", "iter", "thin", "n.cores")
library.shared <- "topicmodels" # Same for library or functions.


ldaOut <- c()

    foreach (k = 2:(30 / n.cores - 1), .export = var.shared, .packages = library.shared) %dopar% {
        ret <- LDA(dtm, k*n.cores , method="Gibbs", 
                   control=list(nstart=nstart, seed = seed, best=best, 
                                burnin = burnin, iter = iter, thin=thin))
        assign(paste("ldaOut", k*n.cores, sep = "_"), ret)
    }

Код выполнялся без ошибок, но теперь есть 16 процессов «R для интерфейса Windows», 15 из которых используют 0% ЦП, а 1 использует 16-17% ... И когда процесс завершился я получил это сообщение:

A LDA_Gibbs topic model with 16 topics.

    Warning messages:
    1: In e$fun(obj, substitute(ex), parent.frame(), e$data) :
      already exporting variable(s): dtm, nstart, seed, best, burnin, iter, thin, n.cores
    2: closing unused connection 10 (<-MyPC:11888) 
    3: closing unused connection 9 (<-MyPC:11888) 
    4: closing unused connection 8 (<-MyPC:11888) 
    5: closing unused connection 7 (<-MyPC:11888) 
    6: closing unused connection 6 (<-MyPC:11888) 
    7: closing unused connection 5 (<-MyPC:11888) 
    8: closing unused connection 4 (<-MyPC:11888) 
    9: closing unused connection 3 (<-MyPC:11888) 

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

Я думаю, что lda трудно сделать параллельно, так как каждый цикл использует результат предыдущего цикла.

Так что, чтобы ускорить процесс, вы можете imo

- reduce your dtm
- use faster libraries e.g. vowpal wabbit 
- use faster hardware e.g. aws

Если вы оптимизируете для «гиперпараметров», таких как альфа, эта, Burnin и т. Д., Вы можете запустить полный lda с разными гиперпараметрами на каждом ядре.

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

Вы можете использовать библиотеку doParallel

library(doParallel)

Чтобы узнать количество ядер вашего компьютера:

n.cores <- detectCores(all.tests = T, logical = T) 

Вы можете увидеть различие между логическим и физическим ядрами.

Теперь вам нужно назначить ядро ​​и настроить весь процесс:

cl <- makePSOCKcluster(n.cores) 
doParallel::registerDoParallel(cl)

Вы можете создать больше процессов, чем у вас есть ядер на вашем компьютере. Поскольку R создает новые процессы, вам нужно определить библиотеку и переменные, которыми вы хотите поделиться с работниками.

var.shared <- c("ldaOut", "dtm", "nstart", "seed", "best", "burnin", "iter", "thin", "n.cores")
library.shared <- c() # Same for library or functions.

Тогда цикл изменится на:

 ldaOut <- #Init the output#

 foreach (k = 2:(30 / n.cores - 1), .export = var.shared, .packages = library.shared)) %dopar% {
      ret <- LDA(dtm, k*n.cores , method="Gibbs", 
                     control=list(nstart=nstart, seed = seed, best=best, 
                                  burnin = burnin, iter = iter, thin=thin))
      assign(paste("ldaOut", k*n.cores, sep = "_"), ret)
}

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

...