Нам нравится думать, что доступ к памяти является быстрым и постоянным, но на современной архитектуре/Ose, это не обязательно верно.
Рассмотрите следующий код C:
int i = 34;
int *p = &i;
// do something that may or may not involve i and p
{...}
// 3 days later:
*p = 643;
Какова ориентировочная стоимость этого последнего присвоения в инструкциях ЦП, если
i
находится в кэше L1,i
находится в кэше L2,i
находится в кэше L3,i
находится в надлежащей RAM,i
разбит на страницы к диску SSD,i
разбит на страницы к традиционному диску?Где еще может i
быть?
Конечно, числа не являются абсолютными, но я только интересуюсь порядками величины. Я пытался искать сети, но Google не благословлял меня на этот раз.
Вот некоторые точные цифры, демонстрирующие, что точное время варьируется от семейства ЦП и версии к версии: http://www.agner.org/optimize/
Эти числа являются хорошее руководство:
L1 1 ns
L2 5 ns
RAM 83 ns
Disk 13700000 ns
И в качестве инфографики, чтобы дать вам порядки величин:
Это также может быть в регистре ЦП. Ключевое слово "register" C / C ++ сообщает процессору, что переменная должна храниться в регистре, но вы не можете гарантировать, что она останется там или вообще когда-либо попадет туда.
Норвиг имеет некоторые значения с 2001 года. С тех пор кое-что изменилось, но я думаю, что относительные скорости все еще примерно верны.
Пока кэш / ОЗУ / жесткий диск / твердотельный накопитель не занят обслуживанием другого доступа (например, запросов DMA) и что оборудование достаточно надежно, стоимость остается постоянной (хотя они могут быть большой константой).
Когда вы получаете промах в кэше, и вам нужно перейти на жесткий диск, чтобы прочитать переменную, тогда это просто простой запрос чтения с жесткого диска, это огромная стоимость, так как ЦП должен: отправить прерывание в ядро для чтения с жесткого диска запрос, отправьте запрос на жесткий диск, дождитесь, пока жесткий диск запишет данные в ОЗУ, затем считайте данные из ОЗУ в кэш и в регистр. Однако эта стоимость по-прежнему является постоянной стоимостью.
Фактические числа и пропорции будут зависеть от вашего оборудования и от совместимости вашего оборудования (например, если ваш процессор работает на частоте 2000 МГц, а ваша оперативная память отправляет данные на частоте 333 МГц, тогда они не очень хорошо синхронизируются). Единственный способ выяснить это - протестировать это в своей программе.
И это не преждевременная оптимизация, это микрооптимизация. Пусть компилятор позаботится об этих деталях.
Где еще я могу быть?
i
и * i
- разные вещи, они оба могут находиться в любом месте в вашем списке . Адрес указателя может дополнительно храниться в регистре ЦП при выполнении назначения, поэтому его не нужно извлекать из RAM / Cache /…
Что касается производительности: это очень CPU- зависимый. Если мыслить масштабами, то доступ к ОЗУ хуже, чем доступ к записям кеша, а доступ к выгруженным страницам - наихудший. Все они немного непредсказуемы, потому что они также зависят от других факторов (то есть от других процессоров, в зависимости от архитектуры системы).
Эти числа постоянно меняются. Но для приблизительной оценки на 2010 год У Кэтрин МакКинли есть хорошие слайды в сети , которые я не чувствую себя обязанным копировать здесь.
Требуемый термин для поиска - «иерархия памяти» или «стоимость иерархии памяти».