简体   繁体   English

Haskell - 从List转换为Data.Vector

[英]Haskell - converting from List to Data.Vector

After profiling my haskell program, I've found that 66% of the time in the program is spent indexing into lists. 在对我的haskell程序进行概要分析后,我发现该程序中有66%的时间用于索引到列表中。 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. 解决方案似乎是使用Data.Vector,但我在转换时遇到问题:当我更改代码以使用Vector时,它使用了大量的内存,并且挂得很厉害我甚至无法对其进行分析。 What could cause this? 什么可能导致这个?

Here is the file I would like to convert: https://github.com/drew-gross/Blokus-AI/blob/master/Grid.hs 这是我想要转换的文件: 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 我尝试转换它: 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. fromList将整个列表转换为Vector ,但repeat defaultCell是一个无限列表。

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 . 看起来你的Grids只有Colors它对于一个小的'网格'可能不会做太多,但是为Color创建一个Unbox实例相对容易。 Then a grid will contain an unboxed array. 然后网格将包含一个未装箱的数组。 In Grid.hs you would import Data.Vector.Unboxed rather than Data.Vector . Grid.hs您将导入Data.Vector.Unboxed而不是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. 由于许多原因,这通常好得多,但是需要在许多定义上放置一个Unbox a =>约束。 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. 如果你想制作或“映射”到格子中的其他类型的东西而不是Color ,这可能会产生影响,除非它有一个Unbox实例。

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. 下面我只是添加来自vector-th-unbox的TH咒语(我刚刚了解了这个包,并且正在借此机会再次测试它)和两个必要的定义。 It wouldn't be much harder to write it by hand following the Bool instance in Data.Vector.Unboxed.Base . Data.Vector.Unboxed.Base按照Bool实例手动编写它并不困难。

{-#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: 编辑:在0.1之前的vector-th-unbox版本中,使用了以下模板:

derivingUnbox "Color"
    [d| instance Unbox' (Color) Word8 |]
    [| fromColor |]
    [| toColor |]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM