Если вы прокомментируете одну из этих строк, вы либо сохраняете один и тот же адрес несколько раз (и, вероятно, оптимизируете его в цикле), либо не сохраняете вообще.Неудивительно, что время неизмеримо мало и округляется до 0 микросекунд.
В тестовом коде, который вы связали, вы набираете 32 КБ на магазин, на недавно выделенной памяти без прогрева,Вы, вероятно, получаете мягкую ошибку страницы и копирование при записи при каждой итерации.(Память malloc
ed, вероятно, все лениво отображалась на одну и ту же физическую нулевую страницу.)
256 итераций также совершенно недостаточно для того, чтобы разогнать процессор до нормальной / турбо тактовой частоты, вне скорости холостого хода.
На моем i7-6700k Arch Linux destkop (в режиме ожидания 800 МГц, нормальная тактовая частота 3,9 ГГц, регулятор / energy_performance_preference = balance_performance
(не по умолчанию balance_power
, поэтому он увеличивается быстрее):
Я скомпилировал с помощью gcc8.2.1 и запустил получившийся исполняемый файл в цикле с while ./a.out ;do :;done
, чтобы процессор оставался на высокой тактовой частоте. Программа печатает такие моменты времени, как 1.125us
+ - немного. Это звучит примерно как для страницы-fault + обнуление страницы + обновление таблиц страниц и сброс TLB.
Используя Linux perf stat
, я запускал его 100 раз с усреднением подсчетов. (Столбец вторичной статистики "rate" имеетфиктивные устройства из-за ошибки перфокарта, которую Arch еще не обновил, чтобы исправить. Таким образом, на самом деле он измеряет 4,4 ГГц (что я считаю фиктивным, Turbo отключен на моем процессоре, чтобы вентиляторы не работали).
peter@volta:/tmp$ perf stat -etask-clock,context-switches,cpu-migrations,page-faults,cycles,branches,instructions,uops_issued.any,uops_executed.thread,dtlb_store_misses.miss_causes_a_walk,tlb_flush.dtlb_thread,dtlb_load_misses.miss_causes_a_walk -r100 ./a.out
Performance counter stats for './a.out' (100 runs):
1.15 msec task-clock # 0.889 CPUs utilized ( +- 0.33% )
0 context-switches # 40.000 M/sec ( +- 49.24% )
0 cpu-migrations # 0.000 K/sec
191 page-faults # 191250.000 M/sec ( +- 0.09% )
4,343,915 cycles # 4343915.040 GHz ( +- 0.33% ) (82.06%)
819,685 branches # 819685480.000 M/sec ( +- 0.05% )
4,581,597 instructions # 1.05 insn per cycle ( +- 0.05% )
6,366,610 uops_issued.any # 6366610010.000 M/sec ( +- 0.05% )
6,287,015 uops_executed.thread # 6287015440.000 M/sec ( +- 0.05% )
1,271 dtlb_store_misses.miss_causes_a_walk # 1270910.000 M/sec ( +- 0.21% )
<not counted> tlb_flush.dtlb_thread (0.00%)
<not counted> dtlb_load_misses.miss_causes_a_walk (0.00%)
0.00129289 +- 0.00000489 seconds time elapsed ( +- 0.38% )
Эти подсчеты включают режим ядра, но - это 191 сбоев страниц для 256 итераций цикла, так что огромное большинство времени, проведенного этой программой, находится в ядре.
И как только мы возвращаемся в пространство пользователя, более 1000 хранилищ вызывают пропуски dTLB, которые также пропускаются в TLB 2-го уровня, требуя обхода страницы.Но никаких загрузок не было.
Вероятно, мы могли бы получить намного более чистые данные, выделив намного больше памяти, чтобы мы могли увеличить Count
без сегментации.Профилирование с perf record
показывает, что только около 20% общего времени программы тратится на main
;остальная часть находится в динамическом компоновщике / загрузке, частично от печати.