在C中使用硬件定时器

发布于 2024-09-25 21:08:30 字数 497 浏览 3 评论 0原文

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

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

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

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

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

Okay, so I've got some C code to perform a mathematical operation which could, pretty much, take any length of time (depending on the operands supplied to it, of course). I was wondering if there is a way to register some kind of method which will be called every n seconds which can analyse the state of the operation, i.e. what iteration it is currently at, possibly using a hardware timer interrupt or something?

The reason I ask this is because I know the common way to implement this is to be keeping track of the current iteration in a variable; say, an integer called progress and have an IF statement like this in the code:

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

but I believe that a mod operation takes a relatively long time to execute, so the idea of having it inside a loop which will be ran many, many times scares me, from an optimisation point of view.

So I get the feeling that having an external way of signalling a progress print is nice and efficient. Are there any great ways to perform this, or is the simple 'mod check' the best (in terms of optimising)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

对你的占有欲 2024-10-02 21:08:30

我会进行 mod 检查,但也许会进行减法:-)

icount = 0;
progress = 10000;
/* ... */
    if (--progress == 0) {
        progress = 10000;
        printf("Currently at iteration %d0000\n", ++icount);
    }
/* ... */

I'd go with the mod check, but maybe with subtractions instead :-)

icount = 0;
progress = 10000;
/* ... */
    if (--progress == 0) {
        progress = 10000;
        printf("Currently at iteration %d0000\n", ++icount);
    }
/* ... */
情未る 2024-10-02 21:08:30

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

过早的优化是万恶之源。 -高德纳

While mod operations are usually slow, the compiler should be able to optimize and predict this really well and only mis-predict once ever 10'000 ifs, burning one mod operation and ~20 cycles (for the mis-prediction) on it, which is fine. So you are trying to optimize one mod operation every 10'000 iterations. Of course this assumes you are running it on a modern and typical CPU, and not some embedded system with unknown specs. This should even be faster than having a counter variable.
Suggestion: Test it with and without the timing code, and figure out a complex solution if there is really a problem.

Premature optimisation is the root of all evil. -Knuth

面如桃花 2024-10-02 21:08:30

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

然而,如果你在另一个线程或类似的东西中工作,你想要避免循环旋转是正确的,如果你在unixish系统上有timer_create()或在linux上使用timerfd_create()要容易得多,

但对于单线程,只需将 if 放入就足够了。

mod is about the same speed as division, on most CPU's these days that means about 5-10 cycles... in other words hardly anything, slower than multiply/add/subtract, but not enough to really worry about.

However you are right to want to avoid sting in a loop spinning if you're doing work in another thread or something like that, if you're on a unixish system there's timer_create() or on linux the much easier to use timerfd_create()

But for single threaded, just putting that if in is enough.

醉态萌生 2024-10-02 21:08:30

使用 alarm setitimer 定期发出 SIGALRM 信号。

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 变量来完成。

Use alarm setitimer to raise SIGALRM signals at regular intervals.

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! */
}

Note, only a smattering of functions are OK to call inside handler. They are listed partway down this page. If you want to communicate anything for a fancier printout, do it through a sig_atomic_t variable.

温柔少女心 2024-10-02 21:08:30

您可以有一个用于迭代的全局变量,您可以从外部线程监视它。

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

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

you could have a global variable for the iterations, which you could monitor from an external thread.

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

You may need to watch out for data races though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文