C/C++--프로 그래 밍 중인 메모리 장벽(Memory Barriers)(1)

3822 단어 C/C++코드 기술
내일 이면 transfor 가 검색엔진 을 하 러 갑 니 다.오늘 은 한가 해 졌 습 니 다.블 로 그 를 업데이트 하 세 요.이전에@고 V 학생 들 은 본인 이 전에 작성 한 글 제6 조 에 대해 cache 명중 과 cpu 흐름 최적화 에 관심 이 있 고 그의 의견 도 제시 했다.오늘 은 일부 프로 그래 밍 의 점 인 메모리 장벽 과 내부 저장 장벽 이 코드 에 미 친 영향 을 세분 화 했다.
       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 을 적 절 히 활용 하면 됩 니 다.

좋은 웹페이지 즐겨찾기