"मल्टीकोर" का उपयोग करने के लिए मेरी आर स्क्रिप्ट को कैसे अनुकूलित करें


15

मैं Ubuntu-Lucid PC में GNU R का उपयोग कर रहा हूं जिसमें 4 CPU हैं। सभी 4 सीपीयू का उपयोग करने के लिए, मैंने "आर-क्रैन-मल्टीकोर" पैकेज स्थापित किया। जैसा कि पैकेज के मैनुअल में व्यावहारिक उदाहरणों की कमी है जो मुझे समझ में आती है, मुझे सभी सीपीयू का उपयोग करने के लिए अपनी स्क्रिप्ट को अनुकूलित करने के तरीके में सलाह की आवश्यकता है।

मेरा डेटासेट एक डेटा.फ़्रेम (पी 1 कहा जाता है) जिसमें 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 सीपीयू का उपयोग करने के लिए स्क्रिप्ट को कैसे संशोधित और चलाया जाए?


उपरोक्त कार्यक्रम में एक त्रुटि है: लाइन "के लिए (i: 1 में: प्लंबिंग)" होनी चाहिए
साइमन बायरन

आप कठोर हैं, thx!
प्रोडूनिस

1
यह StackOverflow पर नहीं है?
R_Coholic

1
यह StackOverflow पर संबंधित है। यहाँ कोई आँकड़े सवाल नहीं है। केवल एक सामान्य प्रोग्रामिंग प्रश्न।
जेडी लॉन्ग

जवाबों:


11

का प्रयोग करें foreach और doMC । विस्तृत विवरण यहां पाया जा सकता है । आपकी स्क्रिप्ट बहुत कम बदल जाएगी, रेखा

for(i in 1:plength){

को बदलना चाहिए

foreach(i=1:plength) %dopar% { 

इन पैकेजों का उपयोग करके किसी भी मल्टीटास्किंग स्क्रिप्ट के लिए आवश्यक शर्तें हैं

library(foreach)
library(doMC)
registerDoMC()

सावधानी बरतें। प्रलेखन के अनुसार आप इसे GUI में उपयोग नहीं कर सकते।

आपकी समस्या के लिए, क्या आपको वास्तव में मल्टीटास्किंग की आवश्यकता है? आपका डेटा.फ्रेम लगभग 1.2GB RAM लेता है, इसलिए इसे आपकी मेमोरी में फिट होना चाहिए। तो आप बस आवेदन का उपयोग कर सकते हैं:

p1smry <- apply(P1,1,summary)

परिणाम प्रत्येक पंक्ति के सारांश के साथ एक मैट्रिक्स होगा।

आप फ़ंक्शन का उपयोग भी कर सकते हैं मल्टीक्ले का जो पैकेज मल्टीकोर में है। तब आपकी स्क्रिप्ट इस तरह दिख सकती है:

loopfun <- function(i) {
     summary(P1[i,])
}

res <- mclapply(1:nrow(P1),loopfun)

यह सूची वापस कर देगा, जहां i-th तत्व i-th पंक्ति का सारांश होगा। आप इसे नीलम का उपयोग करके मैट्रिक्स में बदल सकते हैं

mres <- sapply(res,function(x)x)

आपका बहुत बहुत धन्यवाद। आप सही हैं, कि "लागू होने" के साथ स्क्रिप्ट को अनुकूलित किया जा सकता है। मैंने केवल संदेश प्राप्त करने के लिए अपनी स्क्रिप्ट को एक न्यूनतम-उदाहरण के रूप में उपयोग किया ... Thx a lot, आपका जवाब बिल्कुल वही है जिसकी मुझे तलाश थी !!
प्रोडुनिस

15

आपको पहले से ही एक उत्तर मिल गया है कि एक से अधिक कोर का उपयोग कैसे किया जाए, लेकिन असली समस्या यह है कि आपने अपने छोरों को किस तरह लिखा है। लूप के प्रत्येक पुनरावृत्ति पर अपने परिणाम वेक्टर / ऑब्जेक्ट का विस्तार कभी न करें । यदि आप ऐसा करते हैं, तो आप अपने परिणाम वेक्टर / ऑब्जेक्ट को कॉपी करने के लिए R को बाध्य करते हैं और इसे बढ़ाते हैं, जिसमें सभी को समय लगता है। इसके बजाय, लूप शुरू करने से पहले पर्याप्त स्टोरेज स्पेस का प्रचार करें और जैसे ही आप साथ जाएं, उसे भरें। यहाँ एक उदाहरण है:

set.seed(1)
p1 <- matrix(rnorm(10000), ncol=100)
system.time({
p1max <- p1mean <- p1sum <- numeric(length = 100)
for(i in seq_along(p1max)){
   p1max[i] <- max(p1[i,])
   p1mean[i] <- mean(p1[i,])
   p1sum[i ]<- sum(p1[i,])
}
})

   user  system elapsed 
  0.005   0.000   0.005

या आप इन चीज़ों के माध्यम से कर सकते हैं apply():

system.time({
p1max2 <- apply(p1, 1, max)
p1mean2 <- apply(p1, 1, mean)
p1sum2 <- apply(p1, 1, sum)
})
   user  system elapsed 
  0.007   0.000   0.006 

लेकिन ध्यान दें कि यह है नहीं है लूप को ठीक से करने और कभी-कभी धीमी गति से करने से तेज ।

हालाँकि, हमेशा वेक्टर कोड की तलाश में रहते हैं। आप पंक्ति रकम और साधनों का उपयोग कर सकते हैं rowSums()और rowMeans()जो लूप या applyसंस्करणों की तुलना में तेज़ हैं :

system.time({
p1max3 <- apply(p1, 1, max)
p1mean3 <- rowMeans(p1)
p1sum3 <- rowSums(p1)
})

   user  system elapsed 
  0.001   0.000   0.002 

यदि मैं एक सट्टेबाजी का आदमी था, तो मेरे पास धड़कन का उल्लेख करने वाले तीसरे दृष्टिकोण पर पैसा होगा foreach() आपके मैट्रिक्स पर गति परीक्षण में या अन्य मल्टी-कोर विकल्पों का क्योंकि उन्हें स्थापित करने में ओवरहेड को सही ठहराने के लिए चीजों को तेजी से बढ़ाना होगा। अलग-अलग प्रक्रियाओं को अलग सीपीयू कोर से अलग किया जाता है।

अद्यतन: @shabbychef की टिप्पणी के बाद, क्या यह एक बार रकम करने और मतलब की गणना में पुन: उपयोग करने के लिए तेज़ है?

system.time({
    p1max4 <- apply(p1, 1, max)
    p1sum4 <- rowSums(p1)
    p1mean4 <- p1sum4 / ncol(p1)
    })

   user  system elapsed 
  0.002   0.000   0.002

इस टेस्ट रन में नहीं, लेकिन यह बहुत दूर है ...


एफडब्ल्यूआईडब्ल्यू, मैटलैब में प्रचार और विस्तार करने वाले वैक्टर के बारे में समान मुद्दे हैं, और यह एक क्लासिक कोड 'ब्लॉपर' है। आपके दांव के अतिरिक्त, rowSumsपंक्ति साधनों की गणना करने के परिणामों का उपयोग करने के लिए यह संभवतः तेज है (जब तक कि मैं उदाहरण के लिए Na या NaN के बारे में कुछ याद नहीं कर रहा हूं )। आपके तीसरे दृष्टिकोण के कोड में प्रत्येक कॉलम को दो बार लिखा जाता है ।
shabbychef

@shabbychef आपको आश्चर्य होगा (मेरे संपादित उत्तर देखें)। हाँ रकम कल्पना की दृष्टि से दो बार गणना की जाती है, लेकिन 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.368 सेकंड लेता है; वह जो 1.396 लेता है। फिर से, थकावट से दूर, लेकिन अधिक सम्मोहक ...
shabbychef

@shabbychef पर हमारे पास अलग-अलग विचार होने चाहिए कि क्या है या सम्मोहक नहीं है ;-) वास्तव में, आपके अधिक कठोर सिमुलेशन मेरे मुख्य बिंदु को सुदृढ़ करते हैं, जो कि कुशल, अनुकूलित संकलित कोड में कार्यान्वित होते हैं rowMeansऔर rowSumsउन्हें हरा पाना मुश्किल होता है।
मोनिका - जी। सिम्पसन

@ गेविन सिम्पसन दरअसल, मेरे उदाहरण के साथ समस्या यह है कि अधिकतम गणना करने के लिए अधिकांश समय आवेदन भाग में लिया जाता है। मैं आपके साथ सहमत हूं कि एक सी-आधारित वेक्टराइज्ड फ़ंक्शन जैसे rowMeanसामान्य-उद्देश्य आर टूल के माध्यम से हरा करना मुश्किल है *apply। हालांकि, अगर आप सुझाव देने के लिए यह 10000 संख्या योग करने के लिए तेजी से होता है कि लगता है दो बार के माध्यम से rowMeanऔर rowSumनहीं बल्कि केवल एक बार और उपयोग आर के builtin विभाजन ऑपरेटर से। मुझे पता है कि आर में कुछ दक्षता के मुद्दे हैं ( उदाहरण के लिए घुंघराले ब्रेसिज़ बनाम कोष्ठक की हाल की खोज), लेकिन यह पागल लगता है।
shabbychef

1

बर्फ और बर्फबारी पर एक नज़र पैकेज । उन लोगों के साथ बहुत सारे उदाहरण ...

यदि आप R और समानता के बारे में सीखने के बजाय उस विशिष्ट कोड को गति देना चाहते हैं तो आपको ऐसा करना चाहिए

P1 = matrix(rnorm(1000), ncol=10, nrow=10
apply(P1, 1, max)
apply(P1, 1, mean)
apply(P1, 1, sum)

कृपया मेरी स्क्रिप्ट को संशोधित करने में मेरी मदद करें ...
प्रोडूनिस

2
वे सिर्फ आप से लूप छिपा रहे हैं। @Produnis कोड के साथ असली समस्या यह है कि जबरन नकल की जा रही है क्योंकि परिणाम वैक्टर लूप के प्रत्येक पुनरावृत्ति पर बढ़ाया जा रहा है।
मोनिका - जी। सिम्पसन

बर्फबारी पैकेज गैविन के समाधान को "केक" कहकर विस्तारित कर सकता है। पैकेज में मल्टीकोरिंग करने के लिए संशोधित फ़ंक्शन का ढेर है। आवेदन समारोह के लिए, आप sfApply (<yourarguments as apply>) का उपयोग करेंगे। बर्फबारी भी अच्छी तरह से प्रलेखित है। मुझे यह बताना चाहिए कि मल्टी-कोर प्रोसेसर पर इसे करने के लिए किसी अतिरिक्त सॉफ्टवेयर की आवश्यकता नहीं है। SfLapply उदाहरण के लिए stackoverflow.com/questions/4164960/… देखें ।
रोमन लुसट्रिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.