почему использование clock() получает минусовое число при измерении времени процессора

Я использую clock() для измерения количества процессорного времени для моего алгоритма.

Код выглядит так:

start_time = clock();
//code to be timed
.
end_time = clock();
elapsed_time = (end_time - start_time)*1000 / CLOCKS_PER_SEC;

printf("Time taken %d seconds %d milliseconds\n", elapsed_time/1000, elapsed_time%1000 );

Но в результате я получаю «0 секунд -175 миллисекунд». Я не могу понять, почему. И кажется, что «1 секунда 349 миллисекунд» действительно может занять 10 минут или более по прошествии времени. Это обычное дело?


person rei liu    schedule 30.05.2012    source источник
comment
Вы пытаетесь рассчитать время программы, которая разветвляется?   -  person nhahtdh    schedule 30.05.2012
comment
Да, это как раз то, что я хотел бы сделать.   -  person rei liu    schedule 30.05.2012
comment
Пожалуйста, покажите нам больше кода — с типами переменных и т. д. И убедитесь, что то, что вы показываете здесь, точно такое же, как то, что вы компилируете и тестируете (например, если вы измените printf на использование %lld, покажите это здесь). А также сообщите нам, на какой платформе вы работаете (и для какой архитектуры вы работаете — 32-битной или 64-битной).   -  person abarnert    schedule 30.05.2012


Ответы (2)


Форкинг — это особый случай, когда этот тип кода приводит к отрицательному времени. Одна из причин заключается в том, что clock() вернет количество тиков часов с момента запуска программы.

Напоминаем, что значение в start_time будет скопировано в дочерний процесс.

  • Для родительского процесса время должно быть положительным. Поскольку количество тактов часов для start_time и end_time относится к одному и тому же процессу.

  • Для дочернего процесса, поскольку он запускается только после fork(), clock() вернет количество тактовых импульсов, которые программа выполняет с этого момента и далее. Время до fork() не записывается.

    Поскольку начальная ссылка для подсчета тактовых импульсов отличается:

    • start_time is the number of clock ticks since the start of the parent process till the first clock()
    • end_time – количество тактов с момента запуска дочернего процесса до второго clock())

    Это может привести к отрицательному результату. Положительный результат также возможен, если дочерний процесс выполняется достаточно долго, чтобы превысить время запуска родительского процесса.

ИЗМЕНИТЬ

Я не уверен, каково ожидаемое время, но если вы хотите подсчитать: такты родительского процесса от начала до конца и такты дочернего процесса после fork() до конца, измените свой код, чтобы перезаписать start_time новым значением. из clock() в дочернем процессе. Или вы можете просто установить start_time на 0.

person nhahtdh    schedule 30.05.2012
comment
Привет nhahtdh, я запретил многопоточность. Так что это не должно быть вилкой, верно? - person rei liu; 30.05.2012
comment
Я не понимаю. Как долго может работать программа? И вы создаете поток/процессы между ними? - person nhahtdh; 30.05.2012
comment
Я имел в виду, что отключил использование пула потоков. Работает около часа. - person rei liu; 30.05.2012
comment
В этом случае возможно переполнение. Можете ли вы проверить sizeof и clock_t на машине, на которой запущена программа? - person nhahtdh; 30.05.2012
comment
Кажется, clock_t здесь 8 байт. Я удалил * 1000 и изменил elapsed_time, чтобы оно было беззнаковым. У вас есть другие советы? - person rei liu; 30.05.2012
comment
Извините, я действительно понятия не имею. - person nhahtdh; 30.05.2012
comment
@rei liu: я не уверен, что означает запрещенная многопоточность или отключенное использование пула потоков, но многопоточность не имеет ничего общего с разветвлением (кроме глубоко на уровне ядра). Вопрос в том, вызываете ли вы fork() между двумя вызовами clock(). Поскольку в вашем ответе на комментарии по фактическому вопросу говорилось, что это именно то, что я хотел бы сделать, nhahtdh предположил, что это действительно то, что вы хотели бы сделать. Если нет, так и скажи. - person abarnert; 30.05.2012

Если start_time и end_time являются 32-битными целыми числами, они могут содержать только около 2147 секунд (около 35 минут), прежде чем преобразоваться в отрицательные числа, потому что CLOCKS_PER_SEC равно 1000000.

Но это еще хуже, потому что вы умножаете разницу на 1000, а это означает, что если она превысит 2,147 секунды, она переполнится.

С другой стороны, если они не являются 32-битными целыми числами, вы используете неправильные спецификаторы формата printf (и вы, вероятно, получаете и игнорируете предупреждение от компилятора), поэтому вы видите мусор.

person abarnert    schedule 30.05.2012
comment
Они оба типа clock_t. Будет ли это переполнение? Да, я попробую еще раз с %f. Спасибо! - person rei liu; 30.05.2012
comment
IIRC, clock_t имеет длину без знака, что означает, что ваша арифметика будет переполняться в 32-битных сборках, а ваш printf будет печатать мусор в 64-битных сборках. И… я надеюсь, что это не оскорбляет ваш интеллект, но переход на %f не поможет, если вы также не переключите все переменные на двойные. - person abarnert; 30.05.2012