yads
написал 29 мая 2008 года в 00:53 (1262 просмотра)
Ведет себя
неопределенно; открыл 6 тем в форуме, оставил 36 комментариев на сайте.
Для получения времени выполнения кода перед ним вызываю функцию timebeg()
после него функцию timeend() (функции приведены ниже).
Обычно время бывает разумным, но иногда оказывается <0,
например -0.973169
Возможность повреждения timenow1 исключена.
struct timeval timenow1,timenow2;
void timebeg()
{
gettimeofday(&timenow1, NULL);
}
float timeend()
{
gettimeofday(&timenow2, NULL);
return(=(float)timenow2.tv_sec-(float)timenow1.tv_sec+((float)(timenow2.tv_usec-timenow1.tv_usec))/1000000.);
}
Последние комментарии
- OlegL, 17 декабря в 15:00 → Перекличка 21
- REDkiy, 8 июня 2023 года в 9:09 → Как «замокать» файл для юниттеста в Python? 2
- fhunter, 29 ноября 2022 года в 2:09 → Проблема с NO_PUBKEY: как получить GPG-ключ и добавить его в базу apt? 6
- Иванн, 9 апреля 2022 года в 8:31 → Ассоциация РАСПО провела первое учредительное собрание 1
- Kiri11.ADV1, 7 марта 2021 года в 12:01 → Логи catalina.out в TomCat 9 в формате JSON 1
ecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.
Посмотрите http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
У меня плохо с английским, как я понял там говорится о точности плавающей арифметики, но ошибки плавающей арифметики при одной операции вычитания обычно бывают лишь в последнем знаке (ну может в двух), а здесь все число неверное.
У меня работает. Кстати, дизайн ваших функций имеет как минимум 2 недостатка:
1) использование глобальных переменых засоряет код и должно быть сведено к минимуму
2) Функция timeend возвращает разницу во времени, но ее название об этом не говорит, т.к. timebeg просто запоминает начало. Мой совет или используйте gettimeofday напрямую и вводите одну функцию time_diff например, или используйте 3 функции save_start/save_end/duration. Конечно юе приведенные имена функций для примера :)
Мои функции были написаны для тестирования кода и вставлялись по нескольку раз сразу в несколько функций, поэтому были использованы глобальные переменные (об использовании статических не подумал — для теcтирования не так важно, как и имена функций).
Использование Вами double вместо float не принципиально, поскольку величина ошибки у меня бывает слишком большой (нормальные значения примерно от 0.001 до 0.1, а не нормальные почти -1). Проблема либо в gettimeofday, либо время в линуксе может идти не только вперед.
Где-то я уже на такое натыкался… Вспомню — напишу.
Возникла версия что gettimeofday сначала копирует данные в .tv_sec, а потом в .tv_usec, а между этими копированиями может происходить обновление обоих переменных в системе и я получаю старое .tv_sec и новое .tv_usec — в результате ошибка на -1 секунду, если при обновлении изменилось .tv_sec. Если это правда, то как с этим бороться?
После изучения Ваших постов возникает впечатление, что Ваш код ВСЕГДА правилен, а системных библиотек нет :) Я говорю о malloc/free и росте памяти процесса и gettimeofday. Конечно, всегда есть малюсенькая вероятность, что ошибка не у Вас, но, поверьте человеку, очень давно программирующему, ошибка 99.999% у Вас. Извините если обидел, но тяжело удержаться.
Разве я говорил, что «системных библиотек нет"? Они есть и я ими пользуюсь.
Опыт в программировании у меня тоже не маленький и отлаживалась эта программа довольно долго, но знаний линукса у меня недостаточно. Я не знал что free, освобождая память, не возвращает ее ядру и предполагал, что она работает не так, как должна. Я не знал и о функции malloc_trim, которая возвращает освобожденную память ядру. С ней сейчас тоже проблема — она возвращает память не каждый раз — возможно я что-то еще не знаю.
А с gettimeofday возможно проблема сложнее — на тестовой машине мне не удается увидеть отрицательное время, ошибка проявляется только на рабочем сервере. А поскольку мой код в три строчки и к таким эффектам приводить не может, то проблема явно не в нем. (и врятли к такому эффекту может приводить железо).
Мой опыт показывает, что железо может приводить к любым эффектам:) Ту деление на миллион есть, сразу была мысль что проблема в нем. Но я не смог придумать ее механизм. Как насчет написать маленький тест который будет делать тоже самое но не со временем. Будет ли он всегда корректно работать на этой машине?
Тест сделать можно, только я не понял что использовать вместо времени?
И сколько его гонять при не проявлении проблемы? (машина-то не тестовая, а работающий интернет-сервер с кучей сайтов и сильно грузить его не желательно).
Сымитировать выполнение этой функции, т.е. заполнить самостоятельно структуру и провести вычисления. Кстати, в твоей функции, gettimeofday не проверяется на ошибки.
Протестировать попробую.
А про проверку на ошибки:
————-
КОДЫ ОШИБОК
EPERM
settimeofday вызвана без прав суперпользователя.
EINVAL
Неправильно указан часовой пояс (или какие-то другие параметры).
EFAULT
Или tv или tz указывают на недоступную область адресного пространства.
————--
Ни одна из возможных ошибок произойти все равно не может.
Если судить по документации, то да, но не стоит ей доверять на 100%.
Вcе было просто…
Надо было написать не
return((float)timenow2.tv_sec-(float)timenow1.tv_sec+((float)(timenow2. tv_usec-timenow1.tv_usec))/1000000.);
а
return(timenow2.tv_sec-timenow1.tv_sec+((float)(timenow2. tv_usec-timenow1.tv_usec))/1000000.);