没有内存泄漏或错误,但是我的代码以指数方式减慢了C#

时间:2019-01-12 05:03:34

标签: c#

我对这个问题感到困惑。我相信我只是在我的面前错过了一个容易解决的问题,但现在我需要第二点意见来指出我所缺少的任何明显的问题。我最小化了代码并简化了代码,因此只显示了一部分代码。完整的代码只是在下面添加的许多不同的计算。

for (int h = 2; h < 200; h++)
{
     var List1 = CalculateSomething(testValues, h);
     var masterLists = await AddToRsquaredList("Calculation1", h, actualValuesList, List1, masterLists.Item1, masterLists.Item2);

     var List2 = CalculateSomething(testValues, h);
     masterLists = await AddToRsquaredList("Calculation2", h, actualValuesList, List2, masterLists.Item1, masterLists.Item2);

     var List3 = CalculateSomething(testValues, h);
     masterLists = await AddToRsquaredList("Calculation3", h, actualValues, List3, masterLists.Item1, masterLists.Item2);
}

public static async Task<(List<RSquaredValues3>, List<ValueClass>)> AddToRsquaredList(string valueName, int days, 
        IEnumerable<double> estimatedValuesList, IEnumerable<double> actualValuesList, 
        List<RSquaredValues3> rSquaredList, List<ValueClass> valueClassList)
    {
        try
        {
            RSquaredValues3 rSquaredValue = new RSquaredValues3
            {
                ValueName = valueName,
                Days = days,
                RSquared = GoodnessOfFit.CoefficientOfDetermination(estimatedValuesList, actualValuesList),
                StdError = GoodnessOfFit.PopulationStandardError(estimatedValuesList, actualValuesList)
            };

            int comboSize = 15;
            double max = 0;
            var query = await rSquaredList.OrderBy(i => i.StdError - i.RSquared).DistinctBy(i => i.ValueName).Take(comboSize).ToListAsync().ConfigureAwait(false);

            if (query.Count > 0)
            {
                max = query.Last().StdError - query.Last().RSquared;
            }
            else
            {
                max = 10000000;
            }

            if ((rSquaredValue.StdError - rSquaredValue.RSquared < max || query.Count < comboSize) && rSquaredList.Contains(rSquaredValue) == false)
            {
                rSquaredList.Add(rSquaredValue);
                valueClassList.Add(new ValueClass { ValueName = rSquaredValue.ValueName, ValueList = estimatedValuesList, Days = days });
            }
        }
        catch (Exception ex)
        {
            ThrowExceptionInfo(ex);
        }

        return (rSquaredList, valueClassList);
    }

2 个答案:

答案 0 :(得分:1)

StdError - RSquared显然具有重要意义,因此更改RSquaredValues3以暴露该值(即在构造时计算一次,因为值不变),而不是在此期间在多个位置重新计算处理循环。

此新属性中的值是对列表进行排序的方式。与其一遍又一遍地对列表进行排序,不如考虑首先将列表中的项目保持在该顺序中。您可以通过确保每次添加项目时将其插入列表中的正确位置来执行此操作。这称为insertion sort。 (我假设SortedList<TKey,TValue>由于重复的“键”而不合适。)

可以进行类似的改进以避免对DistinctBy(i => i.ValueName)的需要。如果您只对不同的值名称感兴趣,那么请考虑在没有改善的情况下避免插入该项目。

您的List需要在处理过程中增长-在引擎盖下,列表每次增长都会翻倍,因此增长的次数为O(log(n))。您可以指定建议的构造容量。如果您在开始时指定了足够大的预期大小,则列表在处理过程中将不需要这样做。

据我所知,await的{​​{1}}并没有为这段代码增加任何优势。

ToListAsync的检查看起来像是冗余检查,因为这是对无法实例化列表中新实例化的项目的参考比较。因此,您可以删除它以使其运行更快。

答案 1 :(得分:0)

使用Taskawait进行所有操作时,您实际上并没有获得任何收益,因为您只有一个线程来处理它并等待顺序执行,所以对所有人来说,它似乎是开销。我不确定是否可以并行化此工作负载,但是从2到200的主循环似乎是Parallel.For()循环的主要候选者。如果您实施并行处理以避免死锁问题,则还应该考虑将System.Collections.Concurrent.ConcurrentBag()用于主列表。