|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Мар 27, 2003 17:12:41 Привет! как рассчитать частоту (количество тиков в секунду) для счетчика, значение которого возвращается инструкцией RDTSC. Спасибо! |
|
|
Дата: Мар 27, 2003 17:15:35 RDTSC возвращает не частоту, а кол-во тактов. |
|
|
Дата: Мар 27, 2003 17:28:28 ??? |
|
|
Дата: Мар 28, 2003 01:13:22 Ну эта комманда возвращает текущее количество тактов, которое процессор сделал с момента его включения. |
|
|
Дата: Мар 28, 2003 04:09:56 · Поправил: P2M andsin Если речь о частоте процессора, то общая идея такая: 1. Выполнить RDTSC, сохранить EDX:EAX - old. 2. Сделать паузу - Sleep(500). 3. Выполнить RDTSC, сохранить EDX:EAX - cur. 4. Определить прошедшее число тактов cnt = cur - old. 5. Опередлить частоту (Гц) freq = cnt / 500. Для более точного определения необходимо выполнить эти шаги несколько раз. Если делать их под win32, то приложение должно выполняться с высоким классом приоритета SetPriorityClass + SetThreadPriority. Еще посмотрите Using the RDTSC Instruction for Performance Monitoring (73'944 байта) |
|
|
Дата: Мар 28, 2003 10:11:43 Спасибо! вопрос стоял именно в определении частоты процессора. сегодня пришла идея отмерить временной интервал, выпулив в СОМ порт пачку байтов (в моем драйвере обрабатываются прерывания порта и передача длится ровно 1с). получил довольно точное значение частоты(возможности использовать CPUID нет-старая машина). |
|
|
Дата: Мар 28, 2003 10:36:38 Когда мне нужно было определить частоту процессора (в мегагерцах), я писал следующий код: ;------ биты регистра edx после cpuid (eax=1 - второй вызов) bFPU equ 00000001h ;0 bVME equ 00000002h ;1 bDE equ 00000 004h ;2 bPSE equ 00000008h ;3 bTSC equ 00000010h ;4 bMSR equ 000 00020h ;5 bPAE equ 00000040h ;6 bMCE equ 00000080h ;7 bCX8 equ 0 0000100h ;8 bAPIC equ 00000200h ;9 bReserv equ 00000400h ;10 bSEP equ 00000800h ;11 bMTRR equ 00001000h ;12 bPGE equ 00002000h ;13 bMCA equ 00004000h ;14 bCMOV equ 00008000h ;15 bPAT equ 0001000 0h ;16 bPSE36 equ 00020000h ;17 bID equ 00040000h ;18 bMMX equ 0 0800000h ;23 bFXSR equ 01000000h ;24 bSIMD equ 02000000h ;25 .d ata align 4 TSC_Start LARGE_INTEGER <> ;счетчик тактов начала теста TSC_End LARGE_INTEGER <> ;счетчик тактов окончания теста LI_Start LARGE_INTEGER <> ;время начала теста LI_End LARGE_INTEGER <> ;время окончания теста TickFreq LARGE_INTEGER <> ;частота обновления счетчика temp DWORD ;временная переменная .code ;------ определяем возможность использования команды CPUID pushfd pop eax xor eax,00200000h ;изменить флаг ID push eax popfd pushfd pop ebx .if eax==ebx ;команда CPUID поддерживается xor eax,eax cpuid ;первый вызов cpuid ;------ если при первом вызове cpuid в eax не ноль, ; эту команду можно вызывать еще раз .if eax mov eax,1 cpuid ;------ определить наличие бита TSC, необходимого ; для определения частоты процессора test edx,bTSC .if !ZERO? ;------ определить частоту обновления счетчика invoke QueryPerformanceFrequency,offset TickFreq invoke Sleep,1 .repeat ;------ определяем время начала теста invoke QueryPerformanceCounter,offset LI_Start ;------ считываем счетчик тактов rdtsc mov TSC_Start.HighPart,edx mov TSC_Start.LowPart,eax invoke Sleep,1 ;------ определяем время окончания теста invoke QueryPerformanceCounter,offset LI_End ;------ считываем счетчик тактов rdtsc mov TSC_End.HighPart,edx mov TSC_End.LowPart,eax mov eax,LI_End.LowPart ;------ если перешагнули через границу между старшим ; и младшим словом, - повторяем операцию. .until eax>LI_Start.LowPart sub eax,LI_Start.LowPart ;------ теперь в eax находится чистое время между измерениями push eax mov temp,0FFFFFFFFh fild TSC_End.HighPart fld1 fiadd temp fmulp st(1),st fiadd TSC_End.LowPart fild TSC_Start.HighPart fld1 fiadd temp fmulp st(1),st fiadd TSC_Start.LowPart fsubp st(1),st ;T2-T1 fimul TickFreq.LowPart ;------ т.к. меня интересует частота в мегагерцах, ; ввожу коэффициент 1/1000000 mov temp,1000000 fidiv temp pop temp fidiv temp fistp temp ;в переменной temp - результат .endif ;конец (!ZERO?) .endif ;конец (eax) - первый вызов cpuid .endif ;конец (eax==ebx) |
|
|
Дата: Мар 28, 2003 11:14:44 наверное, я что-то не понял... если есть возможность вызвать QueryPerformanceXXX, которые возвращают именно частоту в МГц и кол-во системных тиков, то зачем RDTSC. |
|
|
Дата: Мар 28, 2003 11:22:32 наверное, я что-то не понял... если есть возможность вызвать QueryPerformanceXXX, которые возвращают именно частоту в МГц и кол-во системных тиков, то зачем RDTSC. |
|
|
Дата: Мар 28, 2003 14:06:03 Вот, выдрал из какого-то исходника. Код достаточно ламерной, но работает, по крайней мере на незагруженной машине. Что там будет если камень посильнее нагрузить не знаю. .586p .model flat, stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\kernel32.inc include \masm32\include\user32.inc includelib \masm32\lib\kernel32.lib includelib \masm32\lib\user32.lib .data szCaption db "CPU speed (MHz)", 0 szFormat db "%u", 0 .data? timerHi dd ? timerLo dd ? szBuffer db 42 dup (?) .const ; delay delay dd 500 constant dd 1000 .code determineSpeed proc LOCAL prClass:DWORD, priority:DWORD pushad ; save initial priority settings invoke GetCurrentProcess invoke GetPriorityClass, eax mov [prClass], eax invoke GetCurrentThread invoke GetThreadPriority, eax mov [priority], eax ; set new priority settings invoke GetCurrentProcess invoke SetPriorityClass, eax, REALTIME_PRIORITY_CLASS invoke GetCurrentThread invoke SetThreadPriority, eax, THREAD_PRIORITY_TIME_CRITICAL ; get speed ; revoke rest of our timeslice invoke Sleep, 0 rdtsc mov [timerLo], eax mov [timerHi], edx ; -------- invoke Sleep, delay ; -------- ; ; mostly for fun: serialize by using RDTSC xor eax, eax rdtsc rdtsc sub eax, [timerLo] sbb edx, [timerHi] mov [timerLo], eax mov [timerHi], edx ; restore initial priority settings invoke GetCurrentThread invoke SetThreadPriority, eax, [priority] invoke GetCurrentProcess invoke SetPriorityClass, eax, [prClass] ; final calculations finit fild dword ptr [constant] fild dword ptr [delay] fmulp st(1), st fild dword ptr [timerLo] fxch fdivp st(1), st frndint fistp dword ptr [esp + 28] ; EAX offset in PUSHAD block wait popad ret determineSpeed endp start: invoke Sleep, 100 call determineSpeed invoke wsprintf, addr szBuffer, addr szFormat, eax invoke MessageBox, NULL, addr szBuffer, addr szCaption, MB_OK invoke ExitProcess, 0 end start |
|
|
Дата: Мар 28, 2003 15:36:19 Ребята, большое спасибо! наверное, я не сделал достаточный акцент на то, что это драйвер, хотя в (andsin Дата: Мар 28, 2003 10:11:43) я об этом писал. извините. из драйвера я не имею доступа к таймеру, который вызывается по Sleep, мало того, мне такой таймер необходим аки воздух. вчера я задал вам вопрос, основательно изломав голову над тем, как приостановить драйвер на какое-то время. сегодня утром понял - можно подождать пока по порту отправляется пакет, чем порт не таймер. спасибо за помощь и содействие! |
|
|
Дата: Мар 28, 2003 17:46:00 В ядре тоже можно таймер создать, принципиальной разницы никакой, только функции другие, а если поспать, то KeDelayExecutionThread. |
|
|
Дата: Мар 28, 2003 18:54:45 Спасибо! на счет KeDelayExecutionThread не знал. искал в DDK, но найти не смог |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.073 |