So I've been taking full advantage of the new #haskell-in-depth channel, and with the thanks of blackh and others, I've made a few more changes, and I've shaved another whole 30 seconds of my already not too shabby 1m17s. I'm now down to 47.215s, making a saving of 30s, or a saving of 39%.
If you're wondering what I'm on about, take a look at this post for the story of my n-bodies program so far, and this port for what my code looked like before.
So how did I do it this time? Well, I decided STRefs weren't necessary, and could easily be replaces with accumulating parameters in basically all of my code that used them. I did this in the hope they would be kept in registers, but even if they're not, it's still faster. I also saved about 3 seconds by inlining all my read* and write* functions with {-# INLINE #-} pragmas that would write or fetch the various parts of the Body's info. So here's the code, first the original one:
advance dt ps = do forM_ index1 $ \i -> do -- (B p v m) <- readBody ps i p <- readPos ps i v <- readVel ps i m <- readMass ps i vvar <- newSTRef v forM_ (index2 i) $ \j -> do -- (B p' v' m') <- readBody ps j p' <- readPos ps j v' <- readVel ps j m' <- readMass ps j let dp = p .-. p' dst = mag dp magnit = dt / (dst * dst * dst) change = magnit *. dp (sca1,sca2) = (m' *. change, m *. change) writeVel ps j (v' .+. sca2) modifySTRef vvar (.-. sca1) vvar'@(V nx ny nz) <- readSTRef vvar -- unsafeIOToST (print vvar') writeVel' ps i nx ny nz writePos ps i $ move' dt (B p vvar' m)
And the new one, with an inner loop:
advance dt ps = forM_ index1 $ \i -> do -- (B p v m) <- readBody ps i p <- readPos ps i v <- readVel ps i m <- readMass ps i let loop2 !j !v@(V !x !y !z) | j > numPs = return v | otherwise = do p' <- readPos ps j v' <- readVel ps j m' <- readMass ps j let dp = p .-. p' dst = mag dp magnit = dt / (dst * dst * dst) change = magnit *. dp (sca1,sca2) = (m' *. change, m *. change) writeVel ps j (v' .+. sca2) loop2 (j+1) (v .-. sca1) v' <- loop2 (i+1) v -- unsafeIOToST (print v') writeVel ps i v' writePos ps i $ move' dt (B p v' m)

Leave a comment