Estou usando o GNU R em um PC Ubuntu-Lucid que possui 4 CPUs. Para usar todas as 4 CPUs, instalei o pacote "r-cran-multicore". Como o manual do pacote carece de exemplos práticos que eu entendo, preciso de conselhos sobre como otimizar meu script para fazer uso de todas as 4 CPUs.
Meu conjunto de dados é um data.frame (chamado P1) que possui 50.000 linhas e 1600 cols. Para cada linha, eu gostaria de calcular a máxima, soma e média. Meu script é o seguinte:
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,]))
}
Alguém poderia me dizer como modificar e executar o script para usar todas as 4 CPUs?
Respostas:
Use foreach e doMC . A explicação detalhada pode ser encontrada aqui . Seu script mudará muito pouco, a linha
deve ser alterado para
Os pré-requisitos para qualquer script multitarefa usando esses pacotes são
Nota de cuidado. De acordo com a documentação, você não pode usar isso na GUI.
Quanto ao seu problema, você realmente precisa de multitarefa? Seu data.frame ocupa cerca de 1,2 GB de RAM, portanto deve caber na sua memória. Então você pode simplesmente usar o Apply:
O resultado será uma matriz com resumos de cada linha.
Você também pode usar a função mclapply, que está no pacote multicore. Então seu script pode ficar assim:
Isso retornará a lista, onde o i-ésimo elemento será o resumo da i-ésima linha. Você pode convertê-lo em matriz usando sapply
fonte
Você já tem uma resposta sobre como usar mais de um núcleo, mas o verdadeiro problema está na maneira como você escreveu seus loops. Nunca estenda seu vetor / objeto resultante a cada iteração de um loop . Se você fizer isso, forçará R a copiar o vetor / objeto resultante e estendê-lo, o que leva tempo. Em vez disso, pré-aloque espaço de armazenamento suficiente antes de iniciar o loop e preencher à medida que avança. Aqui está um exemplo:
Ou você pode fazer essas coisas através de
apply()
:Mas observe que isso não é mais rápido do que fazer o loop corretamente e, às vezes, mais lento.
No entanto, esteja sempre atento ao código vetorizado. Você pode fazer somas e meios de linha usando
rowSums()
erowMeans()
que são mais rápidos que o loop ou asapply
versões:Se eu fosse um apostador, teria dinheiro com a terceira abordagem que menciono bater
foreach()
ou com as outras opções de múltiplos núcleos em um teste de velocidade em sua matriz, porque elas teriam que acelerar as coisas consideravelmente para justificar a sobrecarga incorrida na configuração do processos separados criados nos diferentes núcleos da CPU.Atualização: Após o comentário de @shabbychef, é mais rápido fazer as somas uma vez e reutilizar no cálculo da média?
Não nesta execução de teste, mas isso está longe de ser exaustivo ...
fonte
rowSums
para calcular os meios de linha (a menos que eu esteja perdendo algo relacionado a, por exemplo, Na ou NaN). O código na sua terceira abordagem soma cada coluna duas vezes .rowSums
erowMeans
são altamente otimizado código compilado e o que ganhamos em apenas calcular as somas uma vez, perdemos de novo em fazer o cálculo médio no código interpretado.system.time({ for (iii in c(1:1000)) { p1max3 <- apply(p1, 1, max) p1mean3 <- rowMeans(p1) p1sum3 <- rowSums(p1) } })
e da mesma formasystem.time({ for (iii in c(1:1000)) { p1max4 <- apply(p1, 1, max) p1sum4 <- rowSums(p1) p1mean4 <- p1sum4 / ncol(p1) } })
; a versão que não recalcula a soma leva 1.368 segundos no meu computador; o que faz leva 1.396. mais uma vez, longe de ser exaustiva, mas mais atraente ...rowMeans
erowSums
são implementados em código eficiente, otimizado compilado eles estão vai ser difícil de bater.rowMean
será difícil de superar por meio de uma ferramenta R de uso geral como*apply
. No entanto, você parece sugerir que é mais rápido somar 10000 números duas vezes viarowMean
erowSum
não apenas uma vez e usar o operador de divisão interno de R. Eu sei que o R tem alguns problemas de eficiência ( por exemplo, a recente descoberta de chaves entre parênteses), mas isso parece loucura.Dê uma olhada nos pacotes de neve e queda de neve . Muitos exemplos com esses ...
Se você deseja acelerar esse código específico em vez de aprender sobre R e paralelismo, faça isso
fonte