Używam GNU R na Ubuntu-Lucid PC, który ma 4 procesory. Aby korzystać ze wszystkich 4 procesorów, zainstalowałem pakiet „r-cran-multicore”. Ponieważ w podręczniku pakietu brakuje praktycznych przykładów, które rozumiem, potrzebuję porady, jak zoptymalizować mój skrypt, aby wykorzystać wszystkie 4 procesory.
Mój zestaw danych to ramka danych (zwana P1), która ma 50 000 wierszy i 1600 kolumn. Dla każdego wiersza chciałbym obliczyć maximun, sumę i średnią. Mój skrypt wygląda następująco:
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,]))
}
Czy ktoś mógłby mi powiedzieć, jak zmodyfikować i uruchomić skrypt, aby używać wszystkich 4 procesorów?
Odpowiedzi:
Użyj foreach i doMC . Szczegółowe wyjaśnienie można znaleźć tutaj . Twój skrypt zmieni się bardzo niewiele, linia
należy zmienić na
Wymagania wstępne dla każdego skryptu wielozadaniowości używającego tych pakietów to
Uwaga ostrożnie. Zgodnie z dokumentacją nie można tego używać w GUI.
Jeśli chodzi o twój problem, czy naprawdę potrzebujesz wielozadaniowości? Twoja data.frame zajmuje około 1,2 GB pamięci RAM, więc powinna zmieścić się w Twojej pamięci. Możesz więc po prostu użyć zastosowania:
Wynikiem będzie macierz ze streszczeniami każdego wiersza.
Możesz także użyć funkcji mclapply, która znajduje się w pakiecie wielordzeniowym. Wtedy twój skrypt może wyglądać następująco:
Zwróci to listę, gdzie i-ty element będzie podsumowaniem i-tego wiersza. Możesz przekonwertować go na macierz za pomocą sapply
źródło
Masz już odpowiedź, jak używać więcej niż jednego rdzenia, ale prawdziwy problem polega na sposobie pisania pętli. Nigdy nie rozszerzaj wektora wynikowego / obiektu przy każdej iteracji pętli . Jeśli to zrobisz, zmusisz R do skopiowania wektora wynikowego / obiektu i przedłużenia go, co zajmuje cały czas. Zamiast tego należy wstępnie przydzielić wystarczającą ilość miejsca do przechowywania przed rozpoczęciem pętli i wypełnić w miarę postępów. Oto przykład:
Lub możesz zrobić te rzeczy poprzez
apply()
:Pamiętaj jednak, że nie jest to szybsze niż prawidłowe wykonanie pętli, a czasem wolniejsze.
Jednak zawsze szukaj kodu wektorowego. Można zrobić sum wierszy i sposoby korzystania
rowSums()
irowMeans()
które są szybsze niż jednej pętli lubapply
wersjach:Gdybym był bukmacherem, miałbym pieniądze na trzecie podejście, o którym wspominam pokonanie,
foreach()
lub na inne wielordzeniowe opcje w teście prędkości na twojej matrycy, ponieważ musiałyby one znacznie przyspieszyć, aby uzasadnić narzut związany z konfiguracją oddzielne procesy wykonywane z różnych rdzeni procesora.Aktualizacja: Czy po komentarzu z @shabbychef szybciej jest zrobić sumy raz i użyć ponownie w obliczeniu średniej?
Nie w tym teście testowym, ale nie jest to wyczerpujące ...
źródło
rowSums
do obliczenia średnich wierszy (chyba że brakuje mi czegoś dotyczącego np. Na lub NaN). Kod w trzecim podejściu sumuje każdą kolumnę dwa razy .rowSums
irowMeans
są wysoce zoptymalizowany kod skompilowany i co uzyskujemy jedynie obliczania sum raz, ponownie straci w ten średni obliczeń w kodzie interpretowane.system.time({ for (iii in c(1:1000)) { p1max3 <- apply(p1, 1, max) p1mean3 <- rowMeans(p1) p1sum3 <- rowSums(p1) } })
i podobniesystem.time({ for (iii in c(1:1000)) { p1max4 <- apply(p1, 1, max) p1sum4 <- rowSums(p1) p1mean4 <- p1sum4 / ncol(p1) } })
; wersja, która nie przelicza sumy, zajmuje 1.368 sekund na moim komputerze; ten, który zajmuje 1,396. znowu, dalekie od wyczerpującego, ale bardziej przekonującego ...rowMeans
irowSums
realizowane są w wydajny i zoptymalizowany kod skompilowany mają zamiar być trudne do pokonania.rowMean
będzie trudno pokonać za pomocą narzędzia R ogólnego przeznaczenia, takich jak*apply
. Wydaje się jednak sugerować, że szybciej jest zsumować 10000 liczb dwa razy za pośrednictwemrowMean
irowSum
zamiast tylko raz i użyć wbudowanego operatora podziału R. Wiem, że R ma pewne problemy z wydajnością ( np . Niedawne odkrycie nawiasów klamrowych vs. nawias), ale to wydaje się szalone.Spójrz na śnieg i śniegu opakowaniach. Wiele przykładów z tymi ...
Jeśli chcesz przyspieszyć ten konkretny kod, zamiast uczyć się o R i równoległości, powinieneś to zrobić
źródło