14. 거짓 공유(false sharing)와 캐시 라인 정렬

난이도 중 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C++
// ─────────────────────────────────────────────────────────────
// 주제: 거짓 공유(false sharing)와 캐시 라인 정렬
//
// 게임 서버의 워커들이 서로 다른 카운터(처리량/통계)를 atomic 으로 증가시킨다.
// 아래 두 레이아웃 Counters / PaddedCounters 가 있다.
//
// 과제(실행 전에 예측하라):
//   1) 아래 4개의 출력값(sizeof/alignof, Counters 와 PaddedCounters)을 예측하라.
//   2) 스레드 A는 .a 만, 스레드 B는 .b 만 각각 1억 번 증가시킨다고 하자.
//      두 레이아웃 중 어느 쪽이 빠른가? 그 이유를 "캐시 라인"과 캐시 일관성
//      프로토콜(예: MESI) 관점에서 설명하라.
//   3) PaddedCounters 가 메모리를 더 쓰는데도 쓰는 이유와, 적정 패딩 크기를
//      무엇으로 정해야 하는지 설명하라.
//   (내부 동작 설명은 answer.md 에서 다룬다. 여기서는 예측만.)
// ─────────────────────────────────────────────────────────────
#include <atomic>
#include <cstddef>
#include <cstdio>
#include <thread>
#include <chrono>

struct Counters {
    std::atomic<long> a{0};
    std::atomic<long> b{0};
};

struct alignas(64) PaddedCounters {
    alignas(64) std::atomic<long> a{0};
    alignas(64) std::atomic<long> b{0};
};

template <class T>
double bench(T& c) {
    constexpr long N = 100'000'000;
    auto t0 = std::chrono::steady_clock::now();
    std::thread ta([&]{ for (long i = 0; i < N; ++i) c.a.fetch_add(1, std::memory_order_relaxed); });
    std::thread tb([&]{ for (long i = 0; i < N; ++i) c.b.fetch_add(1, std::memory_order_relaxed); });
    ta.join(); tb.join();
    auto t1 = std::chrono::steady_clock::now();
    return std::chrono::duration<double, std::milli>(t1 - t0).count();
}

int main() {
    printf("sizeof(Counters)=%zu alignof(Counters)=%zu\n",
           sizeof(Counters), alignof(Counters));
    printf("sizeof(PaddedCounters)=%zu alignof(PaddedCounters)=%zu\n",
           sizeof(PaddedCounters), alignof(PaddedCounters));

    Counters c;        double t1 = bench(c);
    PaddedCounters p;  double t2 = bench(p);
    printf("shared   : %.0f ms (a=%ld b=%ld)\n", t1, c.a.load(), c.b.load());
    printf("padded   : %.0f ms (a=%ld b=%ld)\n", t2, p.a.load(), p.b.load());
    return 0;
}
내 리뷰 · C++
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.