2013년 C++ 효율 코드 글에 해커뉴스 '요즘 C++가 더 어려워졌다' vs '더 쉬워졌다' 논쟁
- 2013년 폴란드 Programista 매거진에 실린 글이 다시 올라옴. 객체를 포인터로 흩어 놓는 대신 메모리 레이아웃과 자료구조를 먼저 설계하는 데이터 지향 설계(DOD)를 제안하며, 포인터를 따라다니는 구조는 캐시 미스를 늘리고 스레드 병렬화도 안전하게 할 수 없다고 지적함
- 저자는 게임의 FPS 저하나 실시간 미디어 스트림처럼 속도를 타협할 수 없는 분야, 그리고 게임 콘솔처럼 CPU 속도와 RAM 용량이 고정된 환경에서 C++가 사실상 유일한 선택이라고 봄
- C++의 강점으로 가상머신이나 프레임워크 없이 OS에 접근하고, 예측 불가능한 시점에 도는 가비지 컬렉터 없이 메모리를 직접 관리한다는 점을 듦. 컴퓨팅 클러스터와 데이터센터의 전력·냉각 비용도 효율 코드가 필요한 이유로 제시함
Hacker News opinions
폴란드 잡지 2013년 글인데 조언은 여전히 좋음. 근데 C++가 지난 10년간 효율적이고 단순한 저수준 코드를 짜기 더 어려운 방향으로 가버린 게 아쉽다
무슨 소리임? 똑같은 저수준 코드 오늘도 그대로 짤 수 있는데
오히려 더 쉬워졌다고 봄. constexpr 덕분에 런타임에 하던 복잡한 계산을 컴파일 타임으로 옮길 수 있고, move semantics로 컴파일러에 정보를 더 줘서 더 나은 코드를 뽑게 됨
지난 15년간 C++ 개선은 질적으로 컸음. 예전에 효율적인 코드 생성을 위해 필요했던 주술 같은 코드가 이제 필요 없음
난 매일 C++ 쓰는데 속도 최적화가 필요했던 적이 없음. 평범하게 짜도 이미 충분히 빠름
난 C++ 쓸 때는 속도 때문임. 인트린직 잘 쓰면 순진한 구현보다 10배 빨라지는 일이 흔함
도메인에 따라 다름. 로보틱스는 CPU, 메모리 대역폭, GPU, 배터리까지 다 제로섬 게임임. 임베디드도 마찬가지고
폴리모픽 포인터 리스트를 std::variant로 바꾸면 TLB랑 캐시라인 지역성만으로 2~3배 빨라지고, 거기서 SoA로 가면 4~8배가 더 붙음. 데이터 우선으로 가면 거의 25배임
DB 엔진이나 게임 엔진, 3D 렌더러에서는 최적화가 핵심 작업 자체임. 자료구조만 잘 골라도 C++이 충분한 경우가 많긴 함
C로 먼저 짠 3D 렌더러를 C++로 다시 짰는데, AoS와 SoA 중 뭘 쓸지 모를 때 템플릿으로 파이프라인 코드를 그대로 재사용할 수 있어서 골랐음. SoA 레이아웃은 공짜로 안 나오고 직접 구현해야 함
그럼 넌 스케일 있는 제품을 안 만드는 거임
게임이나 대규모 웹앱은 최적화가 필요함. 중복 작업 없애고 큰 객체 복사 줄여서 CPU 30% 줄였는데 안 할 이유가 없음. 화려한 알고리즘이 아니라 7년 된 코드베이스에 쌓인 대충 짠 구현을 걷어낸 것뿐임
그건 니가 상위 수준 언어에서 더 생산적이라는 신호임
"충분히 빠름"이라는 개념이 존재하는 코드와 존재하지 않는 코드가 따로 있음
성능 때문이 아니면 왜 C++ 씀? 일반 앱 개발이면 Java나 C#, Go도 충분히 빠른데
1마이크로초도 끔찍하게 느린 분야가 있음
10Gbit/s 시세 스트림에 트레이딩 룰을 한 코어에서 몇 개나 돌릴 수 있는지, 100Gbit NIC 트래픽을 64바이트 패킷으로 방화벽에서 라인 속도로 걸러낼 수 있는지가 궁금하면 답이 나옴
소프트 실시간 오디오는 콜백 예산이 1.3ms임. 넘기면 드롭아웃이 들려서 그때부터 미친 듯이 최적화하게 됨
게임 그래픽스랑 성능 쪽에서 일하는데, 이 글 내용은 게임을 제 성능으로 출시하려면 필수임
분기 예측이나 컨텍스트 스위칭, 동기화 얘기가 빠져 있음. 스레드 병렬화랑 SIMD도 아주 짧게만 나옴. 범위가 너무 넓어서 블로그 한 편으로는 부족하고 시리즈나 책이 맞음
SIMD가 잘 먹는 명령어를 알아두고, 루프에서 삼항연산자로 마스킹하고, 삼각함수 항등식이랑 룩업 테이블을 쓰면 됨. sin(3t)를 매번 계산하지 말고 sin(t) 테이블로 두 번 곱하는 식으로. 0.5f처럼 나눠떨어지는 상수를 쓰고 --fast-math로 컴파일해야 errno가 SIMD 파이프라인을 망치지 않음