2012-02-17 4 views
8

runhaskell에서 프로그램을 실행할 때 성능 이상을 확인하려고합니다. 문제Runhaskell 성능 이상

이 프로그램은 다음과 같습니다

isFactor n = (0 ==) . (mod n) 
factors x = filter (isFactor x) [2..x] 
main = putStrLn $ show $ sum $ factors 10000000 

나는이 실행

, 그것은 1.18 초 정도 걸립니다.

그러나, 나는 isFactor로 재정의하는 경우 :

isFactor n f = (0 ==) (mod n f) 

다음 프로그램이 17.7 초 정도 걸립니다.

성능면에서 엄청난 차이가 있으며 프로그램이 동등 할 것으로 기대합니다. 아무도 내가 여기서 뭘 놓치고 있는지 알아?

참고 : GHC에서 컴파일 할 때 발생하지 않습니다.

+1

내 생각에 runhaskell은 단지 몇 가지 최적화를 수행하기 때문에 두 번째 것은 특정 엄격 성 문제가 있습니다. – fuz

답변

9

기능은 동일해야하지만 적용 방법에는 차이가 있습니다 . 첫 번째 정의에서 isFactor은 전화 사이트 isFactor x에 완전히 적용됩니다. 두 번째 정의에서는 그렇지 않습니다. 왜냐하면 이제 isFactor은 명시 적으로 두 개의 인수를 취하기 때문입니다.

GHC가 이것을보고 다른 코드와 동일한 코드를 작성하는 데는 최소한의 최적화만으로도 충분하지만 -O0 -ddump-simpl으로 컴파일하면 최적화하지 않아도 ghc-7.2.1 , 다른 버전의 YMMV). 제 isFactor 함께

는 GHC는 인라인 mod 10000000(==)에 대한 호출과, 술어가 "GHC.List.Filter"으로 전달되는 하나의 함수를 생성한다. 두 번째 정의에서, 대신에 isFactor 내의 대부분의 호출이 클래스 함수에 대한 레터 바운드 참조이고 isFactor의 여러 호출간에 공유되지 않습니다. 그래서 사전 불필요한 오버 헤드가 많이 있습니다.

기본 컴파일러 설정으로도 최적화되므로 런타임 문제가 거의 없지만 runhaskell은 그렇게 많이하지 않습니다. 심지어 someFun이 부분적으로 적용된다는 것을 알고 있기 때문에이 코드는 someFun x y = \z ->으로 가끔 구조화 된 코드를 가지고 있습니다.이 코드는 호출간에 공유를 유지하는 유일한 방법입니다 (즉, GHC의 최적화 도구는 충분히 영리하지 못했습니다).

5

제가 알고 있듯이 runhaskell은 최적화를 거의하지 않습니다. 코드를 신속하게로드하고 실행하도록 설계되었습니다. 최적화를 더 많이 수행하면 코드 실행이 오래 걸립니다. 물론이 경우 코드는 최적화가되면 더 빨리 실행됩니다.

내가 알고 있듯이 컴파일 된 코드가있는 경우 runhaskell이이 코드를 사용합니다. 따라서 성능이 중요한 경우 먼저 최적화 기능을 활성화하여 컴파일해야합니다. (심지어 스위치를 runhaskell에 전달하여 최적화를 활성화 할 수도 있습니다. 설명서를 확인해야합니다 ...)

+0

답변 해 주셔서 감사합니다! 나는 runhaskell이 많은 최적화를 수행하지 않는다는 것을 이해하지만, 내 머리 속에'foo x = bar x'와'foo = bar'가 똑같은 코드를 생성해야한다고 생각합니다. 그게 내 혼란의 근원입니다. 최적화가 없다고하더라도, 나는 왜 그 두 가지가 다르게 작동하는지 이해하려고 노력하고 있습니다. – Steve

+1

나는 썽크가 당신이 함수를 정의하는 방법에 따라 어떻게 구조화되는지 정확히 약간의 차이가 있다고 생각합니다. 한 버전과 같은 것은 모든 호출과 한 썽크를 공유하는 반면, 다른 호출은 각 호출에 대한 복사본을 만들어 더 많은 할당과 할당 해제를 발생시킵니다. 그것은 어쨌든 내 _guess_ 것입니다; GHC 개발자에게 "진짜"이유를 묻습니다. 분명히 최적화가 켜지면 두 방법 모두 동일한 코드를 생성해야합니다. 최적화 과정이 없으면 그런 일이 발생하지 않습니다. – MathematicalOrchid

+0

ghci와 runhaskell AFAIK에서 모든 최적화가 해제됩니다. 인터프리터는 unboxed 값을 지원하지 않기 때문에. – fuz