Счётчики потоков в соседних ячейках массива
Каждый из 8 воркеров считает обработанные пакеты в свою ячейку:
std::array<std::atomic<uint64_t>, 8> counters{};
void worker(int id) {
while (running) {
handle_packet();
counters[id].fetch_add(1, std::memory_order_relaxed);
}
}
Логических пересечений нет — каждый пишет только в свою ячейку. Но при росте с 1 до 8 потоков общий throughput почти не растёт, а perf показывает всплеск обращений к общей памяти. В чём дело?
- `memory_order_relaxed` заставляет процессор сбрасывать кэш-линию в память на каждой операции
- Ложное разделение: соседние счётчики попадают в одну кэш-линию, и запись одного ядра инвалидирует её у остальных
- `std::atomic<uint64_t>` реализован через глобальный мьютекс библиотеки, поэтому все потоки сериализуются на нём
- Восемь потоков превышают разумную степень параллелизма, ограничение снимается переходом на пул из 2-4 потоков
