【问题标题】:Ideas wanted for analyzing near-realtime data over specific intervals with memory/cpu efficiency需要在特定时间间隔内以内存/cpu 效率分析近实时数据的想法
【发布时间】:2011-01-27 06:53:41
【问题描述】:

我有一些环境传感器,我想检测温度的突然变化,以及随时间推移的缓慢趋势......但是我想根据内存中的内容进行大部分数学运算,参数可能如下所示: (可能会发生变化)

(注意:括号中的项目是在添加数据时实时计算的)

  • 5 分钟(导数、最大值、最小值、平均值)+ 最近 3 小时的 36 个数据点
  • 10 分钟(导数、最大值、最小值、平均值)+ 0 个数据点,计算基于 5 分钟样本
  • 30 分钟(导数、最大值、最小值、平均值)+ 0 个数据点,计算基于 5 分钟样本
  • 每小时(微分、最大值、最小值、平均值)+ 最近 1 天的 24 个数据点
  • 最近一个月的每日(微分、最大值、最小值、平均值)+ 32 个数据点
  • 每月(微分、最大值、最小值、平均值)+ 过去一年的 12 个数据点

每个数据点都是一个两字节浮点数。所以每个传感器将消耗多达 124 个浮点数,加上 24 个计算变量。我想支持 .NET 嵌入式设备允许的尽可能多的传感器。

由于我在此项目中使用嵌入式设备,因此我的内存受到限制,我的 IO 和 CPU 能力也受到限制。

您将如何在 .NET 中实现这一点?到目前为止,我已经创建了几个结构并将其称为“TrackableFloat”,其中插入一个值会导致旧的值从数组中删除并完成重新计算。

唯一让这更重要的东西 比想象的要复杂,是吗 对于任何传感器都不会报告 数据,那么该数据点需要是 排除/忽略所有后续 实时计算。

说完了,如果任何值:(derivative, max,min,avg) 达到预定义的设置,则触发 .NET 事件

我认为有人会认为这是一个有趣的问题,并且很想听听他们将如何实现它。

  1. 你会使用类还是结构?

  2. 如何触发计算? (最有可能发生的事件)

  3. 如何触发警报?

  4. 您将如何分层存储数据?

  5. 是否有一个库已经做了这样的事情? (也许这应该是我的第一个问题)

  6. 如何有效地计算导数?

这是我的第一次破解,它并没有完全达到规范,但非常有效。很想听听您的想法。

enum UnitToTrackEnum
{
    Minute,
    FiveMinute,
    TenMinute,
    FifteenMinute,
    Hour,
    Day,
    Week,
    Month,
    unknown
}
class TrackableFloat
{
    object Gate = new object();

    UnitToTrackEnum trackingMode = UnitToTrackEnum.unknown;
    int ValidFloats = 0;
    float[] FloatsToTrack;

    public TrackableFloat(int HistoryLength, UnitToTrackEnum unitToTrack)
    {
        if (unitToTrack == UnitToTrackEnum.unknown)
            throw new InvalidOperationException("You must not have an unknown measure of time to track.");

        FloatsToTrack = new float[HistoryLength];

        foreach (var i in FloatsToTrack)
        {
            float[i] = float.MaxValue;
        }


        trackingMode = unitToTrack;

        Min = float.MaxValue;
        Max = float.MinValue;
        Sum = 0;
    }
    public void Add(DateTime dt, float value)
    {
        int RoundedDTUnit = 0;

        switch (trackingMode)
        {
            case UnitToTrackEnum.Minute:
                {
                    RoundedDTUnit = dt.Minute;
                    break;
                }
            case UnitToTrackEnum.FiveMinute:
                {
                    RoundedDTUnit = System.Math.Abs(dt.Minute / 5);
                    break;
                }
            case UnitToTrackEnum.TenMinute:
                {
                    RoundedDTUnit = System.Math.Abs(dt.Minute / 10);
                    break;
                }
            case UnitToTrackEnum.FifteenMinute:
                {
                    RoundedDTUnit = System.Math.Abs(dt.Minute / 15);
                    break;
                }
            case UnitToTrackEnum.Hour:
                {
                    RoundedDTUnit = dt.Hour;
                    break;
                }
            case UnitToTrackEnum.Day:
                {
                    RoundedDTUnit = dt.Day;
                    break;
                }
            case UnitToTrackEnum.Week:
                {
                    //RoundedDTUnit = System.Math.Abs( );
                    break;
                }
            case UnitToTrackEnum.Month:
                {
                    RoundedDTUnit = dt.Month;
                    break;
                }
            case UnitToTrackEnum.unknown:
                {
                    throw new InvalidOperationException("You must not have an unknown measure of time to track.");
                }
            default:
                break;
        }


        bool DoRefreshMaxMin = false;
        if (FloatsToTrack.Length < RoundedDTUnit)
        {
            if (value == float.MaxValue || value == float.MinValue)
            {
                // If invalid data...
                lock (Gate)
                {
                    // Get rid of old data...
                    var OldValue = FloatsToTrack[RoundedDTUnit];
                    if (OldValue != float.MaxValue || OldValue != float.MinValue)
                    {
                        Sum -= OldValue;
                        ValidFloats--;

                        if (OldValue == Max || OldValue == Min)
                            DoRefreshMaxMin = true;
                    }

                    // Save new data
                    FloatsToTrack[RoundedDTUnit] = value;
                }
            }
            else
            {
                lock (Gate)
                {
                    // Get rid of old data...
                    var OldValue = FloatsToTrack[RoundedDTUnit];
                    if (OldValue != float.MaxValue || OldValue != float.MinValue)
                    {
                        Sum -= OldValue;
                        ValidFloats--;
                    }

                    // Save new data
                    FloatsToTrack[RoundedDTUnit] = value;
                    Sum += value;
                    ValidFloats++;

                    if (value < Min)
                        Min = value;

                    if (value > Max)
                        Max = value;

                    if (OldValue == Max || OldValue == Min)
                        DoRefreshMaxMin = true;
                }
            }

            // Function is placed here to avoid a deadlock
            if (DoRefreshMaxMin == true)
                RefreshMaxMin();
        }
        else
        {
            throw new IndexOutOfRangeException("Index " + RoundedDTUnit + " is out of range for tracking mode: " + trackingMode.ToString());
        }
    }

    public float Sum { get; set; }
    public float Average
    {
        get
        {
            if (ValidFloats > 0)
                return Sum / ValidFloats;
            else
                return float.MaxValue;
        }
    }
    public float Min { get; set; }
    public float Max { get; set; }
    public float Derivative { get; set; }

    public void RefreshCounters()
    {
        lock (Gate)
        {
            float sum = 0;
            ValidFloats = 0;

            Min = float.MaxValue;
            Max = float.MinValue;

            foreach (var i in FloatsToTrack)
            {
                if (i != float.MaxValue || i != float.MinValue)
                {
                    if (Min == float.MaxValue)
                    {
                        Min = i;
                        Max = i;
                    }

                    sum += i;
                    ValidFloats++;

                    if (i < Min)
                        Min = i;

                    if (i > Max)
                        Max = i;
                }
            }
            Sum = sum;
        }
    }
    public void RefreshMaxMin()
    {
        if (ValidFloats > 0)
        {
            Min = float.MaxValue;
            Max = float.MinValue;

            lock (Gate)
            {
                foreach (var i in FloatsToTrack)
                {
                    if (i != float.MaxValue || i != float.MinValue)
                    {
                        if (i < Min)
                            Min = i;

                        if (i > Max)
                            Max = i;
                    }
                }
            }
        }
    }
}

【问题讨论】:

  • 这些 2 字节浮点数是什么格式?您是否使用它们进行计算或转换为普通浮点数?这是什么类型的 CPU?

标签: c# math real-time .net-micro-framework


【解决方案1】:

您应该考虑查看CEP 库,例如Nesper

【讨论】:

  • 我只能做 L-GPL...GPL2 不行,因为我嵌入了来自其他供应商的不兼容的许可代码。
  • 我发现其他人可以托管 GPL2 代码,我可以将它作为 Web 服务链接到它,而不会影响我的其他应用程序
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
  • 1970-01-01
  • 1970-01-01
  • 2019-08-10
  • 1970-01-01
相关资源
最近更新 更多