Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否有更有效的方法来省略for循环实例_C#_Performance - Fatal编程技术网

C# 是否有更有效的方法来省略for循环实例

C# 是否有更有效的方法来省略for循环实例,c#,performance,C#,Performance,如果我有一个循环的标准,有没有更有效的方法来省略某些事件 例如: A: 并得到以下结果: A结果:56355毫秒。 B结果:40612毫秒。 C结果:56214毫秒。 D结果:51810毫秒 Edit2:在预计算循环外n/2 n/3和n/4的值后,得到: A结果:50873毫秒。 B结果:39514毫秒。 C结果:51167毫秒。 D结果:42808毫秒 D循环似乎再次接近于B的“展开”,A和C仍然需要更多的时间 就每种方法之间的比较而言,这与我的预期相符 我的问题是,有没有更有效的方法 将次要

如果我有一个循环的标准,有没有更有效的方法来省略某些事件

例如:

A:

并得到以下结果:

A结果:56355毫秒。 B结果:40612毫秒。 C结果:56214毫秒。 D结果:51810毫秒

Edit2:在预计算循环外n/2 n/3和n/4的值后,得到:

A结果:50873毫秒。 B结果:39514毫秒。 C结果:51167毫秒。 D结果:42808毫秒

D循环似乎再次接近于B的“展开”,A和C仍然需要更多的时间

就每种方法之间的比较而言,这与我的预期相符


我的问题是,有没有更有效的方法

将次要条件嵌入到for循环中

未经测试:

for (int i = 0; i < n || (i != n / 2 && i != n / 3 && i != n / 4); i++)
  val += DoWork(i);
}
for(int i=0;i

我认为只要其中一个条件是真的,它就会继续运行,这取决于上下文。在许多情况下,一种可能是欺骗。因此,与其忽略这些数字,不如将它们包括在内,然后从您不想要的数字中反转结果:

    for (int i = 0; i < n; i++) 
    { 
        val += DoWork(i); 
    } 
    val -= DoWork(i/2);
    val -= DoWork(i/3);
    val -= DoWork(i/4);
for(int i=0;i

通过比较节省的时间可能会超过两次计算某些数字的结果,这取决于DoWork操作的开销。

如果
DoWork()
不是瓶颈,那么它是一个足够小的方法,可以嵌入到循环中,因此您不需要调用,因为调用本身会耗费时间。如果
DoWork()
完成了大部分工作,那么您就是在浪费时间:)

您可以计算操作数

选项A:
n
检查for循环中的
i
,然后对每个不是该值的i进行3次检查。。。所以有4n个操作只是为了检查

选项B:
你只是在区间中循环,所以你在做
n-3
操作

选项C:

与选项A相同,
4n
操作。

我不会因为这些修改而使代码复杂化(因为许多人已经对您的问题发表了评论)


相反,您可能希望使用在多个线程中同时运行DoWork。如果您的DoWork()做了什么,这将对性能产生更大的影响。

首先,在这40-60秒内暂停几次,这样您就可以大致了解DoWork中有多少时间。如果你甚至可以让你的循环不花费任何时间,你仍然需要花费那部分时间

现在看看你的比较。 每个人都在问一个问题。 如果一个问题的答案几乎总是正确的或几乎总是错误的,这是一个加速的机会。 (所有log(n)和n*log(n)算法的工作原理是使它们的决策点更像公平硬币。)

这样你就能明白为什么你的B更快了。平均而言,每个循环问的问题更少。 您可以通过展开循环(更少地问问题)使其更快


(我知道,我知道,编译器可以展开循环。好吧,也许吧。自己动手,你就不必下赌注了。)

你可以计算循环之外的值,然后跳过它们:

  int skip1 = n/2;
  int skip2 = n/3;
  int skip3 = n/4;
  for (int i = 0; i < n; i++)
  {
      if (i != skip1 && i != skip2 && i != skip3)
      {
         val += DoWork(i);
      }
  }
int skip1=n/2;
int skip2=n/3;
int skip3=n/4;
对于(int i=0;i
不过,我不确定这是否能节省足够的毫秒,是否值得


更新:我刚刚注意到@surfen在评论中提出了这一点。

这是您的应用程序的性能瓶颈吗?听起来不太可能。您不需要
否则{continue;}
。在
C:
示例中,将您的
if
语句更改为
if(!(…){val+=DoWork(i);}
并将
else
一起省略;嫁妆(1);DoWork(2)…DoWork(n)它可能会更快。不管我的答案是什么,我刚刚意识到当for循环达到这些条件之一时,它将停止for循环,而不会继续。真的。如果它不是硬编码的,那么就值得预先计算这些表达式,比如:n/2,n/3,并为它们分配变量,而不是每次在循环中都计算它们。这有点老套,也没有那么冗长。我现在在猜测我自己,并为它设置测试用例。但我想,是的,我相信是这样的,我也尝试过这个,但不能让它正常工作,如果你让它
I
对我来说似乎更有可能,但它在I>=I之后进入无限循环,我认为这行不通,因为在循环的每次迭代后都会检查条件,而且它会给您错误的结果,因为您包含了应该排除的事件(i@surfen他的观点并不完全正确,但它让我在编辑我的问题时进入了一个循环,它实际上明显比其他问题都快(除了B可能最终是最快的)有时“DoWork”函数不能并行完成,我只是好奇是否有更好的优化方法来解决这种情况。然后我猜答案是否定的(B是最快的)对于B,如果你在循环之前定义了I变量,你可以获得更多的毫秒-你不必在每个循环之前计算它,只要在你完成的地方继续就行了。+1的想法,尽管我感觉这在大多数情况下不会优化性能。只有在有少数例外情况。如果DoWork取决于某些条件,例如某个时间点的运行总数,会发生什么情况?我不确定是否有
        for (int i = 0; i < n; i =  (i != n / 2 -1 && i != n / 3 -1  && i != n / 4-1) ? i+1: i+2)
        {
            val += DoWork(i);
        }
for (int i = 0; i < n || (i != n / 2 && i != n / 3 && i != n / 4); i++)
  val += DoWork(i);
}
    for (int i = 0; i < n; i++) 
    { 
        val += DoWork(i); 
    } 
    val -= DoWork(i/2);
    val -= DoWork(i/3);
    val -= DoWork(i/4);
  int skip1 = n/2;
  int skip2 = n/3;
  int skip3 = n/4;
  for (int i = 0; i < n; i++)
  {
      if (i != skip1 && i != skip2 && i != skip3)
      {
         val += DoWork(i);
      }
  }