从文件中读取样本到数组

时间:2017-01-22 11:16:35

标签: arrays haskell bytestring repa

我编写了一个程序来分析包含文件的样本数据。目前,我的程序将样本读入列表,然后对样本列表([Float])执行进一步的分析/处理。

我对性能不太满意,我正在考虑使用Arrays而不是列表来获得更好的性能。我也在考虑并行化我的实现,Data.Array.Repa看起来很有希望。

目前,从文件中读取的内容如下:

  1. 我使用ByteString将所有样本读入hGet
  2. 我知道每个样本都由3个字节表示,因此我将ByteString分组为ByteString的3个列表。
  3. 我将toFloat函数映射到ByteString列表中,以获取Float的列表。
  4. 这导致我分析的[Float]以获得所需信息。

    我想知道在这个过程的哪一步我应该开始使用一个数组。我首先考虑使用listArray函数将我的[Float]转换为浮点数组。我不确定,但这似乎不是最有效的方式。

    是否可以在步骤2之后使用Data.Array.Repa.fromFunction构建数组并跳过中间[Float]?对于该功能,我可以使用(map toFloat bsList)之类的东西吗?其中bsList是分组后ByteString的列表。

    或者有没有办法将样本直接读入数组?

1 个答案:

答案 0 :(得分:1)

Repa实际上能够在ByteString上作为数组的后端进行操作。所以你可以通过尝试沿着这些方向开始处理并行处理ByteString:

#!/usr/bin/env stack
-- stack runghc --package repa

import Data.ByteString as BS
import Data.Array.Repa as R
import Data.Array.Repa.Repr.ByteString as R

getFloatsArr :: ByteString -> Array D DIM1 Float
getFloatsArr bs = R.traverse strArr (\(Z :. n) -> Z :. (n `div` 3)) getFloat where
  strArr = R.fromByteString (Z :. BS.length bs) bs
  getFloat getWord8 (Z :. k) =
    toFloat (getWord8 (Z :. k*3)) (getWord8 (Z :. k*3+1)) (getWord8 (Z :. k*3+2))
  toFloat = undefined -- convert to `Float` from 3 `Word8`s

processFurther :: Array U DIM1 Float -> a
processFurther = undefined

main :: IO ()
main = do
  bs <- BS.readFile "file.txt"
  arr <- R.computeUnboxedP $ getFloatsArr bs
  processFurther arr
  return ()