जीएचसी कार्यों को याद नहीं करता है।
हालांकि, यह कोड में किसी दिए गए अभिव्यक्ति को प्रति बार एक बार गणना करता है कि इसके आसपास के लैम्ब्डा-अभिव्यक्ति दर्ज की जाती है, या सबसे अधिक बार यह शीर्ष स्तर पर होती है। निर्धारण जहां लैम्ब्डा-अभिव्यक्ति कर रहे हैं एक छोटे से मुश्किल है जब आप अपने उदाहरण की तरह वाक्यात्मक चीनी का उपयोग किया जा सकता है, तो चलो बराबर desugared वाक्य रचना करने के लिए इन कन्वर्ट करते हैं:
m1' = (!!) (filter odd [1..]) -- NB: See below!
m2' = \n -> (!!) (filter odd [1..]) n
(नोट: हास्केल 98 रिपोर्ट वास्तव में एक छोड़ दिया ऑपरेटर का वर्णन करता है (a %)
तरह अनुभाग \b -> (%) a b
के रूप में बराबर है, लेकिन GHC (%) a
करने के लिए इसे desugars। ये तकनीकी रूप से अलग हैं, क्योंकि वे द्वारा seq
। मुझे लगता है कि मैं इस बारे में GHC Trac टिकट प्रस्तुत हो सकता है प्रतिष्ठित किया जा सकता।)
इस को देखते हुए, आप कर सकते हैं देखें कि m1'
में, अभिव्यक्ति filter odd [1..]
निहित नहीं है I n किसी भी lambda- अभिव्यक्ति, तो यह केवल आपके प्रोग्राम के प्रति रन के बाद गणना की जाएगी, जबकि m2'
, filter odd [1..]
प्रत्येक बार लैम्ब्डा-अभिव्यक्ति दर्ज की जाएगी, यानी m2'
के प्रत्येक कॉल पर गणना की जाएगी। इससे आप जो समय देख रहे हैं उसमें अंतर बताते हैं।
दरअसल, कुछ ऑप्टिमाइज़ेशन विकल्पों के साथ जीएचसी के कुछ संस्करण उपरोक्त वर्णन से अधिक मूल्य साझा करेंगे। यह कुछ स्थितियों में समस्याग्रस्त हो सकता है। उदाहरण के लिए, समारोह
f = \x -> let y = [1..30000000] in foldl' (+) 0 (y ++ [x])
पर विचार
GHC देख सकते हैं कि y
f = let y = [1..30000000] in \x -> foldl' (+) 0 (y ++ [x])
इस मामले में करने के लिए x
पर निर्भर करते हैं और फिर से लिखने नहीं करता समारोह, नए संस्करण में काफी कम कुशल है, क्योंकि यह होगा स्मृति से लगभग 1 जीबी पढ़ने के लिए जहां y
संग्रहीत किया जाता है, जबकि मूल संस्करण निरंतर स्थान पर चलाया जाता है और प्रोसेसर के कैश में फिट होता है। वास्तव में, GHC 6.12.1 के तहत, समारोह f
लगभग दो बार के रूप में तेजी से जब बिना अनुकूलन संकलित की तुलना में यह -O2
साथ संकलित किया गया है है।
मूल्यांकन करने की लागत (फिल्टर विषम [1 ..]) अभिव्यक्ति शून्य के करीब है - यह सभी के बाद आलसी सूची है, इसलिए असली लागत (x !! 10000000) एप्लिकेशन में है जब सूची वास्तव में है का मूल्यांकन किया। इसके अलावा, एम 1 और एम 2 दोनों को कम से कम एक परीक्षण के भीतर -O2 और -O1 (मेरे ghc 6.12.3 पर) का मूल्यांकन किया जाता है: (test = m1 10000000 'seq' m1 10000000)। हालांकि कोई फर्क नहीं पड़ता है जब कोई अनुकूलन ध्वज निर्दिष्ट नहीं किया जाता है। और आपके "एफ" के दोनों प्रकारों में ऑप्टिमाइज़ेशन के बावजूद 5356 बाइट्स का अधिकतम निवास है, वैसे (कम कुल आवंटन के साथ -ओ 2 का उपयोग किया जाता है)। –
@ एडका: 'f' की उपरोक्त परिभाषा के साथ, इस परीक्षण कार्यक्रम को आजमाएं:' main = interact $ unlines। (शो। नक्शा एफ पढ़ें)। lines'; '-O2' के साथ या बिना संकलित करें; फिर 'echo 1 | ।/Main'। यदि आप 'मुख्य = प्रिंट (एफ 5)' जैसे परीक्षण लिखते हैं, तो 'y' कचरा इकट्ठा किया जा सकता है क्योंकि इसका उपयोग किया जाता है और दोनों' एफ 'के बीच कोई अंतर नहीं होता है। –
एर, यह निश्चित रूप से 'नक्शा (शो। एफ। पढ़ा जाना चाहिए' होना चाहिए। और अब जब मैंने जीएचसी 6.12.3 डाउनलोड किया है, तो मुझे जीएचसी 6.12.1 के समान परिणाम दिखाई देते हैं। और हां, आप मूल 'एम 1' और' एम 2' के बारे में सही हैं: जीएचसी के संस्करण जो अनुकूलन के साथ इस तरह के भारोत्तोलन को सक्षम करते हैं, 'एम 2' को' एम 1' में बदल देंगे। –