Часы С++ остаются равными нулю

Я пытаюсь получить прошедшее время моей программы. На самом деле я думал, что должен использовать yclock() из time.h. Но он остается нулевым на всех этапах программы, хотя я добавляю 10 ^ 5 чисел (должно быть затрачено некоторое время процессора). Я уже искал эту проблему, и похоже, что люди, работающие под Linux, сталкиваются только с этой проблемой. Я использую Ubuntu 12.04LTS.

Я собираюсь сравнить инструкции AVX и SSE, поэтому использование time_t на самом деле не вариант. Любые подсказки?

Вот код:

 //Dimension of Arrays
unsigned int N = 100000;
//Fill two arrays with random numbers
unsigned  int a[N];
clock_t start_of_programm = clock();
for(int i=0;i<N;i++){
    a[i] = i;
}
clock_t after_init_of_a = clock();
unsigned  int b[N];
for(int i=0;i<N;i++){
    b[i] = i;
}
clock_t after_init_of_b = clock();

//Add the two arrays with Standard
unsigned int out[N];
for(int i = 0; i < N; ++i)
    out[i] = a[i] + b[i];
clock_t after_add = clock();

cout  << "start_of_programm " << start_of_programm  << endl; // prints
cout  << "after_init_of_a " << after_init_of_a  << endl; // prints
cout  << "after_init_of_b " << after_init_of_b  << endl; // prints
cout  << "after_add " << after_add  << endl; // prints
cout  << endl << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << endl;

И вывод консоли. Я также использовал printf() с %d без разницы.

start_of_programm 0
after_init_of_a 0
after_init_of_b 0
after_add 0

CLOCKS_PER_SEC 1000000

person toebs    schedule 09.09.2013    source источник
comment
Я пытаюсь вычислить время работы моего процесса... вы имеете в виду прошедшее время? clock() возвращает количество процессорного времени, использованного процессом.   -  person trojanfoe    schedule 09.09.2013
comment
истинный. я не естественный оратор. в любом случае, какие-либо предложения по решению моей проблемы?   -  person toebs    schedule 09.09.2013
comment
Что, если добавить еще две 0 к N?   -  person trojanfoe    schedule 09.09.2013
comment
Если у вас есть доступ к C++11 (любому недавнему компилятору), попробуйте использовать std::chrono вместо функций времени C.   -  person Appleshell    schedule 09.09.2013
comment
@toebs, если вы собираетесь сравнивать код AVX и SSE, вы, вероятно, захотите использовать память с выравниванием по 32 байтам, а также массивы большего размера. В этом случае размещение ваших массивов в стеке не будет работать. Я бы использовал _mm_malloc(sizeof(int)*N, 32).   -  person Z boson    schedule 09.09.2013
comment
@redrum: да, это будет следующий шаг, но сначала мне нужно было выяснить, как измерить прошедшее время. Мне все еще нужно сравнить все с инструкциями без SSE, AVX.   -  person toebs    schedule 09.09.2013
comment
@toebs, см. мой ответ для вычисления измеренного прошедшего времени. Я не думаю, что вы найдете более простой ответ (и тот, который также работает в Windows и MSVC).   -  person Z boson    schedule 09.09.2013
comment
@redrum: все будет работать только на Linux, поэтому мне не нужно заботиться об окнах :)   -  person toebs    schedule 09.09.2013


Ответы (4)


Самый простой способ получить время — просто использовать функцию-заглушку из OpenMP. Это будет работать на MSVC, GCC и ICC. С MSVC вам даже не нужно включать OpenMP. С ICC вы можете связать только заглушки, если хотите -openmp-stubs. С GCC вы должны использовать -fopenmp.

#include <omp.h>

double dtime;
dtime = omp_get_wtime();
foo();
dtime = omp_get_wtime() - dtime;
printf("time %f\n", dtime);
person Z boson    schedule 09.09.2013
comment
Кажется, работает по крайней мере. Можете ли вы объяснить, где добавить -openmp-stubs в Eclipse, когда я использую ICC? Я добавил его как параметры компоновщика и компилятора, но выдает ошибку, что функция неизвестна. Для gcc это работает - person toebs; 09.09.2013
comment
Вы можете использовать -fopenmp или -openmp с ICC, как и с GCC. Я не использовал Eclipse (я использую QtCreator или просто текстовый редактор и оболочку). Что вы используете для создания Makefile? - person Z boson; 09.09.2013
comment
Вот ссылка, показывающая -openmp-stubs для ICC. - person Z boson; 09.09.2013

clock действительно возвращает использованное процессорное время, но степень детализации составляет порядка 10 Гц. Поэтому, если ваш код не занимает более 100 мс, вы получите ноль. И если оно не значительно превышает 100 мс, вы не получите очень точного значения, потому что ваша погрешность будет около 100 мс.

Таким образом, ваш выбор — увеличить N или использовать другой метод измерения времени. std::chrono, скорее всего, даст более точное время (но оно будет измерять «время стены», а не время процессора).

timespec t1, t2; 
clock_gettime(CLOCK_REALTIME, &t1); 
... do stuff ... 
clock_gettime(CLOCK_REALTIME, &t2); 
double t = timespec_diff(t2, t1);

double timespec_diff(timespec t2, timespec t1)
{
    double d1 = t1.tv_sec + t1.tv_nsec / 1000000000.0;
    double d2 = t2.tv_sec + t2.tv_nsec / 1000000000.0;

    return d2 - d1;
}
person Mats Petersson    schedule 09.09.2013
comment
эта библиотека уже является функцией gcc4.6? Мой компилятор выдает ошибку, что хроно все еще находится в стадии тестирования - person toebs; 09.09.2013
comment
Это функция C++11, поэтому в старых версиях gcc ее может не быть. - person Mats Petersson; 09.09.2013
comment
есть ли возможность увеличить детализацию? - person toebs; 09.09.2013
comment
@toebs: решение, которое работает для Linux, теперь опубликовано с использованием высокого разрешения clock_gettime. - person Mats Petersson; 09.09.2013
comment
спасибо, это отлично работает и дает тот же результат, что и решение openmp! - person toebs; 10.09.2013

Во-первых, компилятор, скорее всего, оптимизирует ваш код. Проверьте параметр оптимизации вашего компилятора.

Поскольку массив, включающий out[], a[], b[], не используется последующим кодом, и никакое значение из out[], a[], b[] не будет выведено, компилятор должен оптимизировать блок кода следующим образом, чтобы никогда не выполняться вообще:

for(int i=0;i<=N;i++){
    a[i] = i;
}

for(int i=0;i<=N;i++){
    b[i] = i;
}

for(int i = 0; i < N; ++i)
    out[i] = a[i] + b[i];

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

И еще одно, установите N побольше. 100000 слишком мало для теста производительности, в настоящее время компьютер работает очень быстро с кодом o(n) в масштабе 100000.

unsigned int N = 10000000;
person lulyon    schedule 09.09.2013
comment
к сожалению, это не было решением. В любом случае я скомпилировал без оптимизации, но даже если я, например. распечатайте [] прошедшее время по-прежнему равно 0. - person toebs; 09.09.2013

Добавьте это в конец кода

int sum = 0;
for(int i = 0; i<N; i++)
    sum += out[i];
cout << sum;

Тогда вы увидите времена.

Поскольку вы не используете a[], b[], out[], соответствующие циклы for игнорируются. Это связано с оптимизацией компилятора.

Кроме того, чтобы увидеть точное время, которое требуется, используйте debug mode вместо release, тогда вы сможете увидеть время, которое требуется.

person smttsp    schedule 09.09.2013
comment
к сожалению, это не было решением. В любом случае я скомпилировал без оптимизации, но даже если я, например. распечатайте [] прошедшее время по-прежнему равно 0. Мне все еще любопытно, почему гранулярность составляет 10 Гц, куда бы вы ни посмотрели, часы рекомендуют измерять прошедшее время: \ - person toebs; 09.09.2013
comment
вы увеличили N, потому что он слишком мал? N=10^8 подходит для теста. Также вы можете делать в коде более сложные вещи, например int tot = 0; for(i=1:N) tot++; tot /=2;. Я не знаю насчет детализации :( - person smttsp; 10.09.2013