Идеи, разыскиваемые для анализа данных о почти реальном времени, через определенные интервалы с эффективностью памяти/процессора

StackOverflow https://stackoverflow.com/questions/4813556

Вопрос

У меня есть некоторые датчики окружающей среды, и я хочу обнаружить внезапные изменения в температуре и медленные тенденции с течением времени ... однако я хотел бы сделать большую часть математики на основе того, что находится в памяти, с параметрами, которые могут выглядеть так: (При условии сдача)

(Примечание: элементы в паренах вычисляются в режиме реального времени при добавлении данных)

  • 5 -минутный (производный, максимум, мин, AVG) + 36 DataPoints для большинства текущих 3 часов
  • 10 -минутная (производная, максимум, мин, AVG) + 0 DataPoints, Calc основан на 5 -минутном образце
  • 30 -минутная (производная, максимум, мин, AVG) + 0 DataPoints, Calc основан на 5 -минутном образце
  • Почасовая (производная, максимум, мин, AVG) + 24 DataPoints для большинства текущих 1 дня
  • Daily (Drevative, Max, Min, AVG) + 32 DataPoints для большинства текущего месяца
  • Ежемесячный (Деривативный, Макс, Мин, AVG) + 12 данных DataPoints за прошедший год

Каждый данных - это два байтового поплавка. Таким образом, каждый датчик будет потреблять до 124 поплавок, плюс 24 рассчитанные переменные. Я хотел бы поддерживать столько датчиков, сколько позволяет устройство .NET Enceddd.

Поскольку я использую встроенное устройство для этого проекта, моя память ограничена, как и моя мощность ввода -вывода и процессора.

Как бы вы внедрили это в .net? До сих пор я создал пару структур и назвал это "TrackableFloat«Где вставка значения заставляет старый сбросить массив, а пересчет выполняется.

Единственное, что делает это более сложным, чем было бы, - это то, что для любого датчика не сообщается о данных обратно, тогда этот DataPoint должен быть исключен/игнорирован из всех последующих калут в реальном времени.

Когда все сказано и сделано, если какое -либо из значений: (Деривативная, максимум, мин, 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;
                    }
                }
            }
        }
    }
}
Это было полезно?

Решение

Вы должны подумать о том, чтобы посмотреть на Прозрачный библиотека как Неспер.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top