Замер времени выполнения кода

Тема в разделе "LANGS.C", создана пользователем ckunep, 28 июн 2009.

  1. ckunep

    ckunep New Member

    Публикаций:
    0
    Регистрация:
    3 сен 2008
    Сообщения:
    19
    Кто-нибудь может подсказать как замерить время выполнения кода, никак не могу найти подходящей функции...
     
  2. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    GetTickCount
    а вообще, на васме была даже отдельная тема, где показывали мануалы с картинками, в которых написано как с точностью до тиков посчитать
     
  3. dgs

    dgs New Member

    Публикаций:
    0
    Регистрация:
    23 июн 2008
    Сообщения:
    434
    rdtsc - кажется так еще можно
     
  4. ckunep

    ckunep New Member

    Публикаций:
    0
    Регистрация:
    3 сен 2008
    Сообщения:
    19
    я пытаюсь подключить winbase.h и компилятор выдает море ошибок(free command line tools от borland). для этого заголовочного файла нужно еще какие то библиотеки?
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    ckunep
    Зачем winbase.h? windows.h!
     
  6. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Несколько миллирдов итерация плюс TSC/KeTickCount - необходимая точность обеспечена.
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Clerk
    Клёво, может ему ещё дровер написать?
     
  8. ckunep

    ckunep New Member

    Публикаций:
    0
    Регистрация:
    3 сен 2008
    Сообщения:
    19
    а если сделать так:
    Код (Text):
    1. start = clock();
    2.  
    3. for(i = 0; i < max; i++)
    4.   testFunc();
    5.  
    6. time = clock() - start;
    то такой способ будет точен, если я хочу определить какая функция будет быстрее работать? вначале подставив первую функцию, а затем вместо нее другую
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Ну можно профилирование заюзать, хотя тоже слишком медленно и напрямую апик читать - он тоже медленно работает.
     
  10. Phuntik

    Phuntik New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2008
    Сообщения:
    318
    ckunep
    QueryPerformanceFrequency, QueryPerformanceCounter. Есть класс Timer. Куда слать?
     
  11. ckunep

    ckunep New Member

    Публикаций:
    0
    Регистрация:
    3 сен 2008
    Сообщения:
    19
    да я решил испл. GetTickCount, всем спасибо
     
  12. coder_x

    coder_x New Member

    Публикаций:
    0
    Регистрация:
    15 окт 2006
    Сообщения:
    12
    По идее, для чистоты эксперимента, неплохо было бы исключить влияния диспетчеризации процессов, хотя ,конечно, эту погрешность можно попытаться задавить очень большим числом итераций. Если чисто, то надо в драйвере повысить IRQL до DISPATCH_LEVEL и там уже посчитать имхо время выполнения цикла. Кстати, над самим циклом тоже можно подумать еще, так как в зависимости от проца (устройство конвейера, время выполнения инструкций) он может выполняться за весьма разное число тактов.
     
  13. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    function TargetFuncTickTest(nIter : DWORD; Func : Pointer; ARG : Pointer) : LONGLONG; stdcall; assembler;

    var CurrentThread,
    CurrentProcess : THandle;
    ThreadPriority : Integer;
    PriorityClass : DWORD;

    asm
    //push ESI
    //push EDI
    //push ECX
    pushad

    mov EBX, ARG
    //push EBX

    call GetCurrentThread
    mov CurrentThread, EAX
    push EAX
    call GetThreadPriority
    mov ThreadPriority, EAX

    call GetCurrentProcess
    mov CurrentProcess, EAX
    push EAX
    call GetPriorityClass
    mov PriorityClass, EAX

    push THREAD_PRIORITY_TIME_CRITICAL
    push CurrentThread
    call SetThreadPriority

    push REALTIME_PRIORITY_CLASS
    push CurrentProcess
    call SetPriorityClass

    //pop EBX

    mov dword ptr [Result], 0
    mov dword ptr [Result + 4], 0

    FNINIT
    mov ECX, nIter
    @loop: db 00Fh, 031h // rdtsc
    push EAX
    push EDX

    push EBX
    call Func

    db 00Fh, 031h // rdtsc
    pop EDI
    pop ESI
    sub EAX, ESI
    sbb EDX, EDI
    add dword ptr [Result], EAX
    adc dword ptr [Result + 4], EDX
    FSTP ST
    loop @loop

    FILD Result
    FIDIV nIter
    FISTP Result

    push ThreadPriority
    push CurrentThread
    call SetThreadPriority

    push PriorityClass
    push CurrentProcess
    call SetPriorityClass

    popad
    //pop ECX
    //pop EDI
    //pop ESI

    end { TargetFuncTickTest };

    в тиках выдаёт среднее значение, правда данные успевают закэшироваться; чтобы максимальное время замерить можно изменить эту
    function GetCPUFreq() : LONGLONG; stdcall; assembler;
    asm
    push ECX
    push EBX

    db 00Fh, 031h // rdtsc
    push EAX
    push EDX
    push 1000
    call Sleep
    db 00Fh, 031h
    pop ECX
    pop EBX
    sub EAX, EBX
    sbb EDX, ECX

    pop EBX
    pop ECX

    end { GetCPUFreq };
     
  14. ohne

    ohne New Member

    Публикаций:
    0
    Регистрация:
    28 фев 2009
    Сообщения:
    431
    страница USER_SHARED_DATA
    везде доступна
     
  15. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    ohne
    Там счётчик тиков изменяется не линейно.
     
  16. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    в продолжение темы. как-то писал апликуху, чтобы можно было замерять время выполнения кода между точками останова. прога запрашивает время активности указанного потока каждую секунду, и выводит результат. при отладке под VC получилась такая странность:
    - если поставить бряк и запустить код на выполнение, то после срабатывания бряка апликуха показывает результат (вполне ожидаемый)
    - если же выполнять код пошагово, то время выполнения не изменяется, т.е. поток просто-напросто спит.

    неужто студия выполняет отлаживаемый код в отдельном потоке?
     
  17. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Ес-но, мгновенно выполняет один шаг и засыпет. А время не тикает, т.к. не хватает разрешающей спсобности системного таймера. Это все равно, что "накапайте мне стаканчик" - можно из кранчика по капельке целое ведерко или бочечку набрать, а счетчик воды при этом ни на копейку не изменится ;)

    Отладчик и отлаживаемый код это разные процессы и ес-но разные потоки - когда один работает второй ждет\спит
     
  18. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    по поводу первого я также думал сначала, пока не сделал подвисание в цикле на несколько секунд, типа

    Код (Text):
    1. void func() { for (int i = 1; i; i ++) for (int j = 1; j; j ++) __asm nop; }
    2. ...
    3. eip -> func();
    по поводу второго я не понял вашей мысли. хотя, может быть я неправильно выразился. меня смущает то, что время активности отлаживаемого пошагово студией потока не меняется. т.е., стоит указатель команды, например, на линии 3; я нажимаю F10 => указатель переместился на линию 4, а время активности отлаживаемого потока не изменилось.
     
  19. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    leo
    Потоки разные, но вот выполняться могут в контексте одного процесса. Чисто теоретически, ядро вначале доставляет сообщение на отладочный порт, затем если не обработано на порт исключений. Последний может быть установлен посредством ProcessExceptionPort, но только в случае если прежде порт установлен не был. А его устанавливает csrss при инициализации процесса(CsrCreateProcess()). Тоесть необходимо создать процесс без нотификации подсистемы, этот процесс должен быть нативным. В нём создать тред, который будет обрабатывать сепшены в текущем процессе.