2015-10-15 15 views
5

सवाल शीर्षक कहते हैं, मुझे पता है क्यों बाइट संकलित आर कोड (compiler::cmpfun का प्रयोग करके) निम्नलिखित गणितीय समारोह के लिए बराबर Rcpp कोड की तुलना में तेजी है करना चाहते हैं के रूप में:यह आरसीपीपी कोड बाइट संकलित आर से धीमा क्यों है?

func1 <- function(alpha, tau, rho, phi) { 
    abs((alpha + 1)^(tau) * phi - rho * (1- (1 + alpha)^(tau))/(1 - (1 + alpha))) 
} 

चूंकि यह एक सरल संख्यात्मक ऑपरेशन है , मैं बाइट संकलित आर (func1c और func2c) से बहुत तेज़ होने के लिए आरसीपीपी (funcCpp और funcCpp2) की अपेक्षा करता था, खासकर जब आरको संग्रहीत करने के लिए अधिक ओवरहेड होगा या इसे पुन: सम्मिलित करने की आवश्यकता होगी। तथ्य यह प्रतिपादक कंप्यूटिंग में दो बार आर में स्मृति आवंटन (func1c बनाम func2c) है, जो विशेष रूप से counterintuitive लगता है, के बाद से n बड़ी है की तुलना में तेजी है। मेरे अन्य अनुमान है कि शायद compiler::cmpfun कुछ जादू बंद खींच रहा है, लेकिन मैं अगर है कि वास्तव में मामला है पता करने के लिए चाहते हैं।

तो सच में, दो बातें मुझे पता करना चाहते हैं कर रहे हैं:

  1. क्यों हैं funcCpp और funcCpp2 func1c और func2c की तुलना में धीमी? (Rcpp की तुलना में धीमी संकलित आर कार्यों)

  2. क्यों funcCpp func2 की तुलना में धीमी है? (Rcpp कोड शुद्ध आर की तुलना में धीमी)

Fwiw, यहाँ मेरी सी ++ और आर संस्करण डेटा

user% g++ --version 
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 
Apple LLVM version 7.0.0 (clang-700.0.72) 
Target: x86_64-apple-darwin14.3.0 
Thread model: posix 

user% R --version 
R version 3.2.2 (2015-08-14) -- "Fire Safety" 
Copyright (C) 2015 The R Foundation for Statistical Computing 
Platform: x86_64-apple-darwin14.5.0 (64-bit) 

है और यहाँ आर और Rcpp कोड है:

library(Rcpp) 
library(rbenchmark) 

func1 <- function(alpha, tau, rho, phi) { 
    abs((1 + alpha)^(tau) * phi - rho * (1- (1 + alpha)^(tau))/(1 - (1 + alpha))) 
} 

func2 <- function(alpha, tau, rho, phi) { 
    pval <- (alpha + 1)^(tau) 
    abs(pval * phi - rho * (1- pval)/(1 - (1 + alpha))) 
} 

func1c <- compiler::cmpfun(func1) 
func2c <- compiler::cmpfun(func2) 

func3c <- Rcpp::cppFunction(' 
    double funcCpp(double alpha, int tau, double rho, double phi) { 
     double pow_val = std::exp(tau * std::log(alpha + 1.0)); 
     double pAg = rho/alpha; 
     return std::abs(pow_val * (phi - pAg) + pAg); 
    }') 

func4c <- Rcpp::cppFunction(' 
    double funcCpp2(double alpha, int tau, double rho, double phi) { 
     double pow_val = pow(alpha + 1.0, tau) ; 
     double pAg = rho/alpha; 
     return std::abs(pow_val * (phi - pAg) + pAg); 
    }') 

res <- benchmark(
      func1(0.01, 200, 100, 1000000), 
      func1c(0.01, 200, 100, 1000000), 
      func2(0.01, 200, 100, 1000000), 
      func2c(0.01, 200, 100, 1000000), 
      func3c(0.01, 200, 100, 1000000), 
      func4c(0.01, 200, 100, 1000000), 
      funcCpp(0.01, 200, 100, 1000000), 
      funcCpp2(0.01, 200, 100, 1000000), 
      replications = 100000, 
      order='relative', 
      columns=c("test", "replications", "elapsed", "relative")) 

और यहाँ उत्पादन है rbenchmark:

       test replications elapsed relative 
    func1c(0.01, 200, 100, 1e+06)  100000 0.349 1.000 
    func2c(0.01, 200, 100, 1e+06)  100000 0.372 1.066 
funcCpp2(0.01, 200, 100, 1e+06)  100000 0.483 1.384 
    func4c(0.01, 200, 100, 1e+06)  100000 0.509 1.458 
    func2(0.01, 200, 100, 1e+06)  100000 0.510 1.461 
    funcCpp(0.01, 200, 100, 1e+06)  100000 0.524 1.501 
    func3c(0.01, 200, 100, 1e+06)  100000 0.546 1.564 
    func1(0.01, 200, 100, 1e+06)  100000 0.549 1.573K 
+7

func1c' तेजी से 'func2c' कचरा कलेक्टर या अन्य मुश्किल से निर्धारित कारणों की वजह से संभावना है कि'। कई बार अपना 'बेंचमार्क' कॉल चलाएं और आप उन दो कार्यों को रैंकिंग में स्थान स्विच कर देखेंगे। कुछ ऐसा मापने की कोशिश करना जो केवल 1 माइक्रोसॉन्ड चलाने के लिए बहुत मुश्किल है। , बिल्कुल हाँ - –

+2

@bunk "यह वास्तव में है कि आश्चर्य की बात सी कार्यों तेजी से सी ++ से कर रहे हैं है?"। इसकी उम्मीद करने का कोई कारण नहीं है। वास्तव में, सी ++ कोड को उसी अबास्ट्रक्शन स्तर के सी कोड की तुलना में * तेज * किया जा सकता है, और कभी धीमा नहीं होना चाहिए। यहां अधिक जानकारी है: http: //programmers.stackexchange।कॉम/ए/2 9 136/2366 –

+0

@ बंक ट्रू, बारह बनाम एक दर्जन है। किसी भी तरह से कोई अंतर नहीं होना चाहिए। "जादू" कि आरसीपीपी स्पिन निश्चित रूप से ओवरहेड ले सकते हैं - हालांकि, यहां 'यूएन'/'सुरक्षा' भी कहा जाता है? आर के सी एपीआई का मेरा ज्ञान सबसे अच्छा है लेकिन चूंकि ये सभी तर्क हैं, वहां कोई सुरक्षा आवश्यक नहीं है, क्या वहां होना चाहिए? –

उत्तर

5

यह अनिवार्य रूप से एक बीमार सवाल है। जब आप भी निर्दिष्ट करने के लिए क्या तर्क हैं बिना

func1 <- function(alpha, tau, rho, phi) { 
    abs((alpha + 1)^(tau) * phi - rho * (1- (1 + alpha)^(tau))/(1 - (1 + alpha))) 
} 

का मानना ​​है (यानी अदिश? वेक्टर? बड़ा? छोटे? स्मृति भूमि के ऊपर) तो आप सबसे अच्छा मामले में बस (आधार, कुशल) फ़ंक्शन कॉल का एक छोटा सेट प्राप्त कर सकते हैं सीधे पार्स अभिव्यक्ति से।

और जब से हमारे पास बाइट कंपाइलर था, तब से बाद में आर रिलीज में ल्यूक टियरनी द्वारा सुधार किया गया था, हम जानते हैं कि यह बीजगणितीय अभिव्यक्तियों को अच्छी तरह से करता है।

अब संकलित सी/सी ++ कोड भी अच्छा करता है - लेकिन संकलित कोयड को कॉल करने में ओवरहेड होगा और आप यहां क्या देखते हैं कि "पर्याप्त रूप से पर्याप्त" समस्याओं के लिए, ओवरहेड वास्तव में अमूर्त नहीं होता है।

तो तुम काफी एक ड्रा के साथ खत्म। जहां तक ​​मैं कह सकता हूं आश्चर्यचकित नहीं है।

+0

"लेकिन संकलित coed को कॉल करने में ओवरहेड होगा" - मुझे लगता है कि यह समस्या का क्रूक्स है। वहां कितना ऊपरी है? क्योंकि पाठ्यक्रम के एक पारंपरिक आर समारोह को बुलाकर भी एक उपरांत होता है, और * उपरोक्त आर समारोह में व्यक्तिगत गणितीय परिचालन इस ओवरहेड को लेते हैं। तो यह सी ++ - संकलित फ़ंक्शन को कॉल करने के एक ओवरहेड की तुलना में, * में * अधिक * बड़ा होना चाहिए। –

+0

आप इसका आकलन क्यों नहीं करते? 'आरसीपीपी :: सीपीपीफ़ंक्शन (' शून्य खाली() {} ') के साथ शुरू करें और वहां से जाएं ... –

+0

यह बात नहीं है। यदि आप यह कहते हैं, तो मैं आपको विश्वास करता हूं। मैं समझना चाहता हूं * क्यों *, और मापने से मेरी मदद नहीं होती है। –

संबंधित मुद्दे