-
캐시 이론게임서버/멀티쓰레드 프로그래밍 2022. 3. 9. 15:47
1. CPU코어 비유
CPU코어는 ALU(연산장치), 캐시장치로 이루어져있다.
주문현황판 메인메모리(RAM) 단기기억 레지스터 미니수첩 L1 캐시 대형수첩 L2 캐시 주문을 받을때마다 주문현황판을 왔다갔다 하는데에 시간이 드니까 기억을 하거나 수첩에 기록하는 방법을 쓴다.
= 메인메모리가 갱신될때마다 CPU가 참조하는건 성능에 부담이 되니까 레지스터나 캐시장치에 기억을 하고 한꺼번에 연산을 한다.
영혼끼리의 기억 혹은 수첩의 내용이 다를 수 있다.
= CPU코어의 캐시에 저장된 내용이 서로 다를 수 있다.
멀티쓰레드에서 발생하는 문제점 중 하나로 메모리에서 어떤 작업이 취소되고 다시 올라오는 경우에 1번 CPU는 취소되기 전의 내용을 캐시에 저장해놨는데 2번 CPU가 다시 올라온 내용을 캐시에 저장해버리면 서로 캐시에 저장된 내용이 달라질 수 있다.
3. 캐시철학
TEMPORAL LOCALITY
시간적으로 보면, 방금 주문한 테이블에서 추가 주문이 나올 확률이 높다.
방금 주문한걸 메모해 놓으면 편하지 않을까?
= 최근에 사용된 변수가 재사용될 확률이 높다.
SPECIAL LOCALITY
공간적으로 보면, 방금 주문한 사람 근처에 있는 사람이 추가 주문을 할 확률이 높다.
방금 주문한 사람과 합석하고 있는 사람들의 주문 목록도 메모해 놓으면 편하지 않을까?
= 최근에 사용된 변수와 관련된 변수도 사용될 확률이 높다.
캐시 철학 적용 예시
아래의 코드는 arr[y, x]와 arr[x, y]로 실행했을 때 걸리는 시간이 다른지 확인해보는 코드이다.
using System; namespace ServerCore { class Program { static void Main(string[] args) { int[,] arr = new int[10000, 10000]; { long now = DateTime.Now.Ticks; for(int y=0; y<10000; y++) for(int x=0; x<10000; x++) arr[y, x] = 1; long end = DateTime.Now.Ticks; Console.WriteLine($"(y,x) 순서 걸린 시간 {end-now}"); } { long now = DateTime.Now.Ticks; for (int y = 0; y < 10000; y++) for (int x = 0; x < 10000; x++) arr[x, y] = 1; long end = DateTime.Now.Ticks; Console.WriteLine($"(x,y) 순서 걸린 시간 {end - now}"); } } } }
실행결과 결과를 보면 arr[y, x]의 시간이 더 빠른걸 볼 수 있는데 이것은 SPECIAL LOCALITY때문이다.
배열의 관점에서보면
[0, 0] [0, 1] [0, 2] [0, 3] [0, 4] [1, 0] [1, 1] [1, 2] [1, 3] [1, 4] [2, 0] [2, 1] [2, 2] [2, 3] [2, 4].....
위와 같이 구성되어 있다.
[0, 0]을 사용하면 SPECIAL LOCALITY에 의해서 [0, 1]이 사용될 확률이 높기 때문에 CPU코어는 [0, 1]을 캐시에다 미리 저장을 해놓는다.
그리고 반복문에서 실제로 [0, 1]이 사용되면 메모리에 다시 접근하지 않아도 되기때문에 시간이 절약되는 것이다.
'게임서버 > 멀티쓰레드 프로그래밍' 카테고리의 다른 글
Interlocked (0) 2022.03.10 메모리 베리어 (0) 2022.03.10 컴파일러 최적화 (0) 2022.03.09 쓰레드 (0) 2022.03.09 멀티쓰레드 개론 (0) 2022.03.09