Приоритет процессов и потоков в Windows 7

У меня есть простой "обучающий" проект, который должен показать механизм приоритетов в Windows.

Это мой код на C ++:

#include <stdio.h>
#include <windows.h>
DWORD WINAPI Thread1(LPVOID);
int stop;
int sleep = 10000;
struct params {
    int num;
    bool* runflg;
};
long long counters[7] = {0,0,0,0,0,0,0};
int priority[7] = {THREAD_PRIORITY_IDLE,  THREAD_PRIORITY_LOWEST,  THREAD_PRIORITY_BELOW_NORMAL,  THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL};
int main(int argc, char* argv[])
{
        int thrds;
        if (argc < 2) stop = 5;
        else stop = atoi(argv[1]);  

         bool runFlag = true;
         __int64 end_time;
         LARGE_INTEGER end_time2;

        HANDLE tm1 = CreateWaitableTimer(NULL, false, NULL);
        end_time = -1 * stop * 10000000;
        end_time2.LowPart = (DWORD) (end_time & 0xFFFFFFFF);
        end_time2.HighPart = (LONG) (end_time >> 32);
        SetWaitableTimer(tm1, &end_time2, 0,NULL, NULL, false); 

        //SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
        printf("process priority = %d \n", GetPriorityClass(GetCurrentProcess()));
        SetProcessPriorityBoost(GetCurrentProcess(), true);

        for (int i = 0; i < 7; i++) {
            DWORD targetThreadId;
            params* param = (params*)malloc(sizeof(params));
            param->num = i;
            param->runflg = &runFlag;
            HANDLE t1 = CreateThread(NULL, 0, Thread1, param, 0, &targetThreadId);
            SetThreadPriority(t1, priority[i]); //задание приоритета

            PBOOL ptr1 = (PBOOL)malloc(sizeof(BOOL));
            GetThreadPriorityBoost(t1, ptr1);
            SetThreadPriorityBoost(t1, true); //запрет динамического изм. приоритета

            CloseHandle(t1);
        }
        WaitForSingleObject(tm1,INFINITE);
        runFlag = false;
        CloseHandle(tm1);
        printf("\n");
        for (int i = 0; i < 7; i++) {
            printf("%d - %ld\n",i,  counters[i]);
        }
        return 0;
}
DWORD WINAPI Thread1(LPVOID prm) 
{       
    params arg = *((params*)prm);
    printf("thread # %d priority  = %d \n", arg.num, GetThreadPriority(GetCurrentThread()));

    while(1) {          
            counters[arg.num]++;
            Sleep(0);
            if(*(arg.runflg) == false)
                break;
    }   
    return 0;
}

В коде я создаю 7 потоков с разными приоритетами потоков. У каждого потока есть свой счетчик. Программа должна работать около 5 секунд, после чего консоль должна показать приоритеты потоков и их значения. Когда я делал это год назад на Win XP 32, все работало - поток с меньшим приоритетом имеет меньшее значение счетчика. Но теперь у меня такие странные результаты:

process priority = 32

thread # 0 priority  = -15
thread # 1 priority  = -2
thread # 2 priority  = -1
thread # 3 priority  = 0
thread # 4 priority  = 1
thread # 5 priority  = 2
thread # 6 priority  = 15

0 - 5401405
1 - 5726804
2 - 6676367
3 - 8320768
4 - 3223481
5 - 3085247
6 - 3177885

Почему не работают уровни приоритета и счетчики имеют такие странные значения (не отсортированы по возрастанию)?


person alena_fox_spb    schedule 27.10.2013    source источник
comment
Приоритет потока - это всего лишь подсказка, эта программа действительно может выводить что угодно (особенно если вы используете Sleep).   -  person user2802841    schedule 27.10.2013
comment
@ user2802841, я спросил о значениях счетчиков, а не о значениях подсказок для каждого приоритета. Значения счетчиков должны быть отсортированы по возрастанию, если приоритеты потоков такие же, как в этой программе.   -  person alena_fox_spb    schedule 27.10.2013
comment
@ alena-fox-spb это именно то, о чем я говорю, в вашей программе, написанной в настоящее время, нет гарантии, что ваши значения счетчика будут ниже для потоков с более низким приоритетом (или отсортированных по возрастанию). Тем более, что вы используете Sleep, в котором говорится: Обратите внимание, что готовый поток не гарантирует немедленного запуска. Следовательно, поток может не работать до тех пор, пока не истечет интервал ожидания. Оба из них могут привести к тому, что ваши значения счетчика будут любыми, поток с самым низким приоритетом может также иметь максимальное значение счетчика.   -  person user2802841    schedule 27.10.2013
comment
@ user2802841, хорошо, а как по-другому показать разницу между потоками с разным приоритетом? (без счетчиков) Не могли бы вы показать бывшую или хоть какое-нибудь представление об этом?)   -  person alena_fox_spb    schedule 27.10.2013
comment
Вы запускаете его на одноядерном процессоре?   -  person Zilog    schedule 29.10.2013
comment
@Zilog, нет, я запускаю на "стандартном" многоядерном процессоре Intel   -  person alena_fox_spb    schedule 29.10.2013
comment
@alena_fox_spb Вот почему. Когда планировщик удаляет готовые потоки из приоритетных очередей для их выполнения, он сначала ищет незанятый процессор. Попробуйте установить маску сходства потоков для имитации одного процессора и проверки результатов. например SetThreadAffinityMask (t1,4); для запуска потоков на 3-м ядре. У вас все еще могут быть странные результаты, поскольку потоки с низким приоритетом могут быть вытеснены высоким приоритетом (иногда из-за того, что низкий приоритет никогда не запускается)   -  person Zilog    schedule 29.10.2013
comment
@Zilog, спасибо! Теоретически это правда, почему не работает я имею в виду)   -  person alena_fox_spb    schedule 01.11.2013


Ответы (1)


Как сказал @Zilog в ответах на этот вопрос - причина каких-то странных действий кроется в MULTI-процессах CPU.

Если кто-то хочет увидеть, как работают потоки с разным приоритетом - они должны использовать определенные функции (например, monitor \ profilier работы системы), либо в программе использовать специальные функции, которые используют только один процессор.

person alena_fox_spb    schedule 01.11.2013