一个简单的for循环的微观优化

问题描述 投票:0回答:1

我有一个特殊问题。我将尽力描述这一点。我正在做一个非常重要的“微优化”。一次运行几天的循环。因此,如果我可以减少此循环时间,则只需花费一半的时间。 10天将减少到只有5天,等等。

我现在拥有的循环是函数:“ testbenchmark1”。

我有4个索引,需要像这样在循环中增加。但是,当我从列表中访问索引时,实际上需要花费一些额外的时间。如果没有其他解决方案,这就是我要尝试的方法。

indexes[n]++; //increase correct index

“ testbenchmark1”的完整代码,需要122毫秒:

        void testbenchmark00()
        {
            Random random = new Random();
            List<int> indexers = new List<int>();
            for (int i = 0; i < 9256408; i++)
            {
                indexers.Add(random.Next(0, 4));
            }
            int[] valueLIST = indexers.ToArray();


            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();

            int[] indexes = { 0, 0, 0, 0 };
            foreach (int n in valueLIST) //Takes 122 ms
            {
                indexes[n]++; //increase correct index
            }

            stopWatch.Stop();
            MessageBox.Show("stopWatch: " + stopWatch.ElapsedMilliseconds.ToString() + " milliseconds");
        }

现在下面的“ testbenchmark2”代码只是实验性的,我知道它是不正确的,但是我想知道是否有任何类似的方法可以使用此类数字:“ 1_00_00_00_00”,并且是否有可能看到:“ 00_00_00_00” ”作为四个不同的整数。例如,如果我将求和:1_00_00_00_00 + 1_00_01_00_00 = 1_00_01_00_00,然后最后可以提取每个数字,则四个这样的每个数字:00、01、00、00

但是我不知道即使使用二进制数也不能以任何方式做到这一点。是的,任何解决方案。只是这样添加数字。就像测试一样,循环仅花费59毫秒,是122毫秒的一半。因此,我很感兴趣看看是否有任何想法吗?

            double num3 = 1_00_00_00_00;
            double num4 = 1_00_01_00_00;
            for (int i = 0; i < valueLIST.Count; i++) //Takes 59 ms
            {
                num3 += num4;
            }

“ testbenchmark2”的完整代码,耗时59毫秒:

        void testbenchmark2()
        {
            List<String> valueLIST = new List<String>(); 
            for (int i = 0; i < 9256408; i++) //56
            {
                valueLIST.Add(i.ToString());
            }
                       
            //https://www.geeksforgeeks.org/binary-literals-and-digit-separators-in-c-sharp/
            double num3 = 1_00_00_00_00;
            double num4 = 1_00_01_00_00;
            
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            for (int i = 0; i < valueLIST.Count; i++) //Takes 59 ms
            {
                num3 += num4;
            }
            stopWatch.Stop();
            MessageBox.Show("stopWatch: " + stopWatch.ElapsedMilliseconds.ToString() + " milliseconds\n\n" + num3);
        }
c# micro-optimization
1个回答
0
投票

由于您已经在索引器列表中包含值,所以请勿循环浏览其他列表:只需将第一个分组。使用Linq:

var random = new Random();
var indexers = new List<int>();
for (int i = 0; i < 9256408; i++)
{
    indexers.Add(random.Next(0, 4));
}

var stopWatch = new Stopwatch();
stopWatch.Start();

var valueList = indexers
    .GroupBy( indexer => indexer )
    .Select( indexer => 
        new
        {
            Indexer = indexer.Key,
            Count = indexer.Count()
        }
    )
    .OrderBy( indexer => indexer.Indexer );
stopWatch.Stop();

这将在我的机器上返回大约50个滴答声(几千个毫微秒)。如果您的实际问题已经有valueList的某些值,则循环遍历并添加总计数。

var someEstablishedList = new List<int> { 5, 12, 30, 20 };
for (var i = 0; i < someEstablishedList.Count; i++)
{
    someEstablishedList[i] += valueList[i].Count;
}
© www.soinside.com 2019 - 2024. All rights reserved.