linux C 프로그래밍에서 캐쉬가 아닌 메모리에서 읽어오게 하는 방법.
글쓴이: trymp / 작성시간: 수, 2020/07/08 - 10:30오전
멀티쓰래드 프로그래밍에서 char *ptr 이라는 포인터가 있을때,
ptr 이 여러 쓰래드에서 갱신되고 읽을수가 있는데, lock API 나 volatile f같은 키워드를
사용하지 않고 레지스터가 아닌 메모리에서 읽어오고 싶습니다.
volatile 키워드를 쓰니 너무 여러군데서 warning 이 발생해서..ㅠㅠ
ptr 포인터 변수를 읽어올때 레지스터에서 읽어오는게 아니라 메모리에서 읽어오고
쓸때도 메모리에 항상 업데이트 할수 있는 방법을 찾고 있습니다.
알려주시면 감사하겠습니다.
Forums:
UNCACHED 옵션을 적용하면 될 것 같네요
궁금해하시는 부분을 리눅스 시스템 저수준 함수로 설정을 할 수 있을 지 의문입니다.
아마, 커널 공간에서 페이지 메모리를 UNCACHED 정책을 적용해 할당 받으면 될 것 같은데요.
아래 매크로 선언부를 참고하시면 좋겠습니다.
https://elixir.bootlin.com/linux/v4.19.30/source/arch/arm/mm/mmu.c
#define CPOLICY_UNCACHED 0
#define CPOLICY_BUFFERED 1
#define CPOLICY_WRITETHROUGH 2
#define CPOLICY_WRITEBACK 3
#define CPOLICY_WRITEALLOC 4
리눅스 커널의 캐시 정책에 대해서는 아래 링크의 내용을 참고하세요.
http://jake.dothome.co.kr/cache1/
(개인블로그)
http://rousalome.egloos.com
여러 쓰레드에서 갱신되고 있다면 캐쉬나
여러 쓰레드에서 갱신되고 있다면 캐쉬나 volatile의 문제가 아닙니다.
mutex를 걸고 사용하셔야 됩니다. 그런데 lock API를 쓰지 않고 읽어오고 싶다고 하셨는데... 솔직히 방법이 떠오르지 않네요.
굳이 하시겠다면 어셈블리 레벨로 접근하셔야 할겁니다.
굳이 하시겠다면 어셈블리 레벨로 접근하시면 됩니다. x86은 movnt가 있네요.
이런 명령 없으면 윗분이 말씀하신 no-cache type의 page를 생성해서 그곳에 변수 만들어 쓰거나, 쓴 직후 일일이 cache 동기화하는 명령을 실행하는거 외는 없습니다.
https://stackoverflow.com/questions/37889896/intel-instructions-for-access-to-memory-which-skips-cache
OS에서 제공하는 mutex, semaphone가 이들을 쓰기 편하게 만든겁니다. 어느 CPU든지 간에 똑같은 효과 내게요.
Written By the Black Knight of Destruction
ddr cache 의 문제가 아니라 컴파일러
ddr cache 의 문제가 아니라 컴파일러 옵티마이즈에 대한 변수의 register caching 이 아닌가요?
그렇다면, volatile 을 쓰는 수 밖에 없어보이는데..
register 대신 memory 이용을 하도록
register 대신 memory 이용을 하도록 컴파일러의 최적화 과정을 확실히 방해하고 싶다면 volatile 이 가장 확실합니다.
lockless 와는 약간 다른 얘기지만,
1. stdatomic 은 libc 혹은 libstdc++ 에 있습니다. https://en.cppreference.com/w/c/atomic
2. GCC 의 것은 https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
3. GCC 에서 Hyun 님이 언급하신 CPU 별 instrinsic 은 https://gcc.gnu.org/onlinedocs/gcc/Target-Builtins.html
만에 하나, 정말로 cache 를 쓰고 싶지 않다는 질문이라면 linux 에선,
open("/dev/mem", O_DSYNC|O_RDWR),
mmap(PROT_READ|PROT_WRITE, MAP_PRIVATE)
정도로 메모리 할당 받아서 변수를 보관하는 방법을 시도해 볼 수는 있습니다. https://elixir.bootlin.com/linux/v5.7.8/source/drivers/char/mem.c#L283
세상에...
멀티스레드 환경에서 thread간 data race가 발생할 수 있다면 정답은 atomic types입니다.
volatile를 그런 상황에서 쓰는 건 권장할 만한 일이 아니에요.
https://en.cppreference.com/w/c/language/atomic
https://en.cppreference.com/w/c/language/volatile
====
지금 귀하의 목표가 그저 컴파일러의 warning을 없애는 것인가요,
아니면 올바른 멀티스레드 프로그램을 만드는 것인가요?
댓글 달기