Re[11]: Исследование: системный таймер Windows
От: ononim  
Дата: 24.02.11 19:17
Оценка: 8 (1)
JR>Чертовщина какая-то Ваш код показал у меня примерно 420000 и 270000. После этого попробовал вновь свой код, и он показал стабильно 1.94-1.97 вне зависимости от timeBeginPeriod, хотя буквально несколько дней назад этот-же тест показывал чёткую связь: 15 до timeBeginPeriod(1), и 1.95 — после. Перзагрузка ничего не меняет.
JR>Пока не знаю, в чём дело Попробую завтра разобраться.
Может в бэкграунде чота крутилось.. например тот же intellisense студии решил обновиться
Кстати, запустил дома на q8400 w2k3 и получил очень любопытный результат — если юзать SignalForSingleObjectAndWait —
на 1м ядре (affinity 1) — 820000 sw/sec (приятно блин
на 2х ядрах (affinity 3) — 290000
на 4х ядрах (affinity 15) — 40000
Если не юзать SignalForSingleObjectAndWait то цифры получаются: 610k, 310k, 40k соответственно.
Поражает и заставляет задуматься провал скорости переключения при работе на всех имеющихся ядрах. Интересно было бы увидеть цифры обладателей i7, вот слегка переделанный код (принимает affinity в командной строке):
// ctxswitchtest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "windows.h"
#include "process.h"
#include "stdio.h"
#include "stdlib.h"


#define SIGNAL_AND_WAIT

struct trdpar
{
    HANDLE wait;
    HANDLE set;
    volatile LONG *counter;
};


void __cdecl switch_perf_trd(void *p)
{
    trdpar *par = (trdpar *)p;
#ifndef SIGNAL_AND_WAIT
    for (;;)
    {
        ::WaitForSingleObject(par->wait, INFINITE);
        ::SetEvent(par->set);
        if (par->counter)InterlockedIncrement(par->counter);
    }
#else
    ::WaitForSingleObject(par->wait, INFINITE);
    for (;;)
    {
        
        ::SignalObjectAndWait(par->set, par->wait, INFINITE, FALSE);
        if (par->counter)InterlockedIncrement(par->counter);
    }
#endif
    
}


void switch_perf()
{
    volatile LONG counter = 0;
    trdpar foo1 = {::CreateEvent(0, 0, 1, 0), ::CreateEvent(0, 0, 0, 0), 0};
    trdpar foo2 = {foo1.set, foo1.wait, &counter};
    _beginthread(switch_perf_trd, 0, &foo1);
    _beginthread(switch_perf_trd, 0, &foo2);
    for (InterlockedExchange(&counter, 0);;)
    {
        Sleep(1000);
        printf("%u sw/sec              \r", InterlockedExchange(&counter, 0));
    }
}

int main(int argc, char **argv)
{
    
    ::SetPriorityClass(::GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    
    if (argc>1)
        ::SetProcessAffinityMask(::GetCurrentProcess(), atoi(argv[1]));
    switch_perf();
    return 0;
}
Как много веселых ребят, и все делают велосипед...
Re[12]: Исследование: системный таймер Windows
От: Jolly Roger  
Дата: 25.02.11 09:13
Оценка:
Здравствуйте, ononim, Вы писали:

Разобрался.

Воспроизводиться у меня перестало из-за службы SqlExpress — до этого мерял без неё, а вчера она была запущена. Судя по всему, эта служба вызывает timeBeginPeriod(4), и мои вызовы уже не действовали. Остановил службу, стало воспроизводиться.

Ну а само такое поведение наблюдалось из-за совершенно идиотской ошибки в тесте Уже и асм перелопатил, а причина была под носом. Я ждал вызовом WaitForSingleObject(h, 1), а хендл (h) был вовсе не того эвента, который взводился в доп. потоке, вот и замерял не скорость переключения, а срабатывание по таймауту, осёл

После устранения бага привязка к кванту таймера пропала, так что всё, что я выше по этому поводу писал — чушь, наплевать и забыть.
"Нормальные герои всегда идут в обход!"
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.