Измерение времени выполнения в коде C++ OpenMP

Я запускаю код .cpp (i) в последовательном стиле и (ii) с использованием операторов OpenMP. Я пытаюсь увидеть разницу во времени. Для расчета времени я использую это:

#include <time.h>
.....
main()
{

  clock_t start, finish;
  start = clock();
  .
  .
  .
  finish = clock();

  processing time = (double(finish-start)/CLOCKS_PER_SEC);

 }

Время довольно точное при последовательном (выше) запуске кода. Это занимает около 8 секунд, чтобы запустить это. Когда я вставляю операторы OpenMP в код и после этого вычисляю время, я получаю сокращение времени, но отображаемое время составляет около 8-9 секунд на консоли, когда на самом деле это всего 3-4 секунды в реальном времени!

Вот как мой код выглядит абстрактно:

#include <time.h>
.....
main()
{

  clock_t start, finish;
  start = clock();
  .
  .
  #pragma omp parallel for
  for( ... )
     for( ... )
       for (...)
    {           
      ...;      
    }
  .
  .
  finish = clock();

  processing time = (double(finish-start)/CLOCKS_PER_SEC);

 }

Когда я запускаю приведенный выше код, я получаю сокращение времени, но отображаемое время не является точным с точки зрения реального времени. Мне кажется, что функция clock() вычисляет индивидуальное время каждого потока, суммирует их и отображает.

Может ли кто-нибудь сказать причину этого или предложить мне какую-либо другую функцию измерения времени для измерения времени в программах OpenMP?

Спасибо.


person Benny    schedule 03.06.2012    source источник
comment
Не могли бы установить этот ответ: stackoverflow.com/a/63621357/3785618 является правильным ответом? Это 8 лет спустя, и технически это наиболее подходящий вариант, поэтому люди сбиваются с толку, когда видят это (stackoverflow.com/a/10874375/ 3785618) проверено.   -  person Maksim Kuzmin    schedule 23.03.2021


Ответы (4)


Я видел, как clock() сообщает о времени процессора, а не в реальном времени.

Вы могли бы использовать

struct timeval start, end;
gettimeofday(&start, NULL);

// benchmark code

gettimeofday(&end, NULL);

delta = ((end.tv_sec  - start.tv_sec) * 1000000u + 
         end.tv_usec - start.tv_usec) / 1.e6;

Вместо этого рассчитывайте время

person Community    schedule 03.06.2012
comment
Я надеюсь, вы видели это, это часть указанного поведения. Также обратите внимание, что (end.tv_sec - start.tv_sec) * 1000000u + end.tv_usec - start.tv_usec гораздо реже переполняется. - person Ben Voigt; 04.06.2012
comment
@BenVoigt Я унижен своей великолепной демонстрацией ошибочности. Я написал это CW, так как за этот ответ я не заслуживаю большего признания, чем уже получил. Спасибо за исправление (тонких/нетонких) ошибок. - person sehe; 04.06.2012
comment
какой заголовочный файл содержит эту функцию gettimeofday()? Все, что у меня есть, это mingw_gettimeofday() в time.h (mingw в windows 64) - person samad montazeri; 17.06.2016
comment
@samadmontazeri первый результат от Google говорит мне #include <sys/time.h> - person sehe; 17.06.2016
comment
Почему не delta = (end.tv_sec-start.tv_sec)+(end.tv_usec-start.tv_usec)*1e-6? Может ли случиться так, что (end.tv_sec-start.tv_sec)*1000000u превысит максимальное unsigned int, если я подождал пару часов? - person Zhuoran He; 09.09.2016
comment
omp_get_wtime следует выбирать по умолчанию для измерения времени выполнения настенных часов в контексте OpenMP. - person Zulan; 10.04.2019
comment
Спасибо, спецификации @Zulan продолжают улучшаться :) Это было добавлено в версии 4.5 (~ 2015 г.) - person sehe; 10.04.2019
comment
На самом деле omp_get_wtime был добавлен как часть OpenMP 2.0 (2002 г.) - person Zulan; 10.04.2019
comment
@Zulan А, я неправильно прочитал ссылку на версию - видимо, там просто указана дата последнего изменения - person sehe; 10.04.2019

Мне кажется, что функция clock() вычисляет индивидуальное время каждого потока, суммирует их и отображает.

Это точно то, что делает clock() — он измеряет время ЦП, используемое процессом, что, по крайней мере, в Linux и Mac OS X, означает совокупное время ЦП всех потоков, которые когда-либо существовали в процессе с момента его запуска. был начат.

Реальные часы (также известные как настенные часы) приложений OpenMP должны выполняться с использованием вызова таймера OpenMP с высоким разрешением omp_get_wtime(), который возвращает значение double количества секунд с произвольной точки в прошлом. Это переносная функция, т.е. существует как в среде выполнения Unix, так и в Windows OpenMP, в отличие от gettimeofday(), который предназначен только для Unix.

person Hristo Iliev    schedule 03.06.2012
comment
все потоки в процессе... могут быть, а могут и не быть. Согласно документации, также могут быть включены собранные дочерние процессы. - person Ben Voigt; 04.06.2012
comment
Хм, ни в ISO/IEC 9899:1999, ни в SUSv3 не упоминаются дочерние процессы: функция clock() должна возвращать наилучшее приближение реализации к процессорному времени, используемому процессом с начала определяемой реализацией эры, связанной только с вызовом процесса. - person Hristo Iliev; 04.06.2012
comment
Что ж, справочная страница Linux говорит, что это проблема несовместимости с некоторыми другими операционными системами (не указано, какие из них на самом деле включают дочерние процессы). - person Ben Voigt; 04.06.2012

Вы можете использовать встроенную функцию omp_get_wtime в самой библиотеке omp. Ниже приведен пример фрагмента кода для определения времени выполнения.

#include <stdio.h>
#include <omp.h>

int main(){

    double itime, ftime, exec_time;
    itime = omp_get_wtime();

    // Required code for which execution time needs to be computed
    
    ftime = omp_get_wtime();
    exec_time = ftime - itime;
    printf("\n\nTime taken is %f", exec_time);

}
person Hemanth Kollipara    schedule 27.08.2020
comment
Это на самом деле лучшее решение - person Maksim Kuzmin; 23.03.2021

Ну да, это то, что clock() должен делать, сказать вам, сколько процессорного времени использовала программа.

Если вы хотите найти прошедшее реальное время, а не время процессора, используйте функцию, которая возвращает время настенных часов, например gettimeofday().

person Ben Voigt    schedule 03.06.2012