VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > C#教程 >
  • 关于C#:clock_gettime()与。 gettimeofday()用于测量OpenMP执行时间


cgettimeofdayopenmpparallel-processingtime
 

clock_gettime() Vs. gettimeofday() for measuring OpenMP execution time

我正在研究一些C代码,这些代码实现了三重嵌套的for循环,以在使用OpenMP并行化时计算矩阵与矩阵的乘法。我试图准确地测量从for循环开始到结束为止所花费的时间。到目前为止,我一直在使用gettimeofday(),但我注意到有时感觉好像并不准确地记录了for循环执行所花费的时间。似乎是在说比实际花费的时间更长。
这是原始代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct timeval start end;
double elapsed;

gettimeofday(&start, NULL);
#pragma omp parallel for num_threads(threads) private(i, j, k)
for(...)
{
 ...
 for(...)
 {
  ...
  for(...)
  {
   ...
  }
 }
}

gettimeofday(&end, NULL);
elapsed = (end.tv_sec+1E-6*end.tv_usec) - (start.tv_sec+1E-6*start.tv_usec)

这是使用clock_gettime()的相同代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 struct timespec start1, finish1;
 double elapsed1;

clock_gettime(CLOCK_MONOTONIC, &start1);

  #pragma omp parallel for num_threads(threads) private(i, j, k)
    for(...)
    {
     ...
     for(...)
     {
      ...
      for(...)
      {
       ...
      }
     }
    }

clock_gettime(CLOCK_MONOTONIC, &finish1);
elapsed1 = (finish1.tv_sec - start1.tv_sec);
elapsed1 += (finish1.tv_nsec - start1.tv_nsec)/1000000000.0;

循环需要3-4秒才能完成,我尝试同时使用两个时间测量,并且使用gettimeofday()的结果几乎总是比clock_gettime()的结果长,有时比我的结果还要长一秒。正在使用clock_gettime():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
struct timespec start1, finish1;
double elapsed1;

struct timeval start end;
double elapsed;

clock_gettime(CLOCK_MONOTONIC, &start1);
gettimeofday(&start, NULL);

  #pragma omp parallel for num_threads(threads) private(i, j, k)
    for(...)
    {
     ...
     for(...)
     {
      ...
      for(...)
      {
       ...
      }
     }
    }

gettimeofday(&end, NULL);
clock_gettime(CLOCK_MONOTONIC, &finish1);

elapsed = (end.tv_sec+1E-6*end.tv_usec) - (start.tv_sec+1E-6*start.tv_usec)

elapsed1 = (finish1.tv_sec - start1.tv_sec);
elapsed1 += (finish1.tv_nsec - start1.tv_nsec)/1000000000.0;

 

 

 

是否有一个原因?使用这两个功能时,可能会导致差异吗?我试图更好地理解这两个功能的性质。

 相关讨论
 

 

  • 我还分别使用两个时间函数运行了代码,然后也注意到了时差。
  • 步骤1:测试后,打印读取的值。
  • 只需使用omp_get_wtime()
  • 发布代码如何报告差异会有所帮助。 特别是在多长时间。
  • 请发布一个最小的可复制示例以及该代码的特定结果,而不仅仅是您的摘要。

 

 


elapsed = (end.tv_sec+1E-6*end.tv_usec) - (start.tv_sec+1E-6*start.tv_usec)在减去两个都很大的相似值时容易丢失精度。

  • 使用elapsed = (end.tv_sec - start.tv_sec) - (start.tv_usec- end.tv_usec)/1E6。这就像OP的第二和第三代码,但不是第一。

  • 公平地说,以一致的顺序安排时间以消除偏见。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    clock_gettime(CLOCK_MONOTONIC, &start1);
    gettimeofday(&start, NULL);

    ...

    // gettimeofday(&end, NULL);
    // clock_gettime(CLOCK_MONOTONIC, &finish1);
    clock_gettime(CLOCK_MONOTONIC, &finish1);
    gettimeofday(&end, NULL);

     

     

     

  • 次要:第三次,尽管非常微妙的改进可以帮助稍微减少不一致性(0.5微秒),但还是要在刻度变化上开始测试。但是请注意@Dietrich Epp评论,以寻求其他改进。

    1
    2
    3
    4
    gettimeofday(&t, NULL);
    do {
      gettimeofday(&start, NULL);
    } while (start == t);

或者,使用宽整数数学以避免精度问题

1
2
long long elapsed_ns = (1LL*finish1.tv_sec - start1.tv_sec)*1000000000LL +
    finish1.tv_nsec - start1.tv_nsec;
 相关讨论
 

 

  • 滴答变化的技巧似乎将采取统一的0.5秒误差,可以通过多次运行减小误差,而用量化误差代替,而不能通过多次运行减小量化误差。
  • 另一方面,0.5秒肯定会低于此测量的噪声阈值。
  • @Dietrich Epp好点。因此,对于很少的运行,它仍然保留一些价值,但是正如您所确定的,其他有价值的技术也可以用于重复运行。
  • 这如何解决> 1差的问题?
  • @Zulan如果OP使用的double精度低于许多平台通常使用的精度,则#1中指出的计算顺序很重要。海事组织,这种计算有些不妥,值得审查。
  • @chux。 C标准特别要求具有53位精度的IEC 60559双格式。为了使这种效果在特定的上下文中有意义,double必须具有小于42位的精度。也就是说,是的,您适合进行一般计算,但是对于接下来的200千年左右,(end.tv_sec+1E-6*end.tv_usec)完全可以。
  • @Zulan C参考,但不需要IEC 60559双重格式,尽管该格式是常用的。 end.tv_sec+1E-6*end.tv_usec当前需要大约31位(假设time_t自1970年1月1日以来以秒为单位)+ 20位。 2 ^ 54(double 60559精度的极限)将成为大约8 * 140年的问题。然而,OP没有详细说明如何比较秒值。 AKAIK,未发布的代码正在ns中进行比较,从而使时间计算不精确。看来OP确实在时间计算方面存在问题,但计算错误。
  • 抱歉,我误用了毫秒。

 

 


感谢大家的帮助。事实证明,该问题与时间函数无关,而是由于在计算结束时间和开始时间之间的差时未正确放置括号。我知道,这是一种反传统和愚蠢的解决方案,但它解决了我的问题。当我使用gettimeofday()时,我正在这样做来计算结果:

经过时间= end.tv_sec + 1E-6 * end.tv_usec-start.tv_sec + 1E-6 * start.tv_usec

当我应该这样做时:

 

 

 

经过的时间=(end.tv_sec + 1E-6 * end.tv_usec)-(start.tv_sec + 1E-6 * start.tv_usec)

我使用的代码是由其他人编写的,以使用gettimeofday()函数,并且它们具有以下#define:

1
2
#define TIME_GET(time) (time).tv_sec+1E-6*(time).tv_usec
#define TIME_GET_RESULT(start,end) TIME_GET(end)-TIME_GET(start)

通过添加括号来更改第一个#define可以解决我的问题:

1
#define TIME_GET(time) ((time).tv_sec+1E-6*(time).tv_usec)

 

 

 

当我开始使用clock_gettime()时,我正确地插入了括号,只是没有注意到代码作者对gettimeofday()的#define不是。


出处:https://www.codenong.com/39710442/



相关教程