[解決済み] 制約条件付き特殊化
質問
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
167行目の一般的なバージョンと比較して。
特殊化のためのルールは 225 行目にあります。私は、このルールは270行目で発火するべきだと考えています。(
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
が、何も動作しないようです。(
EDIT
: を削りすぎたかもしれません。
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でも残っているので、この質問はまだ関連しています。
解決方法を教えてください。
また、GHCでは
SPECIALIZE
タイプクラスのインスタンス宣言です。の(展開された)コードで試してみました。
Foo.hs
は、以下のようにすることで
instance (Num r, V.Vector v r, Factored m r) => Num (VT v m r) where
{-# SPECIALIZE instance ( Factored m Int => Num (VT U.Vector m Int)) #-}
VT x + VT y = VT $ V.zipWith (+) x y
しかし、この変更では、期待された高速化は達成できませんでした。その性能向上を実現したのは
手動
型に特化したインスタンスを追加し
VT U.Vector m Int
を、同じ関数定義で、以下のように記述します。
instance (Factored m Int) => Num (VT U.Vector m Int) where
VT x + VT y = VT $ V.zipWith (+) x y
これには
OverlappingInstances
と
FlexibleInstances
で
LANGUAGE
.
興味深いことに、このサンプルプログラムでは、オーバーラップインスタンスで得られた高速化は、すべての
SPECIALIZE
と
INLINABLE
プラグマ
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】なぜパースエラーになるのか?インデント?
-
[解決済み】Haskellでの挿入ソート
-
[解決済み] エラー haskell: スコープ内にありません。どういう意味ですか?
-
[解決済み] 機能における非網羅的なパターン【重複あり
-
[解決済み] Haskell タプルをリスト化する?
-
[解決済み] モナドはエンドファンクタのカテゴリではただのモノイドですが、何か問題でも?
-
[解決済み] フリーモナドとは何ですか?
-
[解決済み] Haskellで副作用がモナドとしてモデル化されているのはなぜですか?
-
[解決済み] 制約条件付き特殊化
-
[解決済み] GHCでコンパイルした小さなHaskellプログラムを巨大なバイナリにする