
I took your Haskell program as a base and have refactored it into a version
that is about the same speed as your original C++ program. Will follow up
with details when I have a little more time.
On Tue, Dec 18, 2012 at 12:42 PM, Branimir Maksimovic
This time I have tried fasta benchmark since current entries does not display correct output. Program is copy of mine http://benchmarksgame.alioth.debian.org/u64q/program.php?test=fasta&lang=gpp&id=1 c++ benchmark, but unfortunately executes more than twice time.
Seems to me that culprit is in function random as I have tested rest of code and didn't found speed related problems.
bmaxa@maxa:~/shootout/fasta$ time ./fastahs 25000000 > /dev/null
real 0m5.262s user 0m5.228s sys 0m0.020s
bmaxa@maxa:~/shootout/fasta$ time ./fastacpp 25000000 > /dev/null
real 0m2.075s user 0m2.056s sys 0m0.012s
Since I am planning to contribute program, perhaps someone can see a problem to speed it up at least around 3.5 secs which is speed of bench that display incorrect result (in 7.6.1).
Program follows:
{-# LANGUAGE BangPatterns #-} {- The Computer Language Benchmarks Game
http://shootout.alioth.debian.org/
contributed by Branimir Maksimovic -}
import System.Environment import System.IO.Unsafe
import Data.IORef import Data.Array.Unboxed import Data.Array.Storable import Data.Array.Base import Data.Word
import Foreign.Ptr import Foreign.C.Types
type A = UArray Int Word8 type B = StorableArray Int Word8 type C = (UArray Int Word8,UArray Int Double)
foreign import ccall unsafe "stdio.h" puts :: Ptr a -> IO () foreign import ccall unsafe "string.h" strlen :: Ptr a -> IO CInt
main :: IO () main = do n <- getArgs >>= readIO.head
let !a = (listArray (0,(length alu)-1) $ map (fromIntegral. fromEnum) alu:: A) make "ONE" "Homo sapiens alu" (n*2) $ Main.repeat a (length alu) make "TWO" "IUB ambiguity codes" (n*3) $ random iub make "THREE" "Homo sapiens frequency" (n*5) $ random homosapiens
make :: String -> String -> Int -> IO Word8 -> IO () {-# INLINE make #-} make id desc n f = do let lst = ">" ++ id ++ " " ++ desc a <- (newListArray (0,length lst) $ map (fromIntegral. fromEnum) lst:: IO B) unsafeWrite a (length lst) 0 pr a make' n 0 where make' :: Int -> Int -> IO () make' !n !i = do let line = (unsafePerformIO $ newArray (0,60) 0 :: B) if n > 0 then do !c <- f unsafeWrite line i c if i+1 >= 60 then do pr line make' (n-1) 0 else make' (n-1) (i+1) else do unsafeWrite line i 0 l <- len line if l /= 0 then pr line else return ()
pr :: B -> IO () pr line = withStorableArray line (\ptr -> puts ptr) len :: B -> IO CInt len line = withStorableArray line (\ptr -> strlen ptr)
repeat :: A -> Int -> IO Word8 repeat xs !n = do let v = unsafePerformIO $ newIORef 0 !i <- readIORef v if i+1 >= n then writeIORef v 0 else writeIORef v (i+1) return $ xs `unsafeAt` i
random :: C -> IO Word8 random (a,b) = do !rnd <- rand let find :: Int -> IO Word8 find !i = let !c = a `unsafeAt` i !p = b `unsafeAt` i in if p >= rnd then return c else find (i+1) find 0
rand :: IO Double {-# INLINE rand #-} rand = do !seed <- readIORef last let newseed = (seed * ia + ic) `rem` im newran = fromIntegral newseed * rimd rimd = 1.0 / (fromIntegral im) im, ia, ic :: Int im = 139968 ia = 3877 ic = 29573 writeIORef last newseed return newran where last = unsafePerformIO $ newIORef 42
alu :: [Char] alu = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG\ \GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA\ \CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT\ \ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA\ \GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG\ \AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC\ \AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"
mkCum :: [(Char,Double)] -> [(Word8,Double)] mkCum lst = map (\(c,p) -> ((fromIntegral.fromEnum) c,p)) $ scanl1 (\(_,p) (c',p') -> (c', p+p')) lst
homosapiens, iub :: C
iub' = mkCum [('a',0.27),('c',0.12),('g',0.12),('t',0.27),('B',0.02) ,('D',0.02),('H',0.02),('K',0.02),('M',0.02),('N',0.02) ,('R',0.02),('S',0.02),('V',0.02),('W',0.02),('Y',0.02)]
homosapiens' = mkCum [('a',0.3029549426680),('c',0.1979883004921) ,('g',0.1975473066391),('t',0.3015094502008)]
iub = (listArray (0, (length iub')-1) $ map fst iub', listArray (0, (length iub')-1) $ map snd iub')
homosapiens = (listArray (0, (length homosapiens')-1) $ map fst homosapiens', listArray (0, (length homosapiens')-1) $ map snd homosapiens')
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe