C 휘발성 변수와 캐시 메모리
캐시는 프로세서에 투명하게 캐시 하드웨어에 의해 제어되므로 C 프로그램에서 휘발성 변수를 사용할 경우 내 프로그램이 지정된 실제 메모리 주소에서 매번 데이터를 읽지만 캐시는 읽을 수 없다는 것이 어떻게 보장됩니까?
제가 알기로는..
Volatile 키워드는 컴파일러에게 변수 참조가 최적화되어서는 안 되며 코드에 프로그래밍된 대로 읽혀야 한다고 말합니다.
캐시는 캐시 하드웨어에 의해 투명하게 제어되므로 프로세서가 주소를 발행할 때 데이터가 캐시에서 오는 것인지 메모리에서 오는 것인지 알 수 없습니다.
그러면 메모리 주소를 매번 읽어야 한다는 요구사항이 있는 경우 캐시에서 참조되지 않고 필요한 주소에서 참조되는지 확인하려면 어떻게 해야 합니까?
어찌된 일인지 이 두 가지 개념은 잘 맞지 않습니다.어떻게 이루어졌는지 명확히 해주시기 바랍니다.
(문제 분석에 필요한 경우 캐시에 기록 정책이 있다고 상상해 보십시오.)
고마워요, 마이크로커널 :)
펌웨어 개발자입니다.이것은 임베디드 프로그래밍의 표준 문제이며, 많은 (심지어 경험이 풍부한) 개발자들을 괴롭힙니다.
하드웨어 레지스터에 액세스하려고 하면 시간에 따라 레지스터 값이 변경될 수 있습니다(인터럽트 상태, 타이머, GPIO 표시 등).
그volatile
키워드는 솔루션의 일부일 뿐이며, 많은 경우 필요하지 않을 수도 있습니다.이것은 변수가 사용될 때마다 (컴파일러에 의해 최적화되거나 여러 용도에 걸쳐 프로세서 레지스터에 저장되는 것이 아니라) 메모리에서 다시 읽히도록 하지만, 읽혀지는 "메모리"가 실제 하드웨어 레지스터인지 캐시된 위치인지 여부는 코드에 의해 알 수 없고 영향을 받지 않습니다.volatile
키워드.만약 당신의 기능이 레지스터를 한 번만 읽는 것이라면 아마도 당신은 그만둘 수 있을 것입니다.volatile
, 하지만 일반적으로 나는 대부분의 하드웨어 레지스터는 다음과 같이 정의되어야 한다고 제안할 것입니다.volatile
.
더 큰 문제는 캐싱과 캐시 일관성입니다.여기서 가장 쉬운 방법은 레지스터가 캐시되지 않은 주소 공간에 있는지 확인하는 것입니다.즉, 레지스터에 액세스할 때마다 메모리를 캐시하지 않고 실제 하드웨어 레지스터를 읽고 쓸 수 있습니다.더 복잡하지만 잠재적으로 더 나은 성능을 발휘할 수 있는 방법은 캐시된 주소 공간을 사용하고 코드가 이와 같은 특정 상황에 대해 캐시 업데이트를 수동으로 강제하도록 하는 것입니다.두 접근 방식 모두에서, 이를 달성하는 방법은 아키텍처에 의존적이며 질문의 범위를 벗어납니다.여기에는 MTRR(x86의 경우), MMU, 페이지 테이블 수정 등이 포함될 수 있습니다.
도움이 되길 바랍니다.제가 놓친 부분이 있다면 말씀해주시면 답변을 확대하겠습니다.
당신의 질문에는 당신의 잘못된 생각이 있습니다.
Volatile
설명한 것처럼 키워드가 캐시와 관련이 없습니다.
가 인 경우volatile
변수에 대해 지정되며, 이 변수가 프로그램의 다른 부분에서 예기치 않게 변경될 수 있으므로 컴파일러가 특정 최적화를 수행하지 않도록 힌트를 줍니다.
여기서 의미하는 것은 컴파일러가 레지스터에 이미 로드된 값을 재사용하지 말고 레지스터에 저장된 값과 동일한 값이 보장되지 않으므로 다시 메모리에 액세스해야 한다는 것입니다.
캐시 메모리와 관련된 나머지 부분은 프로그래머와 직접적인 관련이 없습니다.
즉, CPU의 캐시 메모리를 RAM과 동기화하는 것은 완전히 다른 주제입니다.
제 제안은 가상 메모리 관리자가 캐시되지 않은 페이지로 표시하는 것입니다.
Windows에서는 호출 시 설정을 통해 이 작업을 수행합니다.
SSE 2 지침은 다소 다른 목적을 위해_mm_stream_xyz
캐시 오염을 방지하기 위한 지침이 여기 당신의 경우에는 적용되지 않는다고 생각합니다.
어느 경우든 C에서 원하는 작업을 수행할 수 있는 휴대용 방법은 없습니다. OS 기능을 사용해야 합니다.
위키피디아에는 x86 계열의 CPU에 적용되는 MTRR(Memory Type Range Registers)에 대한 꽤 좋은 기사가 있습니다.
요약하자면, Pentium Pro Intel(및 AMD 복사)부터 메모리 범위에 캐시되지 않은, 쓰기, 쓰기 결합, 쓰기 방지 또는 쓰기-백 속성을 설정할 수 있는 MTR 레지스터가 있었습니다.
펜티엄 III부터 시작하지만 제가 알기로는 64비트 프로세서에서만 유용한 MTRR을 존중하지만 각 메모리 페이지에 대해 메모리 유형을 설정할 수 있는 페이지 속성 테이블에 의해 무시될 수 있습니다.
제가 알고 있는 MTRR의 주요 용도는 그래픽스 램입니다.쓰기 결합으로 표시하는 것이 훨씬 더 효율적입니다.이를 통해 캐시는 쓰기를 저장하고 모든 메모리 쓰기 순서 규칙을 완화하여 그래픽 카드에 매우 빠른 속도로 쓰기를 허용합니다.
그러나 사용자의 목적을 위해 캐시되지 않은 또는 쓰기 방식의 MTRR 또는 PAT 설정을 원할 것입니다.
당신이 말했듯이 캐시는 프로그래머에게 투명합니다.시스템은 주소를 통해 개체에 액세스할 경우 마지막으로 기록된 값을 항상 볼 수 있도록 보장합니다.캐시에 오래된 값이 있을 경우 발생할 수 있는 "유일한" 문제는 런타임 페널티입니다.
volatile
CPU와 메모리 간의 캐시 문제 없이 필요할 때마다 데이터를 읽을 수 있도록 보장합니다.그러나 캐시된 데이터가 아니라 메모리에서 실제 데이터를 읽어야 하는 경우에는 두 가지 옵션이 있습니다.
- 해당 데이터가 캐시되지 않는 보드를 만듭니다.일부 I/O 장치를 주소로 지정하면 이미 해당될 수 있습니다.
- 캐시를 바이패스하는 특정 CPU 명령을 사용합니다.가능한 SEU 오류를 활성화하기 위해 메모리를 스크러빙해야 할 때 사용됩니다.
두 번째 옵션의 세부 사항은 OS 및/또는 CPU에 따라 달라집니다.
_Uncached 키워드를 사용하면 MQX와 같은 임베디드 OS에서 도움이 될 수 있습니다.
#define MEM_READ(addr) (*((volatile _Uncached unsigned int *)(addr)))
#define MEM_WRITE(addr,data) (*((volatile _Uncached unsigned int *)(addr)) = data)
언급URL : https://stackoverflow.com/questions/7872175/c-volatile-variables-and-cache-memory
'bestsource' 카테고리의 다른 글
요소/문서에 첨부된 자바스크립트 이벤트 청취자/처리자가 있는지 확인하는 방법? (0) | 2023.10.01 |
---|---|
openstdin, stdout, stderr 방향 전환을 제어하는 방법? (0) | 2023.10.01 |
C에서 전역 변수는 항상 0으로 초기화됩니까? (0) | 2023.10.01 |
a = 0, b = a++, c = a++의 정의가 C에 정의된 동작을 가지고 있습니까? (0) | 2023.10.01 |
front end or back end의 api 오류 메시지 국제화? (0) | 2023.10.01 |