Как определить, какой процессор используется во время выполнения? - PullRequest
4 голосов
/ 21 января 2009

Как я могу определить, какой процессор используется во время выполнения? Код C ++ должен различать архитектуры AMD / Intel? Использование gcc 4.2.

Ответы [ 6 ]

13 голосов
/ 21 января 2009

Инструкция cpuid, используемая с EAX=0, вернет 12-символьную строку поставщика в EBX, EDX, ECX в указанном порядке.

Для Intel эта строка "GenuineIntel". Для AMD это «AuthenticAMD». Другие компании, которые создали чипы x86, имеют свои собственные строки. На странице Википедии для cpuid есть много (все?) Перечисленных строк, а также пример списка ASM для получения подробностей. *

Вам действительно нужно только проверить, соответствует ли ECX последним четырем символам. Вы не можете использовать первые четыре, потому что некоторые процессоры Transmeta также начинаются с "Genuine"

  • Для Intel это 0x6c65746e
  • Для AMD это 0x444d4163

Если вы преобразуете каждый байт в них в символ, они будут выглядеть как задом наперед. Это всего лишь результат дизайна с прямым порядком байтов x86. Если вы скопируете регистр в память и рассматриваете его как строку, он будет работать просто отлично.

Пример кода:

bool IsIntel() // returns true on an Intel processor, false on anything else
{
  int id_str; // The first four characters of the vendor ID string

  __asm__ ("cpuid":\    // run the cpuid instruction with...
  "=c" (id_str) :       // id_str set to the value of EBX after cpuid runs...
  "a" (0) :             // and EAX set to 0 to run the proper cpuid function.
  "eax", "ebx", "edx"); // cpuid clobbers EAX, ECX, and EDX, in addition to EBX.

  if(id_str==0x6c65746e) // letn. little endian clobbering of GenuineI[ntel]
    return true;
  else
    return false;
}

РЕДАКТИРОВАТЬ: Еще одна вещь - это можно легко изменить на функцию IsAMD, IsVIA, IsTransmeta и т. Д., Просто изменив магическое число в if.

11 голосов
/ 21 января 2009

Если вы работаете в Linux (или в Windows, работающей под Cygwin), вы можете понять это, прочитав специальный файл /proc/cpuinfo и отыскивая строку, начинающуюся с vendor_id. Если строка GenuineIntel, вы работаете на чипе Intel. Если вы получаете AuthenticAMD, вы работаете на чипе AMD.

void get_vendor_id(char *vendor_id)  // must be at least 13 bytes
{
    FILE *cpuinfo = fopen("/proc/cpuinfo", "r");
    if(cpuinfo == NULL)
        ;  // handle error
    char line[256];
    while(fgets(line, 256, cpuinfo))
    {
        if(strncmp(line, "vendor_id", 9) == 0)
        {
            char *colon = strchr(line, ':');
            if(colon == NULL || colon[1] == 0)
                ;  // handle error
            strncpy(vendor_id, 12, colon + 2);
            fclose(cpuinfo);
            return;
        }
    }

    // if we got here, handle error
    fclose(cpuinfo);
}

Если вы знаете, что работаете на архитектуре x86, менее переносимым методом будет использование инструкции CPUID:

void get_vendor_id(char *vendor_id)  // must be at least 13 bytes
{
    // GCC inline assembler
    __asm__ __volatile__
        ("movl $0, %%eax\n\t"
         "cpuid\n\t"
         "movl %%ebx, %0\n\t"
         "movl %%edx, %1\n\t"
         "movl %%ecx, %2\n\t"
         : "=m"(vendor_id), "=m"(vendor_id + 4), "=m"(vendor_id + 8)  // outputs
         : // no inputs
         : "%eax", "%ebx", "%edx", "%ecx", "memory");  // clobbered registers
    vendor_id[12] = 0;
}

int main(void)
{
    char vendor_id[13];
    get_vendor_id(vendor_id);

    if(strcmp(vendor_id, "GenuineIntel") == 0)
        ; // it's Intel
    else if(strcmp(vendor_id, "AuthenticAMD") == 0)
        ; // it's AMD
    else
        ; // other
    return 0;
}
2 голосов
/ 21 января 2009

В Windows вы можете использовать функцию GetNativeSystemInfo

В Linux попробуйте sysinfo

1 голос
/ 22 января 2009

Вы, вероятно, не должны проверять вообще. Вместо этого проверьте, поддерживает ли процессор функции , которые вам нужны, например, SSE3. Различия между двумя чипами Intel могут быть больше, чем между чипами AMD и Intel.

0 голосов
/ 05 февраля 2013

Я разместил небольшой проект: http://sourceforge.net/projects/cpp-cpu-monitor/ который использует библиотеку libgtop и предоставляет данные через UDP. Вы можете изменить его в соответствии с вашими потребностями. GPL с открытым исходным кодом. Пожалуйста, спросите, если у вас есть какие-либо вопросы относительно этого.

0 голосов
/ 21 января 2009

Вы должны определить его в своей папке Makefile = uname -p 2>&1, затем использовать #ifdef i386 и #endif для различных архитектур.

...