Попытка отключить состояния простоя процессора (состояния C) на ПК с Windows - PullRequest
7 голосов
/ 15 марта 2012

Мне нужно, чтобы процессор не переходил в состояние ожидания (не C0 C). По общему признанию я не знаю много о состояниях процессора C и P, так что терпите меня. Мы используем камеру от стороннего производителя, которая иногда доставляет поврежденные кадры. Поставщик определил, что, когда процессор переходит в состояние ожидания, он мешает передаче кадра по проводному соединению. Чтобы подтвердить это, я использовал следующий код на ПК с Windows 7 и, действительно, отключение состояния простоя решило проблему.

   //WIN7
const DWORD DISABLED = 1;
const DWORD ENABLED = 0;
GUID *scheme;
PowerGetActiveScheme(NULL, &scheme);
PowerWriteACValueIndex(NULL, scheme, &GUID_PROCESSOR_SETTINGS_SUBGROUP, &GUID_PROCESSOR_IDLE_DISABLE, DISABLED);
PowerSetActiveScheme(NULL, scheme);

Если я запускаю свое приложение и открываю permon для Windows и добавляю% C1 Time,% C2 Time и% C3 time, я вижу, что все они равны нулю, когда я отключаю эти состояния, когда я их включаю, я вижу довольно много времени провел в состоянии C3 (это на четырехъядерном ПК Dell Precision T3500).

Мне также нужно сделать это в XP, однако эти вызовы недоступны в XP. Поэтому я попытался сделать следующее, чтобы отключить состояния простоя

  unsigned int ActPwrSch; 
DWORD currPolicy,newPolicy, curr1Policy,curr2Policy, new1Policy, new2Policy;
MACHINE_PROCESSOR_POWER_POLICY Policy; 
if(GetActivePwrScheme(&ActPwrSch)) 
{ 
    if(ReadProcessorPwrScheme(ActPwrSch,&Policy)) 
    { 
        printf("Read Power Scheme:\n"); 
        //if(Policy.ProcessorPolicyAc.DisableCStates!=0) 
        currPolicy = Policy.ProcessorPolicyAc.Policy[0].AllowPromotion;
        curr1Policy = Policy.ProcessorPolicyAc.Policy[1].AllowPromotion;
        curr2Policy = Policy.ProcessorPolicyAc.Policy[2].AllowPromotion;
        Policy.ProcessorPolicyAc.Policy[0].AllowPromotion = 0;
        Policy.ProcessorPolicyAc.Policy[1].AllowPromotion = 0;
        Policy.ProcessorPolicyAc.Policy[2].AllowPromotion = 0;
        newPolicy = Policy.ProcessorPolicyAc.Policy[0].AllowPromotion;

        if(WriteProcessorPwrScheme(ActPwrSch,&Policy)) 
        { 
            printf("WriteProcessorPwrScheme succeed\n"); 
            if(SetActivePwrScheme(ActPwrSch,0,0)) 
            { 
                printf("SetActivePwrScheme succeed!!\n");
            } 
        }

    } 

Однако, когда я запускаю свое приложение, я все еще вижу, что процессор проводит время в состоянии C1 (глядя на те же счетчики в perfmon). И у меня все еще есть проблема с искаженным изображением. ПК XP - это одноядерный ПК Dell Optiplex.

Кто-нибудь знает, как я могу предотвратить вход в любое из состояний C1-C3 на XP? Как я уже сказал, похоже, что я сделал это на Windows 7.

Ответы [ 3 ]

2 голосов
/ 16 марта 2012

Мне кажется, это работает:

void PowerState(bool bEnable)
{
    // CPU idle state
    unsigned int ActPwrSch;
    MACHINE_PROCESSOR_POWER_POLICY Policy;
    if (GetActivePwrScheme(&ActPwrSch))
    {
        if (ReadProcessorPwrScheme(ActPwrSch, &Policy))
        {
            Policy.ProcessorPolicyAc.Policy[0].AllowPromotion = bEnable ? 1: 0; // C1
            Policy.ProcessorPolicyAc.Policy[1].AllowPromotion = bEnable ? 1: 0; // C2
            Policy.ProcessorPolicyAc.Policy[2].AllowPromotion = bEnable ? 1: 0; // C3
            if (WriteProcessorPwrScheme(ActPwrSch, &Policy))
                SetActivePwrScheme(ActPwrSch, 0, 0);
        }
    }
    OSVERSIONINFO osvi;
    memset(&osvi, 0, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    GetVersionEx(&osvi);
    // For Vista and above
    if (osvi.dwMajorVersion >= 6)
    {
        static const GUID processor_idle_disable_guid = {0x5d76a2ca, 0xe8c0, 0x402f, 0xa1, 0x33, 0x21, 0x58, 0x49, 0x2d, 0x58, 0xad};
        GUID *scheme;
        PowerGetActiveScheme(NULL, &scheme);
        PowerWriteACValueIndex(NULL, scheme, &GUID_PROCESSOR_SETTINGS_SUBGROUP, &processor_idle_disable_guid, bEnable ? 0 :  1);
        PowerSetActiveScheme(NULL, scheme);
    }
}
2 голосов
/ 11 сентября 2012

Конечно, TSR, выполняющий математические вычисления каждые 5 минут, предотвратит состояние простоя?В качестве альтернативы вы можете приобрести дешевый аппаратный или программный эмулятор мыши, который посылает сигнал перемещения мыши через определенные интервалы

2 голосов
/ 15 марта 2012

Вы можете использовать функцию SetThreadExecutionState, которая позволяет приложению сообщать системе, что оно используется.

РЕДАКТИРОВАТЬ: После небольшого исследования и тестирования я пришел к решению или я думаю, что я сделал. Вы на правильном пути для Windows XP. Если вы прочтете документацию по структуре PROCESSOR_POWER_POLICY, вы заметите, что можете отключить все состояния C, которые вас оскорбляют:

Policy[0].AllowPromotion = 0; // Disable's C1 (usually C1 won't cause problems, so you should leave it alone.)
Policy[1].AllowPromotion = 0; // Disable's C2
Policy[2].AllowPromotion = 0; // Disable's C3


В Vista и Windows7 вы не можете использовать этот интерфейс, вместо этого вы должны сделать это:

GUID *scheme;
PowerGetActiveScheme(NULL, &scheme); 
PowerWriteACValueIndex(NULL, scheme, &GUID_PROCESSOR_SETTINGS_SUBGROUP,  &GUID_PROCESSOR_IDLE_DISABLE, 1); 
PowerSetActiveScheme(NULL, scheme);


Я не нашел способа отключить отдельные состояния C в Vista и Windows 7. Если вам нужны примеры кодов, пожалуйста, напишите мне, я могу помочь вам.

...