Время исполнения кода.

Тема в разделе "WASM.A&O", создана пользователем gaeprust, 22 май 2011.

  1. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Ну да, ну да, а учитывать макрофьюжн и спекулятивное выполнение не надо, что ли? :)
     
  2. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    Dmitry_Milk
    Что зачем. Вроде я понятно обьяснил. Зачем вообще измерять время исполнения кода =)

    Для не понятливых обьясню проще. Есть код. Нужно узнать сколько времени занимает его исполнение вне зависимости от внешних факторов. Причём время измерения мало(не миллиарды итераций, как обычно вы мерите своим rdtsc).
     
  3. qqwe

    qqwe New Member

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

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    gaeprust
    "Своим" rdtsc "мы", согласно учению великого Фога, как раз и измеряем малые интервалы. Чем меньше интервал относительно вел-ны кванта (в пределах разумного ес-но), тем надежнее его можно определить статистическим методом - просто провести 5-10 измерений и взять из них 2-3 наименьших значения (и таким образом отбросить возможные выбросы за счет виндовых прерываний).
    Если же речь идет о длительных измерениях типа обработки файлов или "перелопачивании" больших объемов памяти, то эти штуки сами по себе дают нехилый разброс по времени, и соотв-но учет\неучет виндовых прерываний тут существенной роли не играет - опять же для надеги производим несколько измерений и "на глаз" оцениваем разброс\правдоподобность рез-тов и значимость различий для разных вариантов обработки
     
  5. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    Можно измерить длительность кванта и длительность прерывания(в dTSC), вот деограмка.
     
  6. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    Тогда механизм будет примерно следующим(одна итерация измерения):
    Код (Text):
    1.     Tq = TSC()
    2.     WaitNextQuantum()   ; Ожидаем начало нового кванта.
    3.     SetIntTrigger() ; Взводим триггер для ожидания возврата из Int.
    4.     Do  ; Цикл ожидания возврата из Int.
    5.         Ti = TSC()
    6.     Loop GetIntTrigger()    ; Триггер взведён - прерывание закончено.
    7.     if QuantumSignal()  ; Проверяем начало нового кванта.
    8.         Tq = TSC() - Tq ; Новый квант. Вычисляем длительность кванта.
    9.     fi
    10.     Ti = TSC - Ti   ; Длительность прерывания или кванта.
     
  7. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    задача не имеет практического смысла увы за некоторыми исключениями
    а некоторым исключениям такая точность не нужна и спалится сиюсекундно
    иначе не имею причины даже задумываться над тем что сказано

    и все же


    есть участок - поток

    при начале выполнения ставим метку времени с учетом частоты и учетом выполения кода определения частоты и поставки в память метки
    перехватываем своп потоков
    там обрабатываем время свопа
    а именно время свопа время выполнения потока1, 2, 3, n, потом ловим переключение потока на наш
    и вычитаем
     
  8. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    вот очевидное решение
    излагайте проблемы
     
  9. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    да прерывания тоже перехватываем точнее обращение к ним
     
  10. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    punxer
    #1: юзермод.
    Память можно залочить в юзермоде(MmProbeAndLockPages() весьма просто используется, через RC-атаку на некоторые сервисы, либо просто частым обращением к буферу из другого треда).
     
  11. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    переносите в кернел тогда
     
  12. h0t

    h0t Member

    Публикаций:
    0
    Регистрация:
    3 апр 2011
    Сообщения:
    735
    Можно еще простой способ ~ замера времени GetThreadTime() вернет количество времени которое отработал поток (по мнению планировщика)
     
  13. asmlamo

    asmlamo Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 май 2004
    Сообщения:
    1.735
    Нельзя на разных системах оно разное. Более того даже в рамкаж одной системы нестабильно.

    Ерунду написали. rdtsc счетчик количества тактов с момента последнего сброса процессора
     
  14. asmlamo

    asmlamo Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 май 2004
    Сообщения:
    1.735
    Зачем ?
    Зачем вычленять точное время а потом вводить поправочные коэфф. если можно СРАЗУ посчитать РЕАЛЬНОЕ время.
    Не мучай попу как говорят ....

    Практического смысла в этом нет вовсе.
     
  15. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    asmlamo
    Околоквантовые длительности через тск не измеряют. Обычно накапливается статистика в течении секунд или десятков секунд для получения необходимой точности(ядро при загрузке например определяет реальные MHz камня, используя большое число итераций). Например длительность исполнения какого то сервиса единичного так не измерить, нужно учесть квантование. Если измерить реальное время исполнения, то можно определить и время исполнения этого кода например с !EFlags.IF. Да и вообще хочу знать сколько времени процессор исполняет код на данном потоке, а сколько простаивает.
     
  16. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    Ап. Предлагайте идеи свои, нечего стесняться. Чего так уныло :dntknw:
     
  17. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Фо фан можно вычесть время загрузки системы в простое(винда наверняка в состоянии предоставить метрики). Для больших замеров это не нужно, так как 5% погоды не сделают. Для маленьких тоже - оно быстрее закончится чем квант. VTune просто прогоняет серию тестов и не заморачивается. Практика показывает, что время выполнения одного и того же кода может хорошо различаться(кэш, фигеш), так что одним прогоном всё равно не обойтись и вообще это фантасмагория.
     
  18. deLight

    deLight New Member

    Публикаций:
    0
    Регистрация:
    26 май 2008
    Сообщения:
    879
    gaeprust
    На деле ведь совсем другое хотелось замерить, правда?? ,)
     
  19. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    гдето такой простейший бенчик пришел в голову
    Код (Text):
    1. #include <stdio.h>
    2. #include <windows.h>
    3.  
    4.  
    5. void test_Q(){
    6.     unsigned t_h, t_l;
    7.  
    8.     _asm{
    9.         pusha
    10.     }
    11.  
    12.     Init:
    13.     _asm{
    14.  
    15.         mov esi,0
    16.         mov edi,0
    17.  
    18.         mov ebx,0
    19.         mov ecx,0
    20.  
    21.         rdtsc
    22.         push edx
    23.         push eax
    24.     }
    25.  
    26.     Q_wait:
    27.     _asm{
    28.         pop esi
    29.         pop edi
    30.  
    31.         xchg eax,edx
    32.         xchg eax,edx
    33.  
    34.         xchg eax,edx
    35.         xchg eax,edx
    36.  
    37.         xchg eax,edx
    38.         xchg eax,edx
    39.  
    40.         xchg eax,edx
    41.         xchg eax,edx
    42.  
    43.         rdtsc
    44.  
    45.         push edx
    46.         push eax
    47.  
    48.         sub eax,esi
    49.         sbb edx,edi
    50.        
    51.         jnz Q_begin
    52.  
    53.         cmp eax,100
    54.         jc Q_wait
    55.     }
    56.     Q_begin:
    57.     _asm{
    58.         mov eax,0
    59.         mov edx,0
    60.     }
    61.  
    62.     Q_time:
    63.     _asm{
    64.         add ebx,eax
    65.         adc ecx,edx
    66.  
    67.         pop esi
    68.         pop edi
    69.  
    70.         xchg eax,edx
    71.         xchg eax,edx
    72.  
    73.         xchg eax,edx
    74.         xchg eax,edx
    75.  
    76.         xchg eax,edx
    77.         xchg eax,edx
    78.  
    79.         xchg eax,edx
    80.         xchg eax,edx
    81.  
    82.         rdtsc
    83.  
    84.         push edx
    85.         push eax
    86.  
    87.         sub eax,esi
    88.         sbb edx,edi
    89.        
    90.         jnz Q_end
    91.  
    92.         cmp eax,100
    93.         jc Q_time
    94.     }
    95.  
    96.     Q_end:
    97.     _asm{
    98.         pop esi
    99.         pop edi
    100.  
    101.         test ebx,ebx
    102.         jz Init
    103.  
    104.         mov t_l,ebx
    105.         mov t_h,ecx
    106.  
    107.         popa
    108.     }
    109.  
    110.     printf("Q time = %d:%d\n", t_h, t_l);
    111. }
    112.  
    113.  
    114. void test_sleep0(){
    115.     unsigned t_h, t_l;
    116.  
    117.     _asm{
    118.         pusha
    119.     }
    120.     Sleep(0);
    121.     _asm{
    122.         rdtsc
    123.         push eax
    124.         push edx
    125.     }
    126.     Sleep(0);
    127.     _asm{
    128.         rdtsc
    129.         pop ecx
    130.         pop ebx
    131.  
    132.         sub eax,ebx
    133.         sbb edx,ecx
    134.  
    135.         mov t_l,eax
    136.         mov t_h,edx
    137.  
    138.         popa
    139.     }
    140.     printf("Sleep(0) time = %d:%d\n", t_h, t_l);
    141. }
    142.  
    143.  
    144. int main(){
    145.     int i;
    146.  
    147.     for(i = 0; i < 20; i++)
    148.         test_Q();
    149.  
    150.  
    151. //  for(i = 0; i < 20; i++)
    152. //      test_sleep0();
    153.  
    154.  
    155.     return 0;
    156. }
    показания довольно стабильные и мало зависят, например, от загрузки проца. но очень часто наблюдается задержка сразу после выхода в квант (test ebx,ebx; jz Init). с чем связана не знаю. возможно, с тем, что используется память (стек). или кэшированием кода (вряд ли).

    прерывания заметны тоже. особенно большая помеха от сети и таймеров.

    там ниже тест слипа. это больше для себя. интересно, что если убрать предварительный слип, то время тестируемого увеличивается вдвое. слип(0) ныряет в ядро и сразу же возвращается не ожидая очередного кванта (абыдна. придется переделать пару вещей). слип(1) берет время както уж очень хаотично. бывает и заметно меньше вымученного времени кванта, бывает и заметно больше. больше понятно, но почему меньше?

    сразу и вопрос - если слип(0) не пропускает квант, то что можно использовать чтобы остановить поток в этом, но нормально получить следующий квант?

    а может, я тут ошибся все. если так, то поправьте.
     
  20. deLight

    deLight New Member

    Публикаций:
    0
    Регистрация:
    26 май 2008
    Сообщения:
    879
    qqwe
    А зачем так все сложно?
    В чем смысл этих конструкций вокруг rdtsc, в двух словах плз.

    Свопился ли поток можно смотреть по gs, при свопе сбрасывается.