1

我目前正在编写一个命令行 C 程序。我的程序中有大量复杂的循环和计算。这里出现了一个问题,我的程序大约需要 2 分钟才能完成计算,所以我想在计算过程中打印一些东西以显示它运行良好,否则程序将静默运行 2 分钟,这似乎太长了用户,他们可能会认为它崩溃了。

但是,如果我只是在主循环中插入一行代码来打印某些值,它会显着减慢我的程序(我想这是因为我的代码会等到printf函数在屏幕上生效)。

现在我有一个实用但非常丑陋的解决方案,即每 1000 个循环打印一次。对我来说,理想情况下,这个问题的最佳解决方案是以百分比打印状态并在后台同时运行代码。(就像sudo apt-get update在 Linux 中执行一样)

4

3 回答 3

1

你可以有一个事件队列机制。假设您的程序执行动作 1,动作 2,动作 3 .. 动作 n。在一个线程中运行主程序,而另一个线程在队列中等待处理事件。将事件从主线程发布到侦听器线程。伪代码

  Main thread

   main()
     {
       create(Q);//Q is global
       thread_launch(listener,Q);//Launch the thread with Q as argument
       do_action_1();
       do_action_2();
       ......
       do_action_n();
    }

    do_action_n()
    {
      .....
      post(event,Q);//this event should have some information about the action.
    }

在单独的侦听器线程中运行它

       void ListenerThread(Queue *Q)
       {
       while ( nextEvent(Q,&event))
       {
         switch(event)
         case action1:
         printf("complete %25");
          ...
         case actionn:
          printf("completed");

       }
       }

您需要有这个事件 - C 中的队列实现,尽管可以通过使用 pthread 库来实现。

于 2013-08-09T06:39:36.633 回答
0

您可以考虑使用一个整数(或更精确的数据类型,用于非常小的数字)作为程序所处的状态。当你想增加百分比时,你可以简单地做identifier++。您还需要运行一个后台进程来检测是否identifier已更改并调用将新百分比输出到屏幕的函数。

这是一个非常简化的解决方案,可能是逻辑推断最简单的解决方案,但是有很多方法(以及更准确/有效的方法)来实现它。

于 2013-08-09T06:21:42.040 回答
0

一个简单的单线程解决方案是检查每 x 次(例如 1000 次)循环迭代是否已达到您想要的下一个状态里程碑(例如 1%),然后打印出一条语句。可选择检查是否至少(半)秒已过。

#include <sys/time.h>

struct timeval last, now;
gettimeofday(&last, NULL);
size_t lastprint = 0;

size_t i;
for (i = 0; i < num_iterations; i++) {
    if (!(i & 0x3FF)) { // every 1024 iterations
        if ( 100 * (i - lastprint) / num_iterations >= 1) { // at least one percent passed
            gettimeofday(&now, NULL);

            if (now.tv_usec - last.tv_usec + (1000000 * (now.tv_sec - last.tv_sec)) > 500000) { // at least half a second passed
                // print status

                last = now;
                lastprint = i;

            }
        }
    }

    // do work
}

根据循环迭代需要多长时间,它可能会或可能不会对性能产生影响。作为一个经验法则:如果你的循环执行时间超过 20 纳秒,你就可以了。

如果您的循环太小以至于您无法在其中为状态消息添加额外的分支,那么

  • 您应该首先考虑并行化您的代码
  • 您应该将迭代索引放入共享变量中,并每隔(半)秒使用状态打印线程对其进行检查,并像这样打印状态消息。
于 2013-08-09T10:59:22.580 回答