8

我的目的是在while定义的时间内执行一个循环(例如,本示例为 90 秒)。它不必精确到 90 秒,但 1-2 秒的误差是可以接受的。我确实为此目的使用了clock()`函数:

int main(void){
      clock_t start, end;
      volatile double elapsed;
      start = clock();
      int terminate = 1;
      while(terminate)
      {
              end = clock();
              elapsed = ((double) (end-start)) / (double) CLOCKS_PER_SEC *1000;
              printf("elapsed time:%f\n",elapsed);
              if(elapsed >= 90.0)
                        terminate = 0;
               usleep(50000);
       }
      printf("done..\n");
    return 0;
}

当我在笔记本电脑(x86、3.13 内核、gcc 4.8.2)上运行它时,我的秒表测量72 秒才能完成。(需要 1000 秒才能elapsed在我的笔记本电脑上达到秒级精度)

当我在 ARM 设备(armv5tejl,3.12 内核,gcc 4.6.3)上运行它时,完成代码需要58 秒。(我需要在armv5上使用)100elapsed

我在室温下运行代码,所以时钟应该是稳定的。我知道内核使线程休眠并且唤醒它们的时间不准确,等等。因此,正如我之前所说,我不希望得到一个完美的时机,但它应该有一定的准确性。

我曾尝试仅使用usleep(甚至nanosleep),但分辨率也不好。最后,我提出了获取系统时间(小时、分钟、秒)的底部代码,然后计算经过的时间。它的工作精度很高。

我想知道是否有另一种使用成本更低的解决方案?

typedef struct{
    int hour;
    int minute;
    int second;
} timeInfo;

timeInfo getTimeInfo(void){
    timeInfo value2return;
    time_t rawtime;
    struct tm * timeinfo;
    time(&rawtime);
    timeinfo = localtime(&rawtime);
    value2return.hour = timeinfo->tm_hour;
    value2return.minute = timeinfo->tm_min;
    value2return.second = timeinfo->tm_sec;
    return value2return;
}

int checkElapsedTime(const timeInfo *Start, const timeInfo *Stop, const int Reference){
    if(Stop->hour < Start->hour){
        printf("1:%d\n", (Stop->hour +24) *3600 + Stop->minute *60 + Stop->second - (Start->hour *3600 +Start->minute * 60 + Start->second));
         if( ( (Stop->hour +24) *3600 + Stop->minute *60 + Stop->second - (Start->hour *3600 +Start->minute * 60 + Start->second)) >= Reference )
            return 0; //while(0): terminate the loop
         else
             return 1; //while(1)
    }else{
        printf("2:%d\n",Stop->hour *3600 + Stop->minute *60 + Stop->second - (Start->hour *3600 +Start->minute * 60 + Start->second));
        if( (Stop->hour *3600 + Stop->minute *60 + Stop->second - (Start->hour *3600 +Start->minute * 60 + Start->second)) >= Reference )
            return 0;
        else
            return 1;
    }
}

int main(void){

    timeInfo stop, start = getTimeInfo();
    int terminate = 1;
    while(terminate)
    {
        stop = getTimeInfo();
        terminate = checkElapsedTime(&start, &stop, 90);
        usleep(5000); //to decrease the CPU load
    }

    printf("terminated\n");

    return 0;
}

最后,我需要在pthread.

4

3 回答 3

7
  1. 使用time()clock().. 编码目标是确定已用的挂墙时间,而不是使用的处理器时间。

    当前代码计算了经过的处理时间 * 1000 并将其与 90 秒进行比较。

    clock(),@uesp 暗示,返回“时钟函数确定使用的处理器时间。” C11dr §7.27.2.1 2。

    time()返回“时间函数确定当前日历时间”§7.27.2.4 2

    difftime()很好地找到了 2 之间的差异time_t(无论它们是什么单位/类型)并以秒为单位返回差异。

    int main(void) {
       time_t start, end;
       double elapsed;  // seconds
       start = time(NULL);
       int terminate = 1;
       while (terminate) {
         end = time(NULL);
         elapsed = difftime(end, start);
         if (elapsed >= 90.0 /* seconds */)
           terminate = 0;
         else  // No need to sleep when 90.0 seconds elapsed.
           usleep(50000);
       }
       printf("done..\n");
       return 0;
     }
    
  2. 次要:注意:使用时clock(),不需要* 1000。在运行 gcc 的基于 Windows 的机器上,对我来说,clock()它还返回了调用进程的 CPU 时间。

    elapsed = ((double) (end-start)) / (double) CLOCKS_PER_SEC *1000;
    elapsed = ((double) (end-start)) / CLOCKS_PER_SEC;
    
  3. 小:不需要volatileelapsed只是由于这个代码而改变。

    // volatile double elapsed;
    double elapsed;
    
于 2014-08-24T23:05:02.440 回答
1

您的第一个版本似乎不起作用的原因是在 Linux 上clock()测量使用的 CPU 时间而不是实际时间(参见此处)。由于您正在休眠进程,因此实际时间和 CPU 时间不匹配。解决方案是检查第二个示例中的实际时钟时间。

请注意,在 Windowsclock()上确实为您提供了真正的时钟时间(请参见此处)。

于 2014-08-24T20:47:44.420 回答
1

使用警报并捕捉信号。信号处理程序将中断进程执行。您也可以尝试pthread_cancel单个运行时间t的基于循环或睡眠的方法可能在时间t时不准确。如果循环是一个长时间运行的、紧凑的执行路径,那么休眠或中断根本不会解决您的问题。

于 2014-08-24T23:25:54.187 回答