cache 관련 조언을 받고 싶어요
이런 주제를 어떤 검색어 키워드로 잡아야 할지 몰라 고민하다 이곳까지 오게 되었습니다.
환경
멀티코어 mcu
문의 내용
data cache flush(clean + invalidate)를 얼마나 오래해도 괜찮은가?
상황
멀티 코어에서 공용으로 사용하는 램 영역이 있습니다.
core 0에서 램 영역의 data + flag를 수정하면 core 1에서 read 해서 뭔가를 진행하는 방식 입니다.
while(core0.flag == 0) { __NOP(); } memcpy(core1.buffer, core0.buffer, 1024);
문제는 core0.flag가 volatile로 선언되어있긴 한데 테스트 해보니 ram 영역이라 그런지 cache에 영향을 받습니다(레지스터 주소는 volatile로 선언하면 직업 읽던데 ram 영역은 다른가봅니다)
그래서 해당 flag를 읽는 동안 계속 반복적으로 cache flush를 해야 할 것 같습니다.
정해진 시간은 없으나 10ms가 될 수도 있을 것 같습니다.
과연 이게 현명한 짓일지 궁금합니다.
차라리 해당 램 영역을 cache가 동작하지 않도록 하는게 전체적인 퍼포먼스 입장에서 나을 것 같기도 하구요
많은 의견 부탁드립니다.
기타 volatile 관련 내용 참고
core 0,1 이 동시에 사용하는 부분은 volatile uint32_t data[1024] 대충 이런 식으로 되어있습니다.
그 중 data[0]은 flag, data[1 ~ 40] 은 data 등으로 역할을 나눠 사용하고 있습니다.
배열이 volatile 로 잡혀있어 매번 직접 ram으로부터 값을 읽을 줄 알았으나 테스트 해보니 data cache에 영향을 받습니다.
우선 하시고 싶은 일이 "core 0에서 램 영역의
우선 하시고 싶은 일이 "core 0에서 램 영역의 data + flag를 수정하면 core 1에서 read 해서 뭔가를 진행하는 것" 이라면 cache와 별 연관이 없습니다.
IPC (Inter-Process Communication) 쪽으로 찾아 보셔야 할 것 같고, 세마포, 시그널, Spin-lock, 메시지 큐 등으로 할 수가 있는(그리고 권장되는) 부분입니다.
volatile은 그 부분에 대해서 컴파일러의 최적화를 하지 않겠다는 지시어입니다. volatile을 쓰더라도 CPU에 cache가 활성화되어 있다면 ram에 대한 접근은 cache를 통하게 될 것 같습니다. cache 자체가 프로그래머가 신경쓰지 않아도 ram의 내용과 같은 값을 갖도록 해줍니다. 보통(임베디드 프로그래머 포함) 유저는 전혀 cache의 동작에 대해서 신경쓸 필요가 없습니다.
보통 어떤 시스템에서 가장 효율적인 IPC 메커니즘을 찾는 것이 큰 일인데 지금 질문하신 내용이 그런 쪽에 포함될 것 같네요.
"ram" 을 "ddr" 과 다른 개념으로 글을
"ram" 을 "ddr" 과 다른 개념으로 글을 쓰셨다면, "ram" 에 cache 를 사용하는건 의미 없을듯 보입니다. 어차피 SoC 안쪽에 있는 sram 일테니 software 입장에서 cache 와 접근속도가 비슷할 듯 보입니다.
"ram" 부분을 non-cached 로 mapping 해서 사용하는건 어떨지... ioremap 등과 같은걸로..
...
제가 embedded 쪽은 경험이 없어서 잘 모릅니다만, x86 기준으로 얘기하자면 "코어 1에서 쓰고 코어 2에서 읽는 것"은 이미 내부적으로 CPU가 캐시 관리를 하기 때문에, 캐시의 문제는 아닙니다.
다만 문제가 되는 것은 읽고 쓰는 순서가 서로 달라질 수 있다는 것입니다. 코어 1에서 (1) "데이터를 쓰고" 그 다음 (2) "데이터가 완료되었다고 flag를 쓴다"라고 해도, 코어 2에서 읽을 때 이 순서로 읽는다는 보장이 없습니다. 즉 코어 2에서는 분명히 "완료"라는 flag 값을 읽었는데 그 다음에 실제로 데이터를 읽어보면 예전 값을 읽을 수 있습니다.
좀 복잡하지만, 자세한 것은 "memory consistency"로 찾아보면 됩니다. 혹시 해당 CPU의 instruction 중에 memory barrier (혹은 fence) instruction이 있나 찾아보세요.
* 그런데, 위에 라스코니 님이 말씀하신 것처럼, 정말 속도가 크리티컬한 게 아니면 그냥 signal, mutex, pipe, condition variable, 기타 등등으로 처리하는 쪽이, 이런 류의 문제 신경 안 써도 되고 훨씬 편합니다.
multi core 초창기에 이거 때문에 프로젝트
multi core 초창기에 이거 때문에 프로젝트 엎어질 위기가 자주 있었죠.
cache coherence 라고 하는데 이걸 키워드로 찾아보세요.
아마 non cached mapping address
아마 non cached mapping address area가 있을 겁니다. 캐시가 신경쓰이면 해당 주소 영역을 사용하세요.
----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라
댓글 달기