C/C++--프로 그래 밍 중인 메모리 장벽(Memory Barriers)(1)
OK,우선'메모리 장벽'이 무엇 인지,공식 적 인 표현 부터 살 펴 볼 수 있 습 니 다. http://www.kernel.org/doc/Documentation/memory-barriers.txt메모리 장벽 은 컴 파일 러 최적화 와 CPU 가 레지스터 와 cache 에 대한 사용 으로 인해 메모리 작업 이 제때에 반영 되 지 못 하기 때 문 입 니 다.예 를 들 어 cpu 가 기록 한 후에 읽 은 값 은 오래된 내용 일 수 있 습 니 다.예 를 들 어 하나의 변수 에 값 을 부여 한 다음'원자'처럼 보 이 는 동작 을 읽 습 니 다.메모리 에 ALU 계산 장치 가 없 기 때문에 메모리 에 계산 할 능력 이 없습니다.한편,CPU 는 일반적인 상황 에서 메모리(emmintrin.h 응용 예외)를 직접 읽 지 않 기 때문에 이 과정 은(컴 파일 러 최적화 후)로 볼 수 있 습 니 다.
메모리 데 이 터 를 cache 로 읽 기--> CPU 읽 기 cache/레지스터 --> CPU 계산 --> 결 과 를 cache/레지스터 에 기록 합 니 다. --> 메모리 에 데 이 터 를 다시 쓰기
컴 파 일 러 최적화 와 CPU 최적화 의 결과 로 메모리 의 시간 지연 이 CPU 보다 높 고 10ns 급 이기 때문에 읽 기와 쓰기 레지스터 를 통 해 최적화 되 는 이 유 를 물 을 수도 있다.이것 은 문제 가 될 수 있 습 니 다.cache 의 데이터 와 메모리 의 실제 데이터 가 일치 하지 않 습 니 다.다 중 스 레 드 상황 에서'더러 운 데이터'를 읽 거나 스 레 드 실행 결과 가 일치 하지 않 을 수 있 습 니 다.이것 이 바로 이른바'메모리 장벽'이다.
인터넷 에서 몇 편의 글 에서 언급 한 중의 코드 는 본인 이 다음 과 같은 유사 버 전 을 썼 다.
include
#include
#include
#include
// global variable
int flag=1;
void* wait(void *context){
while (flag) {
printf("continue
");
sleep(1);
}
}
void wakeup(){
flag=0;
}
int main(int argc, char *argv[])
{
pthread_t pid = 0;
pthread_create(&pid,NULL,wait,NULL);
sleep(3);
wakeup();
printf("Done
");
getchar();
}
책 에 따 르 면 flag 는 다른 스 레 드 에 의 해 의외로 수정 되 었 다 면.while 순환 은 컴 파일 러 에 의 해 최적화 되 고 컴 파일 러 는 wait 함수 에서 flag 를 수정 하지 않 은 것 을 발견 하기 때문에 flag 를 cache 하여 eax 레지스터 에 넣 습 니 다.메모리 에 있 는 flag 실체 가 수정 되면 eax 레지스터 가 감지 되 지 않 습 니 다.직접 해 보 았 습 니 다.최적화 와 Gcc O2 가 없 는 상황 에서 프로그램 이 정상적으로 순환 을 뛰 어 넘 었 습 니 다.cpu 나 Liux 새 커 널 이나 gcc 의 새로운 컴 파일 특성 때 문 일 수 있 습 니 다.(어떤 친구 가 알 고 있다 면 메 시 지 를 남 길 수 있 습 니 다)나중에 이 문 제 를 따라 갈 거 예요.발견 하면 붙 여 놓 을 게 요.
사실 gcc-S 를 통 해 어 셈 블 리 과정의 중간 어 셈 블 리 코드 를 보면 글 을 쓸 수 있 습 니 다.
wait:
.LFB46:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl flag(%rip), %edx
testl %edx, %edx
je .L4
.p2align 4,,10
.p2align 3
.L5:
movl $.LC0, %edi
call puts
movl $1, %edi
call sleep
movl flag(%rip), %eax
testl %eax, %eax
jne .L5
.L4:
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE46:
.size wait, .-wait
.p2align 4,,15
.globl wakeup
.type wakeup, @function
(저 는 큰 소 를 모 은 것 이 아 닙 니 다.틀 렸 습 니 다.폭격 하지 마 세 요.그 중에서 빨간색 을 표시 한 문 구 는 16~18 줄 에서 알 수 있 습 니 다.순환 은 eax 레지스터 가 0 인지 아 닌 지 를 검사 하 는 것 입 니 다.(어 셈 블 리 에 익숙 하지 않 은 친구 가 왜 test%eax,%eax 를 할 수 있 는 지 알 수 있 습 니 다.이것 은 최적화 일 뿐 cmp 보다 빠 르 기 때 문 입 니 다)메모리 가 아 닌 끊임없이 레지스터 를 읽 고 있 음 을 알 수 있 습 니 다.
여기 서 여러분 들 은'메모리 장벽'에 대해 초보적인 인식 을 가지 게 되 었 습 니 다.메모리 장벽 은 주로 세 가지 로 나 뉘 는데 그것 이 바로 컴 파 일 러 최적화(예 를 들 어 케이스)/캐 시 최적화/CPU 난 서 실행(뒤에 언급 될 것 입 니 다)입 니 다.
모두 가 그것 이 이렇게 많은 문 제 를 일 으 킬 수 있 는 것 이 아니 냐 고 물 을 것 이다.사실은 꼭 그렇지 는 않 습 니 다.본인 의 지식 범위 에 따 르 면 대부분의 메모리 장벽 으로 인해 발생 하 는 문 제 는 모두 커 널 상태 에 나타 나 고 사용자 상태 가 주의해 야 할 부분 이 많 지 않 습 니 다.그리고 사용자 도 해당 하 는 해결 방안 이 있 습 니 다.가장 간단 한 것 은 잠 금 체제 이 고 volatile 키워드 도 있 습 니 다.나타 날 수 있 는 cache 를 더러 운 데이터 volatile int tmp=0 을 읽 을 수 있 습 니 다.이렇게 하면 매번 조작 할 때마다 메모리 에서 가 져 옵 니 다.
이후 의 글 은'메모리 장벽'과 CPU 난 서 의 문 제 를 깊이 파고 들 것 이다.캐 시 최적화 로 인 한 메모리 장벽 은 기본적으로 새로운 하드웨어 에서 비교적 좋 은 해결 을 얻 었 고 사용자 상태 에서 기본적으로 감지 되 지 않 았 다.여러 스 레 드 의 잠 금 메커니즘 과 volatile 을 적 절 히 활용 하면 됩 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
09.문자 / 메모리영역//메모리 영역 스택 데이터 ROM(코드) //읽기전용메모리 문자 char(1),wchar(2) 바이트 . char c = 'a'; wchar_t wc = L'a';...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.