Перейти к содержанию

Последнее обновление:2026-10-12

C++ False Sharing и строка кэша

Недавно наткнулся на код с выравниванием, сделанным вручную, и решил разобраться: а какие последствия даёт отсутствие выравнивания?

template <typename T>
class AtomicWithPadding {
 private:
  static constexpr int kCacheLineSize = 64;
  uint8_t padding_before[kCacheLineSize];

 public:
  std::atomic<T> value;

 private:
  uint8_t padding_after[kCacheLineSize];
};
Отсюда вытекает обязательная тема собеседований:

  • Cache line

Вот несколько вопросов с собеседований — сможете ответить?

  • Что такое cache line?
  • Что такое протокол MESI?
  • Что такое False sharing?
  • Как в C++ гарантированно избежать False sharing?
  • Какую пользу приносит избегание False sharing?
  • Знаете ли вы, какие две возможности для решения этой проблемы появились после C++17?

Итак, я взял один тест производительности, примерная реализация такая:

  • определяем 4 переменные a, b, c, d, которые разделяются между потоками
  • кроме того, выравниваем эти четыре переменные и запускаем n потоков на выполнение.

Ниже benchmark:

------------------------------------------------------------------
Benchmark                        Time             CPU   Iterations
------------------------------------------------------------------
singleThread                  4.05 ms         4.04 ms          133
directSharing/real_time       8.78 ms        0.069 ms           77
falseSharing/real_time        8.81 ms        0.083 ms           74
noSharing/real_time           1.16 ms        0.071 ms          578
Видно, что noSharing даёт превосходный результат! Доля попаданий в кэш значительно выросла; конечно, лучше дополнительно проанализировать это с помощью perf — можно посмотреть L1 cache miss.

Ответы на всё выше уже выложены в закрытом сообществе; будем рады обсудить; пишите в комментариях, спасибо~

Похожие темы

Комментарии