2015-03-10 7 views
6

Im help für detectCores() heißt es:Ob die Funktion detectCores in R verwendet werden soll, um die Anzahl der Kerne für die parallele Verarbeitung anzugeben?

Diese für Gebrauch nicht geeignet ist direkt für die mc.cores Argument von mclapply noch die Anzahl der Kerne in makeCluster angeben. Zuerst , weil es NA zurückgeben kann, und zweitens, weil es die Anzahl der zulässigen Kerne nicht gibt.

Allerdings habe ich ziemlich viel Beispielcode wie folgt gesehen:

library(parallel) 
k <- 1000 
m <- lapply(1:7, function(X) matrix(rnorm(k^2), nrow=k)) 

cl <- makeCluster(detectCores() - 1, type = "FORK") 
test <- parLapply(cl, m, solve) 
stopCluster(cl) 

wo detectCores() verwendet wird, die Anzahl der Kerne in makeCluster angeben.

Meine Anwendungsfälle beinhalten die parallele Verarbeitung sowohl auf meinem eigenen Multicore-Laptop (OSX) als auch auf verschiedenen Multicore-Servern (Linux). Ich war mir also nicht sicher, ob es eine bessere Möglichkeit gibt, die Anzahl der Kerne anzugeben, oder ob der Ratschlag, keine detectCores zu verwenden, eher für Paketentwickler gedacht war, deren Code über einen weiten Bereich von Hardware- und Betriebssystemumgebungen laufen sollte.

Also zusammenfassend:

  • Sollten Sie verwenden, um die detectCores Funktion in R die Anzahl der Kerne für die parallele Verarbeitung zu spezifizieren?
  • Wie groß ist der Unterschied zwischen erkannten und erlaubten Kernen und wann ist dieser relevant?
+2

auf welcher plattform bist du? 'system ('getconf _NPROCESSORS_ONLN')' – rawr

+0

Sowohl OSX als auch Linux; Ich habe meine Frage aktualisiert, um dies zu sagen; obwohl ich glaube, dass ich an der allgemeinen Antwort interessiert bin, um das für andere nützlich zu machen. –

Antwort

10

Ich denke, es ist durchaus sinnvoll detectCores als Ausgangspunkt für die Anzahl der Arbeiter/Prozesse zu verwenden, wenn mclapply oder makeCluster aufrufen. Es gibt jedoch viele Gründe dafür, dass Sie weniger Mitarbeiter einstellen möchten oder müssen, und sogar einige Fälle, in denen Sie sinnvollerweise mehr starten können.

Bei einigen Hyperthread-Maschinen ist es unter Umständen nicht sinnvoll, mc.cores=detectCores() als Beispiel zu verwenden. Wenn Ihr Skript in einem HPC-Cluster ausgeführt wird, sollten Sie keine weiteren Ressourcen verwenden, als der Jobplaner Ihrem Job zugewiesen hat. Sie müssen auch in verschachtelten parallelen Situationen vorsichtig sein, wenn Ihr Code parallel von einer aufrufenden Funktion ausgeführt wird oder wenn Sie eine Multithread-Funktion parallel ausführen. Im Allgemeinen ist es eine gute Idee, einige vorläufige Benchmarks zu erstellen, bevor Sie einen langen Job beginnen, um die beste Anzahl von Mitarbeitern zu ermitteln. Normalerweise überwache ich den Benchmark mit top, um zu sehen, ob die Anzahl der Prozesse und Threads sinnvoll ist, und um zu überprüfen, ob die Speichernutzung vernünftig ist.

Der von Ihnen genannte Hinweis ist besonders für Paketentwickler geeignet. Es ist sicherlich eine schlechte Idee für einen Paketentwickler, immer detectCores() Arbeiter zu starten, wenn er mclapply oder makeCluster anruft, also ist es am besten, die Entscheidung dem Endbenutzer zu überlassen. Zumindest sollte das Paket dem Benutzer ermöglichen, die Anzahl der zu startenden Worker anzugeben, aber wohl detectCores() ist nicht einmal ein guter Standardwert. Deshalb wurde der Standardwert für mc.cores von detectCores() zu getOptions("mc.cores", 2L) geändert, wenn mclapply im Paket parallel enthalten war.

Ich denke, der wirkliche Punkt der Warnung, die Sie zitiert haben, ist, dass R-Funktionen nicht davon ausgehen sollten, dass sie die gesamte Maschine besitzen, oder dass sie die einzige Funktion in Ihrem Skript sind, die mehrere Kerne verwendet. Wenn Sie mclapply mit mc.cores=detectCores() in einem Paket anrufen, das Sie an CRAN senden, erwarte ich, dass Ihr Paket zurückgewiesen wird, bis Sie es ändern. Wenn Sie jedoch als Endbenutzer ein paralleles Skript auf Ihrem eigenen Computer ausführen, müssen Sie entscheiden, wie viele Kerne das Skript verwenden darf.

+0

Also, wenn ich die Maschine nicht besitze und mir weniger Kerne pro Knoten als zur Verfügung gestellt wurden, wie kann ich 'detectCores()' oder etwas Ähnliches verwenden, um sicherzustellen, dass ich nur die erlaubten Kerne benutze? In diesem Fall, sollte ich es einfach manuell eingeben? – Plinth

+2

@Plinth In diesem Fall ist 'detectCores()' nicht sehr nützlich. Wenn Sie ein Batch-Queuing-System verwenden, können Sie normalerweise mithilfe einer Umgebungsvariablen ermitteln, wie viele Kerne pro Knoten Ihrem Job zugewiesen wurden. Unter Torque konnten Sie die in $ PBS_NODEFILE aufgelisteten Knotennamen mit etwas wie 'table (readLines (Sys.getenv ('PBS_NODEFILE')))' zählen. Im Allgemeinen müssen Sie diese Informationen jedoch möglicherweise als Befehlszeilenargument für Ihr R-Skript angeben. –

+0

Ich wollte die Dinge nicht zu sehr in meiner 'future :: availableCores()' Antwort verkomplizieren, aber 'future :: availableWorkers()' analysiert bekannte HPC-Dateien wie 'PBS_NODEFILE', die Steve erwähnt. Ich denke, dass dies nur für Multi-Node-Jobs benötigt werden sollte und ich glaube, 'PBS_NUM_PPN' ist immer eingestellt (glücklich, dass es korrigiert/gelernt wurde). – HenrikB

1

Besser in meinem Fall (ich benutze Mac) ist future::availableCores() weil detectCores() zeigt 160, die offensichtlich falsch ist.

1

Autor des future Pakets hier: Die future::availableCores() Funktion verschiedenes HPC Umgebungsvariablen (zB NSLOTS, PBS_NUM_PPN und SLURM_CPUS_PER_TASK) und System-und R-Einstellungen erkennt an, dass die Anzahl der Kerne zur Verfügung, die Verfahren werden verwendet, um anzugeben, und wenn nicht angegeben, fällt es auf parallel::detectCores() zurück. Wenn ich oder andere auf weitere Einstellungen aufmerksam werden, werde ich auch für diese automatisch eine automatische Unterstützung hinzufügen. Es gibt ein immer offenes GitHub-Problem dafür unter https://github.com/HenrikBengtsson/future/issues/22 (es gibt einige offene Hilfeanfragen).

Wenn sysadm die Umgebungsvariable R_FUTURE_AVAILABLECORES_FALLBACK=1 Sitewide setzt, gibt future::availableCores() den Wert 1 zurück, es sei denn, es wurde explizit durch andere Mittel überschrieben (vom Job-Scheduler, von den Benutzereinstellungen, ...). Dies schützt weiter davor, dass Software-Tools standardmäßig alle Kerne übernehmen.

Mit anderen Worten, wenn Sie future::availableCores() verwenden, anstatt parallel::detectCores() können Sie ziemlich sicher sein, dass der Code in Multi-Tenant-Umgebungen schön spielt (wenn es stellt sich heraus, es ist nicht genug, lassen Sie es uns in der oben GitHub Problem kennen) und dass ein Endbenutzer die Anzahl der Kerne immer noch steuern kann, ohne dass Sie Ihren Code ändern müssen.

Verwandte Themen