2010-02-10 16 views
56

Est-ce que quelqu'un connaît un moyen de verrouiller des threads individuels dans un processus Java à des cœurs de processeurs spécifiques (sous Linux)? J'ai fait cela en C, mais je ne trouve pas comment faire cela en Java. Mon instinct est que cela nécessitera un appel JNI, mais j'espérais que quelqu'un ici pourrait avoir un aperçu ou aurait pu le faire avant.Fil d'affinité Java

Merci!

+1

Voir ma réponse ci-dessous le commentaire de Hassan. Certains threads nécessitent beaucoup d'E/S, d'autres sont gourmands en ressources processeur. Si je bloque les interruptions d'E/S vers un coeur particulier, je voudrais que les threads d'E/S intensifs soient sur des cœurs sur le même socket, et je voudrais protéger les threads gourmands en CPU des E/S . – Dave

+40

@gimpf: comme toujours avec ce type de questionnement: SO n'est pas le "pourquoi", mais le "comment". L'affinité CPU existe pour une raison, il y a une raison pour laquelle il existe des utilitaires sous Linux et Windows pour définir l'affinité CPU du processus. La question de l'OP est une question parfaitement valable qui ne veut pas de "pourquoi" mais de "comment". – SyntaxT3rr0r

+6

@WizardOfOdds: Je doute que le "pourquoi" est interdit sur SO, et comme Java n'est généralement pas le premier langage de programmation pour les réglages de performance liés à la concurrence, je pense qu'un contrôle de santé est valide. – gimpf

Répondre

42

Vous ne pouvez pas faire cela en Java pur. Mais si vous en avez vraiment besoin, vous pouvez utiliser JNI pour appeler le code natif qui fait le travail. Ceci est l'endroit idéal pour commencer:

http://ovatman.blogspot.com/2010/02/using-java-jni-to-set-thread-affinity.html

http://blog.toadhead.net/index.php/2011/01/22/cputhread-affinity-in-java/

UPD: Après quelques réflexions, j'ai décidé de créer ma propre classe pour cela: ThreadAffinity.java Il est basé JNA, et très simple - donc, si vous voulez l'utiliser en production, il se peut que vous deviez passer du temps à le rendre plus stable, mais pour l'analyse comparative et les tests, cela fonctionne bien tel quel.

UPD 2: Il existe un autre library pour travailler avec l'affinité de thread dans Java. Il utilise même méthode comme indiqué précédemment, mais a une autre interface

+0

+1 Fonctionne! Impressionnant! Notez le commentaire que j'ai laissé dans le premier blog - vous avez besoin de '#define _GNU_SOURCE' au-dessus de tous les inclus. –

+1

+1: J'ai transformé cette fonctionnalité en une bibliothèque qui utilise JNI ou JNA en fonction de ce qui est disponible. Il a également une minuterie à faible latence et supporte l'attente en attente avec l'instruction PAUSE asm. https://github.com/peter-lawrey/Java-Thread-Affinity –

+0

@PeterLawrey C'est super, merci! (en supposant que cela fonctionne que je n'ai pas encore vérifié). Il y a quelques problèmes avec votre bibliothèque (surtout de la documentation et un bug), cependant; comment puis-je vous contacter à ce sujet? – Raphael

0

IMO, ce ne sera pas possible sauf si vous utilisez des appels natifs. La JVM est censée être indépendante de la plate-forme, tous les appels système effectués pour y parvenir n'aboutiront pas à un code portable.

+6

Je ne suis pas préoccupé par la portabilité. – Dave

+5

@questzen: et si l'appel système est effectué uniquement si le programme Java est exécuté sur un système d'exploitation prenant en charge cet appel? Le code serait toujours portable mais ne définirait aucune affinité de CPU sur d'autres systèmes d'exploitation. C'est la seule chose qui me gêne toujours: les gens crient "code non portable" dès que vous faites du JNI ou du Runtime.exec(). J'ai un programme qui fait les deux et qui fonctionne sur Linux, Windows et OS X. – SyntaxT3rr0r

+0

Il ne s'agit pas d'utiliser ou non des appels natifs, mais de savoir si la plate-forme prend en charge ce "out of the box". @questzen a raison de dire que la JVM ne résorbera pas cet accès car elle n'est pas très plate-forme. Vous pourriez être en mesure de trouver des bibliothèques tierces qui le feront. – PSpeed

0

Ce n'est pas possible (au moins avec Java simple).

Vous pouvez utiliser thread pools pour limiter la quantité de threads (et donc de cœurs) utilisés pour différents types de travail, mais il n'existe aucun moyen de spécifier un cœur à utiliser.

Il y a même la (petite) possibilité que votre runtime Java ne prenne pas en charge le thread natif pour votre système d'exploitation ou votre matériel. Dans ce cas, green threads sont utilisés et un seul cœur sera utilisé pour l'ensemble de la JVM.

9

Je sais que ça fait un moment, mais si quelqu'un trouve ce fil, voici comment j'ai résolu ce problème. J'ai écrit un script qui procédez comme suit:

  1. « jstack -l »
  2. Prenez les résultats, trouver le « nid » de des fils que je veux verrouiller manuellement jusqu'à noyaux.
  3. Taskset ces threads.
+1

Par intérêt, je pensais que taskset ne fonctionnait que sur les processus et pas sur les threads individuels. Quelle est la syntaxe pour le faire à un thread? – Matt