【问题标题】:Represent of a collection of binary data表示二进制数据的集合
【发布时间】:2017-11-13 15:35:47
【问题描述】:

我正在处理样本由Floats 组成的信号。我编写的一些算法只需要知道信号何时穿过 x 轴(即正值到负值,反之亦然)。当我在做这些操作时,我意识到我不需要知道每个样本的实际Float 值。我只需要知道样本的值是否为正。

我最初将信号表示为VectorFloats。在我发现之后,我开始将其表示为 Boolean 值中的 Vector(即,False 表示负值,True 表示正值)。结果证明效率更高,并且我在运行时间和内存消耗方面都提高了程序的性能。

我仍然想知道是否没有更有效的方式来表示这种“二进制数据的集合”。类似于Bit VectorBit Array。我在 Hackage 上找到了 BitArray,但它似乎不支持与 Vector 相同的功能。

是否有更有效的方法来表示我的用例数据,或者我应该坚持使用Boolean 值的Vector 吗?

【问题讨论】:

  • 您需要Vector 的哪些功能?
  • C++ 标准库包括a template specialisation for bool,它使用字节的全部内容来提高空间效率……但这是widely considered a bad idea now。对于此类向量,性能往往会大大更差,因为不再可以直接使用指针运算来执行元素访问。 — 如果您只想有效地表示连续信号的符号,则应考虑仅存储 符号变化的点
  • 如果你想要性能,我认为Bool 中的unboxed vector 是最好的选择。运行时表示根本没有指针,每个单词存储一个布尔值。
  • @jberryman 是的,你是对的。我的错。我在处理Float 值时使用这些原语,但我忘记了在处理Bool 值时我从不使用它们。我只需要能够遍历集合。我需要诸如与 x 轴的第 n 个交叉点、交叉点之间的平均/最大/最小样本数等内容。
  • @ThomasVanhelden 一个未装箱的矢量 Word32/64 怎么样,每个单词代表跨度的长度?偶数索引和奇数索引分别具有相同的符号(我相信)。第 n 个交叉点就是!。当您使用样本时,可以维护这些聚合,否则只会是 Vector.max 等。

标签: performance haskell memory optimization


【解决方案1】:

vectorarray 包分别提供了每字节一个布尔值和每比特一个布尔值选项。

首先,来自Data.Vector.UnboxedVector Bool 使用一个字节数组,每个Bool 一个字节。这可以从模块Data.Vector.Unboxed.Base 中的源代码验证,其中Vector Bool 定义为:

newtype instance Vector    Bool = V_Bool  (P.Vector    Word8)

获取和设置是通过函数来​​调节的:

fromBool :: Bool -> Word8
toBool :: Word8 -> Bool

或者,也可以直接通过profiling程序来验证:

import Data.Vector.Unboxed as V
main = let v = V.replicate 1000000000 True
  in print (v ! 5)

并观察到它分配了超过 1,000,000,000 个字节。

其次,来自Data.Array.UnboxedUArray Int Bool 被实现为位向量,每个位有一个Bool。相关来源在Data.Array.Base,您可以在其中看到实例中使用的位操作:

instance IArray UArray Bool where
    ...
    unsafeAt (UArray _ _ _ arr#) (I# i#) = isTrue#
        ((indexWordArray# arr# (bOOL_INDEX i#) `and#` bOOL_BIT i#)
        `neWord#` int2Word# 0#)

同样,这可以通过分析直接验证:

import Data.Array.Unboxed as A
main = let v = A.listArray (1,1000000000) (repeat True) :: UArray Int Bool
  in print (v ! 5)

并验证它分配了大约 125,000,000 个字节。

【讨论】:

  • 感谢您的回答!我觉得真的很有趣!如果我错了,请纠正我,但 Vector 更快,Array 对我的问题更节省内存?
  • 嗯,Array 肯定比Vector 更节省内存,但至于速度,这可能很大程度上取决于具体的算法。我认为基准测试将是解决这个问题的唯一方法。
猜你喜欢
  • 2012-11-12
  • 2011-08-20
  • 1970-01-01
  • 1970-01-01
  • 2013-05-07
  • 1970-01-01
  • 2013-12-08
  • 2016-09-21
相关资源
最近更新 更多