Sınıf kısıtlaması olan bir işlevi uzmanlaştırmak için GHC elde etmekte sorun yaşıyorum. Benim burada sorunun minimal örnek var: Foo.hs ve Main.hs . İki dosya derlenir (GHC 7.6.2, ghc -O3 Main
) ve çalıştırılır.
NOT:
Foo.hs
gerçekten soyulmuş. Kısıtlamanın neden gerekli olduğunu görmek istiyorsanız, burada biraz daha kod görebilirsiniz . Kodu tek bir dosyaya koyarsam veya başka birçok küçük değişiklik yaparsam, GHC sadece çağrıyı sıralar plusFastCyc
. Gerçek kodda bu gerçekleşmeyecektir, çünkü plusFastCyc
işaretlendiğinde bile GHC'nin satır içi olması için çok büyüktür INLINE
. Mesele, satıriçi değil , çağrıyı uzmanlaştırmaktırplusFastCyc
. plusFastCyc
gerçek kodda birçok yerde çağrılır, bu yüzden GHC'yi bunu yapmaya zorlayabilsem bile böyle büyük bir işlevi çoğaltmak istenmez.
İlgi kodudur plusFastCyc
içinde Foo.hs
burada çoğaltılamaz,:
{-# 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
: Dosya, iki sürücüye sahip vtTest
, ~ 3 saniye içinde çalışır, ve fcTest
kullanılarak -o3 ile derlenmiş ~ 83 saniye içinde çalıştığı, forall
d' uzmanlık.
Çekirdek gösterir için vtTest
test ilaveli kodu için özel olan Unboxed
fazla vektörleri Int
genel vektör kod için kullanılır ise, vb s, fcTest
. Hat 10 üzerinde, GHC bir uzman versiyonunu yazıyor görebilirsiniz plusFastCyc
Bu kural hattı 270. (tetiklenmesi gereken inanıyoruz hat uzmanlık için kural hattı 225 üzerinde 167. jenerik sürümüne göre, main6
aramalar iterate main8 y
böylece, main8
olduğu nerede plusFastCyc
uzmanlaşmalı.)
Amacım uzmanlaşmak fcTest
kadar hızlı yapmak . Bunu yapmanın iki yolunu buldum:vtTest
plusFastCyc
- Explicity çağrı
inline
gelenGHC.Exts
içindefcTest
. Factored m Int
Üzerindeki kısıtlamayı kaldırınplusFastCyc
.
Seçenek 1 tatmin edici değildir, çünkü gerçek kod tabanında plusFastCyc
sık kullanılan bir işlem ve çok büyük bir işlevdir, bu nedenle her kullanımda satır içi olmamalıdır. Aksine, GHC'nin özel bir sürümünü çağırmalıdır plusFastCyc
. Seçenek 2 gerçekten bir seçenek değil çünkü gerçek kod kısıtlaması gerekir.
Ben kullanarak (ve kullanmayan) çeşitli seçenekler denedim INLINE
, INLINABLE
ve SPECIALIZE
, ama hiçbir şey işe görünüyor. ( EDIT : plusFastCyc
Benim örnek küçük yapmak için çok fazla INLINE
sıyırmış olabilir , bu nedenle işlevin satır içine neden olabilir. Bu benim gerçek kodda gerçekleşmez çünkü plusFastCyc
çok büyük.) Bu özel örnekte, ben değilim Herhangi bir match_co: needs more cases
veya RULE: LHS too complicated to desugar
(ve burada ) uyarı alıyorum, ancak match_co
örneği en aza indirmeden önce birçok uyarı alıyordum . Muhtemelen, "problem" Factored m Int
kuraldaki kısıtlamadır; bu kısıtlamada değişiklik yaparsam, bu fcTest
kadar hızlı çalışır vtTest
.
GHC'nin sevmediği bir şey mi yapıyorum? GHC neden uzmanlaşmıyor plusFastCyc
ve bunu nasıl yapabilirim?
GÜNCELLEME
GHC 7.8.2'de sorun devam etmektedir, bu nedenle bu soru hala geçerlidir.
m
yaniM
. Bu iş bitti, ama gerçek programdaki belirli fantom türleri için uzmanlaşamıyorum.