4

如何检测运行时正在使用哪个 CPU?c++ 代码需要区分 AMD / Intel 架构?使用 gcc 4.2。

4

6 回答 6

13

使用 with的cpuid指令EAX=0将按顺序返回 12 个字符的供应商字符串EBX, EDX, ECX, 。

对于 Intel,此字符串为“G​​enuineIntel”。对于 AMD,它是“AuthenticAMD”。其他创建 x86 芯片的公司有自己的字符串。维基百科页面列出了cpuid许多(全部?)字符串,以及用于检索详细信息的示例 ASM 列表。

你真的只需要检查 ECX 是否匹配最后四个字符。前四个不能用,因为有些全美达 CPU 也是以“正版”开头的

  • 对于英特尔来说,这是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.IsTransmetaif

于 2009-01-21T18:38:16.257 回答
11

如果您使用的是 Linux(或在 Cygwin 下运行的 Windows),您可以通过阅读特殊文件/proc/cpuinfo并查找以vendor_id. 如果字符串是GenuineIntel,则您正在英特尔芯片上运行。如果你得到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;
}
于 2009-01-21T18:14:25.027 回答
2

在 Windows 上,您可以使用GetNativeSystemInfo函数

在 Linux 上,尝试sysinfo

于 2009-01-21T18:20:00.490 回答
1

您可能根本不应该检查。相反,请检查 CPU 是否支持您需要的功能,例如 SSE3。两个英特尔芯片之间的差异可能大于 AMD 和英特尔芯片之间的差异。

于 2009-01-22T13:35:07.973 回答
0

您必须在 Makefile arch= 中定义它uname -p 2>&1,然后将 #ifdef i386 some #endif 用于不同的架构。

于 2009-01-21T18:39:41.557 回答
0

我发布了一个小项目: http: //sourceforge.net/projects/cpp-cpu-monitor/ ,它使用libgtop库并通过 UDP 公开数据。您可以修改它以满足您的需要。GPL 开源。请询问您是否对此有任何疑问。

于 2013-02-05T10:55:41.713 回答