멀티스레드 애플리케이션을 사용하여 멀티코어 시스템의 로드 평균 이해

멀티스레드 애플리케이션을 사용하여 멀티코어 시스템의 로드 평균 이해

우리 시스템의 로드 평균에 이상한 상황이 있습니다. 하루 종일 유휴 상태인 ZAG라는 애플리케이션을 실행하고 있습니다. 하지만 매 80분마다 5~15분 동안 지속되는 일종의 폭발적인 활동이 있습니다. 버스트 시 부하 평균은 60, 70, 80, 100 이상으로 올라갈 수 있습니다. 흥미로운 사실: 이러한 높은 버스트 동안 우리는 htop의 CPU 사용률이 CPU당 10-20%만 표시되는 것을 볼 수 있습니다. 또한 내가 작성한 스크립트는 유휴 시간 동안 CPU 사용량이 낮다는 것을 보여줍니다.

ps -eTo psr,user,pid,tid,cputime,class,rtprio,ni,pri,pcpu,stat,wchan:14,args | grep  ZAG | awk '{sum += $10} END{print sum;}'

535.0을 반환할 수 있습니다. 즉, ZAG 응용 프로그램의 모든 CPU 백분율을 추가하면 CPU의 535.0%, 즉 시스템의 모든 CPU 사용률이 5.35/32 또는 16.7%가 반환됩니다. 간단히 말해서, CPU 중 어느 것도 100%에 가깝게 실행되지 않았는데, 이는 대부분의 유휴 시간 동안 우리가 예상했던 것입니다.

이 경우 결과는 약 538.0%... 조금 더 높을 뿐입니다. 또한 아래와 같이 실행 대기열에 더 많은 스레드가 표시됩니다.

while true; do ps -eTo psr,user,pid,tid,cputime,class,rtprio,ni,pri,pcpu,stat,wchan:14,args | grep ZAG | grep ' Rl' | wc -l; sleep 0.5; done

결과적으로 CPU 사용률이 약간 올라가고 더 많은 스레드가 실행됩니다. 하지만 부하 평균이 치솟아도 CPU 사용량은 늘어나지 않는 것 같습니다. 디스크 I/O 또는 네트워크 I/O와 관련하여 항상 거의 발생하지 않았습니다. 이번 사태 동안 SAR 데이터는 크게 증가하지 않았습니다. 메모리 활용도는 증가하지 않으며, 시스템의 전체 프로세스 약 1700개 중 프로세스 수도 약간 증가할 수 있지만 그게 전부입니다. 이 시간 동안 cron에서는 아무 일도 일어나지 않습니다. htop 또는 top 출력은 현재 일부 CPU 사용률(주로 사용자 CPU)이 실제로 발생하고 있음을 보여줍니다(top에서는 시스템 CPU가 5% 미만이라고 보고함). 따라서 데이터를 기다리는 것이 아무것도 없는 것 같습니다.

나는 /proc/interrupts에서 특이한 점을 발견하지 못했습니다. 일정 조정 중단이 심한 것 같으나 짝수 및 홀수 NUMA 노드를 포함해 6개의 코어를 확인해보니 프로세서당 초당 1400 정도에서 안정적인 것으로 보였습니다.

이는 하이퍼스레딩이 켜진 16코어 머신(E5-2667 v4 프로세서)입니다. 여기에는 각각 ps -ef 및 ps -eTf로 표시되는 36개의 ZAG 프로세스와 729개의 ZAG Therad가 있습니다.

그래서 궁금해졌습니다. 내 CPU 사용률은 왜 그렇게 낮고 로드 평균은 그렇게 높은 걸까요? 36개의 ZAG 프로세스 중 700개가 넘는 스레드가 있고 그 중 하나가 sched_yield()여전히 실행 대기열에 있지만 CPU를 축적하지 않기 때문일까요? 아니면 sched_yield()더 이상 실행할 수 없지만 중단할 수 없는 상태에 있습니까(아래 참조)?

브렌든 그레그에 따르면https://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html, "부하 평균이 Linux에서 처음 나타났을 때는 다른 운영 체제와 마찬가지로 CPU 수요를 반영했습니다. 그러나 나중에 Linux에서는 실행 가능한 작업뿐만 아니라 중단할 수 없는 상태(TASK_UNINTERRUPTIBLE 또는 nr_uninterruptible)의 작업도 포함하도록 변경했습니다. 이 상태는 다음에서 사용됩니다. 차단된 작업 및 디스크 I/O의 일부 잠금을 포함하여 신호 중단을 피하려는 코드 경로... 그러나 Linux 로드 평균은 설명할 수 있는 정도까지 디스크 I/O보다 높지 않은 경우가 있습니다. 1993년에는 존재하지 않았던 TASK_UNINTERRUPTIBLE을 사용하는 새로운 코드 경로 때문인 것으로 추측됩니다. Linux 0.99.14에는 TASK_UNINTERRUPTIBLE 또는 TASK_SWAPPING(나중에 스왑 상태가 제거됨)을 직접 설정하는 13개의 코드 경로가 있습니다. Linux 4.12에는 일부 잠금 프리미티브를 포함하여 TASK_UNINTERRUPTIBLE을 설정하는 거의 400개의 코드 경로가 있으며 이러한 코드 경로 중 하나는 로드 평균에 포함되어서는 안 됩니다..."

답변1

찾은 것 같아요.

질문은 간단합니다.

높은 로드 평균(즉, 실행 대기열에 많은 항목)과 낮은 CPU 사용률을 설명하는 방법은 무엇입니까?

나는 그 답이 sched_yield() 시스템 호출에 있다고 믿습니다. 스레드가 다른 스레드에 양보하는 경우 해당 스레드는 CPU의 실행 대기열에 남아 있지만 많은 작업을 수행하지 못할 수 있습니다.

바라보다https://books.google.com/books?id=9yIEji1UheIC&pg=PA370&lpg=PA370&dq=sched_yield+reli[…]&hl=en&sa=X&ved=2ahUKEwimrNvwqrL1AhWIhOAKHQLyBDcQ6AF6BAgCE ​​AM

링크가 사라지는 경우: Bovet 및 Cesati의 2판 "Linux 커널 이해" 370페이지입니다.

"sched_yield() 시스템 호출을 사용하면 프로세스가 일시 중단되지 않고 자발적으로 CPU를 포기할 수 있습니다. 프로세스는 task_running 상태로 유지되지만 스케줄러는 이를 실행 대기열 목록의 끝에 배치합니다. 이렇게 하면 다른 프로세스가 동일한 동적 우선순위를 가진 프로세스는 실행될 기회가 있습니다. 이 호출은 주로 sched_fifo 프로세스에서 사용됩니다."

여기서 그들은 "프로세스"를 언급하지만 맨 페이지에는 있습니다.https://man7.org/linux/man-pages/man2/sched_yield.2.html설명에는 "sched_yield()로 인해 호출 스레드가 CPU를 포기하게 됩니다. 스레드는 정적 우선순위로 인해 대기열의 끝으로 이동되고 새 스레드가 실행되기 시작합니다."라고 나와 있습니다.

따라서 개념적으로 우리는 동일한 동작을 가집니다. 즉, 실행 대기열 목록의 끝에 도달합니다. 우리가 본 내용에 따르면 스레드가 task_running 상태를 유지하는 것이 합리적입니다.

관련 정보