Прошедшее время выполнения программы C

Я хотел бы знать, какие строки кода C добавить в программу, чтобы она сообщала мне общее время, необходимое для запуска программы. Я предполагаю, что должна быть инициализация счетчика в начале основной функции и одна после окончания основной функции. Правильный заголовок clock.h?

Большое спасибо...

Обновление У меня есть машина с Win Xp. Это просто добавление clock() в начале и еще clock() в конце программы? Тогда я смогу оценить разницу во времени. Да, вы правы, это time.h.

Вот мой код:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <share.h>
#include <time.h>


void f(long double fb[], long double fA, long double fB);

int main() {

clock_t start, end;
start = clock();


const int ARRAY_SIZE = 11;

long double* z = (long double*) malloc(sizeof (long double) * ARRAY_SIZE);

int i;
long double A, B;

if (z == NULL) {
    printf("Out of memory\n");
    exit(-1);
}

A = 0.5;
B = 2;


for (i = 0; i < ARRAY_SIZE; i++) {
    z[i] = 0;
}

z[1] = 5;

f(z, A, B);

for (i = 0; i < ARRAY_SIZE; i++)
    printf("z is %.16Le\n", z[i]);



free(z);
z = NULL;

end = clock();
printf("Took %ld ticks\n", end-start);
printf("Took %f seconds\n", (double)(end-start)/CLOCKS_PER_SEC);



return 0;  
}  

void f(long double fb[], long double fA, long double fB) {
    fb[0] = fb[1]* fA;
    fb[1] = fb[1] - 1;
    return;
 }  

Некоторые ошибки с MVS2008:

testim.c(16) : error C2143: syntax error : missing ';' before 'const'  
testim.c(18) :error C2143: syntax error : missing ';' before 'type'  
testim.c(20) :error C2143: syntax error : missing ';' before 'type'   
testim.c(21) :error C2143: syntax error : missing ';' before 'type'    
testim.c(23) :error C2065: 'z' : undeclared identifier   
testim.c(23) :warning C4047: '==' : 'int' differs in levels of indirection from 'void *'  
testim.c(28) : error C2065: 'A' : undeclared identifier
testim.c(28) : warning C4244: '=' : conversion from 'double' to 'int', possible loss of data   

и это идет к 28 ошибкам. Обратите внимание, что у меня нет ошибок/предупреждений без ваших кодов часов.

ПОСЛЕДНИЕ НОВОСТИ: я, к сожалению, не получил здесь хорошего ответа. Но после поиска в гугле код работает. Вот:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


void f(long double fb[], long double fA);

int main() {

clock_t start = clock();


const int ARRAY_SIZE = 11;

long double* z = (long double*) malloc(sizeof (long double) * ARRAY_SIZE);

int i;
long double A;

if (z == NULL) {
printf("Out of memory\n");
exit(-1);
}

A = 0.5;


for (i = 0; i < ARRAY_SIZE; i++) {
z[i] = 0;
}

z[1] = 5;

f(z, A);

for (i = 0; i < ARRAY_SIZE; i++)
printf("z is %.16Le\n", z[i]);



free(z);
z = NULL;

printf("Took %f seconds\n", ((double)clock()-start)/CLOCKS_PER_SEC);



return 0;
}

void f(long double fb[], long double fA) {
fb[0] = fb[1]* fA;
fb[1] = fb[1] - 1;
return;
}

Ваше здоровье

Обновление от 10 апреля: вот лучшее решение благодаря «JustJeff».

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

void f(long double fb[], long double fA);

const int ARRAY_SIZE = 11;

int main(void)
{

   long double* z = (long double*) malloc(sizeof (long double) * ARRAY_SIZE);
   int i;
   long double A;

   LARGE_INTEGER freq;
   LARGE_INTEGER t0, tF, tDiff;
   double elapsedTime;
   double resolution;

   if (z == NULL) {
   printf("Out of memory\n");
   exit(-1);
   }
   QueryPerformanceFrequency(&freq);
   QueryPerformanceCounter(&t0);
   // code to be timed goes HERE
   {
    A = 0.5;


    for (i = 0; i < ARRAY_SIZE; i++) {
    z[i] = 0;
    }

    z[1] = 5;
    f(z, A);


    for (i = 0; i < ARRAY_SIZE; i++)
    printf("z is %.16Le\n", z[i]);

    free(z);
    z = NULL;

   }
QueryPerformanceCounter(&tF);
tDiff.QuadPart = tF.QuadPart - t0.QuadPart;
elapsedTime = tDiff.QuadPart / (double) freq.QuadPart;
resolution = 1.0 / (double) freq.QuadPart;
printf("Your performance counter ticks %I64u times per second\n", freq.QuadPart);
printf("Resolution is %lf nanoseconds\n", resolution*1e9);
printf("Code under test took %lf sec\n", elapsedTime);
return 0;
}


void f(long double fb[], long double fA) {
fb[0] = fb[1]* fA;
fb[1] = fb[1] - 1;
return;
}

Он работает как с MVS2008, так и с Borland C++ builderX 2003 года.


person yCalleecharan    schedule 07.04.2010    source источник
comment
Вы можете опубликовать ответ и принять его, если считаете, что теперь у вас есть лучший ответ. Это может быть полезно для кого-то, кто ищет ответ на поставленный вопрос (и я уверен, что другие люди ищут это все время).   -  person Cam    schedule 08.04.2010
comment
Я не знаю, есть ли у меня правильный ответ. Но это работает. Я всегда приветствую конструктивные предложения, поскольку я все еще учусь. Могу ли я принять (поставить галочку) свой собственный ответ?   -  person yCalleecharan    schedule 08.04.2010
comment
Да, ты можешь. И, кстати, не хочу показаться грубым, но как вы не получили хороший ответ здесь? У вас есть пара хороших ответов, которые должны сработать. Если вы получаете ошибки, это ваш собственный код, а не то, что вам дали ответчики. Если вы не считаете полученные ответы хорошими, скажите, как мы можем их улучшить.   -  person Javier    schedule 08.04.2010
comment
Я протестировал предложения здесь с MVS2008, и у меня были ошибки, как я упоминал в своем посте. Я новичок в программировании на C. Я не могу сказать, почему предложенные здесь коды не работают. Я получил ответ от Google, протестировал его с помощью своего кода, и, похоже, он работает. По мере того, как я улучшаю свои знания C со временем, я могу когда-нибудь вернуться и указать на любые ошибки, если таковые имеются, в предлагаемых здесь кодах. Там может быть что-то с моим собственным кодом. Я этого еще не знаю. Я здесь, чтобы учиться и делиться знаниями. С моими ограниченными знаниями в C мне трудно быть источником информации, но это изменится.   -  person yCalleecharan    schedule 09.04.2010


Ответы (6)


Если вы работаете в Windows и хотите измерять данные в микросекундах, изучите QueryPerformanceCounter() и QueryPerformanceFrequency(). Во многих системах они могут разрешать полные тактовые частоты процессора, треть наносекунды, и я не думаю, что когда-либо видел более грубую частоту, чем 3,5795 МГц, что все еще намного меньше микросекунды.

Вы вызываете QueryPerformanceFrequency(), чтобы определить, сколько счетчиков считает счетчик в секунду. Затем вызовите QueryPerformanceCounter() перед тестируемым кодом, а затем еще раз после. Разделите два показания QPC и разделите на период от QPF, и вы получите время, прошедшее между двумя вызовами QPC. Вот так ...

LARGE_INTEGER freq;
LARGE_INTEGER t0, tF, tDiff;
double elapsedTime;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&t0);
// code to be timed goes HERE
QueryPerformanceCounter(&tF);
tDiff.QuadPart = tF.QuadPart - t0.QuadPart;
elapsedTime = tDiff.QuadPart / (double) freq.QuadPart;
// elapsedTime now has your measurement, w/resolution given by freq

Очевидно, они обращаются к аппаратному счетному устройству, которое привязано к некоторому системному генератору на основной плате, и в этом случае они не должны страдать от джиттера из-за загрузки программного обеспечения. Полученное разрешение зависит от вашей системы.

ПОСЛЕДУЮЩИЕ

Вот очень простая полная программа, демонстрирующая интерфейс:

#include <windows.h>
int main(void)
{
    LARGE_INTEGER freq;
    LARGE_INTEGER t0, tF, tDiff;
    double elapsedTime;
    double resolution;
    QueryPerformanceFrequency(&freq);
    QueryPerformanceCounter(&t0);
    // code to be timed goes HERE
    {
        Sleep(10);
    }
    QueryPerformanceCounter(&tF);
    tDiff.QuadPart = tF.QuadPart - t0.QuadPart;
    elapsedTime = tDiff.QuadPart / (double) freq.QuadPart;
    resolution = 1.0 / (double) freq.QuadPart;
    printf("Your performance counter ticks %I64u times per second\n", freq.QuadPart);
    printf("Resolution is %lf nanoseconds\n", resolution*1e9);
    printf("Code under test took %lf sec\n", elapsedTime);
    return 0;
}

Для чего-то столь же простого быстрее пропустить IDE, просто сохранить его в файле foo.c и (при условии, что MS VS 2008) использовать командную строку

cl foo.c

построить его. Вот вывод в моей системе:

Your performance counter ticks 3579545 times per second
Resolution is 279.365115 nanoseconds
Code under test took 0.012519 sec
person JustJeff    schedule 07.04.2010
comment
Спасибо. Это кажется слишком продвинутым для меня :). - person yCalleecharan; 08.04.2010
comment
вызовы действительно довольно просты, способ их использования такой же, как и с clock(), разрешение намного лучше, чем с clock(), и худшая часть — это работа с 64-битными целыми числами. Ну, это также специфично для Windows, но вы пометили окна. - person JustJeff; 09.04.2010
comment
Спасибо. Я добавил заголовок windows.h, но все равно получаю ошибки. Ошибка возникает в строке QueryPerformanceFrequency(&freq); Компилятор жалуется: E2293 ) ожидается в строке 12. Другой: QueryPerformanceCounter(&t0); ошибка: E2293 ) ожидается в строке 13. Другая ошибка: tDiff = tF - t0; ошибка: E2096 Недопустимая структура в функции main в строке 57. Последняя ошибка: elapsedTime = tDiff / (double) freq; ошибка: E2110 Несовместимое преобразование типов в функции main в строке 58. Я скомпилировал это с помощью Borland C++ BuilderX. Любое предложение? - person yCalleecharan; 09.04.2010
comment
возьмите Microsoft Visual Studio Express 2005 или 2008, они бесплатны и идеально подходят для работы с Windows. - person JustJeff; 09.04.2010
comment
Не уверен, насколько стар компилятор Borland, который вы используете, возможно, вы могли бы усовершенствовать его работу, но он определенно работает с MS VS Express 2008, и я полагаю, что версия 2005 года такая же. - person JustJeff; 09.04.2010
comment
Хорошо спасибо. Я использую borland c++ BuilderX, который вышел в 2003 году. Да, у меня MS VS 2008. Что мне не нравится в VS, так это то, что он создает около 15 файлов для проекта, в то время как builderX создает только 7. Конечно, мне не нравится. не знаю, для чего используются другие файлы :), но я считаю, что они полезны в процессе отладки. - person yCalleecharan; 09.04.2010
comment
Я получаю несколько ошибок с MVS2008. Такие ошибки, как: ошибка C2143: синтаксическая ошибка: отсутствует ')' перед '&' из-за строки QueryPerformanceFrequency(&freq);, ошибка: синтаксическая ошибка: отсутствует '{' перед '&' из-за той же строки, ошибка синтаксической ошибки: '&' из-за той же строки. Все ошибки повторяются для следующей строки: QueryPerformanceCounter(&t0); Какие-либо предложения? - person yCalleecharan; 10.04.2010
comment
Большое спасибо за ваши добрые усилия. Пожалуйста, смотрите мой обновленный пост. Он отлично работает с MVS и с Borland. Не могли бы вы объяснить мне фразы: ваш счетчик производительности тикает 3579545 раз в секунду, а разрешение составляет 279,365115 наносекунд. Разрешение, я думаю, это просто точность, но как насчет счетчика производительности? - person yCalleecharan; 10.04.2010
comment
Счетчик представляет собой аппаратный регистр (64 бита), вероятно, в чипе северного моста, но, насколько мне известно, он может быть и в процессоре. Он свободно подсчитывается со скоростью, которая зависит от аппаратного обеспечения вашей системы, независимо от активности процессора. Внутри вызова QPC ЦП просто считывает этот счетчик. Вы должны прочитать частоту (через QPF), чтобы узнать, сколько времени занимает каждый счет. Распространенными значениями являются полная частота процессора (от ~ 2,4 до 3 ГГц!) и 3,579 МГц, что связано с устаревшей генерацией видеосигнала. - person JustJeff; 10.04.2010
comment
Ok. Спасибо за информацию и за предоставленный мне код, который работает. Между прочим, MVS2008 намного быстрее, чем Borland C++ builderX из 2003 года, примерно в 2 раза. - person yCalleecharan; 11.04.2010

В системах Unix (я думаю) команда time с именем вашей программы в качестве аргумента командной строки сообщит вам время, необходимое для запуска программы. Обратите внимание, что это измеряет время выполнения всей программы. Если вам нужно протестировать только одну часть, включите time.h и используйте функцию часов примерно так:

#include <time.h>

int main() {
    clock_t start;
    clock_t end;
    int function_time;
    start = clock();
    function_you_want_to_time();
    end = clock();
    /* Get time in milliseconds */
    function_time = (double)(end - start) / (CLOCKS_PER_SEC / 1000.0);
    return 0;
}

Это даст вам время в миллисекундах (обратите внимание на часть / 1000.0). Если вам нужны секунды, удалите / 1000.0. Если вам нужны простые тики часов, которые будут более точными, сделайте function_time clock_t и замените строку function_time = ... на:

function_time = end - start;

Чтобы синхронизировать всю программу, я предлагаю создать функцию с именем _main() или что-то в этом роде, переместить весь код, связанный с вашей программой, из main() (не временной код!) в эту функцию и вызвать ее из main(). Таким образом, становится более ясно, что такое временной код и какова остальная часть программы.

person Javier    schedule 07.04.2010
comment
Одним из недостатков этого является то, что если вы хотите, например, рассчитать время фактической части вычислений чего-либо и не хотите включать время загрузки ресурсов/данных или время вывода или что-то еще, команда time не может этого сделать (поскольку это время всего выполнения). - person Amber; 07.04.2010
comment
Это правда. Видимо для этого лучше подходит функция clock(), но я о ней не знал. Добавлю фразу. - person Javier; 07.04.2010
comment
Кстати, если вы хотите рассчитать время всей программы, поместите вызовы clock() в начале и в конце. Кроме того, может ли кто-нибудь сказать мне, правильно ли делить на CLOCKS_PER_SEC? - person Javier; 07.04.2010
comment
Спасибо. Должен ли function_you_want_to_time() принимать аргумент? Я хочу засечь всю программу. - person yCalleecharan; 07.04.2010
comment
@yCalleecharan: Если вы хотите рассчитать время всей программы, как я уже сказал, замените строку function_you_want_to_time(); остальной частью программы. Не имеет значения, принимает ли функция аргумент. Если вы хотите быть очень осторожным при измерении, переместите все в main() в другую функцию и вызовите ее из main(). Это значит, что вы не объявляете переменные до начала отсчета времени. Для C99 или C++ это неприменимо. - person Javier; 08.04.2010
comment
@yCalleecharan: я забыл, если вы хотите быть очень осторожным, вы можете убрать / CLOCKS_PER_SEC и сделать function_time как clock_t, чтобы вы получали счетчик часов вместо секунд. Я добавлю это к ответу. - person Javier; 08.04.2010
comment
Спасибо. 1 такт часов равен 1 с? - person yCalleecharan; 08.04.2010
comment
@yCalleecharan: Нет, намного меньше. Поэтому зачем делить на CLOCKS_PER_SEC. - person Javier; 08.04.2010

Если вам нужна сумма для вашей программы, то в консоли Linux:

$ time myProgram

Вы также можете использовать time.h в своем коде.

#include <time.h>

int main(){
  time_t start, end;
  start = time(0);

  /* some working code */

  end = time(0);
  printf("%i seconds", end - start );
}
person Draco Ater    schedule 07.04.2010
comment
Я получаю много ошибок. Должны ли мы определять тип time_t, start? - person yCalleecharan; 07.04.2010
comment
Я думаю, что это также может быть int. Мне не нужно было определять это нигде в моей Ubuntu. - person Draco Ater; 07.04.2010

Вы можете использовать функцию clock()<time.h>), если хотите протестировать блок кода, или программу time на *nix, как предложил другой ответчик. Например.

> time ./foo my args

Для часов вам нужно вычесть разницу между двумя контрольными точками. Например.

#include <time.h>

void f() {
  clock_t start, end;

  start = clock();

  // some long code.

  end = clock();
  printf("Took %ld ticks\n", end-start);
  // or in (fractional) seconds.
  printf("Took %f seconds\n", (double)(end-start)/CLOCKS_PER_SEC);
}

Обновлять

Что касается ваших новых ошибок, вы не можете смешивать код и объявления в VC. Вы не должны вызывать какие-либо функции, а затем продолжать объявлять переменные. Объявите все свои переменные вверху или скомпилируйте в режиме C++.

person Alex Budovski    schedule 07.04.2010
comment
Я получаю много ошибок. Должны ли мы определять тип clock_t, start? - person yCalleecharan; 07.04.2010
comment
Нужно ли нам иметь void f() ? Или мы можем просто поставить clock_t start, end; start = clock();...end = clock();printf(Пройдено %ld тактов\n, конец-начало); внутри основной? - person yCalleecharan; 07.04.2010
comment
Извините, это не работает для меня. MVS208 тупо ругается со 102 ошибкой. Компилятор жалуется, что многие вещи не определены. Вы уверены, что ничего не пропустили в своем фрагменте кода? - person yCalleecharan; 07.04.2010
comment
Опубликуйте свой код и ошибки. (Я полагаю, вы включили ‹stdio.h› для printf?) - person Alex Budovski; 07.04.2010
comment
Я действительно не понимаю, как моя программа неверна. Я использую C. Программа отлично работает без каких-либо предупреждений, когда у меня нет ваших кодов часов. Покажите мне, что изменить в моем коде, чтобы он оставался программой на C. Спасибо. - person yCalleecharan; 07.04.2010

Вероятно, вам нужен файл time.h и функция clock().

person Amber    schedule 07.04.2010

Вы также можете попробовать GetTickCount. Часы также будут работать нормально. Но я предполагаю, что значения часов изменятся, если какой-либо другой процесс или кто-то вручную изменит системное время, тогда как на значения GetTickCount это не повлияет.

person Jay    schedule 07.04.2010
comment
Да, это альтернатива. Я расследую это. - person yCalleecharan; 08.04.2010