TECH 으로 돌아가기
TECH HACKER NEWS 2026.11.01 22:01 7분 읽기 30 READS

CPU는 메모리를 기다리느라 놀고 있어요: '메모리 레이턴시'가 진짜 병목인 이유

CPU는 메모리를 기다리느라 놀고 있어요: '메모리 레이턴시'가 진짜 병목인 이유
SOURCE IMAGE · HACKER NEWS
CPU는 메모리를 기다리느라 놀고 있어요: '메모리 레이턴시'가 진짜 병목인 이유

성능 문제, 범인은 누구일까요?

프로그램이 느리면 우리는 보통 'CPU가 부족한가?', '알고리즘 복잡도가 문제인가?'부터 의심하잖아요. 그런데 'It's the memory latency, stupid'라는 글은 제목부터 꽤 도발적으로 다른 범인을 지목해요. 진짜 병목은 연산이 아니라 메모리에서 데이터를 가져오는 데 걸리는 시간, 즉 메모리 레이턴시라는 거예요. 제목은 1992년 미국 대선 구호 'It's the economy, stupid'를 패러디한 건데요, 네트워크 분야에도 1996년 스튜어트 체셔가 쓴 'It's the Latency, Stupid'라는 유명한 글이 있어요. '대역폭보다 지연시간이 중요하다'는 메시지가 이번엔 메모리 세계로 넘어온 셈이죠.

레이턴시와 대역폭, 뭐가 다른데요?

택배에 비유하면 쉬워요. 대역폭은 트럭 한 대에 얼마나 많이 실을 수 있느냐고, 레이턴시는 주문하고 첫 상자가 도착할 때까지 얼마나 걸리느냐예요. 트럭이 아무리 커도 물건을 하나씩 주문하고 매번 하루씩 기다려야 한다면 트럭 크기는 별 의미가 없죠.

대략적인 숫자로 보면 이래요. CPU 바로 옆 L1 캐시는 1나노초 안팎, L2는 몇 나노초, L3는 10~20나노초 정도인데요, 메인 메모리(DRAM)까지 가면 80~100나노초 정도 걸려요. 4GHz CPU에서 100나노초면 약 400 사이클이에요. 요즘 CPU는 한 사이클에 명령어를 여러 개 처리하니까, 메모리를 한 번 기다리는 동안 수백에서 천 개 넘는 명령어를 실행할 수 있는 시간을 그냥 날리는 거예요.

더 뼈아픈 건 추세예요. 지난 20년간 CPU 코어 수와 메모리 대역폭은 꾸준히 늘었는데, DRAM 레이턴시는 거의 제자리걸음이에요. DRAM은 아주 작은 커패시터에 전하를 담는 구조라서 읽는 속도를 근본적으로 줄이기가 어렵거든요. 그래서 연산 능력과 메모리 응답 속도 사이의 격차, 흔히 말하는 메모리 월(memory wall)은 점점 벌어지고 있어요.

대역폭은 남는데 왜 느릴까: 포인터 체이싱

핵심은 의존성이에요. 두 코드를 비교해볼게요.

배열은 다음에 읽을 주소를 미리 알 수 있어서, CPU의 하드웨어 프리페처가 '다음 거 필요하겠네' 하고 미리 가져다 놔요. 요청 여러 개를 동시에 보낼 수도 있고요. 반면 연결 리스트는 지금 노드를 다 읽어야 다음 노드 주소를 알 수 있어요. 요청을 하나 보내고, 답이 올 때까지 기다리고, 그다음 요청을 보내는 식이라 대역폭이 아무리 넓어도 한 번에 한 줄씩밖에 못 써요. 이런 패턴을 포인터 체이싱이라고 불러요.

문제는 이 패턴이 생각보다 흔하다는 거예요. 해시 테이블 조회, 트리 탐색, 그래프 순회, 그리고 Java나 JavaScript처럼 객체가 힙 여기저기 흩어져 있는 언어에서 객체 그래프를 따라가는 작업이 다 비슷한 성격이에요.

하드웨어와 소프트웨어는 어떻게 버티고 있나

하드웨어는 캐시를 키우고, 프리페처를 똑똑하게 만들고, 비순차 실행(out-of-order execution)으로 기다리는 동안 다른 일을 하는 방향으로 발전해왔어요. 코어마다 처리 중인 캐시 미스를 동시에 여러 개 유지할 수도 있는데, 이걸 메모리 수준 병렬성(MLP)이라고 해요. 여기서 리틀의 법칙이 나오는데요, 처리량 = 동시 요청 수 ÷ 레이턴시예요. 레이턴시를 못 줄이면 동시에 보내는 요청을 늘려야 처리량이 올라간다는 뜻이죠.

소프트웨어 쪽 해법도 결국 같은 방향이에요. 데이터를 연속된 메모리에 모으는 데이터 지향 설계, 구조체 배열(AoS) 대신 배열 구조체(SoA)를 쓰는 방식, Apache Arrow나 Parquet 같은 컬럼형 포맷, DuckDB나 ClickHouse의 벡터화 실행이 대표적이에요. 이진 트리 대신 노드 하나에 키를 많이 담는 B-트리를 쓰는 것도 같은 이유고요. 여러 조회를 서로 끼워 넣어(interleave) 실행하면서 소프트웨어 프리페치로 캐시 미스를 겹치는 기법을 쓰는 데이터베이스도 있어요.

한국 개발자에게 주는 시사점

CRUD API를 짜는 분이라면 '나노초 얘기가 나랑 무슨 상관이야' 싶을 수 있어요. 그런데 대량 데이터를 메모리에서 처리하는 배치 작업, 인메모리 캐시, 게임 서버, 검색 엔진, 데이터 파이프라인에서는 이 차이가 몇 배의 성능 차이로 나타나요. 같은 알고리즘인데 자료구조만 바꿨더니 몇 배 빨라지는 경험은 대부분 여기서 나와요.

당장 해볼 수 있는 것도 있어요. 프로파일링할 때 CPU 사용률만 보지 말고 perf stat 같은 도구로 캐시 미스와 IPC(사이클당 명령어 수)를 같이 보세요. IPC가 1보다 한참 낮다면 CPU가 계산이 아니라 메모리를 기다리고 있을 가능성이 커요. 핫패스에서 객체 리스트를 순회하고 있다면, 필요한 필드만 원시 타입 배열로 뽑아보는 실험도 해볼 만해요.

마무리

한 줄 정리: CPU는 점점 빨라지는데 메모리 응답 속도는 그대로라서, 이제 성능은 '얼마나 많이 계산하느냐'보다 '얼마나 덜 기다리느냐'의 싸움이에요.

자료구조나 메모리 배치만 바꿔서 성능이 확 좋아진 경험이 있나요? 반대로 이런 최적화가 과하다고 느낀 적은요? 경험담 들려주세요!


🔗 출처: Hacker News

SOURCE · HACKER NEWS
원문 전체 보기 → https://pivotlake.io/blog/its-the-memory-latency-stupid/
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기 →
처리 중...