Từ các tài liệu cho GHC 7.6:
[Y] ou thường không cần đến pragma ĐẶC BIỆT ngay từ đầu. Khi biên dịch mô-đun M, trình tối ưu hóa của GHC (với -O) sẽ tự động xem xét từng hàm quá tải cấp cao nhất được khai báo trong M và chuyên về nó cho các loại khác nhau mà nó được gọi trong M. Trình tối ưu hóa cũng xem xét từng chức năng bị quá tải INLINEABLE, và chuyên về nó cho các loại khác nhau mà nó được gọi là M.
và
Ngoài ra, được cung cấp một pragma ĐẶC BIỆT cho một hàm f, GHC sẽ tự động tạo các chuyên môn hóa cho bất kỳ hàm quá tải loại lớp nào được gọi bởi f, nếu chúng nằm trong cùng một mô-đun như pragma ĐẶC BIỆT, hoặc nếu chúng là TUYỆT VỜI; và cứ thế, quá cảnh.
Vì vậy, GHC nên tự động chuyên môn hóa một số / hầu hết / tất cả (?) Hàm được đánh dấu INLINABLE
mà không có pragma và nếu tôi sử dụng một pragma rõ ràng, thì chuyên môn hóa là bắc cầu. Câu hỏi của tôi là: là tự động quá trình chuyên môn hóa?
Cụ thể, đây là một ví dụ nhỏ:
Chính.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 chuyên các cuộc gọi đến plus
, nhưng không chuyên (+)
trong Qux
Num
ví dụ mà giết hiệu suất.
Tuy nhiên, một pragma rõ ràng
{-# SPECIALIZE plus :: Foo (Qux Int) -> Foo (Qux Int) -> Foo (Qux Int) #-}
kết quả trong bắc cầu chuyên môn như các tài liệu cho thấy, vì vậy (+)
chuyên và mã là 30x nhanh hơn (cả biên soạn với -O2
). Đây có phải là hành vi dự kiến? Tôi chỉ nên mong đợi (+)
được chuyên môn hóa quá mức với một pragma rõ ràng?
CẬP NHẬT
Các tài liệu cho 7.8.2 không thay đổi và hành vi là như nhau, vì vậy câu hỏi này vẫn có liên quan.
plus
đã không đánh dấu là INLINABLE và 2) simonpj chỉ ra rằng có một số nội tuyến xảy ra với mã vé, nhưng cốt lõi từ ví dụ của tôi cho thấy rằng không có chức năng nào được nội tuyến (đặc biệt, tôi không thể thoát khỏi hàm tạo thứ hai Foo
, nếu không thì nội dung được GHC nội tuyến).
plus (Bar v1) = \(Bar v2)-> Bar $ v1 + v2
, để LHS được áp dụng đầy đủ tại trang web cuộc gọi? Liệu nó có được nội tuyến và sau đó chuyên môn hóa đá trong?
plus
áp dụng đầy đủ cụ thể do các liên kết đó, nhưng thực tế tôi đã ít chuyên môn hóa hơn : cuộc gọi đến plus
cũng không chuyên biệt. Tôi không có lời giải thích cho điều đó, nhưng đã có ý định để nó cho một câu hỏi khác, hoặc hy vọng rằng nó sẽ được giải quyết trong một câu trả lời cho câu hỏi này.