На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Помните, что у нас есть FAQ раздела Assembler и Полезные ссылки. Посмотрите, возможно, там уже имеется решение вашего вопроса.

3. Настоятельно рекомендуем обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "Ассемблер" будут отправляться в Корзину для мусора.
  3.2. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).
  3.3. Нежелательно поднимать старые темы (не обновлявшиеся более года) без веской на то причины.

Не забывайте также про главные Правила форума!

Добро пожаловать и приятного вам общения!!! ;)
 
Модераторы: Jin X, Qraizer
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Измерение времени выполнения кода, как средство профилирования
    Имхо замерять время выполнения всей программы наоборот не имеет смысла - если снимать профайл, то с отдельных её участков. Если вместо связки QPC/QPF использовать RDTSC/CPU.freq, то это позволит вычислять время вплоть до нано/секунд, т.е. даже единичные инструкции (например узнать, насколько в цикле лучше DEC,чем LOOP).

    Сейчас-же, всё зависит от частоты таймера QPerfFrequency(), макс.значение которого всего 14 MHz (и то, если задействован HPET, а так 3). Поэтому логичней, взять за основу сразу частоту CPU 1..3 GHz, и его счётчик тактов TSC. Бонусом, не помешала-бы и сериализация на входе/выходе через инструкцию LFENCE.. т.е. учитывать спекулятивное выполнение кода процессором.

    А вообще, для таких случаев в составе Ntdll.dll имеется набор спец.функций NtCreateProfile(), которые в качестве метронома используют таймер локального контролёра LAPIC. Этот таймер работает на частоте шины FSB/DMI (100..200 MHz), а значит и он уступает связке RDTSC+CPUfreq. Однако эти функции точились индусами специально для профайлеров, так-что сбрасывать их со-счетов было-бы глупо.

    Эта тема была разделена из темы "КТЗ!"
      Цитата core-i7 @
      Поэтому логичней, взять за основу сразу частоту CPU 1..3 GHz, и его счётчик тактов TSC. Бонусом, не помешала-бы и сериализация на входе/выходе через инструкцию LFENCE.. т.е. учитывать спекулятивное выполнение кода процессором.

      А можно пример кода, как это запрограммить?
        ..что-то в этом роде:

        ExpandedWrap disabled
          ;====== Частота процессора
                  mov      ecx,2
          @@:     push     ecx
                  lfence
                  rdtsc
                  push     eax
                  invoke   Sleep,500
                  rdtsc
                  pop      ebx
                  sub      eax,ebx
                  mov      ebx,500000
                  cdq
                  div      ebx
                  pop      ecx
                  dec      ecx
                  jnz      @b
                  mov      [cpuFreq],eax     ; запомнить
                 cinvoke   printf,<10,' CPU freq..: %d MHz',0>,eax
           
          ;====== Частота таймера
                  invoke   QueryPerformanceFrequency,qpf
                  mov      eax,[qpf]
                  mov      ebx,1000000
                  cdq
                  div      ebx
                 cinvoke   printf,<10,' Timer freq: %d.%d MHz',0>,eax,edx
           
          ;====== Погрешность = 2 инструкции: сериализация LFENCE, и чтение TSC
                  lfence
                  rdtsc
                  push     eax
                  lfence
                  rdtsc
                  pop      ebx
                  sub      eax,ebx
                  mov      [fix],eax    ; запомнить    
           
          ;***************************
          ; Профайлер
          ;***************************
                  lfence
                  rdtsc
                  push     eax
           
          ;<----- Сюда вставляем профилируемые инструкции
           
                  lfence
                  rdtsc
                  pop      ebx        
                  sub      eax,ebx
                  sub      eax,[fix]
                  push     eax
           
                  fild     dword[esp]    ; такты
                  fidiv    [cpuFreq]     ; разделить на частоту процессора
                  fstp     [fpuBuff]     ; время в нано/секундах
           
                  pop      eax
                 cinvoke   printf,<10,'%u Takt = %.3f Micro/sec',0>,\
                                          eax, dword[fpuBuff], dword[fpuBuff+4]

        Здесь я вывел частоту таймера QPF, чтобы сравнить её с частотой процессора. Если QPF возвратит 3.5 MHz, значит система использует в качестве основного ACPI-таймер (3.579545 MHz), если больше 10 MHz - HPET (в идеале 14). В любом случае, QPF в десятки раз отстаёт от процессора.
          core-i7, привет, Тимур ;)
          Хм... я всегда думал, что QPC тоже использует использует rdtsc или rdtscp (по крайней мере, эта инструкция там есть) и сдвигает результат на 10 бит, но QPF выдал 10 млн, что наводит на размышления.
          Зачем же тогда там эти rdtsc? :huh:

          Т.к. lfence ставит барьер только на чтение и не гарантирует, что перед rdtsc влезет одна из последующих инструкций, я бы делал так всё же:
          ExpandedWrap disabled
            mfence
            rdtsc
            mfence

          Вот хорошая дока по этой теме:
          http://www.mkurnosov.net/uploads/Main/mkur...-rdtsc-2014.pdf

          А есть ещё инструкция rdpmc, которая как раз для профайлинга предназначена, но она сложнее в использовании и не всегда нужна. К тому же, она привилегированная (в винде, в линуксе, видимо, тоже), нужно драйвер писать, хотя у Агнера Фога уже есть: https://www.agner.org/optimize/#testp

          Добавлено
          Можно ещё приоритет потока выставлять по максимуму, кстати.
            Женя, салам!
            Цитата Jin X @
            но QPF выдал 10 млн, что наводит на размышления.
            Зачем же тогда там эти rdtsc?

            10 илн, это значит 10 MHz чтоли? (т.к. там в наносек блоках)
            У меня на буке тоже не подымается выше 10-ти, хотя это HPET и частота его 14 MHz.
            а rdtsc наверное там для какой-нибудь калибровки.
              [cut по просьбе автора]
              Лично мне вот интересно, предложения core-i7 смогут ли улучшить точность С++ шного std::chrono::high_resolution_clock? И чуйка мне подсказывает "несомненно" (я всегда надеюсь на лучшее, прогрессивное и спортивное)!
              [cut по просьбе автора]

              Цитата Jin X @
              Хм... я всегда думал, что QPC тоже использует использует rdtsc или rdtscp

              В качестве антиоффтопика ... когда я увидел код от core-i7, сразу побежал интересоваться незнакомыми мне командами :) Статья-за-статьей, статья-за-статьей ... и у меня есть ответ на твой вопрос (частично). А именно! QPC не точнее кода от core-i7 лишь потому, что там - API, и под капотом у которого стопицот индусов, которых погоняют 10 брахманов (даже если они используют rdtsc или rdtscp). А у core-i7 в примере - только инструкции камня. Ну это чисто мое ИМХО. Мнений конечно дохрена, но я пока вот такое выбрал за истину.
              Сообщение отредактировано: Jin X -
                Цитата core-i7 @
                10 илн, это значит 10 MHz чтоли? (т.к. там в наносек блоках)
                QFP выдаёт частоту, т.е. 10 млн - это 10 МГц. При чём тут наносекунды?
                  Скрытый текст
                  Эх ... удалил такое искреннее сообщение от себя :wall: За два года модерства - расслабился, потерял чуйку! :wall:

                  Добавлено
                  Цитата Jin X @
                  т.к. оно включает в себя больше всего, нежели замер времени.

                  Ну мож быть ... тебе виднее - но я заметил именно профилирование. Но спорить не хочу совсем - мне диалог дальнейший интересен. Мое мнение ... та-сяк ... слушать интереснее, особенно если собеседники плотно в теме.
                    Цитата JoeUser @
                    Эх ... удалил такое искреннее сообщение от себя За два года модерства - расслабился, потерял чуйку!
                    Не понимаю, о чём ты?
                    Если надо, можно найти сообщение (отредактированное, удалённое). Но с этим лучше в Л.С., чтобы не засорять обсуждение.

                    Цитата JoeUser @
                    Ну мож быть ... тебе виднее - но я заметил именно профилирование.
                    Не в заголовке суть, а в великих речах, глаголящих истину :P
                      Что любопытно, XP (виртуальная) выдаёт 3ГГц, а 7ка уже 10МГц

                      Добавлено
                      core-i7, поправь-таки код. Частота путает уменьшаемое и вычитаемое, все замеры путают знаковую и беззнаковую арифметику, а целочисленную арифметику замени на 64-битную, ибо странно наблюдать отрицательные Micro/sec
                        Цитата Qraizer @
                        Что любопытно, XP (виртуальная) выдаёт 3ГГц, а 7ка уже 10МГц
                        В 98 вообще 1.19 МГц :)
                        Там таймер 8254 используется :)
                          Подкину дровишек.
                          1) Для виртуализации TSC сохраняется в контексте процесса и после загружается обратно. Причем виндоус использует это всегда.
                          2)
                          Цитата
                          е RDTSC+CPUfreq. Однако эти функции точились индусами специально для профайлеров,
                          В давние времена да.
                          Суть в том что если делать x64 программы то там эта комбинация плавает в отрицательные области. А х32- программах индусы всё же сделали что'бы они не плавали.

                          3)
                          Цитата
                          таймер локального контролёра LAPIC. Этот таймер работает на частоте шины FSB/DMI (100..200 MHz),

                          Там не 100 Мгц, а частота RDTSC. Только младшие биты 4-5 бит они не контролируют.
                          4) Для профилирования есть PerformanceCounter нужен драйвер. У интела есть IntelPerformanceCounterMonitor-PCM-V2.10 нужно только GUI или API прекрутить.
                            Цитата Qraizer @
                            core-i7, поправь-таки код
                            Как вариант:
                            Скрытый текст
                            ExpandedWrap disabled
                              format  PE Console 4.0
                              entry   start
                               
                              include 'win32axp.inc'
                               
                              ;-- CODE SECTION -------------------------------------------------------------------------------------------------------
                               
                              macro   ReadTSC
                              {
                                      mfence
                                      rdtsc
                                      mfence
                              }
                               
                              .code
                               
                              start:
                                      invoke   SetThreadPriority, -2, THREAD_PRIORITY_TIME_CRITICAL
                               
                              ;====== Частота процессора
                                      ReadTSC
                                      push     eax
                                      push     edx
                                      invoke   Sleep,1000
                                      ReadTSC
                                      pop      ecx
                                      pop      ebx
                                      sub      eax,ebx
                                      sbb      edx,ecx
                                      push     edx
                                      push     eax
                                      fild     qword[esp]
                                      add      esp,8
                                      fidiv    [N1M]
                                      fistp    [cpuFreq]
                                     cinvoke   printf,<10,'  CPU freq: %d MHz',0>,[cpuFreq]
                               
                              ;====== Частота таймера
                                      invoke   QueryPerformanceFrequency,qpf
                                      fild     [qpf]
                                      fidiv    [N1M]
                                      fstp    [fpuBuff]
                                     cinvoke   printf,<10,'Timer freq: %f MHz',0>,dword[fpuBuff],dword[fpuBuff+4]
                               
                              ;====== Погрешность = 2 инструкции: сериализация LFENCE, и чтение TSC
                                      ReadTSC
                                      push     eax
                                      ReadTSC
                                      pop      ebx
                                      sub      eax,ebx
                                      mov      [fix],eax    ; запомнить    
                               
                              ;***************************
                              ; Профайлер
                              ;***************************
                                      ReadTSC
                                      push     eax
                               
                              ;<----- Сюда вставляем профилируемые инструкции
                               
                                      ReadTSC
                                      pop      ebx
                                      sub      eax,ebx
                                      sub      eax,[fix]
                                      push     eax
                               
                                      fild     dword [esp]   ; такты
                                      fidiv    [cpuFreq]     ; разделить на частоту процессора
                                      fstp     [fpuBuff]     ; время в микросекундах
                               
                                      pop      eax
                                     cinvoke   printf,<10,'%i ticks = %f microsec',0>,\
                                                              eax, dword[fpuBuff], dword[fpuBuff+4]
                                     cinvoke   getch
                                      invoke   ExitProcess, 0
                               
                              ;-- DATA SECTION -------------------------------------------------------------------------------------------------------
                               
                              .data
                               
                              N1M     dd       1000000
                              cpuFreq dd       ?
                              fix     dd       ?
                              qpf     dq       ?
                              fpuBuff dq       ?
                               
                              ;-- IMPORT SECTION -----------------------------------------------------------------------------------------------------
                               
                              section '.idata' import data readable
                               
                              library kernel32, 'kernel32.dll',\
                                      msvcrt, 'msvcrt.dll'
                               
                                      import_kernel32
                                      all_api
                               
                              import  msvcrt,\
                                      printf, 'printf',\
                                      getch, '_getch'
                              Скрытый текст
                              Цитата Jin X @
                              Не понимаю, о чём ты?

                              Это и хорошо! 30 гратусов тов. Цельсия в тени меня сводят с ума - и я уже кидаюсь на всех аки собака Баскервили)
                                Цитата Jin X @
                                Как вариант
                                У меня этот код в виртуальной Win98 показывает время пустого кода минус несколько тысяч тактов, в 10-ке в районе -20 (в среднем), на домашнем около нуля (+/-). Любопытненько, однако...
                                И ещё на домашнем частота 3300 измеряется, на вирт. 3700. Хотя всякие там CPU-Z показывают 3700. На самом деле у меня небольшой штатный разгон: 3300 -> 3700.
                                Это что, так Invariant TSC работает?

                                Цитата Pavia @
                                1) Для виртуализации TSC сохраняется в контексте процесса и после загружается обратно. Причем виндоус использует это всегда.
                                А если поподробнее?
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0489 ]   [ 16 queries used ]   [ Generated: 25.06.21, 09:34 GMT ]