简体   繁体   English

嵌套for循环的性能问题

[英]performance issue with nested for loops

I have a nested for loop that performs some calculations and the math has been simplified to a great extent, however I still have a performance issue that I'm not sure I can resolve. 我有一个嵌套的for循环,可以执行一些计算,并且在很大程度上简化了数学运算,但是我仍然有不确定的性能问题。 I don't believe it can be resolved due to the sheer number of times these for loops execute. 我不认为由于这些for循环执行的次数过多而无法解决。 Now I'm not familiar with using any analytical tools to help determine where the slow downs occur within these but I am fairly certain that it's just the number of times these loops execute. 现在,我不熟悉使用任何分析工具来帮助确定减速在其中发生的位置,但是我可以肯定,这只是这些循环执行的次数。

I would greatly appreciate any help in helping trim this down and increase the performance of this code. 我将不胜感激,可以帮助您减少这种情况并提高代码的性能。 I'm trying to stay away from a HPC or highly parallelized solution, but if that's the only way to make this truly effective then I'll look into going down that road. 我试图远离HPC或高度并行化的解决方案,但是,如果这是使其真正有效的唯一途径,那么我会考虑走这条路。

Here's the code with X= 20,000 and N_zero= 45,420 (values pulled from actual tests): 这是X = 20,000和N_zero = 45,420(从实际测试中提取的值)的代码:

Dictionary<decimal, int> n_alpha = new Dictionary<decimal, int>();
Random rand = new Random();
decimal r = 0m;
decimal check=0m;

for (int i = 0; i < X; i++)
{
    B = N_0 = N_1 = N0_ = N1_ = 0;
    for (int j = 0; j < N_zero; j++)
    {
        // need a random decimal value between 0 and 1
        r = (decimal)rand.Next() / int.MaxValue;
        if (r <= r1)
        {
            N0_ += 1;
            N_0 += 1;
        }
        else if (r1 < r && r <= r2)
        {
            B += 1;
            N0_ += 1;
            N_1 += 1;
        }
        else if (r2 < r && r <= r3)
        {
            B += 1;
            N_0 += 1;
            N1_ += 1;
        }
        else if (r > r3)
        {
            N1_ += 1;
            N_1 += 1;
        }

    }
    check = N_0 * N_1 * N0_ * N1_;
    if (check != 0)
    {
        decimal a = 1 - (B * N_zero) / ((N_0 *N1_) + (N0_ *  N_1 ));
        // technically only tracking 4 decimal points, so key should reflect this
        decimal key = Math.Round(a, 4);
        if (n_alpha.ContainsKey(key))
        {
            n_alpha[key] += 1;
        }
        else
        {
            n_alpha.Add(key, 1);
        }
    }
}
  1. The use of rand.Next() is a bit of a performance problem. 使用rand.Next()有点性能问题。 If you can live with a home-brewed, quick and dirty Linear Congruential Generator you will be much better off. 如果您可以使用自制的,快速且肮脏的线性同余发生器,那么您的生活就会好很多。

  2. The use of decimal is also a major performance problem. 使用decimal也是一个主要的性能问题。 Do not use decimal if you can avoid it. 如果可以避免,请不要使用decimal Use double instead. 请改用double

  3. The use of Dictionary can also be a bit of a problem, especially if the distribution of your data is such that it causes lots of hash collisions. 使用Dictionary也可能会有些问题,尤其是在您的数据分布导致大量哈希冲突的情况下。 I do not know what the range of your numeric data is, nor how it is distributed in that range, but if you can replace the dictionary with an array, by all means, do it. 我不知道数字数据的范围是多少,也不知道在该范围内如何分布,但是如果可以用某种方式将字典替换为数组,就可以这样做。

  4. You may be able to completely eliminate your inner nested loop. 您也许可以完全消除内部嵌套循环。 Since rand.Next() supposedly yields numbers with a uniform distribution, and since r1 , r2 and r3 are known in advance and do not change in the loops, you can simply calculate how many r s would be issued that are below r1 , how many many r s would fall between r1 and r2 , etc. without actually issuing any r s. 由于rand.Next()应该产生具有均匀分布的数字,并且由于r1r2r3是预先已知的,并且在循环中不会发生变化,因此您可以简单地计算出多少r低于r1 ,许多r会落在r1r2之间, r2 ,而实际上并没有发出任何r So, just add the corresponding quantities to your N0 , N_1 , etc instead of adding 1 each time. 因此,只需将相应的数量添加到N0N_1等中,而不是每次添加1

EDIT Clarification about #4: 编辑 #4的说明:

So, judging by the way you issue r , it can have values from 0.0 to 1.0 . 因此,根据发出r的方式判断,它的值可以从0.01.0 (Inclusively or exclusively doesn't really matter.) So, I presume that r1 , r2 , and r3 are also between 0.0 and 1.0 . (包含或排除并不重要。)因此,我假设r1r2r3也在0.01.0之间。 Therefore, assuming a perfectly uniform distribution, your r s should be as follows: 因此,假设分布完全均匀,则您的r应如下所示:

  • r < r1 will occur N_Zero * r1 times r < r1将出现N_Zero * r1

  • r1 < r < r2 will occur N_Zero * (r2 - r1) times r1 < r < r2将出现N_Zero * (r2 - r1)

  • r2 < r < r3 will occur N_Zero * (r3 - r2) times r2 < r < r3将出现N_Zero * (r3 - r2)

  • r3 < r will occur N_Zero * (1 - r3) times. r3 < r将出现N_Zero * (1 - r3)次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM