“for”循环中的“if”语句

时间:2013-07-02 13:18:52

标签: c

通常当我有一个大的for循环时,我会把消息告诉我程序的哪个部分,例如:

for(i = 0; i < large_n; i++) {
    if( i % (large_n)/1000 == 0) {
       printf("We are at %ld \n", i);
    }
    // Do some other stuff
}

我想知道这是否会对性能造成太大影响(先验),如果有更聪明的替代方案就是这种情况。谢谢提前。

6 个答案:

答案 0 :(得分:5)

也许你可以分割大循环以便有时只检查条件,但我不知道这是否真的可以节省时间,这更多地取决于你的“其他东西”。

int T = ...; // times to check the condition, make sure large_n % T == 0
for(int t = 0; t < T; ++t)
{
  for(int i = large_n/T * t; i < large_n/T * (t+1); ++i)
  {
    // other stuff
  }
  printf("We are at %ld \n", large_n/T * (t+1));
}

答案 1 :(得分:4)

无论循环中有什么内容,我都不会留下像printf这样的语句,除非它对应用程序/用户是必不可少的,我也不会使用有效冗余的if语句,同样的道理。

这两个都是跟踪级调试的示例。它们完全有效,在某些情况下非常有用,但在最终应用中通常不是最终有效的。在这方面,通常要做的是在实际想要使用它们提供的信息时仅将它们包含在构建中。在这种情况下,您可能会这样做:

#define DEBUG

for(i = 0; i < large_n; i++) 
{
    #ifdef DEBUG
        if( i % (large_n)/1000 == 0) 
        {
            printf("We are at %ld \n", i);
        }
    #endif
}

关于始终包含这些调试输出的性能成本,它将完全取决于您正在运行的系统,您用于输出数据的任何“打印”语句的效率,检查/您是否正在表演,当然还有你尝试执行输出的频率。

答案 2 :(得分:3)

你的mod测试可能不会影响性能,但是如果你想要一个非常快速的测试并且你准备了两倍的倍数,那么考虑一个数学and测试:

if ( ( i & 0xFF ) == 0 ) {
    /* this gets printed every 256 iterations */
    ...
}

if ( ( i & 0xFFFF ) == 0 ) {
    /* this gets printed every 65536 iterations */
    ...
}

答案 3 :(得分:0)

通过在f​​or循环中放置一个print语句,你会牺牲一些性能。

由于每次打印消息时程序都需要进行系统调用以将输出写入屏幕,因此需要CPU时间远离程序本身。

您可以看到这两个循环之间的性能差异:

int i;
printf("Start Loop A\n");
for(i = 0; i < 100000; i++) {
    printf("%d ", i);
}
printf("Done with Loop A\n");

printf("Start Loop B\n");
for(i = 0; i < 100000; i++) {
    // Do Nothing
}
printf("Done with Loop B\n");

我会包含计时代码,但我正处于工作中,可以在午餐后更新。

如果差异不明显,您可以将100000增加到更大的数字(虽然数字太大会导致第一个循环花费太长时间才能完成)。

哎呀,忘了完成我的回答。

要减少程序需要进行的系统调用次数,可以先检查一个条件,只有在条件成立时才打印。

例如,如果您按照我的示例代码进行计算,则只能使用%打印出每100个数字:

int i;
for(i = 0; i < 100000; i++) {
    if(i%100 == 0)
        printf("%d", i);
}

这会将系统调用的数量从~100000减少到~1000,这反过来会提高循环的性能。

答案 4 :(得分:0)

问题是IO操作printf比处理器计算花费的时间多。你可以减少时间,如果你可以全部添加并最终打印。

答案 5 :(得分:0)

符号:

Tp = total time spent executing the progress statements.
Tn = total time spent doing the other normal stuff.
>> = Much greater than

如果表现是您的主要标准,您需要Tn&gt;&gt; TP。这强烈建议应对代码进行分析,以便您可以选择适当的值。例程'printf()'被认为是一个慢例程(比%慢得多)并且是一个阻塞例程(也就是说,调用它的线程可能会等待它使用的资源)。

就个人而言,我喜欢抽象出进度指标。它可以是一种记录机制, 一个printf,一个进度框,......哎呀,它可能正在更新另一个线程/任务/进程读取的结构。

id = progressRegister (<some predefined type of progress update mechanism>);
for(i = 0; i < large_n; i++) {
    progressUpdate (id, <string>, i, large_n);
    // Do some other stuff
}
progressUnregister(id);

是的,在每次迭代中调用例程'progressUpdate()'都会有一些开销,但同样,只要Tn&gt;&gt; Tp,它通常不那么重要。

希望这有帮助。