Menu Close
Settings Close

Language and Page Formatting Options

Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

3.3. 권장 설정

Red Hat Enterprise Linux에는 시스템을 설정할 때 관리자에게 유용한 여러 도구가 있습니다. 다음 부분에서는 이러한 도구에 대해 설명하고 Red Hat Enterprise Linux 7에서 프로세서 관련 성능 문제를 해결하는 방법에 대해 설명합니다.

3.3.1. 커널 틱 시간 설정

기본적으로 Red Hat Enterprise Linux 7에서는 틱리스 커널을 사용합니다. 이 커널은 전력 소비를 감소시키기 위해 유휴 상태의 CPU를 인터럽트하지 않도록 하여 새로운 프로세서가 완전 절전 상태가 될 수 있게 합니다.
Red Hat Enterprise Linux 7에서는 동적 틱리스 옵션 (기본적으로 비활성화)을 제공하여 고성능 컴퓨팅 또는 실시간 컴퓨팅과 같은 대기 시간 제약이 있는 작업에 유용합니다.
특정 코어에서 동적 틱리스 동작을 활성화하려면 커널 명령행에 nohz_full 매개 변수를 사용하여 이러한 코어를 지정합니다. 16 코어 시스템에서 nohz_full=1-15를 지정하면 동적 틱리스 동작이 코어 1에서 15 까지 활성화되고 모든 시간 기록은 지정되지 않은 코어 (코어 0)로 이동됩니다. 이러한 동작은 부팅 시 임시적으로 활성화하거나 /etc/default/grub 파일에서 영구적으로 활성화할 수 있습니다. 영구적으로 활성화하려면 grub2-mkconfig -o /boot/grub2/grub.cfg 명령을 실행하여 설정을 저장합니다.
동적 틱리스 동작을 활성화에는 일부 수동 관리가 필요합니다.
  • 시스템 시작 시 rcu 스레드를 대기 시간 제약이 없는 코어로 이동시켜야 합니다. 이 경우 코어 0가 됩니다.
    # for i in `pgrep rcu[^c]` ; do taskset -pc 0 $i ; done
  • 커널 명령행에서 isolcpus 매개 변수를 사용하여 특정 코어를 사용자 공간 작업에서 분리합니다.
  • 옵션으로 커널 write-back bdi-flush 스레드의 CPU 선호도를 housekeeping 코어로 설정합니다:
    echo 1 > /sys/bus/workqueue/devices/writeback/cpumask
다음 명령을 실행하여 동적 틱리스 설정이 올바르게 작동하고 있는지 확인합니다. 여기서 stress는 1 초 동안 CPU 에서 실행되는 프로그램입니다.
# perf stat -C 1 -e irq_vectors:local_timer_entry taskset -c 1 stress -t 1 -c 1
stress를 대신하여 while :; do d=1; done과 같은 스크립트를 실행할 수 있습니다. 또한 다음의 링크에 있는 사용 가능한 프로그램도 이를 대신하여 사용할 수 있습니다: https://dl.fedoraproject.org/pub/epel/6/x86_64/repoview/stress.html.
기본 커널 타이머 설정은 사용 중인 CPU에서 1000 틱으로 되어 있습니다:
# perf stat -C 1 -e irq_vectors:local_timer_entry taskset -c 1 stress -t 1 -c 1
1000 irq_vectors:local_timer_entry
동적 틱리스 커널을 설정하면 1틱이 됩니다:
# perf stat -C 1 -e irq_vectors:local_timer_entry taskset -c 1 stress -t 1 -c 1
1 irq_vectors:local_timer_entry

3.3.2. 하드웨어 성능 정책 설정 (x86_energy_perf_policy)

x86_energy_perf_policy 도구를 사용하여 관리자는 성능 및 전력 효율성의 상대적 중요성을 지정할 수 있습니다. 이러한 정보를 사용하여 성능과 전력 효율성 사이에서 절충할 수 있는 옵션을 선택하면 기능을 지원하는 프로세서를 작동시킬 수 있습니다.
기본적으로 이는 performance 모드의 모든 프로세서에서 작동합니다. CPUID.06H.ECX.bit3의 표시가 있으면 프로세서의 지원이 필요한 것이므로 root 권한을 사용하여 실행해야 합니다.
x86_energy_perf_policykernel-tools 패키지에서 제공됩니다. x86_energy_perf_policy 사용 방법에 대한 보다 자세한 내용은 A.10절. “x86_energy_perf_policy” 또는 man 페이지에서 참조하십시오:
$ man x86_energy_perf_policy

3.3.3. taskset으로 프로세스 친화도 설정

taskset 도구는 util-linux 패키지로 제공됩니다. Taskset을 사용하여 관리자는 실행 중인 프로세스의 친화도를 검색 및 설정하거나 지정된 프로세스 친화도로 프로세스를 시작할 수 있습니다.

중요

taskset은 로컬 메모리 할당을 보장하지 않습니다. 로컬 메모리 할당을 통해 추가적으로 성능을 향상시켜야 할 경우 Red Hat은 taskset 대신 numactl을 사용할 것을 권장합니다.
taskset에 대한 보다 자세한 내용은 A.16절. “taskset” 또는 man 페이지에서 참조하십시오:
$ man taskset

3.3.4. numactl로 NUMA 친화도 관리

관리자는 numactl을 사용하여 지정된 스케줄링 또는 메모리 배치 정책에 따라 프로세스를 실행할 수 있습니다. Numactl은 공유 메모리 세그먼트나 파일에 영구 정책을 설정하고 프로세서 친화도 및 메모리 친화도를 설정할 수 있습니다.
NUMA 토폴로지 시스템에서 프로세스의 메모리 액세스 속도는 프로세서와 메모리 뱅크 사이의 거리가 멀어질 수록 느려집니다. 따라서 성능에 민감한 애플리케이션은 가장 가까운 메모리 뱅크에서 메모리를 할당하도록 설정해야 합니다. 동일한 NUMA 노드에 있는 메모리와 CPU를 사용하는 것이 가장 좋습니다.
성능에 민감한 멀티 스레드 애플리케이션은 특정 프로세서 대신 특정 NUMA 노드에서 실행하도록 설정하는 것이 좋습니다. 이러한 설정이 적합한 지에 대한 여부는 시스템 및 시스템 애플리케이션의 요구 사항에 따라 다릅니다. 여러 애플리케이션 스레드가 동일한 캐시 데이터에 액세스하는 경우 이러한 스레드를 동일한 프로세서에서 실행되도록 설정하는 것이 적합할 수 있습니다. 하지만 다른 데이터에 액세스하여 캐시되는 여러 스레드가 동일한 프로세스에서 실행되는 경우 각 스레드는 이전 스레드에 의해 액세스된 캐시된 데이터를 삭제할 수 있습니다. 즉 이로 인해 각각의 스레드가 캐시를 '누락'시키고 디스크에서 데이터를 가져와서 이를 캐시 교체하는데 실행 시간이 낭비될 수 있습니다. A.7절. “perf”에서 설명되어 있듯이 perf 도구를 사용하여 캐시 누락이 과도하게 발생하고 있는지 확인할 수 있습니다.
Numactl에서는 프로세스와 메모리 친화도를 관리하는데 유요한 여러 옵션을 제공합니다. 보다 자세한 내용은 A.12절. “numastat” 또는 man 페이지에서 참조하십시오:
$ man numactl

참고

numactl 패키지에는 libnuma 라이브러리가 포함되어 있습니다. 이러한 라이브러리는 커널에서 지원하는 NUMA 정책에 대한 간단한 프로그래밍 인터페이스를 제공하며 numactl 애플리케이션 보다 더 정교한 튜닝에 유용합니다. 보다 자세한 내용은 man 페이지에서 참조하십시오:
$ man numa

3.3.5. numad를 사용하여 NUMA 친화도 자동 관리

numad는 NUMA 친화도 자동 관리 데몬입니다. 이는NUMA 리소스 할당 및 관리 개선을 위해 NUMA 토폴로지 및 시스템 리소스 사용을 모니터링합니다.
numad는 다양한 작업 관리 시스템을 쿼리할 수 있는 사전 배포 컨설팅 서비스도 제공하고 있으며 프로세스의 CPU 및 메모리 리소스의 초기 바인딩을 제공합니다. 이러한 사전 배포 컨설팅 서비스는 시스템에서 numad가 실행 가능한 파일로 또는 서비스로 실행되고 있는지에 대한 여부와 상관 없이 사용 가능합니다.
numad 사용 방법에 대한 자세한 내용은 A.14절. “numad” 또는 man 페이지에서 참조하십시오:
$ man numad

3.3.6. 스케줄링 정책 조정

Linux 스케줄러는 여러 스케줄링 정책을 통해 스레드 실행 위치 및 실행 기간을 지정할 수 있습니다. 스케줄링 정책은 일반 정책과 실시간 정책이라는 두 가지 주요 범주로 나뉘어 집니다. 일반 정책은 일반적인 우선 순위 작업에 사용되며 실시간 정책은 인터럽트없이 완료해야 하는 시간적 제약이 있는 작업에 사용됩니다.
실시간 스레드는 지정된 타임 슬라이스에 영향을 받지 않습니다. 이 스레드는 차단, 종료, 자체 중단 또는 실행할 준비가 된 보다 높은 우선 순위를 갖는 스레드로 대체될 때 까지 실행됩니다. 우선 순위가 가장 낮은 실시간 스레드는 일반 정책 스레드 보다 먼저 스케줄링됩니다.

3.3.6.1. 스케줄링 정책

3.3.6.1.1. SCHED_FIFO를 사용한 정적 우선 순위 스케줄링
SCHED_FIFO (정적 우선 순위 스케줄링이라고도 함)는 실시간 정책으로 각 스레드에 고정된 우선 순위를 지정합니다. 이러한 정책을 통해 관리자는 이벤트 응답 시간을 개선하고 대기 시간을 감소시킬 수 있으므로 오랜 기간 동안 실행하지 않는 시간적 제약이 있는 작업의 경우 사용 권장됩니다.
SCHED_FIFO를 사용하고 있을 때 스케줄러는 우선 순위에서 모든 SCHED_FIFO 스레드 목록을 스캔하고 실행 준비된 가장 높은 우선 순위의 스레드를 스케줄링합니다. SCHED_FIFO 스레드의 우선 순위는 1에서 99로 지정할 수 있으며 99가 가장 높은 우선순위가 됩니다. Red Hat은 낮은 우선 순위 번호에서 시작하고 대시 시간 문제가 확인되는 경우에만 우선 순위를 증가시킬 것을 권장합니다.

주의

실시간 스레드는 타임 슬라이스에 영향을 받지 않기 때문에 Red Hat은 우선 순위를 99로 설정할 것을 권장하지 않습니다. 이러한 우선 순위로 설정하면 마이그레이션 및 워치독 스레드와 동일한 우선 순위로 프로세스를 배치하게 됩니다. 스레드가 연산 루프로 들어가 차단되면 스레드 실행을 할 수 없게 됩니다. 단일 프로세스 시스템은 이러한 경우 결국 중단됩니다.
관리자는 SCHED_FIFO 대역폭을 제한하여 실시간 애플리케이션 프로그래머가 프로세서를 독점하는 실시간 작업을 시작하지 않도록 할 수 있습니다.
/proc/sys/kernel/sched_rt_period_us
이 매개 변수는 프로세서 대역폭의 100 %로 간주되는 시간을 마이크로 초 단위로 지정합니다. 기본값은 1000000 μs, 또는 1 초입니다.
/proc/sys/kernel/sched_rt_runtime_us
이 매개 변수는 실시간 스레드 실행에 할당된 시간을 마이크로 초 단위로 지정합니다. 기본값은 950000 μs, 또는 0.95 초입니다.
3.3.6.1.2. SCHED_RR을 사용한 라운드 로빈 방식의 우선 순위 스케줄링
SCHED_RRSCHED_FIFO의 라운드 로빈 변형입니다. 이 정책은 여러 스레드를 동일한 우선 순위로 실행해야 할 경우 유용합니다.
SCHED_FIFO와 같이 SCHED_RR은 각 스레드에 고정된 우선 순위를 지정하는 실시간 정책입니다. 스케줄러는 우선 순위에 있는 모든 SCHED_RR 스레드 목록을 스캔하고 실행 준비된 가장 우선 순위가 높은 스레드를 스케줄링합니다. 하지만 SCHED_FIFO와는 다르게 동일한 우선 순위를 갖는 스레드는 특정 타임 슬라이스 내에서 라운드 로빈 방식으로 스케줄링됩니다.
이러한 타임 슬라이스 값을 sched_rr_timeslice_ms 커널 매개 변수 (/proc/sys/kernel/sched_rr_timeslice_ms)를 사용하여 밀리초로 설정할 수 있습니다. 가장 작은 값은 1 밀리 초입니다.
3.3.6.1.3. SCHED_OTHER를 사용한 일반적인 스케줄링
SCHED_OTHER는 Red Hat Enterprise Linux 7에서 기본 스케줄링 정책입니다. 이러한 정책은 CFS (Completely Fair Scheduler)를 사용하여 이러한 정책에 스케줄링된 모든 스레드에 공정한 프로세서 액세스를 제공합니다. 이 정책은 시간이 지남에 따라 보다 더 효율적인 스케줄링을 가능하게 하므로 대량의 스레드가 있거나 데이터 처리량이 중요한 경우 아주 유용합니다.
이 정책을 사용하면 스케줄러는 각 프로세스 스레드의 niceness 값에 따라 동적 우선 순위 목록을 생성합니다. 관리자는 프로세스의 niceness 값을 변경할 수 있지만 스케줄러의 동적 우선 순위 목록을 직접 변경할 수 없습니다.
niceness 프로세스를 변경하는 방법에 대한 보다 자세한 내용은 http://access.redhat.com/site/documentation/Red_Hat_Enterprise_Linux/에 있는 Red Hat Enterprise Linux 7 Deployment Guide에서 참조하십시오.

3.3.6.2. CPU 분리

isolcpus 부트 매개 변수를 사용하여 스케줄러에서 여러 CPU를 분리할 수 있습니다. 이를 통해 스케줄러가 CPU에 있는 사용자 영역 스레드를 스케줄링하지 못하게 합니다.
CPU가 분리되면 CPU 친화도 시스템 호출 또는 numactl 명령을 사용하여 분리된 CPU에 수동으로 프로세스를 할당해야 합니다.
시스템에 3 번째 및 6 번째에서 8 번째 CPU로 분리시키려면 다음을 커널 명령행에 추가합니다:
isolcpus=2,5-7
Tuna 도구를 사용하여 CPU를 분리할 수 있습니다. Tuna를 사용하여 부팅 때에만 아니라 언제든지 CPU를 분리할 수 있습니다. 하지만 이러한 분리 방법은 isolcpus 매개 변수를 사용하는 경우와는 조금 다르기 때문에 isolcpus를 통한 성능 향상은 기대하기 어렵습니다. 이 도구에 대한 보다 자세한 내용은 3.3.8절. “Tuna를 사용하여 CPU, 스레드, 인터럽트 친화도 설정 ”에서 참조하십시오.

3.3.7. 인터럽트 친화도 설정

인터럽트 요청에 있는 관련 친화도 속성 smp_affinity는 인터럽트 요청을 처리하는 프로세서를 지정합니다. 애플리케이션 성능을 향상시키려면 인터럽트 친화도 및 프로세스 친화도를 동일한 프로세 또는 동일한 코어에 있는 프로세서에 지정합니다. 이를 통해 지정된 인터럽트 및 애플리케이션 스레드는 캐시 라인을 공유할 수 있습니다.
특정 인터럽트 요청의 인터럽트 친화도 값은 해당 /proc/irq/irq_number/smp_affinity 파일에 저장됩니다. smp_affinity는 시스템에서 모든 프로세서를 표시하는 16 진수 비트 마스크로 저장됩니다. 기본값은 f이며 이는 인터럽트 요청이 시스템에 있는 모든 프로세서에서 처리될 수 있음을 의미합니다. 이 값을 1로 설정하면 프로세서 0만이 인터럽트를 처리할 수 있음을 의미합니다.
32 이상의 프로세서가 있는 시스템에서 32 비트 그룹에 smp_affinity 값을 구분하여 설정해야 합니다. 예를 들어 64 프로세서 시스템의 첫 번째 32 프로세서에만 인터럽트 요청을 처리하고자 할 경우 다음을 실행합니다:
# echo 0xffffffff,00000000 > /proc/irq/IRQ_NUMBER/smp_affinity
다른 방법으로 BIOS가 NUMA 토폴로지를 내보낼 경우 irqbalance 서비스는 하드웨어 요청 서비스에 로컬이 되는 노드에서 인터럽트 요청을 처리하는데 이러한 정보를 사용할 수 있습니다. irqbalance에 대한 보다 자세한 내용은 A.1절. “irqbalance”에서 참조하십시오.

참고

인터럽트 스티어링을 지원하는 시스템에서 인터럽트 요청의 smp_affinity를 수정하여 하드웨어를 설정하고 인터럽트를 특정 프로세서에서 실행하는 결정을 커널 개입없이 하드웨어 수준에서 수행할 수 있습니다. 인터럽트 스티어링에 대한 보다 자세한 내용은 6장. 네트워킹 에서 참조하십시오.

3.3.8. Tuna를 사용하여 CPU, 스레드, 인터럽트 친화도 설정

Tuna는 CPU, 스레드, 인터럽트 친화도를 관리하고 엔티티 유형에 대한 다양한 동작을 제공합니다. Tuna 기능에 대한 전체 목록은 A.2절. “Tuna”에서 확인하십시오.
지정된 여러 CPU에서 모든 스레드를 분리하려면 다음 명령을 실행합니다. 여기서 CPUs는 분리하고자 하는 CPU 번호로 변경합니다.
# tuna --cpus CPUs --isolate
특정 스레드를 실행할 수 있는 CPU 목록에 특정 CPU를 포함시키려면 다음 명령을 실행합니다. 여기서 CPUs는 포함시키고자 하는 CPU 번호로 변경합니다.
# tuna --cpus CPUs --include
특정 CPU에 인터럽트 요청을 옮기려면 다음 명령을 실행합니다. 여기서 CPU를 CPU 번호로 변경하고 IRQs를 옮기고자 하는 인터럽트 요청을 쉼표로 구분하여 변경합니다.
# tuna --irqs IRQs --cpus CPU --move
다른 방법으로 다음 명령을 사용하여 sfc1* 패턴의 모든 인터럽트 요청을 검색할 수 있습니다.
# tuna -q sfc1* -c7 -m -x
스레드 정책과 우선 순위를 변경하려면 다음 명령을 실행합니다. 여기서 thread는 변경하고자 하는 스레드로 변경하고 policy는 스레드에 적용할 정책 이름으로 변경하며 level은 0 (가장 낮은 우선 순위)에서 99 (가장 높은 우선 순위) 까지의 정수로 변경합니다.
# tuna --threads thread --priority policy:level