【问题标题】:How do I retrieve the number of processors on C / Linux?如何检索 C/Linux 上的处理器数量?
【发布时间】:2011-02-11 05:52:23
【问题描述】:

我正在编写一个小型 C 应用程序,它使用一些线程来处理数据。我希望能够知道某台机器上的处理器数量,而无需将system() & 结合到一个小脚本中。

我能想到的唯一方法是解析 /proc/cpuinfo。还有其他有用的建议吗?

【问题讨论】:

  • 几乎是这个问题的一个严格子集:stackoverflow.com/questions/150355/…(最佳答案有一个 linux 单线)。这个问题实际上说的是 C++,但答案也是 C。
  • 确实,感谢史蒂夫的反馈,但是如果我可以这样称呼的话,什么被认为是“POSIX 世界”中最便携的方法?
  • 不确定。 Linux 支持 _SC_NPROCESSORS_ONLN,但 POSIX 没有强制要求。假设其他答案很好,它在 BSD 上使用完全不同的非 POSIX 机制这一事实表明没有简单的 POSIX 可移植答案。另外,我在网上发现了一个警告,_SC_NPROCESSORS_ONLN 为“我不知道”返回 1 而不是 -1,如果它仍然是真的,那就不好了。
  • glibc 实现sysconf( _SC_NPROCESSORS_ONLN ) 的方式是首先尝试 /proc/stat 。如果它在那里,它会计算匹配 /^cpu[0-9]/ 的行。否则,它会查看 /proc/cpuinfo ,其格式因架构而异。

标签: c posix parallel-processing


【解决方案1】:

这是一个如何获取物理内核和虚拟线程的最小示例:

#include <stdio.h>

...

unsigned int thread_count, core_count;
FILE *cpu_info = fopen("/proc/cpuinfo", "r");
while (!fscanf(cpu_info, "siblings\t: %u", &thread_count))
  fscanf(cpu_info, "%*[^s]");
while (!fscanf(cpu_info, "cpu cores\t: %u", &core_count))                   
  fscanf(cpu_info, "%*[^c]");                                                                                          
fclose(cpu_info);

它比 _SC_NPROCESSORS_ONLN 更便携,因为它不需要 glibc 扩展。

请注意,在此示例中您无需检查 EOF,因为如果达到 fscanf 将返回 EOF。这将导致循环安全停止。

此外,此示例不包含检查 fopen 是否失败的错误检查。这应该按照您认为合适的方式进行。

fscanf 技术源自这里:https://stackoverflow.com/a/43483850

【讨论】:

    【解决方案2】:

    为什么不使用 sys/sysinfo.h?

    #include <sys/sysinfo.h>
    #include <stdio.h>
    void main () {
       printf ("You have %d processors.\n", get_nprocs ());
    }
    

    可以在手册页上找到更多信息

    $ man 3 get_nprocs
    

    【讨论】:

    • “这些函数是 GNU 扩展”根据该手册页。问题一般是关于 C/Linux(并不总是使用 glibc),最好是 POSIX。
    【解决方案3】:

    正如其他人在 cmets 中提到的,this 答案很有用:

    numCPU = sysconf( _SC_NPROCESSORS_ONLN );
    

    为可能跳过 cmets 的人们提供解决方案...

    【讨论】:

    • 不错的解决方案,但似乎是 POSIX 的 Linux 扩展:pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html
    • 该解决方案很烦人,因为它是恒定的硬件配置,但仍然使用优化标志进行编译并不会减少汇编代码中的 sysconf 调用。 (红帽上的 gcc 4.4.6,英特尔 CPU)
    • @Aviv CPU 的数量不是恒定的硬件。它们是可热插拔的。
    • 你是对的,后来我才意识到我错了。但是忘记了这个评论。谢谢
    【解决方案4】:
    #include <stdio.h>
    
    void getPSN(char *PSN)
    {int varEAX, varEBX, varECX, varEDX;
       char str[9];
       //%eax=1 gives most significant 32 bits in eax 
       __asm__ __volatile__ ("cpuid": "=a" (varEAX), "=b" (varEBX), "=c" (varECX), "=d" (varEDX) : "a" (1));
       sprintf(str, "%08X", varEAX); //i.e. XXXX-XXXX-xxxx-xxxx-xxxx-xxxx
       sprintf(PSN, "%C%C%C%C-%C%C%C%C", str[0], str[1], str[2], str[3], str[4], str[5], str[6], str[7]);
       //%eax=3 gives least significant 64 bits in edx and ecx [if PN is enabled]
       __asm__ __volatile__ ("cpuid": "=a" (varEAX), "=b" (varEBX), "=c" (varECX), "=d" (varEDX) : "a" (3));
       sprintf(str, "%08X", varEDX); //i.e. xxxx-xxxx-XXXX-XXXX-xxxx-xxxx
       sprintf(PSN, "%s-%C%C%C%C-%C%C%C%C", PSN, str[0], str[1], str[2], str[3], str[4], str[5], str[6], str[7]);
       sprintf(str, "%08X", varECX); //i.e. xxxx-xxxx-xxxx-xxxx-XXXX-XXXX
       sprintf(PSN, "%s-%C%C%C%C-%C%C%C%C", PSN, str[0], str[1], str[2], str[3], str[4], str[5], str[6], str[7]);
    }
    
    int main()
    {
        char PSN[30]; //24 Hex digits, 5 '-' separators, and a '\0'
        getPSN(PSN);
        printf("%s\n", PSN); //compare with: lshw | grep serial:
        return 0;
    }
    

    【讨论】:

      【解决方案5】:

      以下是我用来计算核心数的代码.....它可能会对你有所帮助

      //Finding the number of cores(logical processor) using cpuid instruction.....
          __asm
          {
              mov eax,01h //01h is for getting number of cores present in the processor
              cpuid
              mov t,ebx
          }
      

      (t>>16)&0xff 包含核心数............

      我想这可以帮助你 http://lists.gnu.org/archive/html/autoconf/2002-08/msg00126.html

      【讨论】:

      • 这不是可移植的,也不能用 gcc 编译。
      • 这个返回的信息可能是错误的。如果是 NUMA 机器(高端台式机或多颗 CPU 包的服务器),只会得到一个 CPU 包的核数。
      【解决方案6】:
      machine:/sys/devices/system/cpu$ ls
      cpu0  cpu3  cpu6     kernel_max  perf_counters  sched_mc_power_savings
      cpu1  cpu4  cpu7     offline     possible
      cpu2  cpu5  cpuidle  online      present
      

      如果您有一台带有 sysfs 的机器,请查看 /sys/devices/system/cpu。

      确保您要求的是您想要的 - CPU、内核、超线程等。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-04
        • 1970-01-01
        • 2017-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-23
        相关资源
        最近更新 更多