1. 메모리 계층 구조
1.1. 캐시 메모리 (L1, L2, L3 캐시)
L1 캐시:
- CPU 코어에 가장 가까운 캐시
- 보통 32KB ~ 64KB 크기
- 접근 속도: ~4 사이클
- 일반적으로 명령어 캐시와 데이터 캐시로 분리됨
L2 캐시:
- L1보다 크고 느림
- 보통 256KB ~ 512KB 크기
- 접근 속도: ~10 사이클
- 대부분의 경우 코어별로 독립적
L3 캐시:
- 가장 큰 온칩 캐시
- 보통 수 MB ~ 수십 MB 크기
- 접근 속도: ~40 사이클
- 일반적으로 모든 코어가 공유
캐시의 역할:
1) 자주 사용되는 데이터를 빠르게 접근할 수 있는 위치에 저장
2) 메모리 접근 지연 시간 감소
3) 메모리 대역폭 병목 현상 완화
멀티스레딩에서의 주의점:
- 캐시 일관성 문제(Cache Coherence): 여러 코어가 같은 데이터를 각자의 캐시에 저장하고 수정할 때 서로의 데이터가 달라질 수 있음
- 메모리 가시성 문제(Memory Visibility): 한 스레드에서 수정한 데이터가 다른 스레드에 즉시 보이지 않음
1.2. 메인 메모리 (RAM)
- 용량: 수 GB ~ 수 TB
- 접근 속도: ~200 사이클
- 모든 프로세스와 스레드가 공유
- 가상 메모리 시스템을 통해 관리됨
가상 메모리와 페이징
- 각 프로세스에게 독립적인 가상 주소 공간 제공
- 물리적 메모리를 페이지 단위로 관리 (보통 4KB 크기)
- 페이지 테이블을 통해 가상 주소를 물리 주소로 변환
- 필요한 페이지만 물리 메모리에 로드 (요구 페이징)
2. 스레드별 스택과 공유 힙
2.1.스택 메모리
- 각 스레드마다 독립적인 스택 할당
- 함수 호출, 지역 변수, 임시 데이터 저장에 사용
- LIFO (Last In First Out) 구조
- 크기: 기본적으로 1MB(설정가능)
스택의 특징:
1) 빠른 할당과 해제
2) 자동 메모리 관리
3) 스레드 안전 (다른 스레드의 스택에 직접 접근 불가)
2.2. 힙 메모리
- 모든 스레드가 공유
- 동적 메모리 할당에 사용 (예: C++의 new, Java의 객체 생성)
- 크기: 프로그램 실행 중 동적으로 변경 가능
힙의 특징:
1) 유연한 메모리 관리
2) 객체의 수명이 생성 범위를 벗어날 때 사용
3) 스레드 간 데이터 공유에 사용되나, 동기화 필요
멀티스레딩에서의 특징:
- 스택: 스레드 안전성 보장, 캐시 지역성 향상
- 힙: 스레드간 데이터 공유 가능, 서로 다른 스레드가 같은 메모리에 동시에 접근하면 Race condition이 발생할 수 있음
3. 메모리 모델과 가시성(Visibility)
순차적 일관성 모델
- 정의: 모든 스레드가 모든 메모리 연산을 동일한 순서로 관찰
- 특징: 직관적이지만 현대 하드웨어에서 구현 시 성능 저하
Release - Acquire 의미론
- Release: 메모리 연산이 다른 스레드에게 보이도록 보장
- Acquire: 다른 스레드의 릴리즈 연산 결과를 관찰
메모리 배리어와 volatile 키워드
- 메모리 배리어: 메모리 연산의 재배치를 제한하는 CPU 명령
- 종류: 읽기 배리어, 쓰기 배리어, 전체 배리어
- volatile 키워드: 컴파일러의 최적화를 제한, 하드웨어 레지스터에 직접 접근 (C/C++)
멀티스레딩에서의 의미:
- 올바른 동기화 없이는 한 스레드의 변경사항이 다른 스레드에게 즉시 보이지 않을 수 있음
- 메모리 모델을 이해하고 적절한 동기화 기법을 사용해야 함
'멀티스레딩' 카테고리의 다른 글
동기화 기법: Lock (0) | 2024.10.05 |
---|---|
동기화 기법: Atomic 연산 (0) | 2024.10.05 |
데이터 동기화 기초 (0) | 2024.10.01 |
스레드 생성과 관리 (0) | 2024.09.28 |
멀티스레딩 기초 (0) | 2024.09.28 |