nixp.ru v3.0

17 января 2017,
вторник,
20:13:56 MSK

DevOps с компанией «Флант»
yads написал 29 мая 2008 года в 00:53 (567 просмотров) Ведет себя неопределенно; открыл 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.);

}

sas

Посмотрите http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

yads

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

sas


#include 
#include 
#define TIMEV(t) ((double)t.tv_sec + (double)t.tv_usec/1000000.0)
int main( void ) {
        struct timeval t1, t2;
        int i = 0, j;
        for ( i = 0; i < 100000; i++ ) {
            gettimeofday( &t1, NULL );
            gettimeofday( &t2, NULL );
            printf( "Diff\t%.24F\n", TIMEV( t2 ) - TIMEV( t1 ) );
        }
        return 0;
}

У меня работает. Кстати, дизайн ваших функций имеет как минимум 2 недостатка:

1) использование глобальных переменых засоряет код и должно быть сведено к минимуму

2) Функция timeend возвращает разницу во времени, но ее название об этом не говорит, т.к. timebeg просто запоминает начало. Мой совет или используйте gettimeofday напрямую и вводите одну функцию time_diff например, или используйте 3 функции save_start/save_end/duration. Конечно юе приведенные имена функций для примера :)

yads

Мои функции были написаны для тестирования кода и вставлялись по нескольку раз сразу в несколько функций, поэтому были использованы глобальные переменные (об использовании статических не подумал — для теcтирования не так важно, как и имена функций).

Использование Вами double вместо float не принципиально, поскольку величина ошибки у меня бывает слишком большой (нормальные значения примерно от 0.001 до 0.1, а не нормальные почти -1). Проблема либо в gettimeofday, либо время в линуксе может идти не только вперед.

myst

Где-то я уже на такое натыкался… Вспомню — напишу.

yads

Возникла версия что gettimeofday сначала копирует данные в .tv_sec, а потом в .tv_usec, а между этими копированиями может происходить обновление обоих переменных в системе и я получаю старое .tv_sec и новое .tv_usec — в результате ошибка на -1 секунду, если при обновлении изменилось .tv_sec. Если это правда, то как с этим бороться?

sas

После изучения Ваших постов возникает впечатление, что Ваш код ВСЕГДА правилен, а системных библиотек нет :) Я говорю о malloc/free и росте памяти процесса и gettimeofday. Конечно, всегда есть малюсенькая вероятность, что ошибка не у Вас, но, поверьте человеку, очень давно программирующему, ошибка 99.999% у Вас. Извините если обидел, но тяжело удержаться.

yads
sas
После изучения Ваших постов возникает впечатление, что Ваш код ВСЕГДА правилен, а системных библиотек нет :) Я говорю о malloc/free и росте памяти процесса и gettimeofday. Конечно, всегда есть малюсенькая вероятность, что ошибка не у Вас, но, поверьте человеку, очень давно программирующему, ошибка 99.999% у Вас. Извините если обидел, но тяжело удержаться.

Разве я говорил, что «системных библиотек нет"? Они есть и я ими пользуюсь.

Опыт в программировании у меня тоже не маленький и отлаживалась эта программа довольно долго, но знаний линукса у меня недостаточно. Я не знал что free, освобождая память, не возвращает ее ядру и предполагал, что она работает не так, как должна. Я не знал и о функции malloc_trim, которая возвращает освобожденную память ядру. С ней сейчас тоже проблема — она возвращает память не каждый раз — возможно я что-то еще не знаю.

А с gettimeofday возможно проблема сложнее — на тестовой машине мне не удается увидеть отрицательное время, ошибка проявляется только на рабочем сервере. А поскольку мой код в три строчки и к таким эффектам приводить не может, то проблема явно не в нем. (и врятли к такому эффекту может приводить железо).

metal
yads
(и врятли к такому эффекту может приводить железо).

Мой опыт показывает, что железо может приводить к любым эффектам:) Ту деление на миллион есть, сразу была мысль что проблема в нем. Но я не смог придумать ее механизм. Как насчет написать маленький тест который будет делать тоже самое но не со временем. Будет ли он всегда корректно работать на этой машине?

yads

Тест сделать можно, только я не понял что использовать вместо времени?

И сколько его гонять при не проявлении проблемы? (машина-то не тестовая, а работающий интернет-сервер с кучей сайтов и сильно грузить его не желательно).

metal

Сымитировать выполнение этой функции, т.е. заполнить самостоятельно структуру и провести вычисления. Кстати, в твоей функции, gettimeofday не проверяется на ошибки.

yads

Протестировать попробую.

А про проверку на ошибки:

————-

КОДЫ ОШИБОК

EPERM

settimeofday вызвана без прав суперпользователя.

EINVAL

Неправильно указан часовой пояс (или какие-то другие параметры).

EFAULT

Или tv или tz указывают на недоступную область адресного пространства.

—————

Ни одна из возможных ошибок произойти все равно не может.

metal
yads
Протестировать попробую.

А про проверку на ошибки:

————-

КОДЫ ОШИБОК

EPERM

settimeofday вызвана без прав суперпользователя.

EINVAL

Неправильно указан часовой пояс (или какие-то другие параметры).

EFAULT

Или tv или tz указывают на недоступную область адресного пространства.

—————

Ни одна из возможных ошибок произойти все равно не может.

Если судить по документации, то да, но не стоит ей доверять на 100%.

yads

В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.);

ecobeingecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.