จากเอกสารสำหรับ GHC 7.6:
[Y] คุณไม่ต้องการแม้แต่ความเชี่ยวชาญเป็นพิเศษในตอนแรก เมื่อทำการรวบรวมโมดูล M เครื่องมือเพิ่มประสิทธิภาพของ GHC (พร้อม -O) จะพิจารณาฟังก์ชั่นโอเวอร์โหลดระดับสูงสุดแต่ละรายการที่ประกาศใน M โดยอัตโนมัติและเชี่ยวชาญสำหรับประเภทต่าง ๆ ที่เรียกว่าเป็น M เครื่องมือเพิ่มประสิทธิภาพจะพิจารณาฟังก์ชั่นโอเวอร์โหลด และเชี่ยวชาญสำหรับประเภทต่าง ๆ ที่มันถูกเรียกว่าใน M
และ
ยิ่งไปกว่านั้นเมื่อได้รับ SPECIALIZE pragma สำหรับฟังก์ชั่น f GHC จะสร้างความเชี่ยวชาญเฉพาะสำหรับฟังก์ชั่นประเภทเกินพิกัดใด ๆ ที่เรียกโดย f หากอยู่ในโมดูลเดียวกันกับ SPECAGIZE pragma หรือหากไม่มีการเชื่อมโยง; และอื่น ๆ ต่อเนื่อง
ดังนั้น GHC ควรใช้ฟังก์ชันบางส่วน / มากที่สุด / ทั้งหมด (?) ที่ทำเครื่องหมายINLINABLE
โดยไม่มี pragma โดยอัตโนมัติและถ้าฉันใช้ pragma อย่างชัดเจน คำถามของฉันคือ: การเปลี่ยนคำจำกัดความอัตโนมัติโดยอัตโนมัติหรือไม่
นี่เป็นตัวอย่างเล็ก ๆ :
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
GHC เชี่ยวชาญการโทรplus
แต่ไม่ชำนาญ(+)
ในQux
Num
อินสแตนซ์ที่ฆ่าประสิทธิภาพ
อย่างไรก็ตาม pragma ชัดเจน
{-# SPECIALIZE plus :: Foo (Qux Int) -> Foo (Qux Int) -> Foo (Qux Int) #-}
ส่งผลให้มีความเชี่ยวชาญด้านสกรรมกริยาตามที่เอกสารระบุดังนั้นจึง(+)
มีความเชี่ยวชาญและรหัสคือ 30x เร็วขึ้น (ทั้งคู่รวบรวมด้วย-O2
) เป็นพฤติกรรมที่คาดหวังหรือไม่ ฉันควรคาดหวังว่า(+)
จะมีความเชี่ยวชาญด้านการขนส่งโดยเฉพาะด้วยการปฏิบัติที่ชัดเจน?
UPDATE
เอกสารสำหรับ 7.8.2 ยังไม่ได้เปลี่ยนแปลงและพฤติกรรมเหมือนกันดังนั้นคำถามนี้ยังคงเกี่ยวข้อง
plus
ถูกไม่ได้ทำเครื่องหมายเป็น INLINABLE และ 2) simonpj ชี้ให้เห็นว่ามีบาง inlining ที่เกิดขึ้นกับรหัสตั๋ว แต่หลักจาก ตัวอย่างของฉันแสดงให้เห็นว่าไม่มีฟังก์ชั่นใดที่ inline (โดยเฉพาะฉันไม่สามารถกำจัดFoo
นวกรรมิกตัวที่สองได้มิฉะนั้น GHC inline stuff)
plus (Bar v1) = \(Bar v2)-> Bar $ v1 + v2
เพื่อให้ LHS ถูกนำไปใช้อย่างเต็มที่ในไซต์การโทร มันได้รับการ inline และจากนั้นจะเชี่ยวชาญในการเตะ?
plus
นำไปใช้อย่างเต็มที่โดยเฉพาะเนื่องจากการเชื่อมโยงเหล่านั้น แต่ในความเป็นจริงฉันมีความเชี่ยวชาญน้อยลง : การโทรไปplus
ยังไม่เฉพาะเจาะจง ฉันไม่มีคำอธิบายสำหรับเรื่องนี้ แต่ตั้งใจที่จะทิ้งไว้เพื่อคำถามอื่นหรือหวังว่ามันจะได้รับการแก้ไขในคำตอบของคำถามนี้