2 optimization bugs ?

It seems like I have found two optimization bugs. Before filing bugs , I wanted to double check if others agreed and can reproduce the bugs. Compile and run the attached file: ghc -O2 optBugs.hs Loaded package environment from /Users/avie/.ghc/aarch64-darwin-9.10.1/environments/default [1 of 2] Compiling Main ( optBugs.hs, optBugs.o ) optBugs.hs:45:49: warning: [GHC-18042] [-Wtype-defaults] • Defaulting the type variable ‘b0’ to type ‘Integer’ in the following constraints (Integral b0) arising from a use of ‘^’ at optBugs.hs:45:49 (Num b0) arising from the literal ‘6’ at optBugs.hs:45:50 • In the first argument of ‘counts’, namely ‘(10 ^ 6)’ In the second argument of ‘(.)’, namely ‘counts (10 ^ 6)’ In the second argument of ‘(.)’, namely ‘elems . counts (10 ^ 6)’ | 45 | solve = product . map (+ 1) . elems . counts (10^6) -- 1000000 | ^ [2 of 2] Linking optBugs avie@Anabela-Air Documents % ./optBugs +RTS -s ./optBugs +RTS -s 39001250856960000 2,932,564,768 bytes allocated in the heap 143,405,696 bytes copied during GC 76,022,072 bytes maximum residency (4 sample(s)) 11,034,312 bytes maximum slop 164 MiB total memory in use (0 MiB lost due to fragmentation) Tot time (elapsed) Avg pause Max pause Gen 0 263 colls, 0 par 0.032s 0.036s 0.0001s 0.0020s Gen 1 4 colls, 0 par 0.048s 0.060s 0.0150s 0.0368s INIT time 0.003s ( 0.003s elapsed) MUT time 3.343s ( 3.333s elapsed) GC time 0.080s ( 0.096s elapsed) EXIT time 0.002s ( 0.008s elapsed) Total time 3.428s ( 3.440s elapsed) %GC time 0.0% (0.0% elapsed) Alloc rate 877,099,801 bytes per MUT second Productivity 97.5% of total user, 96.9% of total elapsed Now change the line solve = product . map (+ 1) . elems . counts (10^6) -- 1000000 to solve = product . map (+ 1) . elems . counts 1000000 save the file to disk, compile and rerun: ghc -O2 optBugs.hs Loaded package environment from /Users/avie/.ghc/aarch64-darwin-9.10.1/environments/default [1 of 2] Compiling Main ( optBugs.hs, optBugs.o ) [Source file changed] [2 of 2] Linking optBugs [Objects changed] avie@Anabela-Air Documents % ./optBugs +RTS -s ./optBugs +RTS -s 39001250856960000 1,920,053,000 bytes allocated in the heap 16,488 bytes copied during GC 8,028,224 bytes maximum residency (2 sample(s)) 393,152 bytes maximum slop 22 MiB total memory in use (0 MiB lost due to fragmentation) Tot time (elapsed) Avg pause Max pause Gen 0 239 colls, 0 par 0.000s 0.001s 0.0000s 0.0002s Gen 1 2 colls, 0 par 0.000s 0.001s 0.0007s 0.0011s INIT time 0.003s ( 0.003s elapsed) MUT time 2.011s ( 2.015s elapsed) GC time 0.001s ( 0.002s elapsed) EXIT time 0.000s ( 0.007s elapsed) Total time 2.015s ( 2.027s elapsed) %GC time 0.0% (0.0% elapsed) Alloc rate 954,738,679 bytes per MUT second Productivity 99.8% of total user, 99.4% of total elapsed Allocation decreased by a billion bytes and runtime has decreased by almost a third. This is hard to believe. The obvious explanation is that I dropped a zero when I wrote out 10^6 but I checked that I have six zeros. Also I get the same answer in both cases. Next uncomment the following two lines in factor: -- let p = sm ! m -- sm = smallest maxN and comment out the line: let p = smallest maxN ! m save the file, compile and rerun: ghc -O2 optBugs.hs Loaded package environment from /Users/avie/.ghc/aarch64-darwin-9.10.1/environments/default [1 of 2] Compiling Main ( optBugs.hs, optBugs.o ) [Source file changed] [2 of 2] Linking optBugs [Objects changed] avie@Anabela-Air Documents % ./optBugs +RTS -s ./optBugs +RTS -s 39001250856960000 16,051,152 bytes allocated in the heap 10,040 bytes copied during GC 44,328 bytes maximum residency (1 sample(s)) 29,400 bytes maximum slop 22 MiB total memory in use (0 MiB lost due to fragmentation) Tot time (elapsed) Avg pause Max pause Gen 0 2 colls, 0 par 0.000s 0.000s 0.0001s 0.0002s Gen 1 1 colls, 0 par 0.000s 0.001s 0.0015s 0.0015s INIT time 0.003s ( 0.003s elapsed) MUT time 0.019s ( 0.018s elapsed) GC time 0.000s ( 0.002s elapsed) EXIT time 0.001s ( 0.002s elapsed) Total time 0.023s ( 0.025s elapsed) %GC time 0.0% (0.0% elapsed) Alloc rate 866,786,478 bytes per MUT second Productivity 78.9% of total user, 72.5% of total elapsed Allocation has dropped from 2 billion bytes to 16 million and runtime has dropped from 2 seconds to 0.02 seconds. I think the optimizer should move the call to smallest outside of the "loop" in go. This seems like a bug to me.

I haven't looked at the second one, but for the first you may be interested
in the source code -
https://hackage.haskell.org/package/ghc-internal-9.1001.0/docs/src/GHC.Inter...
- and the comments around [Inlining] and [Powers with small exponent].
Notably, it only covers until x^a until a = 5, and indeed with 10^5 the
results of the two different ways of writing the number are the same.
--
Noon
On Tue, 2 Jul 2024 at 12:35, George Colpitts
It seems like I have found two optimization bugs. Before filing bugs , I wanted to double check if others agreed and can reproduce the bugs.
Compile and run the attached file:
ghc -O2 optBugs.hs Loaded package environment from /Users/avie/.ghc/aarch64-darwin-9.10.1/environments/default [1 of 2] Compiling Main ( optBugs.hs, optBugs.o ) optBugs.hs:45:49: warning: [GHC-18042] [-Wtype-defaults] • Defaulting the type variable ‘b0’ to type ‘Integer’ in the following constraints (Integral b0) arising from a use of ‘^’ at optBugs.hs:45:49 (Num b0) arising from the literal ‘6’ at optBugs.hs:45:50 • In the first argument of ‘counts’, namely ‘(10 ^ 6)’ In the second argument of ‘(.)’, namely ‘counts (10 ^ 6)’ In the second argument of ‘(.)’, namely ‘elems . counts (10 ^ 6)’ | 45 | solve = product . map (+ 1) . elems . counts (10^6) -- 1000000 | ^
[2 of 2] Linking optBugs avie@Anabela-Air Documents % ./optBugs +RTS -s ./optBugs +RTS -s 39001250856960000 2,932,564,768 bytes allocated in the heap 143,405,696 bytes copied during GC 76,022,072 bytes maximum residency (4 sample(s)) 11,034,312 bytes maximum slop 164 MiB total memory in use (0 MiB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause Gen 0 263 colls, 0 par 0.032s 0.036s 0.0001s 0.0020s Gen 1 4 colls, 0 par 0.048s 0.060s 0.0150s 0.0368s
INIT time 0.003s ( 0.003s elapsed) MUT time 3.343s ( 3.333s elapsed) GC time 0.080s ( 0.096s elapsed) EXIT time 0.002s ( 0.008s elapsed) Total time 3.428s ( 3.440s elapsed)
%GC time 0.0% (0.0% elapsed)
Alloc rate 877,099,801 bytes per MUT second
Productivity 97.5% of total user, 96.9% of total elapsed
Now change the line
solve = product . map (+ 1) . elems . counts (10^6) -- 1000000
to
solve = product . map (+ 1) . elems . counts 1000000
save the file to disk, compile and rerun:
ghc -O2 optBugs.hs Loaded package environment from /Users/avie/.ghc/aarch64-darwin-9.10.1/environments/default [1 of 2] Compiling Main ( optBugs.hs, optBugs.o ) [Source file changed] [2 of 2] Linking optBugs [Objects changed] avie@Anabela-Air Documents % ./optBugs +RTS -s ./optBugs +RTS -s 39001250856960000 1,920,053,000 bytes allocated in the heap 16,488 bytes copied during GC 8,028,224 bytes maximum residency (2 sample(s)) 393,152 bytes maximum slop 22 MiB total memory in use (0 MiB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause Gen 0 239 colls, 0 par 0.000s 0.001s 0.0000s 0.0002s Gen 1 2 colls, 0 par 0.000s 0.001s 0.0007s 0.0011s
INIT time 0.003s ( 0.003s elapsed) MUT time 2.011s ( 2.015s elapsed) GC time 0.001s ( 0.002s elapsed) EXIT time 0.000s ( 0.007s elapsed) Total time 2.015s ( 2.027s elapsed)
%GC time 0.0% (0.0% elapsed)
Alloc rate 954,738,679 bytes per MUT second
Productivity 99.8% of total user, 99.4% of total elapsed
Allocation decreased by a billion bytes and runtime has decreased by almost a third. This is hard to believe. The obvious explanation is that I dropped a zero when I wrote out 10^6 but I checked that I have six zeros. Also I get the same answer in both cases.
Next uncomment the following two lines in factor:
-- let p = sm ! m
-- sm = smallest maxN
and comment out the line:
let p = smallest maxN ! m
save the file, compile and rerun:
ghc -O2 optBugs.hs Loaded package environment from /Users/avie/.ghc/aarch64-darwin-9.10.1/environments/default [1 of 2] Compiling Main ( optBugs.hs, optBugs.o ) [Source file changed] [2 of 2] Linking optBugs [Objects changed] avie@Anabela-Air Documents % ./optBugs +RTS -s ./optBugs +RTS -s 39001250856960000 16,051,152 bytes allocated in the heap 10,040 bytes copied during GC 44,328 bytes maximum residency (1 sample(s)) 29,400 bytes maximum slop 22 MiB total memory in use (0 MiB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause Gen 0 2 colls, 0 par 0.000s 0.000s 0.0001s 0.0002s Gen 1 1 colls, 0 par 0.000s 0.001s 0.0015s 0.0015s
INIT time 0.003s ( 0.003s elapsed) MUT time 0.019s ( 0.018s elapsed) GC time 0.000s ( 0.002s elapsed) EXIT time 0.001s ( 0.002s elapsed) Total time 0.023s ( 0.025s elapsed)
%GC time 0.0% (0.0% elapsed)
Alloc rate 866,786,478 bytes per MUT second
Productivity 78.9% of total user, 72.5% of total elapsed
Allocation has dropped from 2 billion bytes to 16 million and runtime has dropped from 2 seconds to 0.02 seconds. I think the optimizer should move the call to smallest outside of the "loop" in go. This seems like a bug to me.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- Noon van der Silk http://silky.github.io/ "My programming language is kindness."

Thanks Noon. I should have been clearer, I expected 10^6 to be changed to
1000000 at compile time as part of constant folding. Even when done at run
time I can't see how that conversion would take that long or why it would
allocate so many bytes.
On Wed, Jul 3, 2024 at 8:12 AM Noon van der Silk
I haven't looked at the second one, but for the first you may be interested in the source code - https://hackage.haskell.org/package/ghc-internal-9.1001.0/docs/src/GHC.Inter... - and the comments around [Inlining] and [Powers with small exponent].
Notably, it only covers until x^a until a = 5, and indeed with 10^5 the results of the two different ways of writing the number are the same.
-- Noon
On Tue, 2 Jul 2024 at 12:35, George Colpitts
wrote: It seems like I have found two optimization bugs. Before filing bugs , I wanted to double check if others agreed and can reproduce the bugs.
Compile and run the attached file:
ghc -O2 optBugs.hs Loaded package environment from /Users/avie/.ghc/aarch64-darwin-9.10.1/environments/default [1 of 2] Compiling Main ( optBugs.hs, optBugs.o ) optBugs.hs:45:49: warning: [GHC-18042] [-Wtype-defaults] • Defaulting the type variable ‘b0’ to type ‘Integer’ in the following constraints (Integral b0) arising from a use of ‘^’ at optBugs.hs:45:49 (Num b0) arising from the literal ‘6’ at optBugs.hs:45:50 • In the first argument of ‘counts’, namely ‘(10 ^ 6)’ In the second argument of ‘(.)’, namely ‘counts (10 ^ 6)’ In the second argument of ‘(.)’, namely ‘elems . counts (10 ^ 6)’ | 45 | solve = product . map (+ 1) . elems . counts (10^6) -- 1000000 | ^
[2 of 2] Linking optBugs avie@Anabela-Air Documents % ./optBugs +RTS -s ./optBugs +RTS -s 39001250856960000 2,932,564,768 bytes allocated in the heap 143,405,696 bytes copied during GC 76,022,072 bytes maximum residency (4 sample(s)) 11,034,312 bytes maximum slop 164 MiB total memory in use (0 MiB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause Gen 0 263 colls, 0 par 0.032s 0.036s 0.0001s 0.0020s Gen 1 4 colls, 0 par 0.048s 0.060s 0.0150s 0.0368s
INIT time 0.003s ( 0.003s elapsed) MUT time 3.343s ( 3.333s elapsed) GC time 0.080s ( 0.096s elapsed) EXIT time 0.002s ( 0.008s elapsed) Total time 3.428s ( 3.440s elapsed)
%GC time 0.0% (0.0% elapsed)
Alloc rate 877,099,801 bytes per MUT second
Productivity 97.5% of total user, 96.9% of total elapsed
Now change the line
solve = product . map (+ 1) . elems . counts (10^6) -- 1000000
to
solve = product . map (+ 1) . elems . counts 1000000
save the file to disk, compile and rerun:
ghc -O2 optBugs.hs Loaded package environment from /Users/avie/.ghc/aarch64-darwin-9.10.1/environments/default [1 of 2] Compiling Main ( optBugs.hs, optBugs.o ) [Source file changed] [2 of 2] Linking optBugs [Objects changed] avie@Anabela-Air Documents % ./optBugs +RTS -s ./optBugs +RTS -s 39001250856960000 1,920,053,000 bytes allocated in the heap 16,488 bytes copied during GC 8,028,224 bytes maximum residency (2 sample(s)) 393,152 bytes maximum slop 22 MiB total memory in use (0 MiB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause Gen 0 239 colls, 0 par 0.000s 0.001s 0.0000s 0.0002s Gen 1 2 colls, 0 par 0.000s 0.001s 0.0007s 0.0011s
INIT time 0.003s ( 0.003s elapsed) MUT time 2.011s ( 2.015s elapsed) GC time 0.001s ( 0.002s elapsed) EXIT time 0.000s ( 0.007s elapsed) Total time 2.015s ( 2.027s elapsed)
%GC time 0.0% (0.0% elapsed)
Alloc rate 954,738,679 bytes per MUT second
Productivity 99.8% of total user, 99.4% of total elapsed
Allocation decreased by a billion bytes and runtime has decreased by almost a third. This is hard to believe. The obvious explanation is that I dropped a zero when I wrote out 10^6 but I checked that I have six zeros. Also I get the same answer in both cases.
Next uncomment the following two lines in factor:
-- let p = sm ! m
-- sm = smallest maxN
and comment out the line:
let p = smallest maxN ! m
save the file, compile and rerun:
ghc -O2 optBugs.hs Loaded package environment from /Users/avie/.ghc/aarch64-darwin-9.10.1/environments/default [1 of 2] Compiling Main ( optBugs.hs, optBugs.o ) [Source file changed] [2 of 2] Linking optBugs [Objects changed] avie@Anabela-Air Documents % ./optBugs +RTS -s ./optBugs +RTS -s 39001250856960000 16,051,152 bytes allocated in the heap 10,040 bytes copied during GC 44,328 bytes maximum residency (1 sample(s)) 29,400 bytes maximum slop 22 MiB total memory in use (0 MiB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause Gen 0 2 colls, 0 par 0.000s 0.000s 0.0001s 0.0002s Gen 1 1 colls, 0 par 0.000s 0.001s 0.0015s 0.0015s
INIT time 0.003s ( 0.003s elapsed) MUT time 0.019s ( 0.018s elapsed) GC time 0.000s ( 0.002s elapsed) EXIT time 0.001s ( 0.002s elapsed) Total time 0.023s ( 0.025s elapsed)
%GC time 0.0% (0.0% elapsed)
Alloc rate 866,786,478 bytes per MUT second
Productivity 78.9% of total user, 72.5% of total elapsed
Allocation has dropped from 2 billion bytes to 16 million and runtime has dropped from 2 seconds to 0.02 seconds. I think the optimizer should move the call to smallest outside of the "loop" in go. This seems like a bug to me.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- Noon van der Silk
"My programming language is kindness."
participants (2)
-
George Colpitts
-
Noon van der Silk