【问题标题】:std::deque memory usestd::deque 内存使用
【发布时间】:2011-09-24 07:59:29
【问题描述】:

我实现了一个简单的统计引擎来返回滚动均值和方差,使用双端队列提供数据队列。

双端队列由与滚动值数量相等的条目数构成。

当一个新值到达时,最旧的值会从前面弹出,新的值会被推到后面。

我需要确保它不会在内存中增长,因为它预计会作为后台任务运行很长时间。

deque 是否在正在使用的堆上分配? 有没有可以用来固定其大小的标志?

我在 RHEL 5.3 上使用 G++ 4.1.2

【问题讨论】:

    标签: c++ memory stl deque


    【解决方案1】:

    作为提示,如果您不需要跟踪值,那么可以使用这个非常轻量级(我什至在 8bit micros 上使用它)并且准确的出色算法。

     class RunningStat
    {
    public:
        RunningStat() : m_n(0) {}
    
        void Clear()
        {
            m_n = 0;
        }
    
        void Push(double x)
        {
            m_n++;
    
            // See Knuth TAOCP vol 2, 3rd edition, page 232
            if (m_n == 1)
            {
                m_oldM = m_newM = x;
                m_oldS = 0.0;
            }
            else
            {
                m_newM = m_oldM + (x - m_oldM)/m_n;
                m_newS = m_oldS + (x - m_oldM)*(x - m_newM);
    
                // set up for next iteration
                m_oldM = m_newM; 
                m_oldS = m_newS;
            }
        }
    
        int NumDataValues() const
        {
            return m_n;
        }
    
        double Mean() const
        {
            return (m_n > 0) ? m_newM : 0.0;
        }
    
        double Variance() const
        {
            return ( (m_n > 1) ? m_newS/(m_n - 1) : 0.0 );
        }
    
        double StandardDeviation() const
        {
            return sqrt( Variance() );
        }
    
    private:
        int m_n;
        double m_oldM, m_newM, m_oldS, m_newS;
    };
    

    此算法由 B. P. Welford 创建,并在 Donald Knuth 的计算机编程艺术,第 2 卷,第 232 页,第 3 版中介绍。

    http://www.johndcook.com/standard_deviation.html

    【讨论】:

    • 我一直在研究这是否可以适应使用固定大小的窗口来进行方差。由于最旧的术语,我正在尝试使用该组件并引入新的组件。我最初的测试表明它会起作用。有谁知道这是否是一个死胡同?使用它,我需要将数据保存在循环缓冲区中,但简单的增量总和将避免进行大量平均。
    【解决方案2】:

    规范将实现细节留给供应商。但是,由于两端的插入是有效的,因此很可能将其实现为堆上的链接结构。话虽如此,当你从堆中弹出一些东西时,它应该被解构,所以你的总内存使用量不应该增加。

    【讨论】:

    • “链接结构”不会削减它,因为双端队列保证 O(1) 索引访问。一些细节留给供应商,但非常需要基于矢量的页面实现。
    【解决方案3】:

    本质上,any 动态大小的容器从堆中分配内存。另一个问题提供了overview over the implementation of the deque

    但在您的特定情况下,队列始终具有相同的大小。如果遇到双端队列问题,在固定大小的数组上使用circular buffer 实现简单的固定大小队列可能会有所帮助。这种实现应该具有从根本上更好的内存行为(因为它从不需要重新分配)。如果不分析数据,很难评估其优势是否值得实施。

    【讨论】:

    • 是的,在这种情况下,缓冲区将非常简单。只需跟踪要插入的下一个索引。一旦它环绕,您将覆盖旧值,从而为您提供您正在寻找的行为。
    • 顺便说一句:boost 有一个循环缓冲区:boost.org/doc/libs/1_46_1/libs/circular_buffer/doc/…
    猜你喜欢
    • 2015-08-27
    • 2015-01-05
    • 1970-01-01
    • 2021-09-19
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    • 2023-03-24
    • 2021-09-10
    相关资源
    最近更新 更多