読者です 読者をやめる 読者になる 読者になる

北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

Re: C vs Python vs Ruby vs Haskell(無意味な処理deベンチマーク)

C vs Python vs Ruby vs Haskell(無意味な処理deベンチマーク)のコードをHaskell でなるべくC実装に忠実に書いて、オーバーヘッドを見てみた。

{-# LANGUAGE ScopedTypeVariables #-}
import Control.Monad
import Data.Array.IO
import Data.IORef

reverseI :: IOUArray Int Int -> IO ()
reverseI arr = do
  (start, end) <- getBounds arr
  let size = end - start + 1
  let list = range (start, start + size `div` 2)

  forM_ list $ \i -> do
      let j = end + start - i
      itemI <- readArray arr i
      itemJ <- readArray arr j
      writeArray arr j itemI
      writeArray arr i itemJ

size :: Int
size = 4000

main :: IO ()
main = do
  counter <- newIORef 1
  arr :: IOArray Int (IOUArray Int Int) <- newArray (0, size - 1) undefined
  bounds <- getBounds arr
  forM_ (range bounds) $ \i -> do
      arr' :: IOUArray Int Int <- newArray (0, size - 1) 0
      writeArray arr i arr'
      bounds' <- getBounds arr'
      flip mapM_ (range bounds') $ \i' -> do
          current <- readIORef counter
          writeArray arr' i' current
          writeIORef counter $ current + 1

  forM_ (range bounds) $ \i -> do
      arr' <- readArray arr i
      reverseI arr'

  arr' <- readArray arr (snd bounds)
  bounds' <- getBounds arr'
  n <- readArray arr' (snd bounds')
  putStrLn $ show n

始め IOArray を使ってたら実行が終わらないレベルだったけど、IOUArray にしたらなんとかなった。

% time ./hogehoge_c
15996001
./hogehoge_c  0.04s user 0.03s system 97% cpu 0.071 total
% time ./hogehoge_hs
15996001
./hogehoge  0.28s user 0.04s system 96% cpu 0.325 total

普通のLL系よりはさすがに速いものの、もうちょっとがんばりたいなーと思った。これ以上攻めるならForeignモジュールとか使えばいいのかな。