2

好的,所以我有一些 C 代码来执行数学运算,这几乎可以花费任何时间(当然取决于提供给它的操作数)。我想知道是否有一种方法可以注册某种方法,该方法每n秒调用一次,可以分析操作的状态,即它当前处于什么迭代,可能使用硬件定时器中断或其他什么?

我问这个的原因是因为我知道实现它的常用方法是跟踪变量中的当前迭代;比如说,一个整数被调用progress并且在代码中有一个这样的 IF 语句:

if ((progress % 10000) == 0)
    printf("Currently at iteration %d\n", progress);

但我相信一个 mod 操作需要相对较长的时间来执行,所以从优化的角度来看,将它放在一个循环中运行很多次的想法让我害怕。

所以我觉得有一种外部方式来发出进度打印信号是很好和有效的。有没有什么很好的方法来执行这个,或者简单的“mod check”是最好的(就优化而言)?

4

5 回答 5

5

我会使用 mod 检查,但可能会使用减法 :-)

icount = 0;
progress = 10000;
/* ... */
    if (--progress == 0) {
        progress = 10000;
        printf("Currently at iteration %d0000\n", ++icount);
    }
/* ... */
于 2010-10-04T15:55:40.363 回答
1

虽然 mod 操作通常很慢,但编译器应该能够很好地优化和预测这一点,并且每 10'000 个 ifs 只会错误预测一次,烧掉一个 mod 操作和大约 20 个周期(用于错误预测),这很好。因此,您尝试每 10'000 次迭代优化一次 mod 操作。当然,这假设您在现代和典型的 CPU 上运行它,而不是在某些规格未知的嵌入式系统上运行。这甚至应该比使用计数器变量更快。建议:有没有计时码的情况下测试一下,如果真的有问题,想出一个复杂的解决方案。

过早的优化是万恶之源。-克努斯

于 2010-10-04T15:53:03.847 回答
1

mod 与除法的速度大致相同,在大多数 CPU 上,这意味着大约 5-10 个周期……换句话说,几乎没有什么,比乘法/加法/减法慢,但还不足以真正担心。

但是,如果您在另一个线程或类似的东西中工作,那么您希望避免循环旋转是正确的,如果您在一个 unixish 系统上,timer_create()或者在 linux 上更容易使用timerfd_create()

但是对于单线程,只要把它放进去就足够了。

于 2010-10-04T15:57:25.547 回答
1

用于定期发出信号。alarm setitimerSIGALRM

struct itimerval interval;

void handler( int x ) {
    write( STDOUT_FILENO, ".", 1 ); /* Defined in POSIX, not in C */
}

int main() {
    signal( SIGALRM, &handler );
    interval.it_value.tv_sec = 5; /* display after 5 seconds */
    interval.it_interval.tv_sec = 5; /* then display every 5 seconds */
    setitimer( ITIMER_REAL, &interval, NULL );

    /* do computations */

    interval.it_interval.tv_sec = 0; /* don't display progress any more */
    setitimer( ITIMER_REAL, &interval, NULL );
    printf( "\n" ); /* done with the dots! */
}

请注意,只有少数函数可以在内部调用handler。它们列在本页的中途。如果您想为更精美的打印输出传达任何内容,请通过sig_atomic_t变量进行。

于 2010-10-04T16:05:36.527 回答
0

您可以有一个用于迭代的全局变量,您可以从外部线程对其进行监控。

While () {
  Print(iteration);
  Sleep(1000);
}

不过,您可能需要注意数据竞争。

于 2010-10-04T15:55:46.770 回答