일관되지 않은 최고 CPU 사용량

일관되지 않은 최고 CPU 사용량

우리가 개발 중인 일부 하드웨어에서 매우 이상한 동작을 경험하고 있습니다. 내 설정은 듀얼 코어 iMX6 CPU에 SMP 및 PREEMPT RT를 갖춘 Linux 4.9.87로 구성되어 있습니다.

이 설정에서 실행되는 애플리케이션은 SCHED_FIFO 스케줄링 정책을 사용하여 실행되는 3개의 스레드로 구성됩니다. 우선순위 수준 10, 20, 30은 CPU0에 바인딩됩니다. 네 번째 스레드는 동일한 예약 정책과 우선 순위 90을 사용하여 CPU1에서 실행됩니다.

내가 겪는 행동은 다음과 같습니다.

프로세스를 모니터링할 때 top은 CPU0이 97.4%의 시간 동안 유휴 상태임을 보여줍니다. 해당 코어에서 실행 중인 가장 바쁜 스레드에는 8.4%가 필요합니다. 이는 5.8%의 차이입니다.

다음은 Solaris 모드의 CPU별 및 스레드별 사용량을 보여주는 최상위 출력입니다.

top - 13:36:41 up  1:21,  2 users,  load average: 0.52, 0.39, 0.26
Threads: 128 total,   2 running, 126 sleeping,   0 stopped,   0 zombie
%Cpu0  :  1.3 us,  1.3 sy,  0.0 ni, 97.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   509348 total,   438164 free,    46888 used,    24296 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   450196 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND      
  798 root     -91   0   37740  35656   3676 S  9.3  7.0   0:04.47 myprog       
  797 root     -31   0   37740  35656   3676 S  8.4  7.0   0:04.43 myprog       
  241 root     -51   0       0      0      0 R  4.7  0.0   3:55.11 irq/26-2014+ 
  242 root      rt   0       0      0      0 S  3.1  0.0   2:33.62 spi3         
  796 root     -21   0   37740  35656   3676 S  1.9  7.0   0:01.14 myprog       
  794 root      20   0    2848   1892   1536 R  1.0  0.4   0:01.04 top          
  795 root     -11   0   37740  35656   3676 S  0.3  7.0   0:00.37 myprog       
    3 root      20   0       0      0      0 S  0.2  0.0   0:09.14 ksoftirqd/0  
   10 root      20   0       0      0      0 S  0.2  0.0   0:00.14 rcuc/0       
  545 root     -51   0       0      0      0 S  0.2  0.0   0:03.74 irq/36-can0  
  595 root      20   0    1700    880    824 S  0.2  0.2   0:00.99 rngd         
    1 root      20   0    1712   1168   1104 S  0.0  0.2   0:01.34 init         
    2 root      20   0       0      0      0 S  0.0  0.0   0:00.01 kthreadd     
    4 root      -2   0       0      0      0 S  0.0  0.0   0:07.99 ktimersoftd+ 
    5 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0  
    6 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0H 

스레드당 사용량은 올바른 것으로 보이지만 총계가 CPU당 사용량과 일치하지 않습니다.

htop이는 동일한 동작을 나타내기 때문에 top 자체에는 문제가 되지 않습니다 . /proc/stat의 값을 사용하여 읽고 계산해도 top 및 htop에서 표시된 것과 동일한 결과가 생성됩니다.

PID 798clock_nanosleep()을 사용하여 500마이크로초마다 우선순위가 가장 높은 스레드( )를 예약합니다 . 10밀리초마다 스레드를 예약하려고 하면 전체 CPU 사용량이 크게 줄어들지만 숫자는 여전히 일치하지 않고 동일한 동작을 나타냅니다. 이는 현재 구성된 낮은 주기 시간으로 인해 문제가 발생하지 않음을 나타냅니다.

라이브 패치 없이 스톡 배포 커널에서 애플리케이션을 실행하면 비슷한 결과가 나타납니다. 또한 문제가 라이브 패치에 있지 않음을 나타냅니다.

단일 코어 CPU에서 애플리케이션을 다시 실행하려고 하면 비슷한 결과가 나오며, 이는 멀티 코어 설정 실행으로 인해 문제가 발생하지 않았음을 나타냅니다.

  • 이전에 비슷한 경험을 한 사람이 있습니까?
  • 각 스레드의 CPU 사용량 합계가 합계와 일치하지 않는 이유를 아는 사람이 있습니까?
  • 총 CPU 사용량에 대한 신뢰할 수 있는 값을 어떻게 얻을 수 있나요?

미리 감사드립니다!

편집하다

이 문제를 내부적으로 더 논의한 결과, 이것이 과소샘플링 문제일 수 있다고 의심됩니다.

커널이 주기적으로 CPU 상태(사용자 공간, 커널 공간 또는 유휴)를 샘플링한다고 가정하면 더 많은 샘플이 수집되고 스레드가 덜 빈번하게 예약될수록 결과가 더 정확해집니다.

또한 샘플이 타이머 틱에서 수집되었다고 가정하고 커널의 CONFIG_HZ를 100Hz에서 1000Hz로 늘리고 100ms마다 스레드를 예약하도록 애플리케이션을 수정했습니다. 약 50%의 로드 평균을 달성하기 위해 카운터 변수를 증가시키는 루프를 입력하면 일부 CPU 시간이 낭비됩니다. 그 후, 로드 평균을 약 50%로 유지하기 위해 지연 루프를 조정하면서 스레드의 스케줄링 간격을 계속 줄였습니다.

테스트 결과 스레드가 50ms와 100ms로 예약되면 top에서 보고한 값이 올바른 것으로 나타났습니다.

스케줄링 간격을 10밀리초로 설정하면 2~4%의 차이가 나타나기 시작합니다. 간격을 5ms로 더 줄이면 차이는 12%로 늘어납니다. 마지막으로 간격을 2ms로 더 줄이면 상단 출력이 완전히 엉망이 되어 애플리케이션이 CPU 시간의 33%를 사용하는 동안 상단이 100% 유휴 시간을 표시하게 됩니다.

이는 문제가 과소샘플링으로 인해 발생했다는 의심을 확증해 주는 것 같습니다.

누구든지 이것을 확인할 수 있습니까? 커널이 CPU 사용량을 어떻게 측정하는지 아는 사람이 있나요?

답변1

표시된 숫자는추정, 대부분은 샘플링을 통해 얻어집니다. 일반적인 개요에는 좋지만 소수점 이하로 세부적으로 관리하는 데는 쓸모가 없습니다. "CPU 사용량"을 측정하는 것은 기본적으로 쓸모가 없습니다. 시스템에 과부하가 걸리면 100%에 가까운 값을 얻을 수 있습니다(작업이 거의 수행되지 않음). 워크로드 성능을 기반으로 전반적인 목표를 정의하고 필요에 따라 측정하고 조정합니다.

CONFIG_HZ를 늘리면 커널 오버헤드가 증가합니다(그러나 대화형 응답이 더 좋아질 수도 있음). 기본값은 "일반적인" 작업 부하에 대한 합리적인 절충안입니다. 다른 값이 사용 사례에 더 적합하다는 확실한 증거가 있는 경우 해당 값을 변경하세요.

관련 정보