如何获取安卓设备的核心数

43

我想要确定(或计算)android设备嵌入式处理器中的核心数。我尝试使用 /proc/cpuinfo,但它没有返回设备的核心数!我在互联网上找不到代码。这里有人知道如何确定吗?谢谢。

更新:

关于这个问题的答案“如何从代码中检测安卓设备的双核CPU?”在一些设备上无法正常运行。我在双核和四核处理器上测试了它们,分别返回2和4,没问题!但是,在Octa Core处理器如三星Note 3上,它只返回4。(也许在note 3中有2组四核处理器单独运行)我正在寻求解决这个问题。

更新

应用程序 CPU-Z 在我的设备三星Note 3中返回了正确的核心数enter image description here。这里似乎存在一种可能的解决方案...


2
请看我的编辑,我已经详细解释了问题!!! - Vivek Warde
@VivekWarde,你应该在问题中提及完整的问题。 - Anirudh Sharma
6
我认为三星note 3应该返回4。你不能同时使用所有8个核心,它本来就不是真正的八核心。只是三星销售更多垃圾的方式。简单来说,它有4个运行1.9GHz的核心和4个运行1.3GHz的核心。根据note当前正在处理的任务和你使用的功能,最多只有4个核心处于活动状态。返回最大活动核心数,因为大多数人将该数字用作线程池大小的数量。 - Bojan Kseneman
我的意思是在Note 3上可以并行运行的最大线程数为4,因此它返回了一个正确的数字。 - Bojan Kseneman
1
CPU-Z 只是依赖于外部数据库,它说有 8 核 (营销谎言)。它不会询问系统本身 (最多只有 4 个核心),一次只能查看到那些核心。 - Irwin Nawrocki
显示剩余5条评论
8个回答

56

你可以将上面的答案与这个答案结合使用。这样,它在运行API 17+的设备上将更快,因为这种方法比过滤文件要快得多。

private int getNumberOfCores() {
    if(Build.VERSION.SDK_INT >= 17) {
        return Runtime.getRuntime().availableProcessors()
    }
    else {
       // Use saurabh64's answer
       return getNumCoresOldPhones();
    }
}

/**
 * Gets the number of cores available in this device, across all processors.
 * Requires: Ability to peruse the filesystem at "/sys/devices/system/cpu"
 * @return The number of cores, or 1 if failed to get result
 */
private int getNumCoresOldPhones() {
    //Private Class to display only CPU devices in the directory listing
    class CpuFilter implements FileFilter {
        @Override
        public boolean accept(File pathname) {
            //Check if filename is "cpu", followed by a single digit number
            if(Pattern.matches("cpu[0-9]+", pathname.getName())) {
                return true;
            }
            return false;
        }      
    }

    try {
        //Get directory containing CPU info
        File dir = new File("/sys/devices/system/cpu/");
        //Filter to only list the devices we care about
        File[] files = dir.listFiles(new CpuFilter());
        //Return the number of cores (virtual CPU devices)
        return files.length;
    } catch(Exception e) {
        //Default to return 1 core
        return 1;
    }
}

public int availableProcessors ()

在API level 1中添加,返回虚拟机可用的处理器内核数量,至少为1。传统上,这返回当前在线的数量,但许多移动设备可以将未使用的内核脱机以节省电力,因此Android 4.2(Jelly Bean)之后的版本将返回最大可用内核数,如果没有电源或热量限制。

还有一个关于位于/sys/devices/system/cpu/present文件内核数量的信息。它以以下格式报告可用CPU的数量:

  • 0 -> 单个CPU/内核
  • 0-1 -> 两个CPU/内核
  • 0-3 -> 四个CPU/内核
  • 0-7 -> 八个CPU/内核

等等。

另外,请检查Note 3上/sys/devices/system/cpu/possible文件的内容。

这两个文件都设置了r--r--r--或者444的文件权限,所以您应该能够在代码中读取它们而无需root设备。

编辑:发布代码以帮助您。

 private void printNumberOfCores() {
        printFile("/sys/devices/system/cpu/present");
        printFile("/sys/devices/system/cpu/possible");

    }

    private void printFile(String path) {
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(path);
            if (inputStream != null) {

                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                String line;

                do {
                    line = bufferedReader.readLine();
                    Log.d(path, line);
                } while (line != null);
            }
        } catch (Exception e) {

        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
        }
    }

结果如下

D//sys/devices/system/cpu/present﹕ 0-3
D//sys/devices/system/cpu/possible﹕ 0-3

这个测试是在运行BlissPop ROM且搭载Android v5.1.1的OnePlus One上进行的,输出结果符合预期。请在您的三星手机上尝试。


为什么你要更改你的评论呢?我非常了解这种类型手机的实际情况,就像你在问题下面的评论中所说的一样。 - Vivek Warde
必须有一种方法可以找到总核心数,而不管它们的行为如何。顺便说一句,我尝试在多任务和玩重型游戏时运行应用程序,但仍然返回4个核心。 - Vivek Warde
@VivekWarde 我对我的帖子进行了编辑,请你检查一下这两个文件里面是什么? - Bojan Kseneman
好的,现在使用 ...cpu/present...cpu/possibleFile[] files 中生成 Null。很抱歉,但是你最后的部分也没有起作用。 - Vivek Warde
这是一个单文件,你需要读取它的内容。我稍后会尝试自己去做。 - Bojan Kseneman
显示剩余6条评论

11
首先,似乎这是不可能的,以下是一些相关信息:
我们将以三星Exynos 5 Octa CPU为例进行讨论,但通常任何ARM处理器都将起到同样的作用。
三星Exynos 5 Octa CPU有8个CPU核心。但实际上它有两个进程,每个进程有4个内核。这被称为big.LITTLE。您有一个快速处理器和一个高效节能处理器。
在Exynos 5 CPU中,它内置了两个不同的CPU,即Cortex a15和Cortex a7...
在big.LITTLE中,两个CPU不能同时运行,只能有一个CPU在任何给定时间处于活动状态...
但也有一种叫做“big.LITTLE mp”的东西,在其中两个CPU可以同时活动,但问题在于(再次!)软件只能同时激活四个内核。下面是一张图片,更好地解释了这个问题:

big.LITTLE mp

现在,您可以看到,在此处使用了来自更强大处理器的单个CPU核心,然后来自更节能的a7 CPU群集中有四个核心处于活动状态。

您可以在此处阅读有关big.LITTLE架构的更多信息: http://www.arm.com/products/processors/technologies/biglittleprocessing.php

您可以在此处阅读有关big.LITTLE mp架构的更多信息: http://www.arm.com/products/processors/technologies/biglittleprocessing.php

现在,您想要找出的是,是否可能知道CPU架构是Big.LITTLE还是BIG.LITTLE mp。然后查看是否可以直接从每个单独的CPU中找到CPU计数,但我找不到任何相关代码。 ARMs网站上有很多文档,但我不太确定是否可能获取此信息。无论如何,只能使用4个CPU核心,因此您拥有的代码在技术上是正确的,因为这是可用核心的数量。

我希望这有所帮助,如果您有任何问题或需要澄清任何事情,请让我知道。有很多信息可供参考。


1
谢谢您让问题更明确了。不过,应用程序 CPU-Z 正在执行我想要的操作。请看我的截图,我编辑了问题。 - Vivek Warde
4
CPU-Z 可能正在查看模型信息并从在线来源获取其余数据。我今晚会进一步调查。遗憾的是,我没有可测试的手机,所以这将会有些困难。 - apmartin1991
1
正确,这总是一个选项。给CPU-Z支持发送电子邮件工作,他们可能能够提供帮助! - apmartin1991
@BinoyBabu 不是,你在做类似的项目吗? - Vivek Warde
@VivekWarde 我制作了一个类似的应用程序。事实上,我分析了cpuZ应用程序,并发现他们使用专有的本地库libcpuid.so来收集这些信息。 - Binoy Babu
显示剩余9条评论

7

试试这个:

Runtime.getRuntime().availableProcessors();

这会返回此特定虚拟机可用的CPU数量,就我所知。虽然这可能不是您想要的,但对于某些目的而言非常方便。您可以轻松测试:关闭所有应用程序,运行上述代码。打开10个非常耗费资源的应用程序,然后再次运行测试。当然,这仅适用于多CPU设备,我想。


4
您可以尝试使用以下方法获取核心数量。
 private int getNumOfCores()
      {
        try
        {
          int i = new File("/sys/devices/system/cpu/").listFiles(new FileFilter()
          {
            public boolean accept(File params)
            {
              return Pattern.matches("cpu[0-9]", params.getName());
            }
          }).length;
          return i;
        }
        catch (Exception e)
        {
              e.printstacktrace();
        }
        return 1;
      }

1

使用此代码可以获取CPU核心数。请仔细阅读此链接,并查看作者在虚拟设备和真实设备之间试图传达的内容。

此代码引用自此网站

/**
 * Gets the number of cores available in this device, across all processors.
 * Requires: Ability to peruse the filesystem at "/sys/devices/system/cpu"
 * @return The number of cores, or 1 if failed to get result
 */
private int getNumCores() {
    //Private Class to display only CPU devices in the directory listing
    class CpuFilter implements FileFilter {
        @Override
        public boolean accept(File pathname) {
            //Check if filename is "cpu", followed by a single digit number
            if(Pattern.matches("cpu[0-9]+", pathname.getName())) {
                return true;
            }
            return false;
        }      
    }

    try {
        //Get directory containing CPU info
        File dir = new File("/sys/devices/system/cpu/");
        //Filter to only list the devices we care about
        File[] files = dir.listFiles(new CpuFilter());
        Log.d(TAG, "CPU Count: "+files.length);
        //Return the number of cores (virtual CPU devices)
        return files.length;
    } catch(Exception e) {
        //Print exception
        Log.d(TAG, "CPU Count: Failed.");
        e.printStackTrace();
        //Default to return 1 core
        return 1;
    }
}

1

Kotlin中的简单而不失优雅的解决方案:

fun getCPUCoreNum(): Int {
  val pattern = Pattern.compile("cpu[0-9]+")
  return Math.max(
    File("/sys/devices/system/cpu/")
      .walk()
      .maxDepth(1)
      .count { pattern.matcher(it.name).matches() },
    Runtime.getRuntime().availableProcessors()
  )
}

1

这是Java相关内容:

    try {
        int ch, processorCount = 0;
        Process process = Runtime.getRuntime().exec("cat /proc/cpuinfo");
        StringBuilder sb = new StringBuilder();
        while ((ch = process.getInputStream().read()) != -1)
            sb.append((char) ch);
        Pattern p = Pattern.compile("processor");
        Matcher m = p.matcher(sb.toString());
        while (m.find())
            processorCount++;
        System.out.println(processorCount);
    } catch (IOException e) {
        e.printStackTrace();
    }

0

在项目中,如果可能的话,使用JNI是一个好的选择。

std::thread::hardware_concurrency()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接