source

리눅스에서 C 또는 C++의 프로세스에 대한 CPU 선호도를 설정하는 방법은 무엇입니까?

ittop 2023. 7. 6. 22:36
반응형

리눅스에서 C 또는 C++의 프로세스에 대한 CPU 선호도를 설정하는 방법은 무엇입니까?

리눅스 운영 체제용 c/c++의 프로세스에 대한 CPU 선호도를 설정하는 프로그래밍 방식이 있습니까?

사용해야 합니다.

예를 들어 CPU 0 및 2에서만 실행하려면 다음을 수행합니다.

#define _GNU_SOURCE
#include <sched.h>

cpu_set_t  mask;
CPU_ZERO(&mask);
CPU_SET(0, &mask);
CPU_SET(2, &mask);
int result = sched_setaffinity(0, sizeof(mask), &mask);

(0첫 번째 매개 변수는 현재 프로세스를 의미하며, 제어하려는 다른 프로세스인 경우 PID를 제공합니다.

참고 항목.

프로세스 수준에서 sched_setaffinity를 사용하거나 개별 스레드에 대해 pthread_attr_setaffinity_np를 사용합니다.

저는 무슨 일이 일어나고 있는지 깨닫기 위해 많은 노력을 했기 때문에 저와 같은 사람들을 돕기 위해 이 답변을 추가합니다(저는 사용합니다).gcc컴파일러 in linux mint)

#include <sched.h> 
cpu_set_t  mask;

inline void assignToThisCore(int core_id)
{
    CPU_ZERO(&mask);
    CPU_SET(core_id, &mask);
    sched_setaffinity(0, sizeof(mask), &mask);
}
int main(){
    //cal this:
    assignToThisCore(2);//assign to core 0,1,2,...

    return 0;
}

그러나 컴파일러 명령에 이 옵션을 추가하는 것을 잊지 마십시오.-D _GNU_SOURCE운영 체제가 특정 코어에 프로세스를 할당할 수 있으므로 다음을 추가할 수 있습니다.GRUB_CMDLINE_LINUX_DEFAULT="quiet splash isolcpus=2,3"다음 위치에 있는 grub 파일로/etc/default그리고 도망가 sudo update-grub터미널에서 원하는 코어를 예약합니다.

업데이트: 더 많은 코어를 할당하려면 다음 코드를 따르십시오.

inline void assignToThisCores(int core_id1, int core_id2)
{
    CPU_ZERO(&mask1);
    CPU_SET(core_id1, &mask1);
    CPU_SET(core_id2, &mask1);
    sched_setaffinity(0, sizeof(mask1), &mask1);
    //__asm__ __volatile__ ( "vzeroupper" : : : ); // It is hear because of that bug which dirtied the AVX registers, so, if you rely on AVX uncomment it.
}

sched_setaffinity+sched_getaffinity최소 실행 가능 예제

이 예제는 C의 Linux에서 sched_getaffinitysched_setaffinity를 사용하는 방법에 대한 답변에서 발췌되었습니다.저는 질문이 중복되지 않는다고 생각합니다. 왜냐하면 질문은 이 질문의 하위 집합이기 때문입니다.sched_getaffinityC++에 대해서는 언급하지 않습니다.

이 예에서는 선호도를 가져와서 수정하고 에 적용되었는지 확인합니다.

주.c.

#define _GNU_SOURCE
#include <assert.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void print_affinity() {
    cpu_set_t mask;
    long nproc, i;

    if (sched_getaffinity(0, sizeof(cpu_set_t), &mask) == -1) {
        perror("sched_getaffinity");
        assert(false);
    }
    nproc = sysconf(_SC_NPROCESSORS_ONLN);
    printf("sched_getaffinity = ");
    for (i = 0; i < nproc; i++) {
        printf("%d ", CPU_ISSET(i, &mask));
    }
    printf("\n");
}

int main(void) {
    cpu_set_t mask;

    print_affinity();
    printf("sched_getcpu = %d\n", sched_getcpu());
    CPU_ZERO(&mask);
    CPU_SET(0, &mask);
    if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) {
        perror("sched_setaffinity");
        assert(false);
    }
    print_affinity();
    /* TODO is it guaranteed to have taken effect already? Always worked on my tests. */
    printf("sched_getcpu = %d\n", sched_getcpu());
    return EXIT_SUCCESS;
}

GitHub 업스트림.

컴파일 및 실행:

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out

샘플 출력:

sched_getaffinity = 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
sched_getcpu = 9
sched_getaffinity = 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
sched_getcpu = 0

그 말은 다음과 같습니다.

  • 처음에는 16개 코어가 모두 활성화되었으며 프로세스가 코어 9(10번째 코어)에서 무작위로 실행되었습니다.
  • 선호도를 첫 번째 코어로만 설정한 후 프로세스는 필연적으로 코어 0(첫 번째 코어)으로 이동되었습니다.

이 프로그램을 실행하는 것도 재미있습니다.taskset:

taskset -c 1,3 ./a.out

형태 출력은 다음과 같습니다.

sched_getaffinity = 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 
sched_getcpu = 2
sched_getaffinity = 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
sched_getcpu = 0

그래서 우리는 처음부터 친화력을 제한했다는 것을 알 수 있습니다.

이는 선호도가 하위 프로세스에 의해 상속되기 때문에 작동합니다.taskset포크 중:하위 분기 프로세스에 의한 CPU 선호도 상속을 방지하는 방법은 무엇입니까?

파이썬:os.sched_getaffinity그리고.os.sched_setaffinity

참고: python을 사용하여 CPU 수를 확인하는 방법

Ubuntu 16.04에서 테스트되었습니다.

요컨대

unsigned long mask = 7; /* processors 0, 1, and 2 */
unsigned int len = sizeof(mask);
if (sched_setaffinity(0, len, &mask) < 0) {
    perror("sched_setaffinity");
}

자세한 내용은 CPU 선호도를 참조하십시오.

cgroupsCPU sub-system이 있는 프로그램에서 수정 없이 셸을 통과할 수도 있습니다.C그룹(v1 이상)은 일반적으로 CPU셋 하위 시스템이 있는 /sys/fs/cgroup에 마운트됩니다.예:

$ ls -l /sys/fs/cgroup/
total 0
drwxr-xr-x 15 root root 380 nov.   22 20:00 ./
drwxr-xr-x  8 root root   0 nov.   22 20:00 ../
dr-xr-xr-x  2 root root   0 nov.   22 20:00 blkio/
[...]
lrwxrwxrwx  1 root root  11 nov.   22 20:00 cpuacct -> cpu,cpuacct/
dr-xr-xr-x  2 root root   0 nov.   22 20:00 cpuset/
dr-xr-xr-x  5 root root   0 nov.   22 20:00 devices/
dr-xr-xr-x  3 root root   0 nov.   22 20:00 freezer/
[...]

CPUet에서 cpuet.cpus는 이 cgroup에 속하는 프로세스가 실행될 수 있는 CPU 범위를 정의합니다.여기서 최상위 수준에서는 모든 CPU가 시스템의 모든 프로세스에 대해 구성됩니다.여기서 시스템에는 8개의 CPU가 있습니다.

$ cd /sys/fs/cgroup/cpuset
$ cat cpuset.cpus
0-7

이 cgroup에 속하는 프로세스 목록은 cgroup.procs 파일에 나열됩니다.

$ cat cgroup.procs
1
2
3
[...]
12364
12423
12424
12425
[...]

CPU의 하위 집합이 허용되는 하위 cgroup을 생성할 수 있습니다.예를 들어 CPU 코어 1과 3이 있는 하위 c그룹을 정의합니다.

$ pwd
/sys/fs/cgroup/cpuset
$ sudo mkdir subset1
$ cd subset1
$ pwd
/sys/fs/cgroup/cpuset/subset1
$ ls -l 
total 0
-rw-r--r-- 1 root root 0 nov.   22 23:28 cgroup.clone_children
-rw-r--r-- 1 root root 0 nov.   22 23:28 cgroup.procs
-rw-r--r-- 1 root root 0 nov.   22 23:28 cpuset.cpu_exclusive
-rw-r--r-- 1 root root 0 nov.   22 23:28 cpuset.cpus
-r--r--r-- 1 root root 0 nov.   22 23:28 cpuset.effective_cpus
-r--r--r-- 1 root root 0 nov.   22 23:28 cpuset.effective_mems
-rw-r--r-- 1 root root 0 nov.   22 23:28 cpuset.mem_exclusive
-rw-r--r-- 1 root root 0 nov.   22 23:28 cpuset.mem_hardwall
-rw-r--r-- 1 root root 0 nov.   22 23:28 cpuset.memory_migrate
-r--r--r-- 1 root root 0 nov.   22 23:28 cpuset.memory_pressure
-rw-r--r-- 1 root root 0 nov.   22 23:28 cpuset.memory_spread_page
-rw-r--r-- 1 root root 0 nov.   22 23:28 cpuset.memory_spread_slab
-rw-r--r-- 1 root root 0 nov.   22 23:28 cpuset.mems
-rw-r--r-- 1 root root 0 nov.   22 23:28 cpuset.sched_load_balance
-rw-r--r-- 1 root root 0 nov.   22 23:28 cpuset.sched_relax_domain_level
-rw-r--r-- 1 root root 0 nov.   22 23:28 notify_on_release
-rw-r--r-- 1 root root 0 nov.   22 23:28 tasks
$ cat cpuset.cpus

$ sudo sh -c "echo 1,3 > cpuset.cpus"
$ cat cpuset.cpus 
1,3

프로세스를 이 cgroup으로 이동하기 전에 cpuset.mems 파일을 채워야 합니다.여기서 현재 셸을 이 새 cgroup으로 이동합니다(cgroup.procs 파일로 이동하는 프로세스의 pid만 기록합니다).

$ cat cgroup.procs

$ echo $$
4753
$ sudo sh -c "echo 4753 > cgroup.procs"
sh: 1: echo: echo: I/O error
$ cat cpuset.mems

$ sudo sh -c "echo 0 > cpuset.mems"
$ cat cpuset.mems
0
$ sudo sh -c "echo 4753 > cgroup.procs"
$ cat cgroup.procs
4753
12569

후자는 현재 셸(pid#4753)이 이제 새로 생성된 cgroup에 있음을 보여줍니다(두 번째 pid 12569는 현재 셸의 자식으로서 cgroup을 상속하는 cat의 명령어입니다).포맷된 ps 명령을 사용하면 프로세스가 실행 중인 CPU를 확인할 수 있습니다(PSR 열).

$ ps -o pid,ppid,psr,command
    PID    PPID PSR COMMAND
   4753    2372   3 bash
  12672    4753   1 ps -o pid,ppid,psr,command

현재 셸이 CPU#3에서 실행되고 cgroups를 상속하는 하위(ps 명령)가 CPU#1에서 실행되고 있음을 알 수 있습니다.

따라서 sched_setaffinity() 또는 pthread 서비스를 사용하는 대신 cgroup 트리에 CPU 집합 계층을 생성하고 해당 cgroup.procs 파일에 해당 pid를 기록하여 프로세스를 해당 계층으로 이동할 수 있습니다.

언급URL : https://stackoverflow.com/questions/280909/how-to-set-cpu-affinity-for-a-process-from-c-or-c-in-linux

반응형