Comment limiter un processus à un seul cœur de CPU?

30

Comment limiter un programme de processus unique exécuté dans un environnement Windows pour s'exécuter uniquement sur un seul processeur sur une machine multicœur?

Est-ce la même chose entre un programme fenêtré et un programme en ligne de commande?

MISE À JOUR:

  • Raison de cela: comparer les différents aspects des langages de programmation
  • J'ai besoin de quelque chose qui fonctionnerait dès le début du processus, donc la réponse de @ akseli, bien qu'excellente pour d'autres cas, ne résout pas mon cas
Jonathan
la source
2
Pourquoi veux-tu faire cela? Laisser le système d'exploitation décider quel processeur / cœur exécute quel processus il sera beaucoup plus efficace.
ChrisF
1
afin de comparer divers aspects du langage de programmation
Jonathan
1
C'est une bonne raison - vous auriez dû inclure cette information dans votre question. C'est important.
ChrisF
La motivation n'est pas essentielle, mais je l'ai ajoutée en suivant vos conseils
Jonathan
1
Cependant, il peut s'agir des informations dont une personne a besoin pour pouvoir répondre.
ChrisF

Réponses:

27

Si vous utilisez Windows Vista / 7 (éventuellement XP, mais pas sûr), c'est vraiment assez simple.

Tapez: Control+Shift+Escpour obtenir votre gestionnaire de tâches.

Cliquez sur l'onglet Processus

Trouver le processus qui a besoin de changer l'affinité de son processeur

Faites un clic droit sur le processus

Cliquez sur "Définir l'affinité"

Ici, vous pouvez sélectionner le ou les processeurs que votre processus utilisera.

Bonne chance!

EDIT: Vous devez être administrateur pour que cela fonctionne.

akseli
la source
13
Une affinité n'est pas une garantie. Les processus préféreront ce processeur, mais s'il a plusieurs threads, ils n'y resteront pas tous.
Joel Coehoorn
1
C'est bien, mais j'ai besoin de quelque chose qui sera déterministe dès le départ
Jonathan
2
@JoelCoehoorn: Non, c'est une garantie. Vous parlez du vecteur processeur préféré , qui est différent du vecteur d'affinité.
Mehrdad
1
@Mehrdad: à moins que le programme lui-même ne le change en ce qu'il veut.
Eugene Ryabtsev
1
@JoelCoehoorn > L'affinité de thread force un thread à s'exécuter sur un sous-ensemble spécifique de processeurs. - vous semblez faire référence à ce que dit cet article est un processeur idéal pour les threads .
Bob
19

à partir de la ligne de commande, utilisez

start / affinity 1 program.exe

cela exécutera program.exe sur le premier CPU car "1" est la valeur hexadécimale du masque d'affinité

CPU3 CPU2 CPU1 CPU0  Bin  Hex
---- ---- ---- ----  ---  ---
OFF  OFF  OFF  ON  = 0001 = 1
OFF  OFF  ON   OFF = 0010 = 2
OFF  OFF  ON   ON  = 0011 = 3
OFF  ON   OFF  OFF = 0100 = 4
OFF  ON   OFF  ON  = 0101 = 5 
OFF  ON   ON   OFF = 0110 = 6
OFF  ON   ON   ON  = 0111 = 7
ON   OFF  OFF  OFF = 1000 = 8
ON   OFF  OFF  ON  = 1001 = 9
ON   OFF  ON   OFF = 1010 = A 
ON   OFF  ON   ON  = 1011 = B
ON   ON   OFF  OFF = 1100 = C
ON   ON   OFF  ON  = 1101 = D
ON   ON   ON   OFF = 1110 = E 
ON   ON   ON   ON  = 1111 = F 

la source
1
Revolter: Savez-vous si je peux faire de même avec l'initialisation des services?
Diogo
Et si vous avez plus de 4 cœurs?
posfan12
7

Cela dépend de ce que vous êtes prêt à faire:

Méthode 1: sur demande

Utilisez ImageCFG . Cet utilitaire vous permettra de configurer un exécutable pour qu'il s'exécute sur n'importe quel nombre de cœurs. Assurez-vous de sauvegarder votre exécutable cible avant d'apporter les modifications et de le restaurer lorsque vous avez fini de jouer avec.

Méthode 2: forcer une session Windows entière (Vista / 7)

  1. Tapez bcdedit /set onecpu onsur une invite de commande
  2. Redémarrez le système.
  3. Lorsque vous avez fini de jouer, tapez 2 - Tapez: bcdedit /set onecpu offet redémarrez à nouveau.

Méthode 2: forcer une session Windows entière (XP)

  1. Ouvrez votre fichier boot.ini (cliquez avec le bouton droit sur Poste de travail -> Propriétés -> onglet Avancé -> bouton Paramètres sous «Démarrage et récupération» -> bouton Modifier dans «Démarrage du système»).
  2. Vous trouverez la section suivante (ou similaire) dans le fichier:

    [systèmes d'exploitation]

    multi (0) disque (0) rdisk (0) partition (2) \ WINDOWS = "Microsoft Windows XP Professionnel" / fastdetect

  3. Modifiez-le en ajoutant le drapeau / onecpu:

    [systèmes d'exploitation]

    multi (0) disque (0) rdisk (0) partition (2) \ WINDOWS = "Microsoft Windows XP Professionnel" / fastdetect / onecpu

  4. Redémarrer. Une fois que vous avez fini de jouer, supprimez le drapeau et redémarrez à nouveau.

Méthode 0: Pas une bonne méthode (affinité du processeur)

Tout ce qui implique autrement l'affinité du processeur n'est pas une bonne option, je le crains. L'affinité du processeur est un indice pour le processeur. Le processeur n'est pas obligé de le respecter et ne le fera pas souvent.

Un nain
la source
La méthode 2 ne semble pas fonctionner sur Win7. D:\>bcdedit /set onecpurésultats en The set command specified is not valid.....The parameter is incorrect.
max
2
technet.microsoft.com/en-us/library/cc938636.aspx dit "... affinité matérielle, ce qui signifie que le masque d'affinité du processeur limite les threads affectés par le masque d'affinité aux processeurs spécifiés par le masque. Threads restreints par un disque dur le masque d'affinité ne fonctionnera pas sur les processeurs qui ne sont pas inclus dans le masque d'affinité ". Une source qui dit que cela ne sera pas respecté?
Eugene Ryabtsev
4

J'ai mis la fonction suivante dans mon programme en python 2.6 et il appelle des fonctions Windows. Ma machine n'a que deux cœurs, vous devrez donc peut-être changer cette partie. Les commentaires vous indiquent comment voir l'affinité actuelle. Il fonctionne «tel quel» pour une machine à cœur unique si vous définissez ou par défaut un masque de 1.

def setaffinitymask(pid = None, mask = 1):
    """ Set The Affinity Mask of a Windows Process.  Affinity Mask is a value between 1-3 where
        1 is for core 0, 2 is for core 1, 3 is for both cores (it is a bitmap)
        Default sets the Affinity Mask to core 0 only
        python process can take any valid process ID. """

    import win32api, win32process, win32con

    if pid  == None:
        pid  = win32api.GetCurrentProcessId()
    if mask == None:
        mask = 1
    if mask  < 1 or mask > 3:
        mask = 1
        print 'process affinity mask out of range [1..3] setting it to 1'
    handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, True, pid)
    # see what mask is currently set to
    # processAffinityMask, systemAffinityMask = win32process.GetProcessAffinityMask(handle)
    # print 'process affinity mask = ', processAffinityMask, ', system affinity mask = ', systemAffinityMask
    # set affinity for process to mask value
    win32process.SetProcessAffinityMask(handle, mask) # 1=core 0, 2=core 1, 3=both
    processAffinityMask, systemAffinityMask = win32process.GetProcessAffinityMask(handle)
    #print 'process affinity mask = ', processAffinityMask, ', system affinity mask = ', systemAffinityMask
Marichyasana
la source
Je ne sais pas si OP a demandé un code ...
bytebuster
Comment exécutez-vous cette fonction à partir de la ligne de commande ou du fichier batch? Existe-t-il un moyen de savoir ou de définir à l'avance quel sera l'ID de processus?
posfan12
4

Alors que je cherchais des informations très similaires à l'aide de PowerShell, j'ai trouvé les informations dont j'avais besoin ici: http://www.energizedtech.com/2010/07/powershell-setting-processor-a.html

Vous n'avez pas mentionné le système d'exploitation Windows que vous utilisiez (les plus anciens n'étaient pas fournis avec PowerShell, bien que vous puissiez l'installer s'il n'est pas là).

Le plus rapide, c'est que dans PowerShell, l'affinité du processus est simplement une propriété que vous pouvez modifier facilement.

Pour voir les propriétés (et d'autres informations) de votre processus (en utilisant foo comme exemple de processus), la commande PowerShell serait:

Get-Process foo | Get-Member

Vous verrez que ProcessorAffinity est l'une de ces propriétés. Le changer est trivial, et vous pouvez sélectionner le noyau sur lequel vous souhaitez exécuter, en utilisant les valeurs du tableau / lien de Revolter ci-dessus.

Pour voir quelle est la valeur de la propriété ProcessorAffinity pour foo, voici la commande:

(Get-Process foo) .ProcessorAffinity

Donc, si vous vouliez exécuter foo sur cpu 4 uniquement, vous définiriez la valeur en tant que telle:

(Get-Process foo) .ProcessorAffinity = 8

Bewc
la source
Je ne peux pas dire à partir de votre explication: cela s'applique-t-il uniquement aux processus existants? L'OP ne veut pas démarrer un processus, puis définir son affinité; il veut démarrer un processus avec son affinité déjà définie , comme dans la start /affinityréponse. Votre technique peut-elle faire cela? Si oui, veuillez expliquer comment.
Scott
2
@Scott Processus existants uniquement. Dans le contexte que vous fournissez, ma réponse n'aide pas. J'ai senti que le «tout début du processus» consistait à démarrer le processus, puis à définir immédiatement son affinité. IE: Start-Process foo ; (Get-Process foo).ProcessorAffinity=8 Cependant, après avoir lu votre commentaire et trouvé qu'il y Start-Processavait un drapeau d'affinité manquant, j'ai trouvé ce qui suit, que j'ai testé: [System.Diagnostics.Process]::start("foo.exe").ProcessorAffinity=0x0010
Bewc
Je vous suggère de modifier votre réponse pour ajouter cette alternative.
Scott