More n-bodies speedups

| No Comments | No TrackBacks

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)

No TrackBacks

TrackBack URL: http://axman6.homeip.net/cgi-bin/mt/mt-tb.cgi/22

Leave a comment

February 2009

Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
OpenID accepted here Learn more about OpenID
Powered by Movable Type 4.23-en

About this Entry

This page contains a single entry by Alex Mason published on February 5, 2009 2:11 AM.

TextMate haskell bundle improvements was the previous entry in this blog.

Other shootout news is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.