GHC에서 클래스 제약 조건으로 함수를 특수화하는 데 문제가 있습니다. 여기에 내 문제의 최소한의 예가 있습니다 : Foo.hs 및 Main.hs. 두 파일을 컴파일하고 (GHC 7.6.2, ghc -O3 Main
) 실행하십시오.제약 조건의 특수화
참고 : Foo.hs
은 실제로 삭제되었습니다. 제약 조건이 필요한 이유를 알고 싶다면 here 코드를 조금 더 볼 수 있습니다. 단일 파일에 코드를 삽입하거나 다른 많은 사소한 변경을하면 GHC는 plusFastCyc
에 대한 호출을 간단히 설명합니다. plusFastCyc
은 GHC가 인라인하기에는 너무 커서 심지어 INLINE
으로 표시된 경우에도 실제 코드에서는 발생하지 않습니다. 요점은 plusFastCyc
에 대한 호출을 전문으로하지 인라인하지 않습니다. plusFastCyc
은 실제 코드의 여러 위치에서 호출되므로 GHC에 강제로 적용 할 수있는 경우에도 그러한 큰 함수를 복제하는 것은 바람직하지 않습니다.
관심의 코드는 여기 재현, Foo.hs
에서 plusFastCyc
입니다 :
{-# 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
파일은 두 드라이버가 있습니다 ~ 83초 경우에 실행되는 2 ~ 3 초 실행 vtTest
, 및 fcTest
을, forall
'd 전문화를 사용하여 -O3로 컴파일됩니다.
다음은 vtTest
시험, 추가 코드가 Unboxed
벡터에 전문되는 core showsInt
이상들, 등, 일반적인 벡터 코드는 fcTest
에 사용된다. 라인 10에서 GHC가 라인 167의 일반 버전과 비교하여 plusFastCyc
의 특수 버전을 작성하고 있음을 알 수 있습니다. 전문화 규칙은 225 행에 있습니다.이 규칙은 270 행에서 실행되어야합니다. (main6
iterate main8 y
를 호출, 그래서 plusFastCyc
는 전문해야하는 위치 main8
입니다.)
내 목표는 plusFastCyc
을 전문으로 빨리 vtTest
로 fcTest
을 확인하는 것입니다. fcTest
에서 GHC.Exts
에서
- 명시 적으로 호출
inline
:이 두 가지 방법을 발견했습니다. plusFastCyc
의Factored m Int
제약 조건을 제거하십시오.
옵션 1은 실제 코드베이스 plusFastCyc
의 매우 큰 기능은 자주 사용하는 작업을하고 있기 때문에 불충분하므로 이는 모든 용도에서 인라인 안된다. 오히려 GHC는 plusFastCyc
의 특수 버전을 호출해야합니다. 옵션 2는 실제 코드에서 제약 조건을 필요로하기 때문에 실제로 옵션이 아닙니다.
나는 (사용하지 않고) INLINE
, INLINABLE
및 SPECIALIZE
을 사용하여 다양한 옵션을 시도했지만 아무 것도 작동하지 않는 것 같습니다. (EDIT : 예제를 작게 만들기 위해 plusFastCyc
을 너무 많이 사용하지 않았기 때문에 INLINE
은 함수가 인라인 될 수 있습니다. plusFastCyc
이 너무 커서 실제 코드에서는 그렇지 않습니다.)이 예제에서는 예제를 최소화하기 전에 많은 match_co
경고가 발생했지만 어떤 match_co: needs more cases
또는 RULE: LHS too complicated to desugar
(및 here) 경고도 표시되지 않습니다. 아마도 "문제"는 규칙의 Factored m Int
제약 조건입니다. 해당 제약 조건을 변경하면 fcTest
은 vtTest
만큼 빠르게 실행됩니다.
GHC에서 뭔가를하고 있습니까? GHC가 plusFastCyc
을 전문으로하지 않는 이유는 무엇입니까? 어떻게 만들 수 있습니까?
UPDATE
문제는 GHC 7.8.2에서 계속 때문에이 질문은 여전히 관련이있다.
방금 * 특정 * m을 전문으로 해 보았습니다. 즉 M입니다. 이 작업은 끝났지 만, 실제 프로그램에서 구체화 된 특정 팬텀 유형을 전문으로 할 수는 없습니다. – crockeea
또한 GHC 버그 보고서 https://ghc.haskell.org/trac/ghc/ticket/8668도 제출했지만 문제는 여전히 열려 있습니다. 버그보고 프로세스를 통해 질문을 정리하는 데 도움이되었으므로 문제가 무엇인지 파악하는 것이 더 쉬워졌습니다. – crockeea
@monojohnny 죄송합니다. 신고 해 주셔서 감사합니다. 저는 GHC에 공정하게 합당한 일을하도록 요구하고 있습니다. 그렇게하지 않을 것입니다. 나는 잘못하고 있는지, 또는 이것이 임시 해결책이 될지도 모르는 컴파일러와의 특이한면이 확실하지 않다. 나는 지금 특정 분야의 도서관에서 전문화와 규칙에 대한 대안을 보았습니다. 그래서 나 자신보다 더 많은 GHC 경험을 가진 커뮤니티의 누군가가 전문 분야를 성취하는 방법을 알고있을 수도 있습니다. – crockeea