Форум русскоязычного сообщества Ubuntu


Считаете, что Ubuntu недостаточно дружелюбна к новичкам?
Помогите создать новое Руководство для новичков!

Автор Тема: [SOLVED] С > метки времени в логе > поясните как это работает.  (Прочитано 1240 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн lukinfore

  • Автор темы
  • Новичок
  • *
  • Сообщений: 33
    • Просмотр профиля
Приветствую.

Нужно было проставить временные метки для ~5 Мб вывода, на sh получалось медленное и где-то в процессе появилась такая байда:
    #include <stdio.h>
    #include <time.h>
    #define size 511
    void main()
    {
    clock_t b,e; e=b=0;
    fdopen (0, "r");
    fdopen (1, "w");
    b=clock();
    char line[size+1];
    while (fgets (line, size, stdin))
    {
    e=clock();
    printf ("%f %ld ", e, e);/*(e-b)/(double)CLOCKS_PER_SEC*/
    printf("%s", line);
    }
    }
   
    $gcc log_ts.db.c -ggdb -O0 -o log_ts
    log_ts.db.c: In function ‘main’:
    log_ts.db.c:14:1: warning: format ‘%f’ expects type ‘double’, but argument 2 has type ‘clock_t’

    $echo "1
    > 2"|./log_ts
    0.000000 -1216321480 1
    0.000000 -1216321480 2
     
    $echo "1
    2"|./log_ts
    0.000000 -1216079816 1
    0.000000 -1216079816 2
Думалось в том смысле, что clock() возвращает число общих тиков системы. По man 3 clock вроде бы только затраты на процесс.
clock_t в глубине хедеров как бы long int. Итак вопросы:

Что это такое клок возвращает? И он ли? Ко времени явно имеет некое отношение. Таки СPU тики?

Если он, то почему по следующим циклам значение не меняется? Думал gсс переоптимизировал, но -O0, да и на -O2 по степпингу gdb клок честно выполняетcя.

Почему сие только при убогом использовании printf заметно? Т.е. если первую переменную убрать, поменять местами, s/%f/%lu выводится очень даже 0. А, допустим, 2й принтф в первый добавить"%f %ld %s" - на выходе непечатные 014 001 и прочие обратные пробелы перед строкой. Перекрывает память чтоле? Это фича принтф? Баг?

Как правильно все же clock() юзать? По гуглу глянул - 1 баг с дебиан3.1, куча советов не юзать и референсы - отнять и поделить(с)

Основной вопрос, в принципе - это я кривым рукоглазом чего-то очевидного не замечаю, или бок в glibc/gcc (clock Є glibc же?)

11.04, libc6 2.13-0ubuntu13, gcc 4.5.2-8ubuntu4

(Нажмите, чтобы показать/скрыть)
« Последнее редактирование: 15 Августа 2011, 15:27:40 от lukinfore »

andrey_p

  • Гость
Re: С : поясните как это работает.
« Ответ #1 : 11 Августа 2011, 15:40:31 »
sudo apt-get install glibc-doc
info libc 'CPU Time'

Оффлайн lukinfore

  • Автор темы
  • Новичок
  • *
  • Сообщений: 33
    • Просмотр профиля
Re: С : поясните как это работает.
« Ответ #2 : 11 Августа 2011, 21:18:57 »
sudo apt-get install glibc-doc
info libc 'CPU Time'

Так я похожим и руководствовался , только из гугеля. Спасибо, конечно.
Ну с clock кажется разобрался - там точность ±10000 => e меняется на ~1000 цикле. Такая особенность есть в документообразном виде? Видел на форуме иноземном нечто подобное, только там речь шла про gcc оптимизирующий обращения к clock.

Про printf тоже понятно примерно.

andrey_p

  • Гость
Re: С : поясните как это работает.
« Ответ #3 : 12 Августа 2011, 08:03:18 »
Там подробно описано как надо использовать clock() и как не надо. Как вы использовали - так не надо. А та особенность, которую вы описали, я уверен, зависит от машины к машине. В той же документации сказано, как измерить точность clock() самостоятельно. Жаль, что вы не посмотрели.

Оффлайн Yurror

  • Старожил
  • *
  • Сообщений: 1966
    • Просмотр профиля
Re: С : поясните как это работает.
« Ответ #4 : 12 Августа 2011, 13:45:15 »
1) реально рабочая версия будет при использовании clock_gettime с CLOCK_MONOTONIC
2) fgets небезопасна и, если мне не изменяет память, читает до символа который будет isspace(), что совсем не то же что и чтение строки. открой для себя getline. man-page приводит хороший пример кода для работы с этой функцией.
3) fdopen (0, "r"); fdopen (1, "w"); это что-то из уличной магии. дэвид блэйн обзавидовался бы. можешь внятно объяснить нафига это надо?
4) какой-то странный diff времени "на половину"

садись, два.

Оффлайн lukinfore

  • Автор темы
  • Новичок
  • *
  • Сообщений: 33
    • Просмотр профиля
Re: С : поясните как это работает.
« Ответ #5 : 12 Августа 2011, 16:29:08 »
andrey_p

в смысле "так не надо"? (clock1-clock2)/CLOCKS_PER_SEC - так и написано, и работает. Про разрешение есть. Оно все-таки hardware-based? От опции ядра зависит ( не помню названия, значения 100, 250, 1000 были)? В измерение точности ткните, не cмог обнаружить.

Yurror

"Unspecified starting point" в man clock_gettime это старт процесса? А CLOCK_PROCESS_CPUTIME_ID - что это?

Чем небезопасна? Читает до newline или eof или size. В getline размер буфера не надо определять, я правильно понял? Но если на входе не будет \n-ов, оно всю память съест? Открыл для себя, спс.

Скорее не могу. Они автоматом открыты же?

Т.е почему микросекунды не считаются? Смысла нет, только старт неточно показывает без.
printf ("%lu.%lu:%s", t.tv_sec-tb.tv_sec, (t.tv_usec>tb.tv_usec)?t.tv_usec-tb.tv_usec:1000000-t.tv_usec-tb.tv_usec,line); Канонично так вроде

2>0, авансы!

andrey_p

  • Гость
Re: С : поясните как это работает.
« Ответ #6 : 12 Августа 2011, 21:17:40 »
Цитировать
в смысле "так не надо"? (clock1-clock2)/CLOCKS_PER_SEC - так и написано, и работает.
Я посчитал, что для каждого замера нужен свой "clock1" и "clock2". У вас один первый старт и много окончаний в цикле. Но сейчас почитав внимательней понял, что скорее всего ошибся.

Про замер я совсем не в тему ляпнул. Поизучав немного, я залез в такие дебри, что понял, что на ура не разобраться (там вопросы с понижением частоты процессора, с переводам процесса с одного ядра или нити на другое, с работой видео, с другими realtime фичами). Но что точность может плясать с каким-то определенным (+/- 10000) числом - не попадалось.

Прошу прощения за неточные утверждения.

Оффлайн Yurror

  • Старожил
  • *
  • Сообщений: 1966
    • Просмотр профиля
Re: С : поясните как это работает.
« Ответ #7 : 14 Августа 2011, 06:14:46 »
...
"Unspecified starting point" в man clock_gettime это старт процесса?
в этом слове такой буквы мане таких слов нет.
обычна эта ошибка значит что в твоих объектниках нет функции main (ну это если в первом приближении)

...
А CLOCK_PROCESS_CPUTIME_ID - что это?
в мане же написано
Цитата: man clock_gettime
       CLOCK_PROCESS_CPUTIME_ID
              High-resolution per-process timer from the CPU.

...
Чем небезопасна? Читает до newline или eof или size. В getline размер буфера не надо определять, я правильно понял? Но если на входе не будет \n-ов, оно всю память съест? Открыл для себя, спс.
да, каюсь, попутал с gets. опасно тем что она не учитывает размер буфера.
да getline сожрет память. обломится при выделении очередного куска, освободит всю память и вернется с кодом -1 =) если конечно пользователь терпеливо дождётся этого момента.

...
Скорее не могу. Они автоматом открыты же?
да открыты автоматом, и указатели на структуры FILE, которые создаются вызовом fdopen, называются соответственно stdin, stdout и stderr. а ты эти структуры просто отправил куда-то в просрацию ни разу не воспользовавшись.

...
Т.е почему микросекунды не считаются? Смысла нет, только старт неточно показывает без.
printf ("%lu.%lu:%s", t.tv_sec-tb.tv_sec, (t.tv_usec>tb.tv_usec)?t.tv_usec-tb.tv_usec:1000000-t.tv_usec-tb.tv_usec,line); Канонично так вроде
канонично будет так:
struct timespec ts_begin;
clock_gettime(CLOCK_MONOTONIC, &ts_begin);
<мега вычисления>
struct timespec ts_end;
clock_gettime(CLOCK_MONOTONIC, &ts_end);
uint64_t diff = (ts_end.tv_sec*1000000000+ts_end.tv_nsec)-(ts_begin.tv_sec*1000000000+ts_begin.tv_nsec);
printf ("%lu.%lu:%s", diff / 1000000000, diff % 1000000000, line);

...
2>0, авансы!
ну с fgets ты всё-таки был прав.
« Последнее редактирование: 14 Августа 2011, 06:17:09 от Yurror »

Оффлайн lukinfore

  • Автор темы
  • Новичок
  • *
  • Сообщений: 33
    • Просмотр профиля
Re: С : поясните как это работает.
« Ответ #8 : 14 Августа 2011, 20:09:53 »
Цитата:  man clock_gettime
...
       CLOCK_MONOTONIC
              Clock that cannot be set and  represents  monotonic  time  since
              some unspecified starting point.
...
Is there other man on the dark side?
в мане же написано
Цитата: man clock_gettime
       CLOCK_PROCESS_CPUTIME_ID
              High-resolution per-process timer from the CPU.
Смущало ID и пер-процесс в функции, где id некуда вставить, но сейчас вижу тот же сlock(), только в nsec-ах и высокоразрешительный. Тогда какой смысл в clock_settime(CLOCK_PROCESS_CPUTIME_ID, ... ) (или, если он гетонли, чего б не написать что он гетонли, как про монотоник)? Мозгосекс какой-то ...

Цитировать
ни разу не воспользовавшись.
Т.е., коли уж использовать, то так?
while (fgets (line, size, fdopen( 0, "r")))
Цитировать
uint64_t diff = (ts_end.tv_sec*1000000000+ts_end.tv_nsec)-(ts_begin.tv_sec*1000000000+ts_begin.tv_nsec);
Ну, может так и канонично, но не нра - помножить поделить, мод. Надо будет попробовать на скорость, хех, экономим нано.
Алсо, ведь в таком виде можно CLOCK_REALTIME, который
Цитата: man clock_gettime
       All  implementations  support the system-wide real-time clock, which is identified by CLOCK_REALTIME.
использовать? Чем монотоник выделился?

andrey_p

Цитировать
Different computers and operating systems vary wildly in how they
keep track of CPU time.  It's common for the internal processor clock
to have a resolution somewhere between a hundredth and millionth of a
second.
Это про точность, но (для меня во всяком случае) совсем не очевидно, что результате будут просто отброшены младшие 0..4 разряда.

Оффлайн Yurror

  • Старожил
  • *
  • Сообщений: 1966
    • Просмотр профиля
Re: С : поясните как это работает.
« Ответ #9 : 14 Августа 2011, 21:16:43 »
REALTIME вернет текущее системное время.
системное время это не то же самое что и понятие времени вообще. оно может прыгать туда сюда, идти не равномерно при различных внешних воздействиях (перевод времени ручками, автоматически, периодическая синхронизация времени, ntpd умеет "плавно" менять время, заставляя его идти "быстрее" или "медленнее" и прочие чудеса науки).
MONOTONIC как раз гарантирует что у тебя будет абстрактная монотонная шкала времени, если тебя не волнует что сейчас именно среда 12ое 4-33 по среднезимбабвийскому времени, а необходимо иметь монотонную постоянно возрастающую последовательность отсчётов через равные промежутки времени... ну я надеюсь до тебя дошло о чем речь
unspecified starting point это значит что тебе никто никаких гарантий с какого числа начнется эта последовательность не даёт. как карта ляжет. скорее всего это обще системный счётчик который просто тупо таймером увеличивается с момента старта системы. и никто не знает когда запустится твоё приложение и тебе начнут отдавать текущее значение счетчика
CLOCK_PROCESS_CPUTIME_ID считает время которое процессор уделил исполнению именно твоего приложения. запусти приложение которое будет считать по реалтайму и по времени на процесс, нагрузи систему еще какими нибудь вычислениями и почувствуй разницу
аналогично для потока
пусть тебя ID не смущает, получить ты сможешь только свои значения.

while (fgets (line, size, fdopen( 0, "r")))иногда лучше жевать чем говорить (с)
не надо никогда открывать таким образом эти сраные дескрипторы. их за тебя уже libc открыл и настроил. просто пользуйся. их имена
FILE *stdin = fdopen(0, "r");
FILE *stdout = fdopen(1, "w");
FILE *stderr = fdopen(2, "w");
объявлять их тоже не надо, всё уже объявлено где-то в недрах stdio.h
блин, ну асиль уже хотябы "Си за 21 день для чайников"

uint64_t diff = (ts_end.tv_sec*1000000000+ts_end.tv_nsec)-(ts_begin.tv_sec*1000000000+ts_begin.tv_nsec);эти "ресурсоёмкие" вычисления надо делать уже после того как замерено время начала и время окончания выполнения куска кода для которого делается хронометраж.

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

Оффлайн lukinfore

  • Автор темы
  • Новичок
  • *
  • Сообщений: 33
    • Просмотр профиля
Re: С : поясните как это работает.
« Ответ #10 : 15 Августа 2011, 02:01:54 »
Итого: все около разжевано, спасибо.
Неясно по-прежнему какой смысл в clock_settime(CLOCK_PROCESS_CPUTIME_ID, ..) - если он сетабельный.

Yurror, я не говорил что помножалка "ресурсоемкая", нравится-не нравится - это чисто эстетическое определение =) Если говорить в контексте, то только первый замер покажет точное время, а остальные все вычисления будут учитывать. Опять же, во-первых это совершенно неважно в практическом плане, хотя бы потому, что нужно овер9000/с строк на входе для обнаружения разницы, во вторых, если уж важно, то принтф явно полезнее оптимизировать какимнить fputs или что там еще есть.

 

Страница сгенерирована за 0.021 секунд. Запросов: 22.