2014-08-29 8 views
8

मान लें कि मैं एक छोटे से फ़ंक्शन f से map पास करता हूं। एक छोटे अनिवार्य पाश का उत्पादन करने के लिए map के साथ Haskell इनलाइन f कर सकते हैं? यदि हां, तो हास्केल कैसे ट्रैक करता है कि f वास्तव में क्या कार्य करता है? क्या तीर संयोजकों के साथ भी ऐसा किया जा सकता है?क्या हास्केल इनलाइन फ़ंक्शन एक तर्क के रूप में पारित हो सकता है?

+0

इनलाइनिंग वास्तव में एक सरल सिंटैक्टिक तंत्र है (इसे बाएं हाथ के किनारों के साथ-साथ कार्यों के दाहिने हाथों के साथ बदलना), "कोई भी 'एफ' का सामना करना नहीं है"। निश्चित रूप से यदि आपके पास कहीं भी आपके कोड में 'मानचित्र f' है तो उस कॉलसाइट पर' मानचित्र' को रेखांकित किया जा सकता है, जिस बिंदु पर 'f' भी हो सकता है। – jberryman

उत्तर

12

यदि f एक तर्क के रूप में पारित किया गया है, तो नहीं, शायद नहीं। यदि f शीर्ष-स्तरीय फ़ंक्शन या स्थानीय फ़ंक्शन का नाम है, तो शायद हां।

foobar f = ... map f ... 
-- Probably not inlined. 

foobar = ... map (\ x -> ...) ... 
-- Probably inlined. 

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

इन चीजों के बारे में "निश्चित" होने का एकमात्र तरीका वास्तव में कोड लिखना है, वास्तव में इसे संकलित करना है, और उत्पन्न होने वाले कोर को देखें। और यह जानने का एकमात्र तरीका है कि इससे कोई फर्क पड़ता है (सकारात्मक या नकारात्मक) वास्तव में चीज़ को बेंचमार्क करना है।

+2

पहले मामले में, 'foobar' को आसानी से रेखांकित किया जा सकता है, जिससे 'f' को भी रेखांकित किया जा सकता है। –

+0

निर्भर करता है कि 'f' — पर कॉल करने के अलावा' foobar' कितनी चीजें करता है लेकिन हां, यह निश्चित रूप से संभव है कि यह रेखांकित किया जाएगा। वास्तव में जानने का एकमात्र तरीका देखना है। – MathematicalOrchid

10

हास्केल भाषा की परिभाषा इनलाइन कोड के लिए हास्केल कार्यान्वयन, या किसी भी प्रकार का अनुकूलन करने के लिए जरूरी नहीं है। कोई भी कार्यान्वयन किसी भी अनुकूलन को लागू करने के लिए स्वतंत्र है जिसे उचित समझा जा सकता है।

कहा जा रहा है कि, हास्केल आजकल अक्सर जीएचसी का उपयोग करके चलाया जाता है, जो हास्केल कोड को अनुकूलित करता है। इनलाइनिंग के लिए, जीएचसी कुछ हेरिस्टिक का उपयोग यह तय करने के लिए करता है कि कुछ रेखांकित किया जाना चाहिए या नहीं। सामान्य सलाह -O2 के साथ अनुकूलन को चालू करना और संकलक के आउटपुट की जांच करना है। आप उत्पादित कोर को -ddump-simpl, या -ddump-asm के साथ असेंबली कोड देख सकते हैं। कुछ अन्य flags भी उपयोगी हो सकते हैं।

यदि आप देखते हैं कि जीएचसी उन चीजों को रेखांकित नहीं कर रहा है जो आप चाहते हैं, तो आप {-# INLINE foo #-} और related pragmas के साथ कंपाइलर को संकेत दे सकते हैं।

दिमागी रूप से अनुकूलन अनुकूलन से सावधान रहें, हालांकि। अक्सर, प्रोग्रामर कार्यक्रम के कुछ हिस्सों को अनुकूलित करने के लिए अपना समय व्यतीत करते हैं, जिसमें नगण्य समग्र प्रदर्शन पर प्रभाव डालता है। इससे बचने के लिए, यह आपके कोड को पहले profile पर दृढ़ता से अनुशंसा की जाती है, ताकि आप जान सकें कि आपका प्रोग्राम कितना समय बिताता है।

import qualified Data.Vector.Unboxed as U 
import qualified Data.Vector as V 

plus :: Int -> Int -> Int 
plus = (+) 

sumVect :: V.Vector Int -> Int 
sumVect = V.foldl1 plus 

plusfoldl1 का तर्क है, जो पूर्णांकों का एक वेक्टर संक्षेप में जो परिणाम के रूप में पारित हो जाता है:

+1

यह उपयोगी सलाह है, लेकिन यह वास्तव में पूछे गए प्रश्न का उत्तर नहीं देता है। –

+0

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

1

एक उदाहरण है जहाँ GHC इनलाइन एक समारोह तर्क के रूप में पारित कर दिया करता है। कोर में, plus inlined है और अनुकूलित अनबॉक्स्ड GHC.Prim.+# :: Int# -> Int# -> Int# रहे हैं:

letrec { 
      $s$wfoldlM_loop_s759 
      :: GHC.Prim.Int# -> GHC.Prim.Int# -> GHC.Prim.Int# 
      $s$wfoldlM_loop_s759 = 
      \ (sc_s758 :: GHC.Prim.Int#) (sc1_s757 :: GHC.Prim.Int#) -> 
       case GHC.Prim.tagToEnum# @ Bool (GHC.Prim.>=# sc_s758 ww1_s748) 
       of _ { 
       False -> 
        case GHC.Prim.indexArray# 
         @ Int ww2_s749 (GHC.Prim.+# ww_s747 sc_s758) 
        of _ { (# ipv1_X72o #) -> 
        case ipv1_X72o of _ { GHC.Types.I# y_a5Kg -> 
        $s$wfoldlM_loop_s759 
        (GHC.Prim.+# sc_s758 1#) (GHC.Prim.+# sc1_s757 y_a5Kg) 
        } 
        }; 
       True -> sc1_s757 
       }; } 

कि GHC.Prim.+# sc1_s757 y_a5Kg है। आप फंक्शन plus के अंदर सरल आर्टिमेमेटिक जोड़ सकते हैं और यह कोर अभिव्यक्ति विस्तारित देख सकते हैं।

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