2016-10-08 3 views
7

У меня есть код, который пытается определить время выполнения кода.Точность функции clock() в C

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

int main() 
{ 
    clock_t start_t, end_t, total_t; 
    int i; 

    start_t = clock(); //clock start 
    printf("Starting of the program, start_t = %ld\n", start_t); 

    printf("Going to scan a big loop, start_t = %ld\n", start_t); 
    for(i=0; i< 10000000; i++) //trying to determine execution time of this block 
    { 
    } 
    end_t = clock(); //clock stopped 
    printf("End of the big loop, end_t = %ld\n", end_t); 

    total_t = (long int)(end_t - start_t); 
    printf("Total time taken by CPU: %lu\n", total_t ); 

    return(0); 
} 

Выход фрагмента кода на моей машине

Starting of the program, start_t = 8965 
Going to scan a big loop, start_t = 8965 
End of the big loop, end_t = 27259 
Total time taken by CPU: 18294 

Так что, если мой процессор был запущен на 21 МГц и при условии, что это было единственным, что получение выполняется, каждый машинный цикл будет примерно равным 47 наносекунд, поэтому (18294 * 47) = 859818 наносекунд.

Будет ли это временем выполнения цикла for в моем коде? Я делаю некоторые неправильные предположения здесь.

+0

Чтобы получить время в секундах, вы должны разделить это число, например 'total_t' в вашем случае с' CLOCKS_PER_SEC'. Обратите внимание, что вам нужно указать 'total_t' значение плавающей запятой для его работы. –

+1

Также небольшая штриховка по вашей схеме именования: Символы, заканчивающиеся суффиксом '_t', обычно используются для псевдонимов типов (как создается с помощью' typdef'). Например, 'size_t' или' time_t' и даже 'clock_t'. –

+0

@JoachimPileborg Я просмотрел документацию для функции clock(), и CLOCK_PER_SEC вернет точное время до 1/100th секунды, и я ищу разрешение до 10 микросекунд, поэтому я использовал упомянутый подход. Также я хочу, чтобы это работало на разных платформах и архитектурах, поэтому я подумал, что просто вычисление разницы, а затем умножение на тактовую частоту будет лучшим вариантом, так как CLOCKS_PER_SEC изменится с архитектурой. – user2808264

ответ

4

Единица времени, используемая функцией clock, является произвольной. На большинстве платформ он не связан с скоростью процессора. Это чаще всего связано с частотой внешнего прерывания таймера, который может быть сконфигурирован в программном обеспечении, или с историческим значением, которое было сохранено для совместимости через годы эволюции процессора. Вам нужно использовать макрос CLOCKS_PER_SEC для преобразования в реальном времени.

printf("Total time taken by CPU: %fs\n", (double)total_t/CLOCKS_PER_SEC); 

Стандартная библиотека C был разработан, чтобы быть осуществимой на широком спектре аппаратных средств, в том числе процессоров, которые не имеют внутреннего таймера и опирающихся на внешней периферии, чтобы сообщить время. На многих платформах есть более точные способы измерения времени настенных часов, чем time, и более точные способы измерения потребления процессора, чем clock. Например, в системах POSIX (например, Linux и других Unix-подобных системах) вы можете использовать getrusage с точностью до микросекунды.

struct timeval start, end; 
struct rusage usage; 
getrusage(RUSAGE_SELF, &usage); 
start = usage.ru_utime; 
… 
getrusage(RUSAGE_SELF, &usage); 
end = usage.ru_utime; 
printf("Total time taken by CPU: %fs\n", (double)(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec)/1e-6); 

При наличии, clock_gettime(CLOCK_THREAD_CPUTIME_ID) или clock_gettime(CLOCK_PROCESS_CPUTIME_ID) может дать более высокую точность. Он имеет наносекундную точность.

Обратите внимание на разницу между точностью и точностью: точность - это единица, о которой сообщаются значения. Точность заключается в том, насколько близкие значения приведены к реальным значениям. Если вы не работаете с real-time system, нет никаких твердых гарантий относительно того, сколько времени занимает часть кода, включая вызов самих измерительных функций.

Некоторые процессоры имеют цикл часы, которые рассчитывают процессорные циклы, а не часы настенных часов, но это становится очень специфичным для системы.

Когда вы делаете тесты, будьте осторожны, что то, что вы измеряете, - это выполнение этого конкретного исполняемого файла на этом конкретном CPU в этих конкретных обстоятельствах, и результаты могут или не могут быть обобщены в других ситуациях. Например, пустой цикл в вашем вопросе будет оптимизирован большинством компиляторов, если вы не отключите оптимизацию. Измерение скорости неоптимизированного кода обычно бессмысленно. Даже если вы добавите настоящую работу в цикл, остерегайтесь игрушечных тестов: они часто не имеют одинаковых характеристик производительности, таких как код реального мира. На современных высокопроизводительных ЦП, таких как найденные на ПК и смартфонах, тесты кода, интенсивно использующего процессор, часто очень чувствительны к эффектам кеша, и результаты могут зависеть от того, что еще работает в системе, от точной модели процессора (из-за разных размеры и макеты кеша), по адресу, на котором загружается код, и т. д.

+0

@Giles Это именно то, что мне нужно. Он имеет разрешение до 1 us по сравнению с функцией часов, которая имеет разрешение 100 мс. Но знаете ли вы, что этот код переносимый. Мне нужно это для работы в системе ARM M0. Есть ли способ сделать этот код переносимым? – user2808264

+0

@ user2808264 Если вам нужно что-то за пределами 'clock', то оно не будет таким портативным, вы создадите зависимость либо от операционной системы, либо от процессора, либо от того и другого. Проверьте, что предоставляет ваша ОС. Если вы работаете на голом металле, если вам нужна точность с точностью до 1 мкс, вам понадобится счетчик с точностью до цикла, проверьте, какие функции отладки присутствуют на вашем процессоре (я думаю, что это дополнительная функция). Если вам не нужна такая точность, вы можете использовать [systick timer] (http://sushihangover.github.io/cortex-m-systick-polling-vs-interrupts/), который является необязательным, но широко распространенным. – Gilles

Смежные вопросы