जीएचसी में ऑटो-विशेषज्ञता की परिवर्तनशीलता


392

GHC 7.6 के लिए डॉक्स से :

[Y] ou अक्सर पहली जगह में विशेषज्ञ की आवश्यकता नहीं है। मॉड्यूल M को संकलित करते समय, GHC का ऑप्टिमाइज़र (-O) स्वचालित रूप से M में घोषित प्रत्येक शीर्ष-स्तरीय अतिभारित फ़ंक्शन पर विचार करता है, और इसे विभिन्न प्रकारों के लिए माहिर करता है जिस पर इसे M. कहा जाता है। ऑप्टिमाइज़र प्रत्येक आयातित INLABLE ओवरलोड फ़ंक्शन को भी मानता है, और इसे विभिन्न प्रकारों के लिए माहिर करता है जिस पर इसे एम कहा जाता है।

तथा

इसके अलावा, एक फ़ंक्शन च के लिए एक विशेष प्रज्ञा दिया जाता है, जीएचसी स्वचालित रूप से किसी भी प्रकार के वर्ग-अधिभारित कार्यों के लिए विशेषज्ञता का निर्माण करेगा जिसे एफ कहा जाता है, यदि वे विशेष मॉड्यूल के रूप में एक ही मॉड्यूल में हैं, या यदि वे शामिल नहीं हैं; और इतने पर, सकर्मक रूप से।

तो जीएचसी को स्वचालित रूप से कुछ / सबसे / सभी (?) कार्यों INLINABLE को एक प्रज्ञा के बिना चिह्नित करना चाहिए , और यदि मैं एक स्पष्ट प्रज्ञा का उपयोग करता हूं, तो विशेषज्ञता सकर्मक है। मेरा सवाल है: क्या ऑटो- स्पेशलाइज़ेशन ट्रांजिटिव है?

विशेष रूप से, यहाँ एक छोटा सा उदाहरण है:

Main.hs:

import Data.Vector.Unboxed as U
import Foo

main =
    let y = Bar $ Qux $ U.replicate 11221184 0 :: Foo (Qux Int)
        (Bar (Qux ans)) = iterate (plus y) y !! 100
    in putStr $ show $ foldl1' (*) ans

Foo.hs:

module Foo (Qux(..), Foo(..), plus) where

import Data.Vector.Unboxed as U

newtype Qux r = Qux (Vector r)
-- GHC inlines `plus` if I remove the bangs or the Baz constructor
data Foo t = Bar !t
           | Baz !t

instance (Num r, Unbox r) => Num (Qux r) where
    {-# INLINABLE (+) #-}
    (Qux x) + (Qux y) = Qux $ U.zipWith (+) x y

{-# INLINABLE plus #-}
plus :: (Num t) => (Foo t) -> (Foo t) -> (Foo t)
plus (Bar v1) (Bar v2) = Bar $ v1 + v2

जीएचसी कॉल करने में माहिर है plus, लेकिन उस उदाहरण में विशेषज्ञ नहीं है जो प्रदर्शन को मारता है।(+)Qux Num

हालांकि, एक स्पष्ट व्यावहारिक

{-# SPECIALIZE plus :: Foo (Qux Int) -> Foo (Qux Int) -> Foo (Qux Int) #-}

डॉक्स संकेत के रूप में सकर्मक विशेषज्ञता में परिणाम है, इसलिए (+)विशिष्ट है और कोड 30x तेज (दोनों के साथ संकलित -O2) है। क्या यह अपेक्षित व्यवहार है? क्या मुझे केवल (+)एक स्पष्ट प्रज्ञा के साथ विशेष रूप से पारगमन की उम्मीद करनी चाहिए ?


अपडेट करें

7.8.2 के लिए डॉक्स नहीं बदले हैं, और व्यवहार समान है, इसलिए यह प्रश्न अभी भी प्रासंगिक है।


33
मुझे उत्तर नहीं पता है, लेकिन ऐसा लगता है कि यह संबंधित हो सकता है: ghc.haskell.org/trac/ghc/ticket/5928 संभवतः एक नया टिकट खोलने या अपनी जानकारी को जोड़ने के लायक है अगर आपको लगता है कि यह 5928 से संबंधित है
jberryman

6
@jberryman उस टिकट और मेरे प्रश्न के बीच दो अंतर प्रतीत होते हैं: 1) टिकट में, समान को INLINABLE और 2 के रूप में चिह्नित नहीं कियाplus गया था ) सिमोनज ने संकेत दिया कि टिकट कोड के साथ कुछ इनलाइनिंग चल रही थी, लेकिन कोर से मेरे उदाहरण से पता चलता है कि कोई भी फ़ंक्शन इनबिल्ड नहीं था (विशेष रूप से, मैं दूसरे कंस्ट्रक्टर से छुटकारा नहीं पा सकता था, अन्यथा जीएचसी इनबिल्ड सामान)। Foo
क्रॉकेए

5
आह ठीक है। जब आप परिभाषित करते हैं तो क्या होता है plus (Bar v1) = \(Bar v2)-> Bar $ v1 + v2, ताकि कॉल साइट पर एलएचएस पूरी तरह से लागू हो? क्या यह इनबिल्ड हो जाता है और फिर स्पेशलाइजेशन किक करता है?
जिब्रीमैन

3
@jberryman मजेदार आपको पूछना चाहिए। मैं इस सवाल के साथ उस सड़क से नीचे उतर गया हूं, जिसके कारण यह ट्रैस रिपोर्ट आई । मेरे पास मूल plusरूप से उन लिंक के कारण विशेष रूप से पूरी तरह से लागू होने के लिए कॉल था , लेकिन वास्तव में मुझे कम विशेषज्ञता प्राप्त हुई: कॉल plusया तो विशेष नहीं थी। मेरे पास इसके लिए कोई स्पष्टीकरण नहीं है, लेकिन यह एक और प्रश्न के लिए छोड़ने का इरादा था, या आशा है कि यह इस एक के जवाब में हल हो जाएगा।
क्रॉकेआ

11
से ghc.haskell.org/trac/ghc/wiki/ReportABug : "संदेह में, तो बस अपने बग रिपोर्ट।" आपको बुरा महसूस नहीं करना चाहिए, विशेष रूप से क्योंकि वास्तव में अनुभवी हेकलर की पर्याप्त संख्या आपके प्रश्न का उत्तर देने का तरीका नहीं जानती है। इस तरह के परीक्षण के मामले शायद जीएचसी देवों के लिए वास्तव में मूल्यवान हैं। वैसे भी शुभकामनाएँ! यदि आप टिकट फाइल करते हैं तो सवाल अपडेट करें
jberryman

जवाबों:


4

छोटे जवाब:

प्रश्न के प्रमुख बिंदु, जैसा कि मैं उन्हें समझता हूं, निम्नलिखित हैं:

  • "ऑटो-स्पेशलाइज़ेशन ट्रांज़िटिव है?"
  • क्या मुझे केवल एक स्पष्ट प्रज्ञा के साथ सकारत्मक रूप से विशिष्ट होने की उम्मीद (+) करनी चाहिए?
  • (जाहिरा तौर पर इरादा) क्या यह जीएचसी का बग है? क्या यह प्रलेखन के साथ असंगत है?

AFAIK, उत्तर नहीं हैं, ज्यादातर हाँ, लेकिन अन्य साधन हैं, और नहीं।

कोड इनलाइनिंग और टाइप एप्लिकेशन विशेषज्ञता गति (निष्पादन समय) और कोड आकार के बीच एक व्यापार-बंद है। डिफ़ॉल्ट स्तर कोड को फुलाए बिना कुछ स्पीडअप प्राप्त करता है। अधिक विस्तृत स्तर चुनना SPECIALISEप्रोग्मा के माध्यम से प्रोग्रामर के विवेक पर छोड़ दिया जाता है ।

स्पष्टीकरण:

ऑप्टिमाइज़र प्रत्येक आयातित INLINABLE ओवरलोड फ़ंक्शन को भी मानता है, और इसे विभिन्न प्रकारों के लिए माहिर करता है, जिस पर इसे एम कहा जाता है।

मान लीजिए fकि एक फंक्शन एक प्रकार है जिसमें एक प्रकार का वैरिएबल शामिल aहोता है जो एक टाइप क्लास द्वारा विवश होता है C a। डिफ़ॉल्ट रूप से GHC fएक प्रकार के अनुप्रयोग के लिए सम्मान के साथ माहिर है (के aलिए प्रतिस्थापन t) यदि fउस प्रकार के अनुप्रयोग को स्रोत कोड में (ए) उसी मॉड्यूल में किसी भी फ़ंक्शन के साथ कहा जाता है, या (बी) यदि fचिह्नित किया गया है INLINABLE, तो कोई अन्य मॉड्यूल जो आयात करता है f से B। इस प्रकार, ऑटो-स्पेशलाइजेशन सकर्मक नहीं है, यह केवल INLINABLEआयात किए गए कार्यों को छूता है और स्रोत कोड में कॉल किया जाता है A

आपके उदाहरण में, यदि आप Numनिम्न के उदाहरण को फिर से लिखते हैं:

instance (Num r, Unbox r) => Num (Qux r) where
    (+) = quxAdd

quxAdd (Qux x) (Qux y) = Qux $ U.zipWith (+) x y
  • quxAddद्वारा विशेष रूप से आयात नहीं किया जाता है MainMainके उदाहरण शब्दकोश का आयात करता है Num (Qux Int), और इस शब्दकोश में quxAddरिकॉर्ड होता है (+)। हालाँकि, यद्यपि शब्दकोश आयात किया गया है, शब्दकोश में प्रयुक्त सामग्री नहीं है।
  • plusकॉल नहीं करता है quxAdd, यह (+)उदाहरण के शब्दकोश में रिकॉर्ड के लिए संग्रहीत फ़ंक्शन का उपयोग करता है Num t। यह डिक्शनरी Mainकंपाइलर द्वारा कॉल साइट (इन ) पर सेट की गई है।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.