커널 3.2-rt로 다운그레이드된 Debian 8(jessie)을 실행하는 컴퓨터가 있습니다. 이는 실시간 우선순위(SCHED_RR)로 설정된 애플리케이션을 실행하고, 1ms마다 깨어나서 일부 처리를 수행하고, 100ms마다 다른 PC에 직렬 메시지를 보내는 것입니다. 이것은 매우 잘 작동합니다. (머신은 실제로 기본 서비스 이외의 다른 것을 실행하지 않습니다. 특히 데스크톱이 아닙니다.)
커널 4.9-rt를 사용하여 Debian 9(stretch)로 업그레이드하려고 할 때 몇 가지 문제에 부딪혔습니다. 가장 큰 문제 중 하나는 시계 안정성이었습니다. 처음에는 제대로 작동하는 것처럼 보였지만 부팅한 직후에 다음과 같은 결과를 얻었습니다.
clocksource: timekeeping watchdog on CPU0: Marking clocksource 'tsc' as unstable because the skew is too large:
clocksource: 'acpi_pm' wd_now: 74c6dd wd_last: 8dd916 mask: ffffff
clocksource: 'tsc' cs_now: 119ac91c7b1 cs_last: 1158a25441d mask: ffffffffffffffff
clocksource: Switched to clocksource acpi_pm
처음 이런 일이 발생하면 위의 메시지는 "hpet"으로의 전환을 보고합니다. 이 전환이 발생한 후 시스템의 모든 타이밍이 불안정한 것처럼 보입니다. clock_gettime(CLOCK_MONOTONIC, ...)
타이밍에 사용된 코드는 이제 매 4ms마다라고 보고합니다. 1ms 깨어나면 직렬 메시지는 실제로 100밀리초마다가 아니라 200밀리초마다 전송되지만 직렬 메시지 내의 타임스탬프는 66밀리초마다 전송되는 것으로 간주함을 나타냅니다. (이 중 일부는 실제 밀리초 대신 깨우기 틱을 계산할 수 있습니다.)
BIOS에서 HPET를 비활성화하려고 시도했는데, 이로 인해 위에 표시된 오류가 발생했고 위의 내용이 기록될 때까지 부팅 시 다시 정상적으로 실행되었습니다. 이 시점에서는 대부분 정상적으로 실행되는 것처럼 보였지만 때로는 일부 타이머가 음의 지속 시간을 보고했습니다.
또 다른 주요 문제는 1밀리초마다 실행되는 처리 코드가 Jessie에서는 실행하는 데 약 200us가 걸리지만 Stretch에서는 뚜렷한 이유 없이 실행되는 데 900us가 걸린다는 것입니다. 실행 perf record
해 보았는데 대부분의 시간(샘플의 40%)이 sys_clock_gettime
.
두 경우 모두 하드웨어는 동일합니다: AMD64 기반 i7-7700K CPU를 탑재한 Supermicro X11SSQ 마더보드입니다. CPU 조절은 BIOS에서 비활성화되어 있지만 다음 constant_tsc
과 같이 보고됩니다 nonstop_tsc
.
if clock_gettime() < wakeup then sched_yield()
애플리케이션이 처리 코드를 예약하기 위해 바쁜 대기 루프(간단한 의사 코드) 를 실행하고 있다는 점이 흥미로울 수 있습니다 .
실험으로 나는 그것을 sleep( clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wakeup)
)으로 변경했고 적어도 지금까지는 시계 소스 오류가 다시 발생하지 않았으며 (다른 시계와 달리) 잘 작동하는 것처럼 보이는 tsc 시계를 여전히 사용합니다.
그러나 웨이크업 지터는 이제 10배 더 나빠졌습니다. 수면 중에는 700-1200us(SD 36us), 바쁜 대기 중에는 890-1120us(SD 2us)입니다.
추가 실험으로 이를 SCHED_DEADLINE(단일 사용 sched_yield()
)으로 변경해 보았지만 이는 clock_nanosleep과 동일한 동작을 합니다.
Jessie와 Stretch 사이(또는 3.2와 4.9 사이에서) 이 동작이 왜 변경되었는지 아시나요? 시스템 시계를 크게 손상시키지 않고 낮은 지터 대기를 달성할 수 있는 더 좋은 방법이 있습니까?
답변1
GRUB_CMDLINE_LINUX_DEFAULT 라인 에 /etc/default/grub
"notsc Clocksource=acpi_pm"을 추가하세요.
내 현재 상황은 다음과 같습니다
GRUB_CMDLINE_LINUX_DEFAULT="quiet notsc clocksource=acpi_pm"
그런 다음 다음을 수행하십시오.sudo update-grub
사용 가능한 다른 클럭 소스를 설정할 수 있습니다.
cat /sys/devices/system/clocksource/clocksource0/available_clocksource