GHCにクラス制約のある関数を特殊化させるのに問題があります。私はここに私の問題の最低限の例がありますFoo.hsと Main.hsを。2つのファイルがコンパイルされ(GHC 7.6.2、ghc -O3 Main
)、実行されます。
注:
Foo.hs
は実際には削除されています。制約が必要な理由を知りたい場合は、ここでもう少しコードを見ることができます。コードを1つのファイルに配置するか、その他多くの小さな変更を加えた場合、GHCはへの呼び出しを単にインライン化しますplusFastCyc
。plusFastCyc
マークされていても、GHCがインライン化するには大きすぎるため、これは実際のコードでは発生しません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
:ファイルには、2つのドライバがあるvtTest
、〜3秒で実行され、fcTest
使用して-O3でコンパイルしたとき〜83秒で実行され、forall
「D専門に。
コアショーのためのvtTest
試験、付加コードがに特化されているUnboxed
オーバーベクトルInt
汎用ベクトル符号をするために使用されている間などの、fcTest
。10行目では、あなたはGHCがの特殊なバージョンを記述していることがわかりますplusFastCyc
、私は(このルールは、ライン270上の解雇すべきであると信じてライン167上のジェネリックバージョンに比べて専門のためのルールはライン225上で、main6
通話iterate main8 y
ので、main8
ありますどこplusFastCyc
に特化すべきか。)
私の目標は、専門にすることとfcTest
同じくらい速く作ることvtTest
ですplusFastCyc
。これを行う2つの方法を見つけました。
- 明示的に呼び出し
inline
からGHC.Exts
の中でfcTest
。 - の
Factored m Int
制約を削除しますplusFastCyc
。
オプション1は、実際のコードベースでplusFastCyc
は頻繁に使用される操作と非常に大きな関数であるため、満足できません。したがって、使用するたびにインライン化する必要はありません。むしろ、GHCはの特殊なバージョンを呼び出す必要がありplusFastCyc
ます。オプション2は、実際のコードに制約が必要なため、実際にはオプションではありません。
私が使用して(と使用していない)のさまざまなオプションを試してみたINLINE
、INLINABLE
とSPECIALIZE
、何も動いていないようにみえ。(編集:私があまりにも多くを取り除いてplusFastCyc
私の例を小さくしたのでINLINE
、関数がインライン化される可能性があります。これは実際のコードでplusFastCyc
は非常に大きいので起こりません。)この特定の例では、私はそうではありませんいずれかの取得match_co: needs more cases
またはRULE: LHS too complicated to desugar
(とここで私は多くなっていたものの、)警告をmatch_co
例を最小化する前に警告を。おそらく、「問題」はFactored m Int
ルールの制約です。その制約に変更を加えると、とfcTest
同じくらい速く実行されvtTest
ます。
私はGHCが嫌いなことをしていますか?GHCはなぜを特化しないのplusFastCyc
ですか、またどのようにして作成できますか?
更新
問題はGHC 7.8.2でも持続するので、この質問は依然として関連しています。
m
、つまりに特化してみましたM
。これで仕事は完了しましたが、具体化されているため、実際のプログラムで特定のファントムタイプに特化することはできません。