After profiling my haskell program, I've found that 66% of the time in the program is spent indexing into lists. The solution seems to be using Data.Vector, but I'm having trouble converting: when I change the code to use a Vector it uses tons and tons of memory, and hangs so badly I can't even profile it. What could cause this?
Here is the file I would like to convert: https://github.com/drew-gross/Blokus-AI/blob/master/Grid.hs
and my attempt at converting it: https://github.com/drew-gross/Blokus-AI/blob/convert-to-vector/Grid.hs
Any ideas what I am doing wrong? Or at least, where to look?
makeEmptyGrid width height defaultCell = Grid (Data.Vector.take arraySize $ fromList $ repeat defaultCell) width height
That's a killer right there. fromList
converts an entire list to a Vector
, but repeat defaultCell
is an infinite list.
makeEmptyGrid width height defaultCell = Grid (fromListN arraySize $ repeat defaultCell) width height
or
makeEmptyGrid width height defaultCell = Grid (fromList $ replicate arraySize defaultCell) width height
would fix that.
A cursory look over the rest didn't result in further obvious traps, but I may easily have overlooked some.
This is just an additional thought following upon Daniel. It looked like your Grids
were only of Colors
It probably won't do much for a small 'Grid' but it is comparatively easy to make an Unbox
instance for Color
. Then a grid will contain an unboxed array. In Grid.hs
you would import Data.Vector.Unboxed
rather than Data.Vector
. This is in general much better for many reasons, but will require you to put an Unbox a =>
constraint on many of the definitions. This might have consequences if you want to make or 'map' into Grids full of things of another type than Color
, unless it has an Unbox
instance.
Below I just add the TH incantation from vector-th-unbox
(I just learned about that package recently, and am taking the occasion to test it again) and the two requisite definitions. It wouldn't be much harder to write it by hand following the Bool instance in Data.Vector.Unboxed.Base
.
{-#LANGUAGE TemplateHaskell, TypeFamilies, MultiParamTypeClasses#-}
module Color where
import Display
import Data.Vector.Unboxed.Deriving
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Mutable as M
import Data.Word (Word8)
data Color = Yellow | Red | Green | Blue | Empty
deriving (Show, Eq, Ord, Enum, Bounded)
fromColor :: Color -> Word8
{-# INLINE fromColor #-}
fromColor = fromIntegral . fromEnum
toColor :: Word8 -> Color
{-# INLINE toColor #-}
toColor x | x < 5 = toEnum (fromIntegral x)
toColor _ = Empty
derivingUnbox "Color"
[t| Color -> Word8 |]
[| fromColor |]
[| toColor |]
-- test
colorCycle :: Int -> V.Vector Color
colorCycle n = V.unfoldr colorop 0 where
colorop m | m < n = Just (toColor (fromIntegral (m `mod` 5)),m+1)
colorop _ = Nothing
-- *Colour> colorCycle 12
-- fromList [Yellow,Red,Green,Blue,Empty,Yellow,
-- Red,Green,Blue,Empty,Yellow,Red]
colorBlack = "\ESC[0;30m"
colorRed = "\ESC[0;31m"
colorGreen = "\ESC[0;32m"
colorYellow = "\ESC[0;33m"
colorBlue = "\ESC[0;34m"
instance Display Color where
display Red = colorRed ++ "R" ++ colorBlack
display Green = colorGreen ++ "G" ++ colorBlack
display Yellow = colorYellow ++ "Y" ++ colorBlack
display Blue = colorBlue ++ "B" ++ colorBlack
display Empty = "."
Edit: In versions of vector-th-unbox
preceding 0.1
the following template was used:
derivingUnbox "Color"
[d| instance Unbox' (Color) Word8 |]
[| fromColor |]
[| toColor |]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With