Performance Problem with Loops

Simon Peyton-Jones simonpj at microsoft.com
Tue Apr 27 17:01:28 EDT 2004


I believe that I've fixed this in the HEAD.

Simon

| -----Original Message-----
| From: cvs-all-bounces at haskell.org [mailto:cvs-all-bounces at haskell.org]
On Behalf Of Wolfgang
| Thaller
| Sent: 23 February 2004 14:19
| To: cvs-ghc at haskell.org
| Subject: Performance Problem with Loops
| 
| Hi All,
| 
| Somebody complained about poor performance with mapArray on the GHC
| list. I tried to optimize it, and I discovered that GHC has a quite
| serious performance problem regarding tight loops.
| Take a look at the following programs:
| 
| // File bar.c:
| void bar(int i) {}		// something simple to do inside a loop
:-)
| 
| -- File FastLoop.hs:
| foreign import ccall unsafe bar :: Int -> IO ()
| 
| main = loop 0
|      where
|          loop 100000000 = return ()
|          loop i = bar i >> loop (i+1)
| 
| -- File SlowLoop.hs:
| foreign import ccall unsafe bar :: Int -> IO ()
| 
| doLoop n = loop 0
|      where
|          loop i | i == n    = return ()
|                 | otherwise = bar i >> loop (i+1)
| 
| {-# NOINLINE doLoop #-} -- don't inline the upper loop bound into
| doLoop above
| 
| main = doLoop 100000000
| 
| The FastLoop program takes about one second to execute on my 1GHz
| PowerBook G4. The SlowLoop program takes about fifteen seconds.
| 
| FastLoop gets compiled to a near-optimal loop - the equivalent C code
| takes 0.72 seconds.
| In the slow version, $wloop returns a closure, which then gets
| explicitly applied to the state of the world using stg_ap_v. A bad
| waste of time. Here's the STG code for SlowLoop:
| 
| lvl = \r [s] GHC.Prim.(#,#) [s GHC.Base.()];
| SRT(lvl): []
| Main.doLoop =
|      \r [n]
| 	let {
| 	  $wloop =
| 	      sat-only \r [ww]
| 		  case n of wild1 {
| 		    GHC.Base.I# y ->
| 			case ==# [ww y] of wild {
| 			  GHC.Base.True -> lvl;
| 			  GHC.Base.False ->
| 			      let {
| 				k = \u [] case +# [ww 1] of sat_s1El {
__DEFAULT -> $wloop
| sat_s1El; }; } in
| 			      let {
| 				sat_s1EH =
| 				    \r [eta] case __ccall bar [ww eta]
of wild11 { GHC.Prim.(# #)
| ds -> k ds; };
| 			      } in  sat_s1EH;
| 			};
| 		  };
| 	} in  $wloop 0;
| SRT(Main.doLoop): []
| Main.lvl1 = NO_CCS GHC.Base.I#! [100000000];
| SRT(Main.lvl1): []
| Main.main = \u [] Main.doLoop Main.lvl1;
| SRT(Main.main): []
| :Main.main =
|      \r srt:(0,*bitmap*) [eta] catch# [Main.main
| GHC.TopHandler.topHandler eta];
| SRT(:Main.main): [Main.main, GHC.TopHandler.topHandler]
| 
| 
| Can something be done about this? I guess mapArray isn't the only
| operation that could get a ten-fold speedup from this.
| 
| Cheers,
| 
| Wolfgang
| 
| _______________________________________________
| Cvs-ghc mailing list
| Cvs-ghc at haskell.org
| http://www.haskell.org/mailman/listinfo/cvs-ghc


More information about the Cvs-ghc mailing list