2012-04-11 3 views
31

मुझे हाल ही में पता चला है कि कोई संकलक पैकेज का उपयोग कर आरआईटी के साथ जेआईटी (बस समय में) संकलन का उपयोग कर सकता है (मैं a recent blog post में इस विषय पर अपने निष्कर्षों को सारांशित करता हूं)।आर के साथ जेआईटी का उपयोग करने के लिए संभावित कमियां?

सवाल मैंने पूछा था से एक है:

कोई ख़तरा है? यह सच होने के लिए बहुत अच्छा लगता है, बस कोड के एक लाइन डालें और यही वह है।

आसपास देखने के बाद मुझे जेआईटी के लिए "स्टार्ट अप" समय के साथ एक संभावित समस्या मिल सकती है। लेकिन क्या जेआईटी का उपयोग करते समय सावधान रहना कोई और मुद्दा है?

मुझे लगता है कि आर के वातावरण आर्किटेक्चर के साथ कुछ सीमाएं होनी चाहिए, लेकिन मैं अपने सिर के ऊपर से समस्या का एक सरल उदाहरण नहीं सोच सकता, कोई सुझाव या लाल झंडे बहुत मददगार होंगे?

+0

मुझे प्रदर्शन हिट (प्रारंभिक संकलन (और शायद स्मृति उपयोग में वृद्धि) के अलावा) के बारे में निश्चित नहीं है, लेकिन "नोट: कोई दृश्यमान बाध्यकारी" संदेश अक्सर नौसिखिया के लिए जबरदस्त नहीं हो सकता है (उदाहरण के लिए, ggplot2 का उपयोग करते हुए) और कर सकते हैं टैब-पूर्ण को फेंक दें (कम से कम, वे मेरे लिए हैं) – mweylandt

+0

हाय mweylandt। क्या आपको पता है कि उस त्रुटि मालिश का मतलब क्या है? –

+4

मैं अपने संकुल की विवरण फ़ाइल में 'बाइटकंपाइल: सत्य' डाल रहा हूं क्योंकि मैं नए संस्करण बना रहा हूं और ऐसा लगता है कि यह ठीक काम करता है। मैंने एक छोटा परीक्षण किया 'http: // www.johnmyleswhite.com/नोटबुक/2012/03/31/जुलिआ-आई-लव-आप/टिप्पणी-पृष्ठ -1/# टिप्पणी -192222' और बाइट संकलित संस्करण, ' fib2c' सामान्य से अधिक 4x तेज चला गया, 'fib2a'। कुछ मामलों में आर पहले से ही बाइट संकलन के बिना भी तेज है (उदाहरण के लिए सी का उपयोग कर अत्यधिक वेक्टरकृत कोड) और उन मामलों में स्पष्ट रूप से गति के लिए थोड़ा अवसर है - यह मुख्य रूप से धीमी आर कोड के लिए उपयोगी है। –

उत्तर

4

rpart उदाहरण ऊपर दिए गए, अब यह समस्या नहीं हो रहा है:

library("rpart") 
fo = function() { 
    for(i in 1:500){ 
    rpart(Kyphosis ~ Age + Number + Start, data=kyphosis) 
    } 
} system.time(fo()) 
# user system elapsed 
# 1.212 0.000 1.206 
compiler::enableJIT(3) 
# [1] 3 
system.time(fo()) 
# user system elapsed 
# 1.212 0.000 1.210 

मैं भी अन्य उदाहरण के एक नंबर की कोशिश की है, इस तरह के रूप

  • एक वेक्टर बढ़ रही है;
  • एक समारोह के आसपास mean

सिर्फ एक आवरण है कि मैं हमेशा एक गति-अप नहीं मिलता है, मैं एक महत्वपूर्ण धीमी गति से नीचे का अनुभव नहीं किया है।


R> sessionInfo() 
R version 3.3.0 (2016-05-03) 
Platform: x86_64-pc-linux-gnu (64-bit) 
Running under: Ubuntu 16.04 LTS 
11

rpart के साथ एक साधारण परीक्षण के उत्पादन में सभी मामलों में enableJIT उपयोग करने के लिए नहीं एक सलाह हो सकता है:

library(rpart) 
fo <- function() for(i in 1:500){rpart(Kyphosis ~ Age + Number + Start, data=kyphosis)} 
system.time(fo()) 
#User  System verstrichen 
#2.11  0.00  2.11 

require(compiler) 
enableJIT(3) 
system.time(fo()) 
#User  System verstrichen 
#35.46  0.00  35.60 

किसी भी explanantion?

+1

यह अजीब है, इसलिए लूप को संकलित करने के बारे में कुछ समस्याएं पैदा कर रही हैं। यदि आप इसे सामान्य रूप से संकलित करते हैं तो ऐसा नहीं होगा। http://ideone.com/Nu8IZ, नोट rpart पहले से ही बाइट संकलित है। – Hansi

+7

संकलन एक अच्छा आधा मिनट लेता है: मैं वही (2.8 एस - 42.6 एस) देखता हूं, लेकिन फिर system.time (fo()) कर रहा है फिर से केवल 2.6 एस लेता है। – cbeleites

+1

मुझे संदेह है कि यह एक अप्रत्याशित व्यवहार है ... –

-2

पिछले उत्तर के आगे, प्रयोग से पता चलता है कि लूप के संकलन के साथ समस्या नहीं है, यह बंद होने के संकलन के साथ है। [enableJIT (0) या enableJIT (1) कोड को तेज़ी से छोड़ दें, सक्षम JIT (2) इसे नाटकीय रूप से धीमा कर देता है, और सक्षम JIT (3) पिछले विकल्प की तुलना में थोड़ा तेज़ है (लेकिन अभी भी बहुत धीमा है)]। हंससी की टिप्पणी के विपरीत, cmpfun एक समान हद तक निष्पादन धीमा कर देता है।

+0

ऐसा लगता है कि विभिन्न परिणामों के कारण आर के विभिन्न संस्करण थे। आर 3.3 का उपयोग करना।2 आज, enableJIT (i) वास्तव में एक ही समय (1.21 सेकंड) देता है चाहे मैं 0, 1, 2, या 3 है, मैं दूसरों को व्याख्या छोड़ दूंगा, लेकिन मुझे संदेश यह है कि इसे बिना किसी अनुकूलित किया गया है अब उपयोगकर्ता से मदद करें। – Elroch

0

सिद्धांत रूप में, एक बार बाइट-कोड संकलित और लोड है, यह हमेशा कम से कम के रूप में तेजी से मूल एएसटी दुभाषिए के रूप में व्याख्या की जानी चाहिए। कुछ कोड बड़े स्पीडअप से लाभान्वित होंगे, यह आमतौर पर बहुत से स्केलर ऑपरेशंस और लूप के साथ कोड होता है जहां आर व्याख्या में अधिकतर समय व्यतीत होता है (मैंने 10x स्पीडअप के साथ उदाहरण देखे हैं लेकिन मनमाने ढंग से माइक्रो-बेंचमार्क वास्तव में इसे आवश्यकतानुसार बढ़ा सकते हैं)। कुछ कोड एक ही गति से चलेंगे, यह आमतौर पर कोड अच्छी तरह से वेक्टरकृत होता है और इसलिए व्याख्या में लगभग कोई समय नहीं लगाता है। अब, संकलन खुद धीमा हो सकता है। इसलिए, समय-समय पर संकलक अब कार्यों को संकलित नहीं करता है जब यह अनुमान लगाता है कि यह भुगतान नहीं करेगा (और समय के साथ हेरिस्टिक बदलता है, यह पहले से ही 3.4.x में है)। हेरिस्टिक्स हमेशा इसे सही नहीं मानते हैं, इसलिए ऐसी परिस्थितियां हो सकती हैं जब संकलन का भुगतान नहीं किया जाएगा। विशिष्ट समस्याग्रस्त पैटर्न कोड पीढ़ी, कोड संशोधन और बंद होने पर कब्जे वाले वातावरण की बाइंडिंग में हेरफेर हैं।

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

पैकेज लेखकों के लिए मेरी सिफारिश डिफ़ॉल्ट का उपयोग करना होगा (केवल समय-समय पर संकलन रिलीज संस्करणों में डिफ़ॉल्ट रूप से चालू है, पैकेज स्थापना समय पर बाइट-संकलन अब विकास संस्करण में है)। अगर आपको एक उदाहरण मिलता है जहां बाइट-कोड कंपाइलर अच्छा प्रदर्शन नहीं करता है, तो कृपया एक बग रिपोर्ट सबमिट करें (मैंने पिछले संस्करणों में rpart से जुड़े मामले को भी देखा है)। मैं कोड पीढ़ी और कोड मैनिपुलेशन के खिलाफ और विशेष रूप से गर्म लूप में अनुशंसा करता हूं। इसमें क्लोजर द्वारा कैप्चर किए गए वातावरण में बंद करने, हटाने और डाइंडिंग को सम्मिलित करना शामिल है। निश्चित रूप से गर्म लूप में eval(parse(text= नहीं करना चाहिए (और यह बाइट-संकलन के बिना पहले से ही खराब था)। गतिशील रूप से नए बंद (शाखाओं के बिना) उत्पन्न करने की तुलना में शाखाओं का उपयोग करना हमेशा बेहतर होता है। साथ ही बड़े अभिव्यक्तियों (बिना लूप के) कोड को गतिशील रूप से उत्पन्न करने की तुलना में लूप के साथ कोड लिखना बेहतर होता है। अब बाइट-कोड कंपाइलर के साथ, अब आर में स्केलर्स पर चलने वाले लूप लिखना ठीक है (प्रदर्शन पहले की तरह खराब नहीं होगा, इसलिए प्रदर्शन महत्वपूर्ण भागों के लिए सी पर स्विच किए बिना कोई अक्सर दूर हो सकता है) ।

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