Zoeken…


Opmerkingen

Parallellisatie op externe machines vereist dat bibliotheken op elke machine worden gedownload. Voorkeur package::function() aanroepen. Verschillende pakketten hebben ingebouwde standaardisatie, inclusief caret , pls en plyr .

Microsoft R Open (Revolution R) maakt ook gebruik van multi-threaded BLAS / LAPACK-bibliotheken die intrinsiek veel algemene functies parallel lopen.

Parallelle verwerking met foreach-pakket

Het foreach pakket brengt de kracht van parallelle verwerking naar R. Maar voordat u multi-core CPU's wilt gebruiken, moet u een multi-core cluster toewijzen. Het doSNOW pakket is een mogelijkheid.

Een eenvoudig gebruik van de foreach-lus is het berekenen van de som van de vierkantswortel en het kwadraat van alle getallen van 1 tot 100000.

library(foreach)
library(doSNOW)

cl <- makeCluster(5, type = "SOCK")
registerDoSNOW(cl)

f <- foreach(i = 1:100000, .combine = c, .inorder = F) %dopar% {
    k <- i ** 2 + sqrt(i)
    k
} 

De structuur van de output van foreach wordt bepaald door het .combine argument. De standaarduitvoerstructuur is een lijst. In de bovenstaande code wordt c gebruikt om in plaats daarvan een vector te retourneren. Merk op dat een berekeningsfunctie (of operator) zoals "+" ook kan worden gebruikt om een berekening uit te voeren en een verder verwerkt object te retourneren.

Het is belangrijk om te vermelden dat het resultaat van elke foreach-lus het laatste gesprek is. In dit voorbeeld wordt dus k aan het resultaat toegevoegd.

Parameter Details
.combineren functie combineren. Bepaalt hoe de resultaten van de lus worden gecombineerd. Mogelijke waarden zijn c , cbind , rbind , "+" , "*" ...
.in volgorde als het TRUE het resultaat geordend volgens de volgorde van de iteratie waarheidsgetrouw (hier i ). Als FALSE het resultaat niet besteld. Dit kan positieve gevolgen hebben voor de rekentijd.
.pakketjes voor functies die worden geleverd door elk pakket behalve base , zoals bijvoorbeeld mass , randomForest of anders, moet u deze pakketten voorzien van c("mass", "randomForest")

Parallelle verwerking met parallel pakket

Het basispakket parallel maakt parallelle berekening mogelijk via vorken, stopcontacten en het genereren van willekeurige getallen.

Detecteer het aantal aanwezige cores op de localhost:

parallel::detectCores(all.tests = FALSE, logical = TRUE)

Maak een cluster van de cores op de localhost:

parallelCluster <- parallel::makeCluster(parallel::detectCores())

Eerst moet een functie worden gecreëerd die geschikt is voor parallellisatie. Overweeg de mtcars gegevensset. Een regressie op mpg kan worden verbeterd door een afzonderlijk regressiemodel te maken voor elk niveau van cyl .

data <- mtcars
yfactor <- 'cyl'
zlevels <- sort(unique(data[[yfactor]]))
datay <- data[,1]
dataz <- data[,2]
datax <- data[,3:11]


fitmodel <- function(zlevel, datax, datay, dataz) {
  glm.fit(x = datax[dataz == zlevel,], y = datay[dataz == zlevel])
}

Maak een functie die alle mogelijke iteraties van zlevels . Dit is nog steeds in serie, maar is een belangrijke stap omdat het het exacte proces bepaalt dat parallel zal worden uitgevoerd.

fitmodel <- function(zlevel, datax, datay, dataz) {
  glm.fit(x = datax[dataz == zlevel,], y = datay[dataz == zlevel])
}


for (zlevel in zlevels) {
  print("*****")
  print(zlevel)
  print(fitmodel(zlevel, datax, datay, dataz))
}

Curry deze functie:

worker <- function(zlevel) {
    fitmodel(zlevel,datax, datay, dataz)
  }

Parallel computing met behulp van parallel heeft geen toegang tot de wereldwijde omgeving. Gelukkig creëert elke functie een lokale omgeving die parallel toegankelijk is. Het creëren van een wrapper-functie maakt parallellisatie mogelijk. De functie die moet worden toegepast, moet ook in de omgeving worden geplaatst.

wrapper <- function(datax, datay, dataz) {
  # force evaluation of all paramters not supplied by parallelization apply
  force(datax)
  force(datay)
  force(dataz)
  # these variables are now in an enviroment accessible by parallel function
  
  # function to be applied also in the environment
  fitmodel <- function(zlevel, datax, datay, dataz) {
    glm.fit(x = datax[dataz == zlevel,], y = datay[dataz == zlevel])
  }
  
  # calling in this environment iterating over single parameter zlevel
  worker <- function(zlevel) {
    fitmodel(zlevel,datax, datay, dataz)
  }
  return(worker) 
}

Maak nu een cluster en voer de wrapperfunctie uit.

parallelcluster <- parallel::makeCluster(parallel::detectCores())
models <- parallel::parLapply(parallelcluster,zlevels,
                              wrapper(datax, datay, dataz))

Stop het cluster altijd wanneer u klaar bent.

parallel::stopCluster(parallelcluster)

Het parallel pakket omvat de hele familie apply() , voorafgegaan door par .

Willekeurige nummergeneratie

Een groot probleem met parallellisatie is het gebruik van RNG als zaden. Willekeurige getallen door het nummer worden herhaald door het aantal bewerkingen vanaf het begin van de sessie of de meest recente set.seed() . Omdat parallelle processen voortkomen uit dezelfde functie, kan het dezelfde seed gebruiken, wat mogelijk identieke resultaten veroorzaakt! Oproepen worden serieel op de verschillende kernen uitgevoerd, bieden geen voordeel.

Een set zaden moet worden gegenereerd en naar elk parallel proces worden verzonden. Dit wordt automatisch gedaan in sommige pakketten ( parallel , snow , enz.), Maar moet in andere pakketten expliciet worden aangepakt.

s <- seed
for (i in 1:numofcores) {
    s <- nextRNGStream(s)
    # send s to worker i as .Random.seed
}

Zaden kunnen ook worden ingesteld voor reproduceerbaarheid.

clusterSetRNGStream(cl = parallelcluster, iseed)

mcparallelDo

Het mcparallelDo pakket zorgt voor de asynchrone evaluatie van R-code op Unix-achtige besturingssystemen (bijvoorbeeld Linux en MacOSX). De onderliggende filosofie van het pakket is afgestemd op de behoeften van verkennende gegevensanalyse in plaats van codering. Overweeg het future pakket voor het coderen van asynchronie.

Voorbeeld

Maak gegevens

data(ToothGrowth)

Mcparallel activeren Doen om analyses op een vork uit te voeren

mcparallelDo({glm(len ~ supp * dose, data=ToothGrowth)},"interactionPredictorModel")

Doe andere dingen, bijv

binaryPredictorModel <- glm(len ~ supp, data=ToothGrowth)
gaussianPredictorModel <- glm(len ~ dose, data=ToothGrowth)

Het resultaat van mcparallelDo keert terug in uw targetEnvironment, bijvoorbeeld. GlobalEnv, wanneer deze compleet is met een bericht (standaard)

summary(interactionPredictorModel)

Andere voorbeelden

# Example of not returning a value until we return to the top level
for (i in 1:10) {
  if (i == 1) {
    mcparallelDo({2+2}, targetValue = "output")
  }
  if (exists("output")) print(i)
}

# Example of getting a value without returning to the top level
for (i in 1:10) {
  if (i == 1) {
    mcparallelDo({2+2}, targetValue = "output")
  }
  mcparallelDoCheck()
  if (exists("output")) print(i)
}


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow