【问题标题】:Is there any probabilistic data structure that reduces the space complexity of a large number of counters?有没有什么概率数据结构可以降低大量计数器的空间复杂度?
【发布时间】:2016-04-12 23:07:52
【问题描述】:

基本上我需要跟踪大量的计数器。我可以按名称递增或递减每个计数器。最简单的方法是使用哈希表,将counter_name 用作key,将其对应的count 用作value 用于key

计数器不需要 100% 准确,count 的近似值就可以了。所以我想知道是否有任何概率数据结构可以将 N 个计数器的空间复杂度降低到低于 O(N),有点类似于 HyperLogLog 如何通过仅给出近似结果来减少计数 N 个项目的内存需求。有什么想法吗?

【问题讨论】:

  • 你真的有空间限制,还是节省时间更重要?按名称访问计数器是否有一些要求?是否需要始终按名称访问计数器,还是仅有时?
  • 您可以通过概率递增来保持近似计数器。例如,如果您愿意损失 k 位精度以节省 k 位空间,那么对于每个递增请求,实际上只以 2^(-k) 的概率递增计数器。

标签: algorithm data-structures hashtable counter counting


【解决方案1】:

在我看来,您正在寻找的是Count-min sketch

读取元素流 a1, a2, a3, ..., an 其中可以有 a 很多重复的元素,在任何时候都会给你答案 下面的问题:到目前为止,你看到了多少个ai元素。

基本上,您的独特元素可以双射到您的计数器中。 Countmin 草图允许您调整参数以用记忆换取准确性。

附:我描述了一些其他流行的probabilistic data structures here

【讨论】:

    【解决方案2】:

    Stefan Haustein 正确地指出,名称可能比计数器占用更多空间,您可以按照他的建议优先考虑某些名称,但如果不这样做,您可以考虑如何最好地存储名称。如果它们相当短(例如 8 个字符或更少),您可以考虑使用一个封闭的哈希表,将它们直接存储在存储桶中。如果它们很长,您可以将它们连续(以 NUL 终止)存储在一块内存中,然后在哈希表中将偏移量存储到它们第一个字符的那个块中。

    对于计数器本身,您可以使用以下概率方法来节省空间:

    template <typename T, typename Q = unsigned>
    class Approx_Counter
    {
      public:
        Approx_Counter() : n_(0) { }
    
        Approx_Counter& operator++()
        {
            if (n_ < 2 || rand() % (operator Q()) == 0)
                ++n_;
            return *this;
        }
    
        operator Q() const { return n_ < 2 ? n_ : 1 << n_; }
    
      private:
        T n_;
    };
    

    然后你可以使用例如Approx_Counter&lt;unsigned char, unsigned long&gt;。如果您愿意,可以将 rand() 换成 C++11 生成器。

    这个想法很简单:

    • n_0时,++肯定没有被调用
    • n_1 时,++ 肯定只被调用过一次
    • n_ &gt;= 2 时,表示++ 可能被调用了大约 2n_

    为了使最后一个含义与实际进行的++ 调用次数保持一致,每次调用都有二分之一n_ 的机会再次实际增加n_

    只需确保您的 rand() 或替代返回值远大于您要跟踪的最大计数器值,否则您将过于频繁地收到 rand() % (operator Q()) == 0 并且不适当地增加。

    也就是说,如果您有指向它的指针或偏移量,那么拥有一个较小的计数器并没有多大帮助,因此您也需要将计数器挤入存储桶中,如果您真的喜欢自己的封闭式哈希实现的另一个原因需要加强内存使用,但想坚持使用哈希表(trie 是另一种可能性)。

    上面在计数器空间中仍然是 O(N),只是有一个更小的常数。对于真正

    【讨论】:

      【解决方案3】:

      名称可能比计数器占用更多空间。

      如果有一个固定数量的计数器,只保留计数最高的计数器,再加上某种 LRU 机制来允许新的计数器上升到顶部呢?我想这真的取决于你的用例......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-01
        • 2015-02-14
        • 2015-02-03
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        • 2011-06-15
        相关资源
        最近更新 更多