Real-Time group scheduling
0. WARNING
이러한 설정을 만지작거리면 시스템이 불안정해질 수 있으며, 노브는 루트만 해당되며 루트가 자신의 작업을 알고 있다고 가정합니다.
가장 주목할 만한 것:
- sched_rt_period_us의 매우 작은 값은 사용 가능한 hrtimer 해상도 또는 예산 새로 고침 자체를 처리하는 데 걸리는 시간보다 기간이 작을 경우 불안정한 시스템을 초래할 수 있습니다.
- sched_rt_runtime_us의 매우 작은 값은 런타임이 너무 작으면 시스템이 전진하는 데 어려움이 있을 때 불안정한 시스템을 초래할 수 있습니다(참고: 마이그레이션 스레드와 kstopmachine은 둘 다 실시간 프로세스입니다).
1. Overview
1.1 The problem
실시간 스케줄링은 결정론에 관한 것으로, 그룹은 일정한 대역폭(예: CPU 시간)의 양에 의존할 수 있어야 합니다. 여러 그룹의 실시간 작업을 스케줄링하려면 각 그룹에 사용 가능한 CPU 시간의 고정된 부분이 할당되어야 합니다. 최소한의 보장이 없으면 실시간 그룹은 당연히 부족합니다. 퍼지 상한은 의존할 수 없으므로 아무 소용이 없습니다. 고정된 부분만 있으면 됩니다.
1.2 The solution
CPU 시간은 주어진 시간 동안 얼마나 많은 시간을 실행하는 데 쓸 수 있는지 지정하는 방법으로 나누어집니다. 우리는 다른 실시간 그룹이 사용할 수 없게 될 각 실시간 그룹에 대해 이 "실행 시간"을 할당합니다.
실시간 그룹에 할당되지 않은 모든 시간은 일반 우선순위 태스크(SCHED_OTHER)를 실행하는 데 사용됩니다. 사용되지 않은 할당된 실행 시간도 SCHED_OTHER에 의해 선택됩니다.
예를 들어 프레임 고정 실시간 렌더러는 초당 25프레임을 전달해야 하며, 이를 통해 프레임당 0.04초의 주기를 얻을 수 있습니다. 이제 프레임 고정 실시간 렌더러는 또한 일부 음악을 재생하고 입력에 응답해야 하며, 이로 인해 그래픽 전용 CPU 시간의 약 80%가 남게 됩니다. 그러면 이 그룹에 0.8 * 0.04s = 0.032s의 실행 시간을 부여할 수 있습니다.
이렇게 하면 그래픽 그룹은 0.04s의 주기를 가지며 실행 시간은 0.032s로 제한됩니다. 이제 오디오 스레드가 0.005s마다 DMA 버퍼를 다시 채워야 하지만 그렇게 하는데 약 3%의 CPU 시간만 필요하다면 0.03 * 0.005s = 0.00015s로 할 수 있습니다. 따라서 이 그룹은 0.005s의 주기와 실행 시간 0.00015s로 예약할 수 있습니다.
남은 CPU 시간은 사용자 입력 및 기타 작업에 사용됩니다. 실시간 작업은 작업 수행에 필요한 CPU 시간을 명시적으로 할당했기 때문에 그래픽이나 오디오의 버퍼 언더런을 제거할 수 있습니다.
참고: 위 예제는 아직 완전히 구현되지 않았습니다. 아직 EDF 스케줄러가 부족하여 비균일한 주기를 사용할 수 없습니다.
2. The Interface
2.1 System wide settings
시스템 전체 설정은 /proc 가상 파일 시스템에서 구성됩니다:
/proc/sys/kernel/sched_rt_period_us:
CPU 대역폭 100%에 해당하는 스케줄링 기간입니다.
/proc/sys/kernel/sched_rt_runtime_us:
실시간 스케줄링이 사용할 수 있는 시간에 대한 전역 제한입니다. 이는 실시간 태스크에 대해 period_us에서 할당된 시간을 나타내기 때문에 항상 period_us보다 작거나 동일합니다. CONFIG_RT_GROUP_SCHED가 활성화되지 않았더라도 이는 실시간 프로세스로 예약된 시간을 제한합니다. CONFIG_RT_GROUP_SCHED=y의 경우 모든 실시간 그룹이 사용할 수 있는 총 대역폭을 나타냅니다.
인터페이스가 s32이기 때문에 시간은 우리에게 지정됩니다. 이것은 1us에서 약 35분의 작동 범위를 제공합니다.
sched_rt_period_us는 1에서 INT_MAX까지의 값을 가져옵니다.
sched_rt_ runtime_us는 -1에서 sched_rt_period_us까지의 값을 가져옵니다.
실행 시간 -1은 runtime == period, 즉 제한 없음을 지정합니다.
2.2 Default behaviour
sched_rt_period_us (1000000 또는 1s) 및 sched_rt_runtime_us (950000 또는 0.95s)의 기본값입니다. 이를 통해 SCHED_OTHER (RT 이외의 태스크)에서 사용할 수 있는 0.05s가 제공됩니다. 이러한 기본값은 실행 중인 실시간 태스크가 시스템을 잠그지 않고 복구하는 데 약간의 시간을 남기기 위해 선택되었습니다. 런타임을 -1로 설정하면 이전 동작을 되돌릴 수 있습니다.
기본적으로 모든 대역폭이 루트 그룹에 할당되고 새 그룹은 /proc/sys/kernel/sched_rt_period_us에서 주기를 가지며 실행 시간은 0입니다. 대역폭을 다른 그룹에 할당하려면 루트 그룹의 대역폭을 줄이고 차이의 일부 또는 전부를 다른 그룹에 할당합니다.
실시간 그룹 스케줄링은 그룹이 실시간 작업을 수락하기 전에 전체 CPU 대역폭의 일부를 할당해야 한다는 것을 의미합니다. 따라서 사용자가 실시간 우선 순위로 프로세스를 실행할 수 있는 권한이 있어도 루트가 아닌 다른 사용자로서 실시간 작업을 실행할 수 없습니다!
2.3 Basis for grouping tasks
CONFIG_RT_GROUP_SCHED를 활성화하면 실제 CPU 대역폭을 태스크 그룹에 명시적으로 할당할 수 있습니다.
이것은 cgroup 가상 파일 시스템과 "<cgroup>/cpu.rt_runtime_us"를 사용하여 각 제어 그룹에 예약된 CPU 시간을 제어합니다.
제어 그룹 작업에 대한 자세한 내용은 제어 그룹도 참조해야 합니다.
그룹 설정은 구성을 예약 가능하게 유지하기 위해 다음 제한을 기준으로 확인됩니다:
Sum_{i} runtime_{i}
현재는 다음과 같이 단순화할 수 있습니다(그러나 향후 계획 참조):
Sum_{i} runtime_{i} <= global_runtime
3. Future plans
각 그룹(<cgroup>/cpu.rt_period_us")의 스케줄링 기간도 설정 가능하도록 하는 작업이 진행 중입니다.
기간에 대한 제약은 부분군의 기간이 부모의 기간보다 작거나 같아야 한다는 것입니다. 하지만 현실적으로 이 기간은 마감일에 맞춰 일정을 잡지 않으면 기아에 빠지기 쉽기 때문에 그다지 유용하지는 않습니다.
두 형제 그룹 A와 B를 생각해 보십시오. 둘 다 대역폭이 50%이지만 A의 주기는 B의 두 배입니다.
- group A: period=100000us, runtime=50000us
- this runs for 0.05s once every 0.1s
- group B: period= 50000us, runtime=25000us
- this runs for 0.025s twice every 0.1s (or once every 0.05 sec).
즉, 현재 A의 (1) 루프는 B의 전체 기간 동안 실행되며 B의 작업을 전체 기간 동안 중단할 수 있습니다(우선 순위가 낮다고 가정할 때).
다음 프로젝트는 SCHED_EDF(Early Datiday First Scheduling)로 리눅스 커널에 완전한 데드라인 스케줄링을 제공합니다. 위 그룹들을 데드라인 스케줄링하고 기간의 끝을 데드라인으로 처리하면 두 그룹 모두 할당된 시간을 확보할 수 있습니다.
SCHED_EDF를 구현하면 완료하는 데 시간이 걸릴 수 있습니다. 현재 리눅스 PI 인프라는 제한된 정적 우선순위 수준 0~99에 맞춰 설계되어 있으므로 우선순위 상속이 가장 큰 문제입니다. 마감 일정을 지정하면 (우선순위는 마감 델타(데드라인 - 지금)와 반비례하므로) 마감 상속을 수행해야 합니다.
이것은 전체 PI 기계를 재작업해야 한다는 것을 의미합니다. 그리고 이것은 우리가 가지고 있는 가장 복잡한 코드 중 하나입니다.