从文件中读取样本到数组中

Reading samples, from a file, into an array

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

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

目前,从文件中读取是这样的:

  1. 我使用 hGet.
  2. 将所有样本读入 ByteString
  3. 我知道每个样本都由 3 个字节表示,所以我将 ByteString 分组为 ByteString 个 3 的列表。
  4. 我将我的 toFloat 函数映射到 ByteString 的列表上以获取 Float 的列表。

这导致我分析以获得所需信息的 [Float]

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

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

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

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 ()