2024 한국 리눅스 커널 개발자 모임
한국 리눅스 커널 개발자 모임 2024년 발표 정리입니다.
https://kernel-dev-ko.github.io/
RT-Linux
Linux feature를 그대로 이용할 수 있는 Real Time System
가장 관심있었던 주제였다. Linux의 Preemt RT와 Linux 기반 RTOS 혹은 Embedded Linux의 차이에 대해서 자세히는 몰랐던 터라 비슷한 것으로만 알고 있었는데 이번 기회에 자세히 알 수 있게 되어 좋았다. 현재 RT-Linux는 기존 Linux에서 분기되어 개발되고 있으며 선점형 Real Time을 구현하는 커널이라고 볼 수 있다. RT-Linux는 Linux의 기능을 그대로 사용할 수 있으며, Real Time System을 구현할 수 있다.
실제로 리눅스 커널이 올라갈 수 있는 하드웨어에 사용하면서도, RT 기능이 필요한 경우에 사용한다. 일반적인 리눅스 응용 프로그램을 사용할 수 있는 것이 최대 장점이다. 이를테면 Systemd로 동작하는 서비스들을 그대로 이용할 수 있다는 점이다. 이 부분이 내 업무와 관련하여 가장 매력적으로 느껴졌다. 이를테면 드론 같은 시스템에서 사용한다고 한다.
Real Time에서 job은 결정론적(deterministic) 이야어하는데, 이는 CPU 공유 및 외부 인터럽트의 영향을 예측 가능해야한다는 것을 의미한다. 최대한 선점지점을 최적화 하여 Sleep이 너무 빠르지도 느리지도 않게 하고, Latency를 적절하게 하여 Deadline miss를 방지해야한다. 사용자 공간에서는 이를 잘 활용할 수 있지만 커널 모드에서는 실행되는 코드가 전부 선점 가능하지가 않다. 때문에 커널 모드에서 실행되는 모든 코드를 선점 가능하도록 만드는 것이 RT-Linux의 핵심 목표라고 볼 수 있다.
먼저, Deadline miss 피하는 것이 목표이다. 이를 달성하기 위해서 선점이 불가능한 구간을 최소화 하는 것이 중요한데, 다음과 같은 방법으로 이를 달성할 수 있다.
- Spin lock을 가능한 사용하지 않는다. 기존의 Spin lock구간도 선점 가능하도록 sleep하는 mutex/semaphore로 변경한다.
- IRQ handler를 Thread에서 동작시킨다. 커널의 Bottom Half 종류에는 kthread를 사용하는 방식이 있는데, 이는 User Task로서 동작하게 된다.
- 우선순위 역전을 방지하기 위해 Priority Inheritance Protocol을 사용한다.
- local_bh_disable()를 사용하지 않는다. 이는 Latency를 높일 수 있기 때문이다.
그 다음으로 다음 내용들을 고려하여 최적화 할 수 있다.
- RT scheduler 사용. SCHED_FIFO, SCHED_RR, SCHED_DEADLINE 중 하나를 사용한다. 이 때 Priority 99는 사용하지 말아야하는데, 이는 watchdog 등 반드시 우선되어야하는 kernel 동작을 방해할 수 있기 때문이다.
- CPU Affinity와 IRQ affinity를 사용하여 지연을 최소화한다. Memory 공유로 인한 지연을 방지하기 위함이다.
- tick interrupt를 최소화 한다. CONFIG_NO_HZ_FULL을 사용할 수 있는데, 이는 RUNABLE 상태의 task가 없을 때 tick interrupt를 중지시키는 방식이다.
- RCU callback의 CPU offloading을 막는다.
- Pagefault를 최소화한다.
- 모든 스레드는 startup time에 생성한다.
- Dynamic Allocation을 최소화 한다. 최대한 메모리는 startup time에 할당한다.
- Pagefault를 유발하는 syscall을 최소화한다.
- Non-RT task가 Pagefault를 유발하지 않도록 유의한다.
- RT mutex를 사용한다. 우선순위 상속을 보장한다.
- Sleep 없는 무한루프를 사용하지 않는다.
- IPC는 POSIX IPC를 사용한다. 공유 메모리 등은 우선순위를 보장하지 않기 때문이다.
- Signal을 지양한다.
- I/O는 사용하지 않는다. 특히 VGA 콘솔은 최악
- 커널 정보 수집. statisitcs, trace 등 디버깅 관련 기능을 사용하지 않는다.
- Task 수를 최소화 한다. 가능하면 user thread, user level batch 등을 사용한다.
- VMstat 갱신 주기를 늘린다.
Real Time의 평가는 위 문서에서 제시한 방법으로 측정하면 좋을 것으로 보인다.
Lazy Unmap Flush (LUF)
Pagefault, TLB invalidate/flush에 대한 작업을 최적화하는 방법에 대한 내용이었다. 대규모 ML/DL 모델을 학습하고 평가하는 경우 파라미터와 데이터에 대해서 많은 메모리를 사용하게 된다. 때문에 TLB invalidation이 자주 발생하고 TLB flush를 요구하여 interrupt와 TLB miss의 비용이 크게 증가한다. 이를 해결하기 위해서 LUF를 구현하여 이를 해결하는 연구에 대한 발표였다. 정확히 이야기하면 공유 메모리에 대한 TLB Shootdown이 성능을 저하시킨다는 문제를 해결하기 위한 방법이었다.
학습 모델이 바뀌지 않는 한 TLB invalidation과 flush 요청을 줄일 수 없기 때문에 Intterupt cost를
줄이고 TLB miss를 줄이는 방법으로 이를 해결한다. 그 방법은 unmap
작업을 lazy하게 처리하는 것이다.
이를 위한 자세한 내용은 추가 요약할 필요는 없어 보여 생략한다. 결국, Reader가 전체 접근의 94%를
차지하고, Reader의 TLB miss의 처리를 미뤄 재사용률을 증가시킨다는 메커니즘을 사용하는 것이다.
Android kernel Longevity
iOS 대비 Android 커널 보증기간에 대한 내용이었는데 흥미로운 내용이 많아 정리(?)한다.
기존에는 OS 버전을 8년이나 보증해주는 iOS와 달리 Android(Pixel)는 기껏해야 3년 정도만 보증해주었다. 기타 제조사들이 만드는 홍미, 갤럭시 등은 제조사가 유지보수하는 식이었다. 하지만 공식 지원하는 버전 이상으로 패치를 제공하는 것은 힘들기 때문에 보증기간은 Android에서 보증하는 기간하고 동일하다고 봐야한다.
이는 어느정도 Android 배포판 빌드과정의 어려움에서 비롯되기도 하였는데, iOS와 달리 하드웨어의 지원이 정말 많은 제조사 제품들을 고려해야하기 때문이다. 그런데 Bazel 방식으로 빌드하게 되면서 문제가 해결되었다.
구글 측이 유지보수하는 Linux Kernel 패치와 Android Kernel과 제조사 specific한 부분을 분리하여 별도로 빌드할 수 있는 시스템이 구축되면서 Android에서 보증하는 기간도 늘어날 수 있었기 때문이다.
댓글남기기