캐시로 인한 실행 시간의 변동 없이 코드가 실행되도록 하려면 어떻게 해야 합니까?
문제
엄격한 실시간 제약이 있는 임베디드 애플리케이션(32비트 프로세서에서 C로 작성)에서 중요한 코드(특히 인터럽트)의 실행 시간은 일정해야 합니다.
시간 변동성이 발생하지 않도록 어떻게 보장합니까? 실행 중 특히 프로세서의 캐시(L1, L2 또는 L3)로 인해 코드가 어떻게 됩니까?
우리는 다음과 같은 이유로 캐시 동작에 관심이 있습니다. 거대한 실행 속도에 미치는 영향(때로는 100:1 대 100:1 이상)RAM에 액세스).특정 프로세서 아키텍처로 인해 발생하는 가변성은 캐시 크기에 미치지 못합니다.
해결책
하드웨어를 손에 넣을 수 있거나 할 수 있는 사람과 협력할 수 있다면 캐시를 끌 수 있습니다.일부 CPU에는 전원 대신(또는 그 반대) 접지에 연결하면 모든 내부 캐시가 비활성화되는 핀이 있습니다.이는 예측 가능성을 제공하지만 속도는 제공하지 않습니다!
그렇지 않으면 소프트웨어 코드의 특정 위치에 의도적으로 캐시를 정크로 채우도록 작성될 수 있으므로 다음에 무슨 일이 일어나든 캐시 누락이 보장될 수 있습니다.올바르게 수행하면 예측 가능성이 생길 수 있으며 특정 장소에서만 수행할 수 있으므로 캐시를 완전히 비활성화하는 것보다 속도가 더 나을 수도 있습니다.
마지막으로, 속도가 중요하다면 고대 8비트 CPU를 프로그래밍하던 시절처럼 소프트웨어와 데이터를 신중하게 설계하고 L1 캐시에 모두 들어갈 수 있을 만큼 작게 유지하세요.나는 요즘 온보드 캐시가 지난 10년 동안 미니컴퓨터에 있던 모든 RAM보다 얼마나 큰지 항상 놀랍습니다.그러나 이것은 힘든 작업이 될 것이며 영리함이 필요합니다.행운을 빌어요!
다른 팁
두 가지 가능성:
캐시를 완전히 비활성화합니다.응용프로그램은 더 느리게 실행되지만 변동은 없습니다.
캐시에 코드를 미리 로드하고 "잠그십시오".대부분의 프로세서는 이를 수행하는 메커니즘을 제공합니다.
실시간 시스템을 염두에 두고 구축되지 않은 x86 프로세서 제품군을 언급하는 것 같으므로 지속적인 시간 실행에 대한 실제 보장은 없습니다. CPU가 조건부 점프를 잘못 예측할 때마다 플러시됩니다...)
이 답변은 비웃는 것처럼 들리겠지만, 다음과 같은 생각을 하도록 의도되었습니다.
코드를 한 번만 실행하세요.
내가 그렇게 말하는 이유는 너무 많은 것이 변수를 만들고 통제할 수 없을 수도 있기 때문입니다.그리고 시간에 대한 당신의 정의는 무엇입니까?운영 체제가 프로세스를 대기 대기열에 넣기로 결정했다고 가정합니다.
다음으로는 캐시 성능, 메모리 대기 시간, 디스크 I/O 등으로 인해 예측이 불가능합니다.이 모든 것은 한 가지로 요약됩니다.코드에서 사용할 수 있는 프로세서로 정보를 가져오는 데 시간이 걸리는 경우도 있습니다.코드 자체를 가져오거나 디코딩하는 데 걸리는 시간도 포함됩니다.
또한 귀하가 허용할 수 있는 차이는 어느 정도입니까?40밀리초라도 괜찮을 수도 있고, 10나노초라도 괜찮을 수도 있습니다.
응용 프로그램 도메인에 따라 분산을 마스킹하거나 숨길 수도 있습니다.컴퓨터 그래픽 사람들은 각 프레임을 렌더링하는 데 걸리는 시간의 차이를 숨기기 위해 수년간 오프 스크린 버퍼에 렌더링해 왔습니다.
기존 솔루션은 알려진 가변율 항목을 가능한 한 많이 제거합니다.파일을 RAM에 로드하고 캐시를 워밍업하여 IO를 방지하세요.
중요한 코드에서 모든 함수 호출을 '인라인'으로 만들고, 가지고 있는 변수의 수를 최소화하여 '레지스터' 유형을 갖도록 할 수 있습니다.이렇게 하면 프로그램의 실행 시간이 향상됩니다.(요즘 컴파일러는 'register' 태그를 무시하는 경향이 있으므로 특별한 방법으로 컴파일해야 할 수도 있습니다.)
나는 메모리에서 무언가를 로드하려고 할 때 페이지 폴트를 일으키지 않을 만큼 충분한 메모리가 있다고 가정합니다.페이지 폴트에는 많은 시간이 걸릴 수 있습니다.
또한 생성된 어셈블리 코드를 살펴보고 실행 코드를 변경할 수 있는 분기 및 메모리 명령이 많이 있는지 확인할 수도 있습니다.
코드 실행 중에 인터럽트가 발생하면 시간이 더 오래 걸립니다.인터럽트/예외가 활성화되어 있습니까?
메모리를 사전 할당하고 인터럽트가 캐시에 영향을 주지 않는지 확인합니다(불가능합니다. 맞음).
/앨런
복잡한 작업에 대한 최악의 런타임을 이해하고 타이머를 사용하십시오.