Я использую GNU R на ПК с Ubuntu-Lucid, который имеет 4 процессора. Чтобы использовать все 4 процессора, я установил пакет «r-cran-multicore». Поскольку в руководстве по пакету отсутствуют практические примеры, которые я понимаю, мне нужен совет, как оптимизировать мой сценарий, чтобы использовать все 4 процессора.
Мой набор данных - это data.frame (называемый P1), который содержит 50 000 строк и 1600 столбцов. Для каждой строки я хотел бы подсчитать максимальную, сумму и среднее. Мой сценарий выглядит следующим образом:
p1max <- 0
p1mean <- 0
p1sum <-0
plength <- length(P1[,1])
for(i in 1:plength){
p1max <- c(p1max, max(P1[i,]))
p1mean <- c(p1mean, mean(P1[i,]))
p1sum <- c(p1sum, sum(P1[i,]))
}
Может ли кто-нибудь сказать мне, как изменить и запустить скрипт, чтобы использовать все 4 процессора?
Ответы:
Используйте foreach и doMC . Подробное объяснение можно найти здесь . Ваш сценарий очень мало изменится, строка
следует изменить на
Необходимые условия для любого многозадачного скрипта, использующего эти пакеты:
Обратите внимание на осторожность. Согласно документации, вы не можете использовать это в графическом интерфейсе.
Что касается вашей проблемы, вам действительно нужна многозадачность? Ваш data.frame занимает около 1,2 ГБ ОЗУ, поэтому он должен уместиться в вашей памяти. Так что вы можете просто использовать apply:
Результатом будет матрица с кратким изложением каждой строки.
Вы также можете использовать функцию mclapply, которая находится в многоядерном пакете. Тогда ваш скрипт может выглядеть так:
Это вернет список, где i-й элемент будет сводкой i-й строки. Вы можете преобразовать его в матрицу, используя sapply
источник
Вы уже получили ответ о том, как использовать более одного ядра, но реальная проблема заключается в том, как вы пишете свои циклы. Никогда не расширяйте ваш результирующий вектор / объект на каждой итерации цикла . Если вы сделаете это, вы заставите R скопировать ваш вектор / объект результата и расширить его, что занимает много времени. Вместо этого предварительно выделите достаточно места для хранения, прежде чем начинать цикл, и заполните его по мере продвижения. Вот пример:
Или вы можете сделать это через
apply()
:Но обратите внимание, что это не быстрее, чем делать цикл правильно, а иногда и медленнее.
Однако всегда следите за векторизованным кодом. Вы можете использовать суммы строк и средства, используя
rowSums()
иrowMeans()
которые быстрее, чем цикл илиapply
версии:Если бы я был игроком на ставки, у меня были бы деньги на третий подход, который я упомянул об избиении,
foreach()
или другие многоядерные опции в тесте скорости на вашей матрице, потому что они должны были бы значительно ускорить процесс, чтобы оправдать накладные расходы, возникающие при настройке отдельные процессы, которые обрабатываются различными ядрами процессора.Обновление: после комментария от @shabbychef, быстрее ли сделать суммы один раз и повторно использовать в вычислении среднего?
Не в этом тесте, но это далеко не исчерпывающий ...
источник
rowSums
для вычисления средних значений строк (если я не пропускаю что-то, например, в отношении Na или NaN). Код вашего третьего подхода суммирует каждый столбец дважды .rowSums
иrowMeans
высоко оптимизированные скомпилированный код , и что мы получаем только в вычислении суммы один раз, мы снова потерять при этом среднем вычислении в интерпретируемом коде.system.time({ for (iii in c(1:1000)) { p1max3 <- apply(p1, 1, max) p1mean3 <- rowMeans(p1) p1sum3 <- rowSums(p1) } })
и аналогичноsystem.time({ for (iii in c(1:1000)) { p1max4 <- apply(p1, 1, max) p1sum4 <- rowSums(p1) p1mean4 <- p1sum4 / ncol(p1) } })
; версия, которая не пересчитывает сумму, занимает на моем компьютере 1,386 секунды; тот, который делает 1.396. опять же, далеко не исчерпывающий, но более убедительный ...rowMeans
иrowSums
реализованы в эффективном, оптимизированном скомпилированном коде , они будут трудно превзойти.rowMean
будет трудно превзойти с помощью общего назначения R инструмент , как*apply
. Тем не менее, вы , кажется, предполагают , что он быстрее подводить 10000 чисел дважды черезrowMean
и ,rowSum
а не только один раз и оператор встроенного разделения использования R в. Я знаю, что у R есть некоторые проблемы с эффективностью ( например, недавнее обнаружение проблемы фигурных скобок и скобок), но это кажется сумасшедшим.Посмотрите на пакеты снега и снегопада . Множество примеров с этими ...
Если вы хотите ускорить этот конкретный код, а не изучать R и параллелизм, вы должны сделать это
источник