12
votes

Performances dégradantes lors de l'augmentation du nombre de cœurs

Mon Mac est armé de 16 noyaux. XXX PRE>

Je cours le code ci-dessous pour voir l'efficacité de l'utilisation de mes noyaux. Le fil "ComptFilelinethread" comptez simplement le nombre de lignes dans un fichier (il y a 133 fichiers dans un dossier) p>

Je prends des notes sur cette ligne: p>

public class TestCores
{   
  public static void main(String args[]) throws Exception
  {
    long start = System.currentTimeMillis();
    System.out.println("START");

    int NUM_CORES = 1;

    List<File> files = Util.getFiles("/Users/adhg/Desktop/DEST/");
    System.out.println("total files: "+files.size());
    ExecutorService es = Executors.newFixedThreadPool(NUM_CORES);
    List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
    for (File file : files)
    {
        Future<Integer> future = es.submit(new CountFileLineThread(file));
        futures.add(future);
    }

    Integer total = 0;

    for (Future<Integer> future : futures)
    {
        Integer result = future.get();
        total+=result;
        System.out.println("result :"+result);

    }

    System.out.println("----->"+total);

    long end = System.currentTimeMillis();
    System.out.println("END. "+(end-start)/1000.0);
}
}


6 commentaires

Parce que votre test fait le fichier d'E / S, vous avez probablement frappé un point avec ce 6ème fil où vous faites maintenant trop d'E / S et ralentissez donc tout.


Je pense que c'est un emploi io lié plutôt que d'un travail consolidé par la CPU. Ajout de plus de threads ne fait que l'accès du disque dur Motif irrégulier sur le disque Navigation entre plusieurs fichiers différents (par opposition à une position consécutive pour un seul fichier, qui est attendu sur un disque régulièrement défragmenté dans le système d'exploitation moderne).


Sur ce type de test, le nombre de cœurs par eux-mêmes n'est pas pertinent lorsque votre code ne fonctionne que dans la mémoire. Une fois que vous avez ajouté E / S, alors qu'un fil a lu un fichier, tous les autres doivent attendre.


FYI RUNTIME.GETRRONTIME (). DisponibleProcesseurs () Renvoie le nombre de processeurs logiques, pas le nombre de cœurs. Par exemple. Si votre processeur dispose de 8 cœurs et est hyperthreadisé, DevisProcesseurs () retournera 16.


@Blueraja - Danny Pflughoeft. Vrai, merci de clarifier cela.


Vous avez peut-être 16 processeurs (peut-être 8 noyaux comme cela a été mentionné), mais combien de caches L3, de banque de mémoire et de disques avez-vous? Sauf si vous avez 16 de chacun de ceux-ci, vous ne pouvez pas obtenir une évolutivité optimale. Si vous créez beaucoup de déchets, cela pourrait surveiller des ressources partagées.


3 Réponses :


19
votes

J'ai ajouté cela comme un commentaire, mais je vais le jeter là-bas comme réponse aussi. Parce que votre test fait le fichier d'E / S, vous avez probablement frappé un point avec ce 6ème fil où vous faites maintenant trop d'E / S et ralentissez donc tout. Si vous voulez vraiment voir l'avantage des 16 noyaux que vous avez, vous devez ré-écrire votre fil de lecture de fichier pour utiliser des E / S non bloquantes.


0 commentaires

5
votes

Mon hunch est que vous avez peut-être mis autant de fardeau sur le disque I / O que vous avez ralentie tout! Voir les performances d'E / S dans "Moniteur d'activité" (si vous êtes sur OSX). Sur Linux, utilisez la commande vmstat code> pour avoir une idée de ce qui se passe. [Si vous voyez beaucoup d'échange ou de taux élevé de lectures / s et d'écrit / s / s, alors là, vous y allez]


Peu de choses que j'ai remarquées: p>

CountFilelinethread code> est pas dans le code. S'il vous plaît mettez-le donc nous pouvons voir exactement ce qui se passe. P>

Suivant, P>

for (Future<Integer> future : futures)
{
    Integer result = future.get();
    total+=result;
    System.out.println("result :"+result);

}


0 commentaires

1
votes

Ajout de processeurs provoque toutes sortes de problèmes, mais surtout, ils ont à voir avec la synchronisation entre les processeurs. Le verrouillage de la tâche dans le système de fichiers, etc., peut devenir un problème, mais encore plus d'un problème est la synchronisation entre les cœurs qui doivent survenir uniquement pour maintenir la cohérence de cache, garder une trace des pages modifiées, etc. Je ne sais pas comment De nombreux cœurs par puce que vous avez (abandonnez le suivi de ce type il y a environ 10 ans), mais généralement une fois que vous avez commencé à synchroniser les performances hors puce descend les tubes.

Je vais ajouter que la JVM peut faire une différence majeure ici. Une conception prudente JVM est nécessaire pour minimiser le nombre de lignes de cache partagées (et fréquemment mises à jour) et des efforts incroyables sont nécessaires pour rendre efficacement des travaux de GC dans un environnement multicœur.


0 commentaires