clock_gettime() Vs. gettimeofday() for measuring OpenMP execution time
这是原始代码:
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 - start.tv_sec) - (start.tv_usec- end.tv_usec)/1E6 。这就像OP的第二和第三代码,但不是第一。 -
公平地说,以一致的顺序安排时间以消除偏见。
1
2
3
4
5
6
7
8
9clock_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
4gettimeofday(&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/