반응형

Kubernetes 1.23 이상 또는 OCP 4.10 이상을 사용하는 Cluster에서 Pod를 구동하다보면, 

Pod Status가 SMTAlignmentError 에러 상태가 되면서 구동하지 못하는 경우를 만난다.

 

CPU Pinning을 위해 아래처럼 Pod Spec을 설정한 경우에 볼 수 있는 에러이다.

아래 YAML 예시에서 cpu 개수를 5개 설정한 것이 문제를 발생시킨다. (홀수로 설명하는 것이 문제)

kind: Pod
metadata:
  name: myapp
spec:
... 중간 생략 ...
  containers:
    resources:
      limits:
        cpu: 5   ## 이렇게 홀수인 정수를 설정한 것이 에러를 발생시킴.
... 중간 생략 ...

 

관련 자료를 찾아보니, 아래 문서가 가장 설명을 잘 해주고 있다.

 

 

Best practices for avoiding noisy neighbor issues using cpu manager behaves wrt hyper-threading - Red Hat Customer Portal

Best practices for avoiding noisy neighbor issues using cpu manager behaves wrt hyper-threading

access.redhat.com

 

위 문서의 요지는 이렇다.

 

X86_64 CPU는 아래 그림처럼 1개의 물리 Core가 2개의 논리 CPU(Thread)로 구성되어 있고, 
이 2개의 논리 CPU(Thread)가 1개의 L2 Cache를 공유하기 때문에
만약 홀수 개로 CPU를 Pinning(즉, Isolation)하면, L2 Cache의 Hit Ratio가 확 떨어지기 때문에
Core의 처리 속도가 겁나게 떨어진다는 것이다.

즉, L2 Cache 1개를 두고 LCore-0과 LCore-1이 치고 박고 시끄럽게 싸우는 꼴~~~
X86_64 CPU 구조에는 늘상 발생하는 현상으로써, "noisy neighbors"라고 표현한다.

 

쉽게 이해하기 위해 일상 생활과 비유해본다면,

2명의 사람이 한 집에 살면서 요리를 하는데

주방이 1개라서 홍길동은 된장찌개(Job-A)를 만들어 먹고 싶고, 이순신은 김밥(Job-B)을 만들어 먹고 싶다면

홍길동이 된장찌개 요리를 마무리하고 주방(L2 Cache)를 비워줘야, 이순신이 그 주방(L2 Cache)에서 김밥을 만들 수 있는 것과 같다.

여기서 핵심은 "주방(L2 Cache)를 비워줘야" 한다에 있다.

Local Thread가 서로 다른 일을 할 경우, L2 Cache에 담을 내용이 서로 다르기 때문에 L2 Cache 메모리에 있는 데이터를 재사용할 수 없고(즉, Hit Ratio가 떨어지고) 실제 L2 Cache는 Cache 로써의 역할을 못하게 된다.

L2 Cache의 내용 싹~~~ 갈아 엎어버리고 다른 CPU Core가 해야 할 일과 관련된 데이터를 복사해야 하니까~~~

 

이렇기 때문에 비슷한 Job(프로그램, 또는 Process)에 대해서 L2 Cache를 같이 사용하도록 2개씩 쌍으로 할당하는 것이 최고의 성능을 낼 수 있다.

그럴 일은 없겠지만, 만약 논리 쓰레드 3개가 1개의 L2 Cache를 공유하는 CPU 제품이 있다면 3개씩 쌍으로 할당해야 최고의 성능을 낼 수 있다. (이것은 그냥 가정이다)

 

 

 

내 생각에는
처음부터 Intel x86 CPU가 Hyper Threading 구조가 아니였다면, 즉 Logical Core가 L2 Cache Memory를 공유하지 않는 구조였다면 CPU Pinning 설정할 때 짝수로 설정해야 하는 제약도 없었을 것 같다.

 

 

 

 

아래 그림은 Red Hat Web Docs에서 인용한 그림.

CPU Core 개수를 홀수로 설정하여 SMTAlignmentError 발생

 

CPU Core 개수를 짝수로 설정하여 CPU의 Virtual Thread가 L2 Cache 영역을 공유하지 않도록 함

 

 

+ Recent posts