Ejemplo n.º 1
0
        private void UpdateSensorStats()
        {
            int     count;
            decimal totalTemp = 0, totalPing = 0;

            for (count = 0; count < CurrentBenchmark.SensorLog.Count; count++)
            {
                Benchmark.SensorValue sensorValue = CurrentBenchmark.SensorLog[count];
                totalTemp += sensorValue.Temperature;
                totalPing += sensorValue.ShareAnswerPing;
            }

            Benchmark.GpuStat currentStat = CurrentBenchmark.CurrentStatistic;
            currentStat.AverageTemperature     = totalTemp / count;
            currentStat.AverageShareAnswerPing = Math.Round(totalPing / count, MidpointRounding.AwayFromZero);
        }
Ejemplo n.º 2
0
        private void UpdateHashRateStats()
        {
            // And so the counting begins
            List <Benchmark.HashEntry> hashList = CurrentBenchmark.HashLogs.ToList();
            int     hashLogSize               = hashList.Count;
            uint    found                     = 0;
            decimal sumOfWeightedRates        = 0;
            decimal sumOfInverseWeightedRates = 0;
            double  productOfWeightedLogRates = 0;
            ulong   totalWeight               = 0;

            decimal[] rates   = new decimal[hashLogSize];
            uint[]    weights = new uint[hashLogSize];

            uint minItemsMoving = 100; // Min amount of items in the moving average
            long lower          = hashLogSize - minItemsMoving;
            uint minItemsLimit  = lower > 0 ? (uint)lower : 0;
            uint minTimeMoving  = 3600; // Max amount of time in the moving average
            uint minTimeLimit   = hashLogSize > 0 ? (uint)(hashList[(hashLogSize - 1)].TimeStamp - minTimeMoving) : 0;

            List <decimal> movingRates       = new List <decimal>();
            List <uint>    movingWeights     = new List <uint>();
            ulong          movingTotalWeight = 0;

            for (int i = 0; i < hashLogSize; i++)
            {
                rates[i]   = hashList[i].HashRate;
                weights[i] = hashList[i].HashCount;

                if (i >= minItemsLimit || hashList[i].TimeStamp >= minTimeLimit)
                {
                    movingRates.Add(hashList[i].HashRate);
                    movingWeights.Add(hashList[i].HashCount);
                    movingTotalWeight += hashList[i].HashCount;
                }

                found += hashList[i].Found;

                sumOfWeightedRates        += (rates[i] * weights[i]);
                sumOfInverseWeightedRates += (weights[i] / rates[i]);
                productOfWeightedLogRates += (Math.Log((double)rates[i]) * weights[i]);
                totalWeight += weights[i];
            }

            // Let's avoid dividing by zero
            if (totalWeight != 0)
            {
                Tuple <List <decimal>, uint>[] groupedRates  = new Tuple <List <decimal>, uint> [100];
                Dictionary <string, decimal>   percentiles   = new Dictionary <string, decimal>();
                Dictionary <decimal, uint>     countModeList = new Dictionary <decimal, uint>(hashLogSize);
                uint    maxModeCount           = 0;
                decimal weightCounter          = 0;
                double  sumOfPow2OfDifferences = 0,
                        sumOfPow3OfDifferences = 0,
                        sumOfPow4OfDifferences = 0;

                Array.Sort(rates, weights); // Sorts the rates from low to high, weights get sorted along

                decimal lowestRate  = rates[0];
                decimal highestRate = rates[rates.Length - 1];
                decimal range       = highestRate - lowestRate;
                if (range > 0)
                {
                    decimal step   = range / 100;
                    decimal offset = Math.Truncate(lowestRate / step);

                    decimal arithmeticAverageHashRate = sumOfWeightedRates / totalWeight;
                    decimal geometricAverageHashRate  = (decimal)Math.Exp(productOfWeightedLogRates / totalWeight);
                    decimal harmonicAverageHashRate   = totalWeight / sumOfInverseWeightedRates;

                    decimal   movingMedian = 0, movingSpreadTop = 0, movingSpreadBottom = 0, movingWeightCounter = 0;
                    decimal[] movingRatesArray   = movingRates.ToArray();
                    uint[]    movingWeightsArray = movingWeights.ToArray();
                    Array.Sort(movingRatesArray, movingWeightsArray);

                    for (int i = 0; i < hashLogSize; i++)
                    {
                        double difference = (double)(rates[i] - harmonicAverageHashRate);
                        sumOfPow2OfDifferences += (difference * difference * weights[i]);
                        sumOfPow3OfDifferences += (difference * difference * difference * weights[i]);
                        sumOfPow4OfDifferences += (difference * difference * difference * difference * weights[i]);

                        if (!countModeList.ContainsKey(rates[i]))
                        {
                            countModeList.Add(rates[i], 1);
                        }
                        else
                        {
                            countModeList[rates[i]] += weights[i];
                            if (countModeList[rates[i]] > maxModeCount)
                            {
                                maxModeCount = countModeList[rates[i]];
                            }
                        }

                        int group = (int)(Math.Truncate(rates[i] / step) - offset);
                        if (group >= 100)
                        {
                            group = 99;               // Sometimes, thx to rounding, it gets higher
                        }
                        if (groupedRates[group] == null)
                        {
                            List <decimal> ratesList = new List <decimal> {
                                rates[i]
                            };
                            groupedRates[group] = new Tuple <List <decimal>, uint>(ratesList, weights[i]);
                        }
                        else
                        {
                            List <decimal> ratesList = groupedRates[group].Item1;
                            ratesList.Add(rates[i]);
                            uint weight = groupedRates[group].Item2 + weights[i];
                            groupedRates[group] = new Tuple <List <decimal>, uint>(ratesList, weight);
                        }

                        weightCounter += (weights[i] / (decimal)totalWeight);

                        if (weightCounter >= 0.00269979606326M && !percentiles.ContainsKey("-3σ"))
                        {
                            percentiles.Add("-3σ", rates[i]);
                        }

                        if (weightCounter >= 0.012419330651552M && !percentiles.ContainsKey("-2.5σ"))
                        {
                            percentiles.Add("-2.5σ", rates[i]);
                        }

                        if (weightCounter >= 0.045500263896358M && !percentiles.ContainsKey("-2σ"))
                        {
                            percentiles.Add("-2σ", rates[i]);
                        }

                        if (weightCounter >= 0.133614402537716M && !percentiles.ContainsKey("-1.5σ"))
                        {
                            percentiles.Add("-1.5σ", rates[i]);
                        }

                        if (weightCounter >= 0.25M && !percentiles.ContainsKey("Q1"))
                        {
                            percentiles.Add("Q1", rates[i]);
                        }

                        if (weightCounter >= 0.317310507862914M && !percentiles.ContainsKey("-1σ"))
                        {
                            percentiles.Add("-1σ", rates[i]);
                        }

                        if (weightCounter >= 0.5M && !percentiles.ContainsKey("0σ"))
                        {
                            percentiles.Add("0σ", rates[i]);
                        }

                        if (weightCounter >= 0.682689492137086M && !percentiles.ContainsKey("+1σ"))
                        {
                            percentiles.Add("+1σ", rates[i]);
                        }

                        if (weightCounter >= 0.75M && !percentiles.ContainsKey("Q3"))
                        {
                            percentiles.Add("Q3", rates[i]);
                        }

                        if (weightCounter >= 0.866385597462284M && !percentiles.ContainsKey("+1.5σ"))
                        {
                            percentiles.Add("+1.5σ", rates[i]);
                        }

                        if (weightCounter >= 0.954499736103642M && !percentiles.ContainsKey("+2σ"))
                        {
                            percentiles.Add("+2σ", rates[i]);
                        }

                        if (weightCounter >= 0.987580669348448M && !percentiles.ContainsKey("+2.5σ"))
                        {
                            percentiles.Add("+2.5σ", rates[i]);
                        }

                        if (weightCounter >= 0.997300203936740M && !percentiles.ContainsKey("+3σ"))
                        {
                            percentiles.Add("+3σ", rates[i]);
                        }

                        if (i < movingRatesArray.Length)
                        {
                            movingWeightCounter += (movingWeightsArray[i] / (decimal)movingTotalWeight);
                            if (movingWeightCounter >= 0.25M && movingSpreadBottom == 0)
                            {
                                movingSpreadBottom = movingRatesArray[i];
                            }

                            if (movingWeightCounter >= 0.50M && movingMedian == 0)
                            {
                                movingMedian = movingRatesArray[i];
                            }

                            if (movingWeightCounter >= 0.75M && movingSpreadTop == 0)
                            {
                                movingSpreadTop = movingRatesArray[i];
                            }
                        }
                    }

                    List <decimal> modes = new List <decimal>();
                    foreach (decimal rate in countModeList.Keys)
                    {
                        if (countModeList[rate] >= maxModeCount)
                        {
                            modes.Add(rate);
                        }
                    }

                    decimal   interquartileRange = percentiles["Q3"] - percentiles["Q1"];
                    decimal[] outerWhiskers      = new decimal[2];
                    outerWhiskers[0] = percentiles["Q1"] - 1.5M * interquartileRange <= 0
                        ? 0
                        : percentiles["Q1"] - 1.5M * interquartileRange;
                    outerWhiskers[1] = percentiles["Q3"] + 1.5M * interquartileRange >= highestRate
                        ? highestRate
                        : percentiles["Q3"] + 1.5M * interquartileRange;
                    HashSet <decimal> outliers = new HashSet <decimal>();

                    decimal[] madMedian = new decimal[hashLogSize];
                    decimal[] madAverage = new decimal[hashLogSize];
                    decimal   sumOfWeightedMedian = 0, sumOfWeightedAverage = 0;
                    // Come on, let's loop again! https://www.youtube.com/watch?v=BqvUkmnDVkM
                    for (int index = 0; index < hashLogSize; index++)
                    {
                        if (rates[index] < outerWhiskers[0] || rates[index] > outerWhiskers[1])
                        {
                            outliers.Add(rates[index]);
                        }

                        madMedian[index]  = Math.Abs((rates[index] - percentiles["0σ"]));
                        madAverage[index] = Math.Abs((rates[index] - harmonicAverageHashRate));

                        sumOfWeightedMedian  += (madMedian[index] * weights[index]);
                        sumOfWeightedAverage += (madAverage[index] * weights[index]);
                    }

                    decimal     madMedianMedian    = GetMedian(madMedian);
                    decimal     madAverageMedian   = GetMedian(madAverage);
                    decimal     madMedianAverage   = sumOfWeightedMedian / totalWeight;
                    decimal     madAverageAverage  = sumOfWeightedAverage / totalWeight;
                    decimal     madMedianMax       = madMedian[hashLogSize - 1];
                    decimal     madAverageMax      = madAverage[hashLogSize - 1];
                    decimal[][] absoluteDeviations = new decimal[2][];
                    absoluteDeviations[0] = new[] { madMedianMedian, madMedianAverage, madMedianMax };
                    absoluteDeviations[1] = new[] { madAverageMedian, madAverageAverage, madAverageMax };
                    decimal variance              = (decimal)(sumOfPow2OfDifferences / totalWeight);
                    decimal standardDeviation     = (decimal)Math.Sqrt((double)variance);
                    decimal stdMadFactor          = madMedianMedian != 0 ? standardDeviation / madMedianMedian : 0;
                    decimal dispersionCoefficient = variance / percentiles["0σ"];
                    decimal variationCoefficient  = (standardDeviation / harmonicAverageHashRate) * 100;
                    decimal interquartileSum      = percentiles["Q3"] + percentiles["Q1"];
                    decimal rangeSum              = highestRate + lowestRate;
                    decimal midRange              = rangeSum / 2;
                    decimal midHinge              = interquartileSum / 2;
                    decimal triMean             = (percentiles["0σ"] + midHinge) / 2;
                    decimal quartileCoefficient = (interquartileRange / interquartileSum) * 100;
                    decimal rangeCoefficient    = (range / rangeSum) * 100;
                    decimal rootMeanSquare      = (decimal)Math.Sqrt((double)
                                                                     ((harmonicAverageHashRate * harmonicAverageHashRate) + (standardDeviation * standardDeviation)));
                    decimal skewness = (decimal)(sumOfPow3OfDifferences / (Math.Pow(sumOfPow2OfDifferences, 1.5d)));
                    decimal kurtosis =
                        (decimal)(sumOfPow4OfDifferences / (sumOfPow2OfDifferences * sumOfPow2OfDifferences)) - 3;
                    decimal nonParametricSkew = (harmonicAverageHashRate - percentiles["0σ"]) / standardDeviation;

                    Benchmark.GpuStat stat = new Benchmark.GpuStat
                    {
                        TimeStamp = UnixTimeStamp(),

                        TotalHashCount   = totalWeight,
                        TotalHashEntries = hashLogSize,

                        ArithmeticAverageHashRate = arithmeticAverageHashRate,
                        GeometricAverageHashrate  = geometricAverageHashRate,
                        HarmonicAverageHashRate   = harmonicAverageHashRate,
                        RootMeanSquare            = rootMeanSquare,

                        MovingSpreadBottom = movingSpreadBottom,
                        MovingMedian       = movingMedian,
                        MovingSpreadTop    = movingSpreadTop,

                        Percentiles = percentiles,

                        OuterWhiskers      = outerWhiskers,
                        InterquartileRange = interquartileRange,
                        Range           = range,
                        LowestHashRate  = lowestRate,
                        HighestHashRate = highestRate,

                        MidRange = midRange,
                        MidHinge = midHinge,
                        TriMean  = triMean,

                        Variance              = variance,
                        StandardDeviation     = standardDeviation,
                        AbsoluteDeviations    = absoluteDeviations,
                        StdMadFactor          = stdMadFactor,
                        DispersionCoefficient = dispersionCoefficient,
                        VariationCoefficient  = variationCoefficient,
                        QuartileCoefficient   = quartileCoefficient,
                        RangeCoefficient      = rangeCoefficient,

                        Skewness          = skewness,
                        Kurtosis          = kurtosis,
                        NonParametricSkew = nonParametricSkew,

                        Founds = found
                    };

                    if (CurrentBenchmark.Statistics == null)
                    {
                        CurrentBenchmark.Statistics = new List <Benchmark.GpuStat>();
                    }
                    CurrentBenchmark.Statistics.Add(stat);

                    CurrentBenchmark.OrderedHashLogs = new Benchmark.OrderedHashLog()
                    {
                        GroupedRates = groupedRates,
                        Outliers     = outliers,

                        ModeHashRates = modes,
                        ModeQuantity  = maxModeCount,
                    };
                }
            }
        }