Jak ograniczyć proces do jednego rdzenia procesora?

30

Jak ograniczyć uruchamianie pojedynczego programu procesowego w środowisku Windows do działania tylko na jednym procesorze na komputerze wielordzeniowym?

Czy to samo dotyczy programu okienkowego i programu wiersza poleceń?

AKTUALIZACJA:

  • Powód tego: analiza porównawcza różnych aspektów języków programowania
  • Potrzebuję czegoś, co działałoby od samego początku procesu, dlatego odpowiedź @ akseli, choć świetna w innych przypadkach, nie rozwiązuje mojej sprawy
Jonathan
źródło
2
Dlaczego chcesz to zrobić? Pozwolenie systemowi operacyjnemu decydować, który procesor / rdzeń uruchamia, który proces będzie znacznie bardziej wydajny.
ChrisF,
1
w celu porównania różnych aspektów języka programowania
Jonathan
1
To dobry powód - powinieneś uwzględnić te informacje w swoim pytaniu. To ważne.
ChrisF,
Motywacja nie jest niezbędna, ale dodałem ją zgodnie z twoją radą
Jonathan
1
Jednak może to być informacja, której ktoś potrzebuje, aby udzielić odpowiedzi.
ChrisF,

Odpowiedzi:

27

Jeśli korzystasz z systemu Windows Vista / 7 (prawdopodobnie XP, ale nie jesteś pewien), to naprawdę dość proste.

Wpisz: Control+Shift+Escaby uruchomić menedżera zadań.

Kliknij kartę Procesy

Znajdź proces, który wymaga zmiany powinowactwa procesora

Kliknij proces prawym przyciskiem myszy

Kliknij „Ustaw koligację”

Tutaj możesz wybrać procesory, których będzie używał Twój proces.

Powodzenia!

EDYCJA: Musisz być administratorem, aby to działało.

akseli
źródło
13
Podobieństwo nie jest gwarancją. Procesy wolą ten procesor, ale jeśli ma kilka wątków, nie wszystkie one tam pozostaną.
Joel Coehoorn
1
To dobrze, ale potrzebuję czegoś, co od samego początku będzie deterministyczne
Jonathan
2
@JoelCoehoorn: Nie, to jest gwarancja. Mówisz o preferowanym wektorze procesora, który różni się od wektora powinowactwa.
Mehrdad
1
@ Mehrdad: chyba że sam program zmieni go na cokolwiek zechce.
Eugene Ryabtsev
1
@JoelCoehoorn > Powinowactwo wątku wymusza uruchomienie wątku na określonym podzbiorze procesorów. - wydaje się, że odwołujesz się do tego, co mówi ten artykuł, że jest idealnym procesorem wątku .
Bob
19

z wiersza poleceń użyj

start / affinity 1 program.exe

spowoduje to uruchomienie programu.exe na pierwszym CPU, ponieważ „1” jest wartością szesnastkową maski koligacji

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 

źródło
1
Revolter: Czy wiesz, czy mogę zrobić to samo z inicjalizacją usług?
Diogo,
Co jeśli masz więcej niż 4 rdzenie?
posfan12
7

Zależy od tego, co chcesz zrobić:

Metoda 1: na żądanie

Użyj ImageCFG . To narzędzie pozwoli ci skonfigurować plik wykonywalny do działania na dowolnej liczbie rdzeni. Upewnij się, że wykonałeś kopię zapasową docelowego pliku wykonywalnego przed dokonaniem zmian i przywróć go, gdy skończysz grać z nim.

Metoda 2: Wymuś całą sesję systemu Windows (Vista / 7)

  1. Wpisz bcdedit /set onecpu onw wierszu polecenia
  2. Uruchom ponownie system.
  3. Po zakończeniu gry wpisz 2 - Type: bcdedit /set onecpu offi uruchom ponownie.

Metoda 2: Wymuś całą sesję systemu Windows (XP)

  1. Otwórz plik boot.ini (kliknij prawym przyciskiem myszy Mój komputer -> Właściwości -> Karta Zaawansowane -> przycisk Ustawienia pod „Uruchamianie i odzyskiwanie” -> przycisk Edytuj w „Uruchamianie systemu”).
  2. W pliku znajdziesz następującą (lub podobną) sekcję:

    [system operacyjny]

    multi (0) dysk (0) partycja rdisk (0) (2) \ WINDOWS = "Microsoft Windows XP Professional" / fastdetect

  3. Zmień to, dodając flagę / onecpu:

    [system operacyjny]

    multi (0) dysk (0) partycja rdisk (0) (2) \ WINDOWS = "Microsoft Windows XP Professional" / fastdetect / onecpu

  4. Restart. Po zakończeniu gry usuń flagę i uruchom ponownie.

Metoda 0: Niezbyt dobra metoda (koligacja procesora)

Obawiam się, że wszystko, co inaczej wiąże się z powinowactwem do procesora, nie jest dobrym rozwiązaniem. Powinowactwo procesora jest wskazówką dla procesora. Procesor nie jest zobowiązany do przestrzegania go i często tego nie zrobi.

Krasnolud
źródło
Metoda 2 nie działa na Win7. D:\>bcdedit /set onecpuskutkuje The set command specified is not valid.....The parameter is incorrect.
maks.
2
technet.microsoft.com/en-us/library/cc938636.aspx mówi „... twarde powinowactwo, co oznacza, że ​​maska ​​koligacji procesora ogranicza wątki dotknięte maską koligacji do procesorów określonych przez maskę. maska ​​koligacji nie będzie działać na procesorach, które nie są zawarte w masce koligacji ". Jakieś źródło mówi, że nie będzie przestrzegane?
Eugene Ryabtsev
4

W moim programie umieściłem następującą funkcję w Pythonie 2.6 i wywołuje ona funkcje systemu Windows. Moja maszyna ma tylko dwa rdzenie, więc może być konieczna zmiana tej części. Komentarze mówią, jak zobaczyć, jakie jest obecne powinowactwo. Działa „tak jak jest” dla maszyny z jednym rdzeniem, jeśli ustawisz lub domyślnie ustawisz maskę 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
Mariczjaszana
źródło
Nie jestem pewien, czy OP poprosił o kod ...
bytebuster
Jak wykonać tę funkcję z wiersza poleceń lub pliku wsadowego? Czy istnieje sposób, aby wcześniej ustalić, jaki będzie identyfikator procesu?
posfan12
4

Gdy szukałem bardzo podobnych informacji za pomocą PowerShell, znalazłem informacje, których potrzebowałem tutaj: http://www.energizedtech.com/2010/07/powershell-setting-processor-a.html

Nie wspominałeś, z którego systemu operacyjnego Windows korzystasz (starsze nie były dostarczane z programem PowerShell, chociaż możesz go zainstalować, jeśli go nie ma).

Najważniejsze jest to, że w PowerShell powinowactwo do procesu jest po prostu właściwością, którą można łatwo zmienić.

Aby zobaczyć właściwości (i inne ciekawostki informacji) twojego procesu (używając foo jako przykładowego procesu), polecenie PowerShell byłoby:

Get-Process foo | Get-Member

Zobaczysz ProcessorAffinity jest jedną z tych właściwości. Zmiana jest trywialna i możesz wybrać rdzeń, na którym chcesz uruchomić, używając wartości z tabeli / linku Revoltera powyżej.

Aby zobaczyć, jaka jest wartość właściwości ProcessorAffinity dla foo, oto polecenie:

(Get-Process foo) .ProcessorAffinity

Więc jeśli chcesz uruchomić foo tylko na procesorze 4, ustaw jako taką wartość:

(Get-Process foo) .ProcessorAffinity = 8

Bewc
źródło
Nie mogę powiedzieć z twojego wyjaśnienia: czy dotyczy to tylko istniejących procesów? OP nie chce rozpocząć procesu, a następnie ustawić swoje powinowactwo; chce rozpocząć proces z już ustalonym powinowactwem , jak w start /affinityodpowiedzi. Czy twoja technika to potrafi? Jeśli tak, proszę wyjaśnić, w jaki sposób.
Scott
2
@Scott Tylko istniejące procesy. W kontekście, który podajesz, moja odpowiedź nie pomaga. Czułem, że „sam początek procesu” polegał na rozpoczęciu procesu, a następnie natychmiastowym ustaleniu jego powinowactwa. IE: Start-Process foo ; (Get-Process foo).ProcessorAffinity=8 Jednak po przeczytaniu twojego komentarza i stwierdzeniu, że Start-Processma brakującą flagę powinowactwa, wpadłem na następujące, które przetestowałem: [System.Diagnostics.Process]::start("foo.exe").ProcessorAffinity=0x0010
Bewc
Sugeruję edycję odpowiedzi, aby dodać tę alternatywę.
Scott