बाधाओं के साथ विशेषज्ञता


156

मुझे जीएचसी होने में समस्या हो रही है ताकि एक वर्ग बाधा के साथ एक फ़ंक्शन को विशेषज्ञ किया जा सके। मैं यहाँ मेरी समस्या का एक न्यूनतम उदाहरण है: Foo.hs और Main.hs । दो फ़ाइलें संकलित (जीएचसी 7.6.2 ghc -O3 Main) , और चलाते हैं।

नोट: Foo.hs वास्तव में नीचे छीन लिया है। यदि आप यह देखना चाहते हैं कि बाधा की आवश्यकता क्यों है, तो आप यहां थोड़ा और कोड देख सकते हैं । अगर मैं किसी एकल फ़ाइल में कोड डालता हूं या कई अन्य छोटे बदलाव करता हूं, तो जीएचसी केवल कॉल को बताता है plusFastCyc। यह वास्तविक कोड में नहीं होगा क्योंकि plusFastCycचिह्नित होने पर भी जीएचसी इनलाइन के लिए बहुत बड़ा है INLINE। बिंदु कॉल को विशेषज्ञ बनाना है plusFastCyc, इसे इनलाइन नहीं करना है। plusFastCycको वास्तविक कोड में कई स्थानों पर कहा जाता है, इसलिए इतने बड़े फ़ंक्शन को डुप्लिकेट करना वांछनीय नहीं होगा, भले ही मैं इसे करने के लिए GHC को बाध्य कर सकता हूं।

ब्याज की कोड plusFastCycमें Foo.hs, यहाँ पुन: प्रस्तुत किया गया है:

{-# INLINEABLE plusFastCyc #-}
{-# SPECIALIZE plusFastCyc :: 
         forall m . (Factored m Int) => 
              (FastCyc (VT U.Vector m) Int) -> 
                   (FastCyc (VT U.Vector m) Int) -> 
                        (FastCyc (VT U.Vector m) Int) #-}

-- Although the next specialization makes `fcTest` fast,
-- it isn't useful to me in my real program because the phantom type M is reified
-- {-# SPECIALIZE plusFastCyc :: 
--          FastCyc (VT U.Vector M) Int -> 
--               FastCyc (VT U.Vector M) Int -> 
--                    FastCyc (VT U.Vector M) Int #-}

plusFastCyc :: (Num (t r)) => (FastCyc t r) -> (FastCyc t r) -> (FastCyc t r)
plusFastCyc (PowBasis v1) (PowBasis v2) = PowBasis $ v1 + v2

Main.hs: फ़ाइल दो ड्राइवरों है vtTest, जो ~ 3 सेकंड में चलाता है, और fcTestका उपयोग करते समय -O3 साथ संकलित जो ~ 83 सेकंड में चलता है, forall'घ विशेषज्ञता।

कोर शो है कि के लिए vtTestपरीक्षण, इसके कोड को विशेष की जा रही है Unboxedपर सदिशों Int, रों, आदि, जबकि सामान्य वेक्टर कोड के लिए प्रयोग किया जाता है fcTest। लाइन 10 पर, आप देख सकते हैं कि जीएचसी plusFastCycलाइन 167 पर जेनेरिक संस्करण की तुलना में , का एक विशेष संस्करण लिखता है। विशेषज्ञता के लिए नियम लाइन 225 पर है। मेरा मानना ​​है कि इस नियम को लाइन 270 पर आग लगनी चाहिए। ( main6कॉल iterate main8 y, ऐसा main8है) जहां plusFastCycविशेष होना चाहिए।)

मेरा लक्ष्य विशेषज्ञता fcTestसे उतनी ही तेजी vtTestसे आगे बढ़ना है plusFastCyc। मुझे ऐसा करने के दो तरीके मिले हैं:

  1. स्पष्ट रूप से कॉल inlineसे GHC.Extsमें fcTest
  2. निकालें Factored m Intपर बाधा plusFastCyc

विकल्प 1 असंतोषजनक है क्योंकि वास्तविक कोड बेस plusFastCycमें अक्सर उपयोग किया जाने वाला ऑपरेशन और एक बहुत बड़ा कार्य होता है, इसलिए इसे हर उपयोग में इनलाइन नहीं किया जाना चाहिए। बल्कि, जीएचसी को विशेष संस्करण का आह्वान करना चाहिए plusFastCyc। विकल्प 2 वास्तव में एक विकल्प नहीं है क्योंकि मुझे वास्तविक कोड में बाधा की आवश्यकता है।

मैं का उपयोग कर (और का उपयोग नहीं) विकल्प की एक किस्म की कोशिश की है INLINE, INLINABLEऔर SPECIALIZE, लेकिन कुछ भी काम करने लगता है। ( EDIT : मैंने plusFastCycअपने उदाहरण को छोटा बनाने के लिए बहुत अधिक छीन लिया है , इसलिए INLINEफ़ंक्शन के इनलाइन होने का कारण हो सकता है। यह मेरे वास्तविक कोड में नहीं होता है क्योंकि plusFastCycयह बहुत बड़ा है।) इस विशेष उदाहरण में, मैं नहीं हूं। किसी भी match_co: needs more casesया RULE: LHS too complicated to desugar(और यहां ) चेतावनी प्राप्त करना, हालांकि match_coउदाहरण को छोटा करने से पहले मुझे कई चेतावनी मिल रही थी । वर्तमान में, "समस्या" Factored m Intनियम में बाधा है; अगर मैं उस बाधा में बदलाव करता हूं, तो fcTestउतनी ही तेजी से चलता है vtTest

मैं कुछ कर रहा हूँ GHC पसंद नहीं है? जीएचसी विशेषज्ञ क्यों नहीं होगा plusFastCyc, और मैं इसे कैसे बना सकता हूं?

अपडेट करें

यह समस्या GHC 7.8.2 में बनी हुई है, इसलिए यह प्रश्न अभी भी प्रासंगिक है।


3
मैंने सिर्फ एक विशिष्ट के लिए विशेषज्ञता की कोशिश की m, अर्थात् M। यह काम मिल गया, लेकिन मैं वास्तविक कार्यक्रम में विशिष्ट प्रेत प्रकारों के लिए विशेषज्ञ नहीं हो सकता, क्योंकि वे पुनरीक्षित हैं।
क्रॉकेए

मैंने GHC बग रिपोर्ट ghc.haskell.org/trac/ghc/ticket/8668 भी सबमिट की, लेकिन समस्या अभी भी खुली है। बग रिपोर्ट प्रक्रिया ने मुझे प्रश्न को थोड़ा साफ करने में मदद की, इसलिए उम्मीद है कि यह पता लगाना आसान होगा कि क्या चल रहा है।
crockeea

@monojohnny यह सुनने के लिए क्षमा करें, मेरा मानना ​​है कि आप इसे इस तरह से ध्वजांकित कर सकते हैं। मुझे लगता है कि मैं GHC को कुछ उचित करने के लिए कह रहा हूं, और यह ऐसा नहीं करेगा। मुझे यकीन नहीं है कि अगर मैं इसे गलत कर रहा हूं, या यदि यह कंपाइलर के साथ एक आइडिओसिंक्रैसी है जिसमें वर्कअराउंड हो सकता है। मैंने हैकिंग पर कुछ विशिष्ट लाइब्रेरी में विशेषज्ञता और नियमों के लिए वर्कअराउंड देखा है जो इस समय मुझसे बचता है, इसलिए मैं समुदाय में किसी से उम्मीद कर रहा हूं कि अपने आप से अधिक जीएचसी अनुभव वाले व्यक्ति को पता हो सकता है कि विशेषज्ञता कैसे प्राप्त करें।
क्रॉकिया

1
मैं अपनी टिप्पणी के स्वर के लिए माफी माँगता हूँ - यह इस साइट के लिए मेरा सबसे अच्छा योगदान नहीं है - आपकी पोस्ट के साथ वास्तव में कुछ भी गलत नहीं है (यह मेरी समझ की कमी है जो मुझे लगता है कि मेरी नाराज़गी का स्रोत था!)
monojohnny

@monojohnny माफी स्वीकार की गई, लेकिन यह बहुत बुरा है कि
डाउनवोट

जवाबों:


5

जीएचसी SPECIALIZEएक प्रकार-श्रेणी के उदाहरण घोषणा के लिए एक विकल्प भी देता है । मैंने Foo.hsनिम्न डालकर, (विस्तारित) कोड के साथ यह कोशिश की :

instance (Num r, V.Vector v r, Factored m r) => Num (VT v m r) where 
    {-# SPECIALIZE instance ( Factored m Int => Num (VT U.Vector m Int)) #-}
    VT x + VT y = VT $ V.zipWith (+) x y

यह परिवर्तन, हालांकि, वांछित गति को प्राप्त नहीं किया था। उस प्रदर्शन में सुधार ने मैन्युअल रूप से एक VT U.Vector m Intही फ़ंक्शन परिभाषाओं के साथ टाइप के लिए एक विशेष उदाहरण जोड़ रहा था , जो निम्नानुसार था:

instance (Factored m Int) => Num (VT U.Vector m Int) where 
    VT x + VT y = VT $ V.zipWith (+) x y

इसके लिए ऐड OverlappingInstancesऔर FlexibleInstancesइन की आवश्यकता होती है LANGUAGE

दिलचस्प बात यह है कि उदाहरण कार्यक्रम में, ओवरलैपिंग उदाहरण के साथ प्राप्त किया गया स्पीडअप तब भी बना रहता है जब आप प्रत्येक SPECIALIZEऔर INLINABLEप्राग्म को हटा देते हैं ।


निश्चित रूप से इष्टतम नहीं है, लेकिन यह पहला समाधान है जो वास्तव में लक्ष्य को पूरा करता है, इसलिए मुझे लगता है कि मैं इसे अभी के लिए ले
जाऊंगा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.