R използва само 13% от моя процесор

Система:

Операционна система - Windows 7

RAM -8GB

Процесор -Intel i7

R версия - Винаги я поддържайте актуална

Проблем:

R използва само 13% (т.е. 1 от 8 ядра) от моя процесор Intel i7. Искам да използвам няколко ядра за по-бързо изпълнение на моя код. Но за съжаление не може.

Опити:

Започнах да използвам пакети Parallel, Snow, Snowfall, дори ги конфигурирах да използват 8 ядра, но за съжаление не използвам никоя от функциите за прилагане, за да използвам персонализираните функции, които предоставят (като mcapply, sflapply).

for (i in 1:number.of.accounts){
  if (is.na(s$rev2012[i]) == "FALSE" && is.na(s$rev2013[i]) == "TRUE"){
    loss = rbind(loss, s[i,])
  }
  x = x + 1
}

Рамката с данни "s" в горния код има около 56 000 реда с 14 колони. "rev" означава приходи. Това, което се опитвам да направя, е, че ако има приходи през 2012 г., но не и през 2013 г., тогава сме „загубили“ този клиент. Използвам "x", за да отчитам скоростта.

Изпълнението на тази част от кода отнема много време и все още не съм я оставил да завърши. Когато прекъсвам, виждам, че няма много напредък.

Всяка помощ за отключване на всички ядра за изпълнение на този код би била наистина страхотна.

Благодаря!


person Pragith    schedule 13.03.2014    source източник
comment
Смятам, че е най-лесно да използвам foreach за паралелни изчисления в Windows. Въпреки това, ускоряването, което можете да постигнете чрез паралелизиране, е изключително ограничено (от броя на процесорите). Ако пренапишете кода си към векторизиран подход вместо for цикъл, можете да очаквате ускоряване с порядъци.   -  person Roland    schedule 13.03.2014
comment
Опитайте loss <- s[!is.na(s$rev2012) & is.na(s$rev2013),]. Това не го паралелизира, а вместо това използва векторизираната форма, за която R е оптимизиран.   -  person shadow    schedule 13.03.2014
comment
моля, проверете stackoverflow.com/questions /1395309/   -  person Nachiket Kate    schedule 13.03.2014
comment
Благодаря за отговорите ви. Роланд, можеш ли да ми помогнеш с псевдокод за foreach? Не може да се намери помощ за това. shadow, благодаря за твоя код. Сега го пробвам. Ще се актуализира, ако видя някакви подобрения. Все още търся отключване на моите ядра специално.   -  person Pragith    schedule 13.03.2014
comment
joyofdata.de/blog/   -  person Raffael    schedule 13.03.2014
comment
Благодаря много Рафаел. Ще се опитам да актуализирам тук.   -  person Pragith    schedule 13.03.2014


Отговори (2)


Тъй като R не поддържа първоначално паралелна обработка, трябва да добавите някаква шаблонна плоча към вашия скрипт, за да го накарате да използва всичките 8 ядра.

Разгледайте пакета doParallel. Ето винетка, показваща как да използвате < пакет strong>doParallel. Освен това вижте този въпрос относно как да използвате chunking за ускоряване на производителността.

Това ще изисква да използвате foreach цикъл, който може да бъде успореден с %dopar%, вместо for цикъл.

person Christopher Louden    schedule 13.03.2014
comment
doParallel прави магията, но използва 6+ GB моя RAM (от 8 GB), а използването на процесора е по-малко от 3% (дори не е 13% както преди). Като цяло кодът работи още дълго време (›10 минути) foreach (i = 1:number.of.accounts) %dopar% if (is.na(s$rev2012[i]) == "FALSE" && is.na(s$rev2013[i]) == "TRUE"){ loss = rbind(loss, s[i,]) } - person Pragith; 14.03.2014

Всъщност има два проблема с вашия код. Първо, вие оценявате по редове, като използвате for цикъл. На практика няма обстоятелства, при които това е добра практика в R. Второ, вие добавяте ред по ред към loss. Това също е изключително бавно.

Използването на паралелна обработка ще осигури най-много 8-кратно подобрение. Векторизирането ще осигури повече от 50-кратно подобрение, а използването на data.tables ще подобри още повече.

df <- data.frame(rev2012=sample(c(NA,1:99),56000,replace=T),
                 rev2013=sample(c(NA,1:99),56000,replace=T))
df   <- cbind(df,matrix(rnorm(56000*12),ncol=12))

for.loop <- function(){
  loss <- c()
  for (i in 1:nrow(df))
    if (is.na(df$rev2012[i]) == "FALSE" && is.na(df$rev2013[i]) == "TRUE") loss = rbind(loss, df[i,])
}

df.vectorized <- function(){
  loss <- with(df,df[!is.na(rev2012) & is.na(rev2013),])
}

library(data.table)
dt <- function(){
  dt <- data.table(df)
  setkey(dt,rev2012,rev2013)
  loss <- dt[!is.na(rev2012)&is.na(rev2013)]
}

library(microbenchmark)
microbenchmark(for.loop(),df.vectorized(),dt(),times=10)
# Unit: milliseconds
#             expr        min         lq     median         uq        max neval
#       for.loop() 3141.53686 3431.99529 3620.90536 3845.81394 3875.92435    10
#  df.vectorized()   38.76076   55.01082   58.97976   64.19538   67.33192    10
#             dt()   28.20870   31.10005   40.54224  165.20777  184.48776    10

Причината, поради която таблиците с данни се подобряват само с около 33% в сравнение с подхода на векторизираната рамка от данни, е, че 56 000 реда не са чак толкова големи. Ако df имаше >1e6 редове, използването на data.table определено би било най-добрият вариант.

person jlhoward    schedule 13.03.2014
comment
Добавените към data.table ме притесняват :( - person Dason; 13.03.2014
comment
Накрая имате data.tables вместо data.table няколко пъти. - person Dason; 13.03.2014
comment
Хей, благодаря за кода и обяснението. Въпреки това трябваше да прекратя процеса, защото и това отнемаше много време (›10 минути) за изпълнение. - person Pragith; 14.03.2014
comment
@Pragith Вярвам, че не си разбрал нещо. Решението data.table трябва да бъде изключително бързо. - person Roland; 14.03.2014