ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 캐시 이론
    게임서버/멀티쓰레드 프로그래밍 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
Designed by Tistory.