2011-06-06 19 views
6

में चलते समय वैश्विक पर्यावरण को लिखना मेरे पास कक्ष, मान और निर्देशांक का डेटा है। यह वैश्विक पर्यावरण में रहता है।समांतर

> head(cont.values) 
    cell value x y 
1 11117 NA -34 322 
2 11118 NA -30 322 
3 11119 NA -26 322 
4 11120 NA -22 322 
5 11121 NA -18 322 
6 11122 NA -14 322 

अपने कस्टम समारोह लगभग एक व्यक्ति सेल की गणना करने के लिए दूसरा लेता है क्योंकि (और मैं कोशिकाओं के हजारों है की गणना करने के) मैं कोशिकाओं एक मूल्य है कि पहले से ही के लिए गणना नकल करने नहीं करना चाहती। मेरा निम्नलिखित समाधान इससे बचने की कोशिश करता है। समानांतर निष्पादन के लिए चिल्लाते हुए प्रत्येक सेल को स्वतंत्र रूप से गणना की जा सकती है।

मेरा कार्य वास्तव में क्या करता है यह जांचता है कि निर्दिष्ट सेल नंबर के लिए कोई मान है और यदि यह एनए है, तो यह इसकी गणना करता है और एनए के स्थान पर इसे सम्मिलित करता है।

मैं अपने जादू समारोह चल सकते हैं (परिणाम एक इसी cell के लिए value है) कार्यों का परिवार लागू करते हैं और apply के भीतर से, मैंने पढ़ा है और एक समस्या (यह वैश्विक वातावरण में है) के बिना cont.values लिख सकते हैं का उपयोग कर।

अब, मैं इसे समानांतर में चलाने के लिए चाहता हूं (snowfall का उपयोग करके) और मैं व्यक्तिगत कोर से इस चर से पढ़ने/लिखने में असमर्थ हूं।

प्रश्न: समांतर में फ़ंक्शन निष्पादित करते समय कार्यकर्ता (कोर) के भीतर से वैश्विक वातावरण में रहने वाले गतिशील चर से पढ़ने/लिखने में कौन सा समाधान सक्षम होगा। क्या ऐसा करने का कोई बेहतर तरीका है?

उत्तर

4

एक केंद्रीय दुकान के पैटर्न है कि श्रमिकों मूल्यों के लिए परामर्श क्रैन पर rredis पैकेज में कार्यान्वित किया जाता है। विचार यह है कि रेडिस सर्वर कुंजी-मूल्य जोड़े (आपका वैश्विक डेटा फ्रेम, पुनः लागू) की एक स्टोर बनाए रखता है।श्रमिक यह देखने के लिए सर्वर से पूछताछ करते हैं कि मूल्य की गणना की गई है (redisGet) और यदि गणना नहीं की जाती है और इसे स्टोर (redisSet) ताकि अन्य कर्मचारी इसका पुन: उपयोग कर सकें। श्रमिक आर स्क्रिप्ट हो सकते हैं, इसलिए कार्य बल का विस्तार करना आसान है। यह एक बहुत अच्छा वैकल्पिक समांतर प्रतिमान है। यहां एक उदाहरण दिया गया है जो प्रत्येक परिणाम को 'यादगार' करने की धारणा का उपयोग करता है। हम एक समारोह है कि धीमा है (एक दूसरे के लिए सोता है)

fun <- function(x) { Sys.sleep(1); x } 

हम एक 'memoizer' कि fun का एक प्रकार देता है कि पहले जांच करता है कि x के लिए मूल्य पहले से ही गणना की गई है यह देखने के लिए लिखते हैं, और यदि ऐसा है तो का उपयोग करता है

memoize <- 
    function(FUN) 
{ 
    force(FUN) # circumvent lazy evaluation 
    require(rredis) 
    redisConnect() 
    function(x) 
    { 
     key <- as.character(x) 
     val <- redisGet(key) 
     if (is.null(val)) { 
      val <- FUN(x) 
      redisSet(key, val) 
     } 
     val 
    } 
} 

उसके बाद हम हमारी समारोह

funmem <- memoize(fun) 

memoize और

012 जाना
> system.time(res <- funmem(10)); res 
    user system elapsed 
    0.003 0.000 1.082 
[1] 10 
> system.time(res <- funmem(10)); res 
    user system elapsed 
    0.001 0.001 0.040 
[1] 10 

इसके लिए आर के बाहर चल रहे एक रेडिस सर्वर की आवश्यकता होती है लेकिन स्थापित करने में बहुत आसान है; rredis पैकेज के साथ आता है कि दस्तावेज देखें।

एक के भीतर आर समानांतर संस्करण हो सकता है

library(snow) 
cl <- makeCluster(c("localhost","localhost"), type = "SOCK") 
clusterEvalQ(cl, { require(rredis); redisConnect() }) 
tasks <- sample(1:5, 100, TRUE) 
system.time(res <- parSapply(cl, tasks, funmem)) 
+0

मैं इस कुछ दिन लागू कर सकते हैं, लेकिन मैं वर्तमान में आधिकारिक तौर पर एक POSIX प्रकार सिस्टम (Windows पर अटक), जिसका मतलब है मैं कर सकते हैं 'के लिए पहुँच नहीं है एक सर्वर अभी तक चलाने के लिए। –

4

यह इस बात पर निर्भर करेगा कि प्रश्न में कार्य क्या है, लेकिन मुझे डर है कि snowfall वहां बहुत मदद नहीं होगी। बात यह है कि, आपको विभिन्न कोरफ्रेम को विभिन्न कोरों में निर्यात करना होगा (?sfExport देखें) और अभी भी इसे गठबंधन करने का एक तरीका ढूंढें। उस तरह के वैश्विक वातावरण में मूल्य को बदलने का पूरा उद्देश्य धड़कता है, क्योंकि आप शायद जितना संभव हो उतना कम मेमोरी उपयोग रखना चाहते हैं।

आप काम करने के लिए snow के निम्न-स्तरीय कार्यों में जा सकते हैं। उदाहरण निम्न देखें:

#Some data 
Data <- data.frame(
    cell = 1:10, 
    value = sample(c(100,NA),10,TRUE), 
    x = 1:10, 
    y = 1:10 
) 
# A sample function 
sample.func <- function(){ 
    id <- which(is.na(Data$value)) # get the NA values 

    # this splits up the values from the dataframe in a list 
    # which will be passed to clusterApply later on. 
    parts <- lapply(clusterSplit(cl,id),function(i)Data[i,c("x","y")]) 

    # Here happens the magic 
    Data$value[id] <<- 
    unlist(clusterApply(cl,parts,function(x){ 
     x$x+x$y 
     } 
    )) 
} 
#now we run it 
require(snow) 
cl <- makeCluster(c("localhost","localhost"), type = "SOCK") 
sample.func() 
stopCluster(cl) 
> Data 
    cell value x y 
1  1 100 1 1 
2  2 100 2 2 
3  3  6 3 3 
4  4  8 4 4 
5  5 10 5 5 
6  6 12 6 6 
7  7 100 7 7 
8  8 100 8 8 
9  9 18 9 9 
10 10 20 10 10 

तुम अब भी कॉपी करने के लिए (का हिस्सा) अपने डेटा हालांकि यह कोर को पाने के लिए होगा। लेकिन यह वैसे भी होगा जब आप snowfall डेटाफ्रेम पर उच्च स्तरीय फ़ंक्शंस को कॉल करते हैं, क्योंकि snowfallsnow के निम्न-स्तरीय फ़ंक्शन का उपयोग करता है।

प्लस, किसी को यह नहीं भूलना चाहिए कि यदि आप डेटाफ्रेम में एक मान बदलते हैं, तो संपूर्ण डेटाफ्रेम स्मृति में भी कॉपी किया जाता है। इसलिए जब आप क्लस्टर से वापस आते हैं तो मूल्यों को एक-एक करके जोड़कर आप इतना जीत नहीं पाएंगे। आप कुछ अलग दृष्टिकोणों को आजमा सकते हैं और कुछ मेमोरी प्रोफाइलिंग भी कर सकते हैं।

1

मैं जोरीस से सहमत हूं कि आपको अपने डेटा को अन्य कोरों में कॉपी करने की आवश्यकता होगी। सकारात्मक तरफ, आपको डेटा में या नहीं, NA के बारे में चिंता करने की ज़रूरत नहीं है। अपने मूल data.framecont.values कहा जाता है:

nnaidx<-is.na(cont.values$value) #where is missing data originally 
dfrnna<-cont.values[nnaidx,] #subset for copying to other cores 
calcValForDfrRow<-function(dfrRow){return(dfrRow$x+dfrRow$y)}#or whatever pleases you 
sfExport(dfrnna, calcValForDfrRow) #export what is needed to other cores 
cont.values$value[nnaidx]<-sfSapply(seq(dim(dfrnna)[1]), function(i){calcValForDfrRow(dfrnna[i,])}) #sfSapply handles 'reordering', so works exactly as if you had called sapply 

अच्छी तरह से काम करना चाहिए (छोड़कर लेखन)