Thursday, September 26, 2019

저비용 비선점형 멀티태스킹, Part 3 - 스케쥴링과 처리량 밸런싱

  • 아래 링크의 글을 구글번역 + 다듬었습니다.
  • 이 시리즈의 이전 1 부와 2 부에서는 마이크로 컨트롤러 기반 임베디드 시스템을 더 작은 구성 요소로 분류 한 다음 이들 구성 요소가 서로 작동하여 시스템 기능을 수행하는 방법을 살펴 보았습니다. 상태 머신 기반 멀티 태스킹 시스템에 대한 태스크 설계 및 인터 태스킹 통신이 논의되었습니다.
  • 이 기사 시리즈의이 부분에서는 모든 하위 시스템을 하나로 묶고 강력한 작업 전환 및 CPU 처리량 균형을 유지하기위한 스케줄링 방법에 대해 설명합니다.
  • 간단한 방법
    • 스케줄링 작업의 가장 간단한 형태는 무한 루프입니다. 이 기사 시리즈의 첫 번째 부분에서 설명한 것처럼 모든 작업은 올바른 실행 순서로 호출됩니다. 목록의 끝에 있으면 맨 위로 이동합니다.
    • 물론이 시스템은 작업 실행에 대한 주기성이 엄격하지 않으며 MP3 플레이어와 같은 복잡한 시스템에는 적합하지 않을 수 있습니다.
    • 이 시스템에서도 작업 실행 시간을 신중하게 측정하고 유휴 작업을 추가하여 다음 밀리 초로 반올림함으로써 타이밍 감각을 도입 할 수 있습니다. 예를 들어, Task1에서 Task 4까지는 4.1ms를 합한 것으로 가정합니다. 이 경우 루프를 5ms로 반올림하기 위해 0.9ms 동안 실행되도록 IdleTask ()에 지연 루틴을 작성할 수 있습니다. 이 체계는 각 작업이 정해진 시간이 걸리거나 타이밍 제약 조건이 엄격하지 않은 간단한 시스템에서 작동합니다. 이 보다 더 복잡한 스케줄링을 필요로 하지 않는 수많은 시스템이 있습니다.
    • 느긋하게 실행해야하는 작업에는 내부 카운터가 있고 일부 호출을 건너 뛰어 처리량을 관리 할 수 ​​있습니다.
    • 여기서 task X는 짝수 번째의 호출에서만 실행되도록 설정되어 있습니다. 마찬가지로 다른 작업을 홀수 번째의 호출에서 실행되도록 설정할 수도 있습니다. 우리는 원하는 CPU 처리량의 균형을 달성하기 위해 두 개 이상의 작업을 엇갈리게하여 조금 더 멋진 경험을 할 수 있습니다.
  • 결정론적 스케줄러
    • MP3 플레이어와 같은보다 복잡한 시스템은 정확한 타이머 틱과 정확한 주기로 작업을 실행해야합니다. 이는 스케줄러에 타이머 인터럽트를 추가하여 쉽게 수행 할 수 있습니다. 타이머는 정해진 간격으로 인터럽트를 제공하도록 구성되어 있습니다.
    • 전역 변수 "TimerTick"은 현재 틱을 갖고 있습니다. 타이머 틱 간격의 경험 법칙은 5ms 또는 7.8125ms입니다 (7.8125 X 2^7 = 1000ms = 1 초, 경우에 따라 유용함). 이 틱 변수는 인터럽트에 의해 비동기 적으로 증가합니다.
    • 스케줄러의 무한 루프는 현재 타이머 틱에 스케줄된 모든 task을 호출 한 후 다음 틱이 도착할 때까지 기다립니다. 여기서 작업 설계의 가장 중요한 기준은 "틱 내에서 완료"입니다.
    • 모든 작업은 각 틱마다 예약 된 모든 작업이 실행되고 다음 틱이 도착하기 전에 스케줄러로 제어권을 되 돌리는 방식으로 설계 및 예약되어야합니다. 작업은 이 "틱 간격"의 다양한 배수로 예약되며 CPU가 고르게 로드되도록 항상 엇갈리게 배치됩니다. 실행하는 데 시간이 오래 걸리는 더 큰 작업은 엇갈리게 분할하여 실행해야합니다.
    • 이 체계를 구현하기 위해 주기 및 오프셋 번호, 연관된 작업 포인터 (C의 함수 포인터)를 가진 데이터 구조가 준비되어야 합니다. 주기는 작업을 실행해야하는 타이머 틱의 배수를 정의하고 오프셋 번호는 실행을 지연시키는 틱 수를 정의합니다.
    • 5ms 틱 시스템에서 {USBTask, 2, 0}을 입력하면 USBTask가 엇갈 리지 않고 10ms마다 (즉, 0ms, 10ms, 20ms 등) 실행해야합니다. {TouchSenseTask, 2, 1}은 10ms의 주기성을 갖지만 1 틱으로 엇갈리게되므로 TouchSenseTask는 5ms, 15ms, 25ms 등에서 실행됩니다. {SystemMonitor, 4, 3} 항목은 SystemMonitor를 15ms, 35ms (20 + 15), 55ms, 75ms 등으로 예약합니다.
    • 마이크로 컨트롤러가 작동하는 속도와 비교하여 사람의 상호 작용은 상당히 느리기 때문에 ServiceUserInput 작업은 매우 느긋하게 예약 할 수 있습니다. ServiceUserInput은 50ms마다 예약되면 {ServiceUserInput, 10, 1}로 나타낼 수 있습니다. (예 : 5ms, 55ms, 105ms) 작업이 올바르게 정의되면 CPU의 부하를 고르게 하는 것이 매우 쉽다는 것을 알 수 있습니다. 작업 테이블은 플래시 메모리에 배치되어 소중한 RAM을 절약합니다.
    • 방금 디자인 한 스케줄러의 의사 코드는 다음과 같습니다.
    • 아래의 그림 1은 5ms 타이머 틱에서 위 작업 테이블의 실행 타임 라인을 보여줍니다. 단순성과 시각화를 위해 DisplayDriver는 호출 당 0.5ms, USBTask는 1.5ms, TouchSenseTask 및 ServiceUserInput는 각각 1ms를 가정합니다.
    • 물론이 숫자는 일반적인 디자인 번호가 아닙니다. 타임 라인의 빈 공간은 각 타이머 틱에서 CPU가 유휴 상태 인 시간을 나타냅니다. 아래 그림 1은 USB MP3 플레이어의 나머지 서브 시스템을 통합하기 위해 여전히 상당한 양의 처리량이 남아 있음을 보여줍니다. 파일 시스템 및 디스플레이 관리자 task은 이제이 타이밍 그래프에서 볼 수있는 유휴 시간으로 예약되어야합니다.
    • 그림 1 : 작업을 부분적으로 통합 한 후 USB MP3 플레이어의 CPU 타임 라인
    • 작업에 우선 순위를 지정하는 것을 검토해 봅시다. 두 작업이 차례로 실행되어야한다고 가정 해보십시오. Task-Description (작업 설명) 테이블에서 하나를 다른 아래에 배치 할 수 있습니다. 이것이 "틱 내 완료"기준을 위반하는 경우, 동일한 기간으로 배치해야하지만 우선 순위가 낮은 작업을 한 번의 틱만큼 엇갈리게 배치해야합니다.
  • 처리량 관리
    • 마이크로 컨트롤러와 관련된 처리량은 CPU가 1 초 안에 실행할 수있는 명령의 양으로 정의 될 수 있습니다. 마이크로 컨트롤러의 처리량은 제한된 자원이며 종종 비용과 관련이 있습니다. 지금까지 멀티 태스킹 시스템에서 CPU 오버 헤드가 거의없는 소프트웨어를 구축했습니다. 이것은 지능적인 작업 디자인과 스마트 스케줄링으로 이루어졌습니다.
    • 우리 시스템에서는 새로운 서브 시스템이나 소프트웨어 스택을 쉽게 연결하고 기존 소프트웨어를 업그레이드로 쉽게 교체 할 수 있습니다. 그러나 이러한 변경으로 인해 RTOS 시스템에도 공통적 인 문제가 발생합니다. 소프트웨어가 변경되면 실행 시간이 변경되고 "틱 내 종료"기준을 위반할 수 있습니다. 따라서 시스템 디버깅에 도움이되는 몇 가지 진단 방법을 추가하는 것이 좋습니다.
    • 편리한 툴은 각 스케줄러 루프 전후에 타이머를 기록하여 틱 간격을 초과 한 정확한 틱을 캡처 할 수 있도록하는 것입니다. 이 시차는 작업 목록에서 가장 큰주기와 동일한 크기의 배열로 저장됩니다. 최대주기가 30 틱이면 로깅 배열에 30 개의 요소가 필요합니다. TimerTick이이 수에 도달하면 로그 배열이 처음부터 채워집니다. 변경된 스케줄러의 의사 코드는 다음과 같습니다.
    • DEBUG는 디버깅 중에 DEBUG 기호가 사용될 때만 코드를 포함하는 C 언어 지시문입니다. 오버 슈트하는 작업을 포착하고 수정하면 로깅을 비활성화 할 수 있습니다. 이러한 방식으로 RAM 및 CPU 사용량은 영향을받지 않습니다. 시스템이 한계를 넘어가더라도 이 로깅 방법을 사용하여 남은 CPU 처리량을 파악하고 업그레이드를 계획 할 수 있습니다.
    • 어떤때에는 모든 작업이 완료되기 전에 타이머 틱이 도착하는 것이 괜찮을 때도 있습니다. 다음 틱에 로드가 거의없는 것으로 확인되고 해당 틱에서 시간이 중요한 작업이 실행되지 않는 경우 틱 사이의 간격을 초과해도됩니다. 이 경우 스케줄러는 틱를 기다리지 않기 때문에 단순히 틱를 따라 잡습니다.
  • 몇 가지 팁과 요령
    • 시스템의 견고성, 결정론적 특성 및 저비용 기능은 신중한 작업 설계 및 스마트 스케줄링으로 달성됩니다. 그러나 소프트웨어를 코딩하기 전에 신중하게 계획해야하기 때문에 이 멀티 태스킹 시스템을 처음 구현하는 동안 쉽게 실수할 수 있습니다. 다음은 이 과정에에 도움이되는 몇 가지 팁입니다.
      • 1. 모든 것을 문서화하십시오. 상태 시스템의 수가 증가함에 따라, 특히 상호 작용이 증가함에 따라 길을 잃어버리기 쉽습니다. 시간을 들여 설계 문서를 작성하고 모든 작업과 그 종속성을 서로 나열하십시오. 코드를 자세히 기록하십시오. 모든 공유 변수의 목적과 범위를 문서화해야합니다. 올바른 코딩 표준을 따르는 것은 항상 가독성을 높이는 데 도움이되며 업그레이드 또는 버그 수정을 위해 코드를 다시 볼 때 도움이됩니다.
      • 2. 어떤 형태의 진단을 구현하십시오. 양산 또는 디버그 시간 전용 기능에 내장 될 수 있습니다. 서브 시스템을 변경하거나 새 기능을 추가하면 시스템 타이밍이 필연적으로 변경됩니다. 작업의 균형을 다시 조정해야 할 수도 있습니다. 타이밍 진단을 구현하는 것이 편리합니다.
      • 3. 길을 잃었을 때 두 가지 작업으로 시작하여 시스템을 다시 구축하십시오. 모든 작업을 시스템에 처음 통합 할 때 지옥이 펼쳐질 수 있습니다. 한 번에 한 task씩 인내심을 갖고 통합하십시오. 이런 식으로 CPU와 함께 도망가는 통합 작업을 해결할 수있는 범인 작업을 찾을 수 있습니다.
      • 4. WaitForTimerTick () 루틴에 들어갈 때 마이크로 컨트롤러를 절전, Doze 또는 유휴 모드와 같은 저전력 상태로 전환 할 수 있는지 확인하고 타이머 인터럽트에서 깨어나게 합니다. 마이크로 컨트롤러가 상당한 시간 동안 유휴 상태인 경우 시스템의 전력 소비가 줄어 듭니다. 일부 저전력 마이크로 컨트롤러에서는 슬립 전류가 매우 낮아서 시스템이 배터리에서 더 오래 실행될 수 있습니다.
      • 5. 상태 머신 스위치 케이스에는 자연수를 사용하십시오. 컴파일러는 case번호가 자연수일 때 스위치 케이스를 최적화하여 CPU 명령의 "decrease and check for zero and jump"로 바꿔줍니다. 다른 방법으로 점프하는 것보다 명령이 훨씬 적게 필요하므로 처리량이 줄어 듭니다.
  • 결론
    • 이 3 부 기사 시리즈에 제시된 상태 머신을 사용한 저비용 협업 멀티 태스킹 방법은 기능이 많고 리소스가 적은 시스템에 효과적입니다.
    • 성공을 위해서는 세심한 계획과 디자인이 필요하지만, 일단 방법을 마스터하면 새로운 프로젝트와 기존 프로젝트의 확장으로 쉽게 확장됩니다.
    • 이 방법은 메모리 사용량이 제한된 저비용 8 비트 및 16 비트 시스템에서 멀티 태스킹이 필요한 경우에 적합합니다.
    • 이 방법은보다 복잡한 시스템에도 적용 할 수 있지만 상태 머신을 구현하는 엔지니어링 노력은 상용 RTOS를 사용하는 것보다 훨씬 더 큰 것으로 입증 될 수 있습니다. 프로젝트 수명주기 초기에 결정을 내려야합니다. 비용을 줄이려면 상태 머신을 사용하는 것이 좋습니다.

No comments: