첫째, -O2 -rtsopts
로 프로그램을 컴파일합니다. 67 %의 시간는 GC에 소요되는
$ ./question +RTS -sstderr
[(0,1000000),(1000000,1000000),(2000000,1000000),(3000000,1000000),(4000000,1000000),(5000000,1000000),(6000000,1000000),(7000000,1000000),(8000000,1000000),(9000000,1000000)]
1,193,907,224 bytes allocated in the heap
1,078,027,784 bytes copied during GC
282,023,968 bytes maximum residency (7 sample(s))
86,755,184 bytes maximum slop
763 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 1964 colls, 0 par 3.99s 4.05s 0.0021s 0.0116s
Gen 1 7 colls, 0 par 1.60s 1.68s 0.2399s 0.6665s
INIT time 0.00s ( 0.00s elapsed)
MUT time 2.67s ( 2.68s elapsed)
GC time 5.59s ( 5.73s elapsed)
EXIT time 0.02s ( 0.03s elapsed)
Total time 8.29s ( 8.43s elapsed)
%GC time 67.4% (67.9% elapsed)
Alloc rate 446,869,876 bytes per MUT second
Productivity 32.6% of total user, 32.0% of total elapsed
공지 것을 : 그런 다음, 최적화 옵션 +RTS -sstderr
으로 프로그램을 실행할 수있는 최초의 아이디어를 얻을 수 있습니다! 분명히 잘못된 것이 있습니다. 어떤 문제가 있는지 확인하려면, 우리는 다음 그림을 생성 (+RTS -h
사용)를 활성화 힙 프로파일 링 프로그램을 실행할 수 있습니다
![First heap profile](https://i.stack.imgur.com/GqXy5.png)
그래서, 당신은 누출하고 썽크를. 어떻게 될까요? 코드를 보면, 썽크가 (재귀 적으로) agg
에 빌드되는 유일한 시간은 추가 작업입니다. 따라서 쾅 패턴을 추가하여 엄격한 cv
를 만드는 것은 문제를 해결
{-# LANGUAGE BangPatterns #-}
import qualified Data.Vector.Unboxed as V
histogram :: [(Int,Int)]
histogram = V.foldr' agg [] $ V.zip k v
where
n = 10000000
c = 1000000
k = V.generate n (\i -> i `div` c * c)
v = V.generate n id
agg kv [] = [kv]
agg [email protected](k,v) [email protected]((ck,!cv):as) -- Note the !
| k == ck = (ck,cv+v):as
| otherwise = kv:acc
main :: IO()
main = print histogram
출력 :
$ time ./improved +RTS -sstderr
[(0,499999500000),(1000000,1499999500000),(2000000,2499999500000),(3000000,3499999500000),(4000000,4499999500000),(5000000,5499999500000),(6000000,6499999500000),(7000000,7499999500000),(8000000,8499999500000),(9000000,9499999500000)]
672,063,056 bytes allocated in the heap
94,664 bytes copied during GC
160,028,816 bytes maximum residency (2 sample(s))
1,464,176 bytes maximum slop
155 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 992 colls, 0 par 0.03s 0.03s 0.0000s 0.0001s
Gen 1 2 colls, 0 par 0.03s 0.03s 0.0161s 0.0319s
INIT time 0.00s ( 0.00s elapsed)
MUT time 1.24s ( 1.25s elapsed)
GC time 0.06s ( 0.06s elapsed)
EXIT time 0.03s ( 0.03s elapsed)
Total time 1.34s ( 1.34s elapsed)
%GC time 4.4% (4.5% elapsed)
Alloc rate 540,674,868 bytes per MUT second
Productivity 95.5% of total user, 95.1% of total elapsed
./improved +RTS -sstderr 1,14s user 0,20s system 99% cpu 1,352 total
이 훨씬 낫다.
그래서 지금 당신이 질문을 할 수있어, 왜 문제가 당신이 seq
을 사용하더라도 나타 납니까? 그 이유는 seq
은 첫 번째 인수가 WHNF이고 두 번째 쌍이 (_,_)
(_은 평가되지 않은 썽크 임)은 이미 WHNF입니다. 너무 seq a a
단지 수단 B 전에이을 평가 평가 : 또한,이 seq a b
(비공식적) 의미하기 때문에 seq a a
는 a
와 동일 는 전에이을 평가 평가하고, 그 단의 평가와 동일!
간단한 '-O' 대신'-O2'를 시도하십시오. 나는 단지'-O'를 사용할 때 디폴트가 무엇인지 모르겠습니다. – Sibi
@Sibi'-O'는'-O1'과 동일하므로'-O2'는 참으로 가치가 있습니다. – bennofs
'quot'는'div'보다 빠릅니다. – Franky