आर

2017-09-02 27 views
5

में मैट्रिक्स की तेज़ सबसेटिंग मुझे निम्न समस्या का सामना करना पड़ता है: मुझे एक बड़े मैट्रिक्स के कई सबसेट की आवश्यकता है। असल में मुझे किसी अन्य फ़ंक्शन f() के इनपुट के रूप में विचारों की आवश्यकता है, इसलिए मुझे मानों को बदलने की आवश्यकता नहीं है। हालांकि ऐसा लगता है कि आर इस कार्य के लिए बहुत धीमी है, या मैं कुछ गलत कर रहा हूं (जो अधिक संभावना है)। खिलौना उदाहरण दिखाता है कि कॉलम का चयन करने में कितना समय लगता है, और फिर उन्हें किसी अन्य फ़ंक्शन में उपयोग करें (इस खिलौने उदाहरण में आदिम फ़ंक्शन योग())। 'बेंचमार्क' के रूप में मैं पूरे मैट्रिक्स को संक्षेप में गणना के समय गणना समय का भी परीक्षण करता हूं, जो आश्चर्यजनक रूप से तेज़ है। मैंने पैकेज रेफरी के साथ भी प्रयोग किया, हालांकि किसी भी प्रदर्शन लाभ को हासिल नहीं किया जा सका। तो मुख्य सवाल यह है कि इसे कॉपी किए बिना मैट्रिक्स को कैसे सब्सक्राइब करना है? मैं किसी भी मदद की सराहना करता हूं, धन्यवाद!आर

library(microbenchmark) 
library(ref) 

m0 <- matrix(rnorm(10^6), 10^3, 10^3) 
r0 <- refdata(m0) 
microbenchmark(m0[, 1:900], sum(m0[, 1:900]), sum(r0[,1:900]), sum(m0)) 
Unit: milliseconds 
      expr  min  lq  mean median  uq 
     m0[, 1:900] 10.087403 12.350751 16.697078 18.307475 19.054157 
sum(m0[, 1:900]) 11.067583 13.341860 17.286514 19.123748 19.990661 
sum(r0[, 1:900]) 11.066164 13.194244 16.869551 19.204434 20.004034 
      sum(m0) 1.015247 1.040574 1.059872 1.049513 1.067142 
     max neval 
58.238217 100 
25.664729 100 
23.505308 100 
    1.233617 100 

पूरे मैट्रिक्स संक्षेप का बेंचमार्क कार्य के बारे में 16 बार अन्य कार्यों की तुलना में तेजी १.०५९८७२ मिलीसेकेंड लेता है और है।

+0

मैं एक त्रुटि जब मिल मैं आपका उदाहरण आज़माता हूं: 'r0 में त्रुटि [, 1: 900]: आयामों की गलत संख्या' – 5th

+0

'लाइब्रेरी (' ref ')' इसे ठीक करती है – dvantwisk

+0

ठीक है तो समाधान के लिए यहां मानदंड क्या है? क्या यह अभी आप जो कर रहे हैं उससे तेज होना चाहिए या पूरे मैट्रिक्स को संक्षेप में तेज करना होगा? –

उत्तर

4

आपके समाधान के साथ समस्या यह है कि सबसेटिंग एक और मैट्रिक्स आवंटित कर रहा है, जिसमें समय लगता है।

तो समय पूरे मैट्रिक्स पर sum के साथ लिया आप के साथ ठीक है, आप colSums पूरे मैट्रिक्स पर इस्तेमाल करते हैं और परिणाम सबसेट सकता है::

sum(colSums(m0)[1:900]) 

या आप

आप दो समाधान है मैट्रिक्स की प्रतिलिपि किए बिना सबसेटिंग के साथ sum की गणना करने के लिए आरसीपीपी का उपयोग कर सकता है।

#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
double sumSub(const NumericMatrix& x, 
       const IntegerVector& colInd) { 

    double sum = 0; 

    for (IntegerVector::const_iterator it = colInd.begin(); it != colInd.end(); ++it) { 
    int j = *it - 1; 
    for (int i = 0; i < x.nrow(); i++) { 
     sum += x(i, j); 
    } 
    } 

    return sum; 
} 

    microbenchmark(m0[, 1:900], sum(m0[, 1:900]), sum(r0[,1:900]), sum(m0), 
        sum(colSums(m0)[1:900]), 
        sumSub(m0, 1:900)) 
Unit: milliseconds 
        expr  min  lq  mean median  uq  max neval 
      m0[, 1:900] 4.831616 5.447749 5.641096 5.675774 5.861052 6.418266 100 
     sum(m0[, 1:900]) 6.103985 6.475921 7.052001 6.723035 6.999226 37.085345 100 
     sum(r0[, 1:900]) 6.224850 6.449210 6.728681 6.705366 6.943689 7.565842 100 
       sum(m0) 1.110073 1.145906 1.175224 1.168696 1.197889 1.269589 100 
sum(colSums(m0)[1:900]) 1.113834 1.141411 1.178913 1.168312 1.201827 1.408785 100 
     sumSub(m0, 1:900) 1.337188 1.368383 1.404744 1.390846 1.415434 2.459361 100 

आप unrolling optimization का उपयोग आगे Rcpp संस्करण अनुकूलन करने के लिए कर सकता है।

+0

हां, यह जवाब है। +1। मुझे लगता है कि हमने अपनी टिप्पणी को लागू करने से पहले इसे बुलाया है, यह भी एक +1 के लायक है;) वास्तव में, अगर 'योग (colSums (m0) [1: 900]) 'क्या यह अच्छी तरह से हमें अधिक बोझिल' Rcpp'। –

+0

प्रतिक्रिया के लिए धन्यवाद। हाँ मुझे लगता है कि आप बिल्कुल सही हैं। मुख्य मुद्दा मैट्रिक्स की प्रति के लिए स्मृति का आवंटन है। मैट्रिक्स की प्रतिलिपि किए बिना आर में ऐसा करना संभव है? मुझे मैट्रिक्स सबसेट को किसी अन्य स्वयं के लिखित फ़ंक्शन के लिए इनपुट के रूप में चाहिए, योग() फ़ंक्शन बस उदाहरण के रूप में कार्य करता है। – maxatSOflow

+0

असल में, मैं अपने सभी कार्यों को बनाता हूं ताकि वे मैट्रिक्स के सबसेट पर जा सकें। अगर आप एक प्रतिलिपि बनाना नहीं चाहते हैं, तो आपको केवल इस तरह के कार्यों की आवश्यकता होगी। –

0

compiler का उपयोग करते हुए मैं एक समारोह है कि (sum(m0) 16x की बजाय कि 8x) के रूप में तेजी से 2x के बारे में परिणाम हो जाता है अपने अन्य तरीके के रूप में लिखा है:

require(compiler) 

compiler_sum <- cmpfun({function(x) { 
    tmp <- 0 
    for (i in 1:900) 
     tmp <- tmp+sum(x[,i]) 
    tmp 
}}) 

microbenchmark( 
       sum(m0), 
       compiler_sum(m0) 
       ) 
Unit: milliseconds 
      expr  min  lq  mean median  uq  max 
      sum(m0) 1.016532 1.056030 1.107263 1.084503 1.11173 1.634391 
compiler_sum(m0) 7.655251 7.854135 8.000521 8.021107 8.29850 16.760058 
neval 
    100 
    100