제약이있는 전문화
클래스 제약 조건이있는 함수를 GHC에서 특수화하는 데 문제가 있습니다. 여기 내 문제의 최소한의 예를 가지고 : Foo.hs 및 Main.hs을 . 두 파일은 컴파일 (GHC 7.6.2, ghc -O3 Main
)되어 실행됩니다.
참고 : Foo.hs
실제로 제거되었습니다. 제약 조건이 필요한 이유를 보려면 여기에서 더 많은 코드를 볼 수 있습니다 . 코드를 단일 파일에 넣거나 다른 많은 사소한 변경을 수행하면 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
: 파일은 두 드라이버가 vtTest
, 2 ~ 3 초 실행하고 fcTest
사용 -O3으로 컴파일시 ~ 83초에서 실행되는, forall
'D 전문화.
핵심 쇼 에 대한 vtTest
테스트, 추가 코드가 전문화되고있는 Unboxed
이상 벡터 Int
일반적인 벡터 코드가 사용되는 동안, 등의, fcTest
. 라인 (10)에, 당신은 GHC이의 전문 버전 쓰기 않는 것을 볼 수 있습니다 plusFastCyc
나는이 규칙이 라인 (270) (에 발사한다고 생각 라인 전문화에 대한 규칙은 라인 225에 167의 일반 버전에 비해 main6
통화 iterate main8 y
그래서 main8
입니다 plusFastCyc
전문화해야 할 곳 )
내 목표는 전문화 하여 fcTest
최대한 빨리 만드는 것 vtTest
입니다 plusFastCyc
. 이 작업을 수행하는 두 가지 방법을 찾았습니다.
- 명시 적으로 호출
inline
에서GHC.Exts
에서fcTest
. - 의
Factored m Int
제약 조건을 제거하십시오plusFastCyc
.
실제 코드 기반 plusFastCyc
에서 자주 사용되는 작업이고 매우 큰 기능 이기 때문에 옵션 1은 만족스럽지 않으므로 매번 사용할 때마다 인라인되지 않아야합니다. 대신 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에서도 문제가 지속되므로이 질문은 여전히 관련이 있습니다.
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
.
Interestingly, in the example program, the speedup obtained with the overlapping instance remains even if you remove every SPECIALIZE
and INLINABLE
pragma.
참고URL : https://stackoverflow.com/questions/21071706/specialization-with-constraints
'development' 카테고리의 다른 글
GitLab 원격 : HTTP 기본 : 액세스 거부 및 치명적 인증 (0) | 2020.06.08 |
---|---|
RMagick 2.13.1을 설치할 수 없습니다. (0) | 2020.06.08 |
두 가지 일반 유형으로 하나의 인터페이스를 구현하는 Java 클래스를 작성하는 방법은 무엇입니까? (0) | 2020.06.08 |
왜 요구가 필요한가? (0) | 2020.06.08 |
API 디자인에서 "너무 많은 매개 변수"문제를 피하는 방법은 무엇입니까? (0) | 2020.06.08 |