TGViewer
about:performance about:performance @troubleperf · 1.5K subscribers
Post #93 1.8K
Как CPU читает данные из памяти и о чем тут стоит подумать

Допустим, у нас есть указатель на счетчик (uint32_t), значение которого нужно увеличить:
uint32_t inc(uint32_t *p) {
return *p + 1;
}


То же самое на ассемблере:
inc:
mov eax, dword ptr [rdi]
inc eax
ret


1. mov загружает в регистр eax 4 байта, при промахе в L1 целая кеш-линия (64 байта) подтягивается со следующих уровней;
2. inc увеличивает значение в eax на 1.

Если после этого программа завершается, то с точки зрения производительности, нас интересует только скорость доставки данных (считаем что инкремент выполняется за константное время, в 1 цикл).

Типичные тайминги:
Типичные тайминги:
| Level | Cycles | Latency (~3 GHz )
|------------------|--------|------------------
| L1D | ~4-5 | ~1.5 ns
| L2 | ~12-15 | ~4-5 ns
| L3 (LLC, local) | ~40-70 | ~14-23 ns
| DRAM (local NUMA)| — | ~80-120 ns
| DRAM (remote) | — | ~140-200 ns


Но если впереди у программы есть другая работа, картина усложняется - появляется фактор пропускной способности. Даже в рамках одного ядра (читаем про out-of-order execution, ссылки в конце).

———

Максимальную пропускную способность для одного ядра можно грубо подсчитать по формуле:

Bandwidth = N_max × line_size / miss_latency

Где:
- N_max: число одновременных загрузок из памяти при L1 miss (memory-level parallelism), в Intel ограничено компонентом Line Fill Buffer (LFB), ~12-16 единиц;
- line_size: размер кеш-линии, 64 байта;
- miss_latency: задержка доступа к данным, пусть в 100ns.

Получается, что одно ядро может потреблять порядка 10 GB/s пропускной способности памяти, при том что один канал DDR5 выдает ~38 GB/s.

И раз переутилизация каналов DRAM часто не наш кейс, все что остается это сокращать задержку доступа к данным (Latency) и/или увеличивать эффективное число загрузок N (Throughput).

Из вариантов:
* сокращать working set (рабочий набор), чтобы больше данных помещались в быстрые кеши процессора
* избегать pointer chasing, особенно в list-подобных структурах, которые ограничивают N
* продумывать layout данных: группировать поля структур по паттернам доступа, чтобы они подтягивались в рамках одной кеш-линии
* использовать software prefetch, Huge Pages и прочие техники.

———

Ссылки по теме:
- Taras Tsugrii о memory-bound
- A whirlwind introduction to dataflow graphs (pointer chasing)
- Про Line Fill Buffer (LFB)
- Out-of-order execution
- Performance Analysis and Tuning on Modern CPUs
  • 🔥 23
  • ✍ 4
  • ❤ 1
More from @troubleperf
  1. Aug 14, 2026Post #120
  2. Jul 12, 2026about:performance pinned «»
  3. Jul 12, 2026Post #118
  4. Jul 11, 2026Post #117
  5. Jul 5, 2026Про бенчмаркинг, часть 3 (части 1,2) Ранее обсудили, что борьба с шумом (noise) процесс бе…
  6. Jun 21, 2026Продублирую свой комментарий на вопрос: Стоит задача оценки достаточности мощности оборудо…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →