Recherche du nombre de cœurs en Java

412

Comment puis-je trouver le nombre de cœurs disponibles pour mon application à partir du code Java?

Damir
la source
3
Pour à peu près toutes les intentions et le but "core == processeur".
Joachim Sauer
32
il est difficile de trouver le nombre de cœurs que la machine possède physiquement en utilisant purement Java. Il est facile de trouver le nombre de cœurs que le programme Java peut utiliser au démarrage en utilisant Runtime.getRuntime (). AvailableProcessors () . En raison de la capacité de tous les principaux systèmes d'exploitation modernes à définir l'affinité du processeur (c'est-à-dire restreindre une application à un certain nombre de cœurs seulement), il convient de garder cela à l'esprit.
SyntaxT3rr0r
6
Cœurs logiques ou physiques? Il y a une différence importante.
b1nary.atr0phy
Voir aussi: stackoverflow.com/questions/1980832/…
Christophe Roussy

Réponses:

726
int cores = Runtime.getRuntime().availableProcessors();

S'il coresest inférieur à un, soit votre processeur est sur le point de mourir, soit votre JVM contient un grave bogue, soit l'univers est sur le point de exploser.

darioo
la source
107
Cela vous donnera le nombre de threads logiques. Par exemple, si vous avez de l'hyper-threading, ce sera le double du nombre de cœurs.
Peter Lawrey
6
@Peter, oui, bon point. Je me suis senti roi de la colline en effectuant cette action avec ma machine i7! :)
Bart Kiers
14
@Peter Lawrey: il ne donne que le nombre de threads logiques réellement disponibles pour la JVM (au démarrage je suppose). En utilisant l'affinité CPU, l'utilisateur / OS peut restreindre le nombre de "cœurs" visibles par la JVM. Vous pouvez même le faire sur une machine virtuelle Java en cours d'exécution, mais je ne sais pas trop comment cela influence les processeurs disponibles () .
SyntaxT3rr0r
25
@PeterLawrey: cela semble être incorrect, la documentation Java pour availableProcessors () indique "Cette valeur peut changer lors d'un appel particulier de la machine virtuelle. Les applications qui sont sensibles au nombre de processeurs disponibles doivent donc parfois interroger cette propriété et ajuster leur l'utilisation appropriée des ressources. " source
JW.
9
@universe explose et autres: ou la machine a en fait plus de 2.147.483.647 threads logiques disponibles? ;)
Pierre Henry
26

Si vous souhaitez obtenir le nombre de cœurs physiques, vous pouvez exécuter la commande cmd et terminal, puis analyser la sortie pour obtenir les informations dont vous avez besoin. Ci-dessous, la fonction indiquée qui renvoie le nombre de cœurs physiques.

private int getNumberOfCPUCores() {
    OSValidator osValidator = new OSValidator();
    String command = "";
    if(osValidator.isMac()){
        command = "sysctl -n machdep.cpu.core_count";
    }else if(osValidator.isUnix()){
        command = "lscpu";
    }else if(osValidator.isWindows()){
        command = "cmd /C WMIC CPU Get /Format:List";
    }
    Process process = null;
    int numberOfCores = 0;
    int sockets = 0;
    try {
        if(osValidator.isMac()){
            String[] cmd = { "/bin/sh", "-c", command};
            process = Runtime.getRuntime().exec(cmd);
        }else{
            process = Runtime.getRuntime().exec(command);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    BufferedReader reader = new BufferedReader(
            new InputStreamReader(process.getInputStream()));
    String line;

    try {
        while ((line = reader.readLine()) != null) {
            if(osValidator.isMac()){
                numberOfCores = line.length() > 0 ? Integer.parseInt(line) : 0;
            }else if (osValidator.isUnix()) {
                if (line.contains("Core(s) per socket:")) {
                    numberOfCores = Integer.parseInt(line.split("\\s+")[line.split("\\s+").length - 1]);
                }
                if(line.contains("Socket(s):")){
                    sockets = Integer.parseInt(line.split("\\s+")[line.split("\\s+").length - 1]);
                }
            } else if (osValidator.isWindows()) {
                if (line.contains("NumberOfCores")) {
                    numberOfCores = Integer.parseInt(line.split("=")[1]);
                }
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    if(osValidator.isUnix()){
        return numberOfCores * sockets;
    }
    return numberOfCores;
}

Classe OSValidator:

public class OSValidator {

private static String OS = System.getProperty("os.name").toLowerCase();

public static void main(String[] args) {

    System.out.println(OS);

    if (isWindows()) {
        System.out.println("This is Windows");
    } else if (isMac()) {
        System.out.println("This is Mac");
    } else if (isUnix()) {
        System.out.println("This is Unix or Linux");
    } else if (isSolaris()) {
        System.out.println("This is Solaris");
    } else {
        System.out.println("Your OS is not support!!");
    }
}

public static boolean isWindows() {
    return (OS.indexOf("win") >= 0);
}

public static boolean isMac() {
    return (OS.indexOf("mac") >= 0);
}

public static boolean isUnix() {
    return (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0 );
}

public static boolean isSolaris() {
    return (OS.indexOf("sunos") >= 0);
}
public static String getOS(){
    if (isWindows()) {
        return "win";
    } else if (isMac()) {
        return "osx";
    } else if (isUnix()) {
        return "uni";
    } else if (isSolaris()) {
        return "sol";
    } else {
        return "err";
    }
}

}

adi9090
la source
4
C'est un morceau de code qui est un bon candidat pour être OOP. :)
Lyubomyr Shaydariv
1
La classe OSValidator prend en charge OSX, mais getNumberOfCores l'ignore complètement. En passant , blog.opengroup.org/2015/10/02/… donc 'Mac' devrait être dans votre isUnix () mais ... Pour BSD, OSX, aucune commande lscpu n'existe et votre getNumberOfCores retournera 0.
Paul Hargreaves
1
Sous Linux, vous devez multiplier "Core (s) par socket" par "Socket (s)". De plus, j'utiliserais des expressions régulières.
Aleksandr Dubinsky
1
Il vaut mieux utiliser "OS.contains ()" au lieu de "OS.indexOf ()". Il améliore la lisibilité et est moins à taper.
Josh Gager
6

C'est un moyen supplémentaire de connaître le nombre de cœurs de CPU (et beaucoup d'autres informations), mais ce code nécessite une dépendance supplémentaire:

Informations sur le système d'exploitation natif et le matériel https://github.com/oshi/oshi

SystemInfo systemInfo = new SystemInfo();
HardwareAbstractionLayer hardwareAbstractionLayer = systemInfo.getHardware();
CentralProcessor centralProcessor = hardwareAbstractionLayer.getProcessor();

Obtenez le nombre de CPU logiques disponibles pour le traitement:

centralProcessor.getLogicalProcessorCount();
Antonio
la source
Cela vous permettra également d'utiliser centralProcessor.getPhysicalProcessorCount (), qui est probablement actuellement le meilleur moyen en java pour obtenir ces informations. Si vous avez des threads qui ont presque constamment du travail à faire et que vous souhaitez connaître le nombre de ces threads que vous pouvez démarrer tout en laissant un reste bien défini de la capacité du processeur pour d'autres threads et processus, c'est le nombre que le calcul doit être basé sur.
malamut
-3

Cela fonctionne sur Windows avec Cygwin installé:

System.getenv("NUMBER_OF_PROCESSORS")

Lyle Z
la source
J'ai installé Cygwin, mais cela fonctionne à partir du shell Windows:groovy -e "println System.getenv('NUMBER_OF_PROCESSORS')"
AbuNassar
Je ne sais pas du haut de ma tête s'il s'agit d'une variable d'environnement Windows standard, mais: set NUMBER_OF_PROCESSORSfonctionne à partir de la ligne de commande Windows pour moi.
AbuNassar