Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/40: Рейтинг темы: голосов - 40, средняя оценка - 5.00
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700

Кеш линии процессора

09.12.2016, 10:18. Показов 8614. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Очень часто со стороны программистов можно заметить утверждение
"Вот эти данные скорее всего попадут в кеш линию процессора" - на чем основываются программисты, когда делают подобные выводы?
Еще интересует то, что если данные которые претендуют на попадание в кеш превышают размер одной линейки кеша, могут ли они сохраниться сразу в двух линейках последовательно?

Например есть массив
L1 ---60% от последовательных данных---
L2 ---40% от последовательных данных(а остаток свободного места занят другими данными)---
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
09.12.2016, 10:18
Ответы с готовыми решениями:

Кеш процессора
Задание Написать программу, многократно выполняющую чтение элементов массива заданного размера. Элементы массива должны представлять...

Не обновляется кеш для потоков
сделал такую штуку: vector<short> done(hard_concur, 1); void task_for_thread(size_t idThread) { // проблема в этом цикле ...

Производительность CPU, КЕШ, многопоточность
Доброго времени суток! Суть проблемы - есть курсовой по системному программированию но я не знаю с чего и начать ( Тема:...

14
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
09.12.2016, 15:40
Лучший ответ Сообщение было отмечено Undisputed как решение

Решение

Кэш лайн - это сплошной кусок памяти размером в 32 байта, выровненный на такой же размер. Этот размер может быть 64 или 128 байт (или ...) - зависит от конкретного устройства процессора. Для простоты буду называть его словами "32 байта".

При обработке запроса в память со стороны процессорв, реальное обращение в память происходит кусками по 32 байта. Т.е. если мы читаем из памяти 1 байт, то в реальности прочтётся кусок размером 32 байта с адреса, выровненного на 32. И весь этот кусок попадёт в кэш в виде кэш-лайна. Допустим, мы читаем байт по адресу 65, в реальности из памяти прочтётся 32 байта из диапазона адресов 64-95 и весь этот кусок памяти осядет в кэше, а до исполнительного устройства дойдёт только один нужный байт. Если после этого мы захотим прочесть один байт по адресу 66, то он уже прочтётся из кэша

Цитата Сообщение от sys_beginner Посмотреть сообщение
"Вот эти данные скорее всего попадут в кеш линию процессора" - на чем основываются программисты, когда делают подобные выводы?
Например, у нас горячим является массив размером 1024 байта. Если мы его разместим в памяти по адресу, выровненному на 32, то мы будем уверены в том, что 32-й, 33-й, ... 63-й байты этого массива попадут в один кэшлайн

Цитата Сообщение от sys_beginner Посмотреть сообщение
Еще интересует то, что если данные которые претендуют на попадание в кеш превышают размер одной линейки кеша, могут ли они сохраниться сразу в двух линейках последовательно?
Необязательно. Да и не нужно это. Если данные попали в кэш, то читаться они будут быстро, независимо от того, в соседних кэш-лайнах, или нет
4
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.12.2016, 01:52  [ТС]
Evg,
Большое спасибо!
Цитата Сообщение от Evg Посмотреть сообщение
Если мы его разместим в памяти по адресу, выровненному на 32, то мы будем уверены в том, что 32-й, 33-й, ... 63-й байты этого массива попадут в один кэшлайн
1. А как это можно сделать? aligned_storage и ему подобные?
2. Что делать если используется большой пул памяти? достаточно что бы его начальный адрес был выровнен на 32? Или внутри пула относительно содержимых там типов так же нужно применять выравнивание?

Добавлено через 6 минут
И как понять какое выравнивание требует процессор для кеша(которое как я понял должно быть равно размеру линейки) что бы когда программа запускалась на разных процессорах всегда использовать эффективное выравнивание
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
10.12.2016, 11:44
Цитата Сообщение от sys_beginner Посмотреть сообщение
1. А как это можно сделать? aligned_storage и ему подобные?
В GNU C это выглядит как:

C
int a[100] __attribute__((aligned(32)));
Цитата Сообщение от sys_beginner Посмотреть сообщение
2. Что делать если используется большой пул памяти? достаточно что бы его начальный адрес был выровнен на 32? Или внутри пула относительно содержимых там типов так же нужно применять выравнивание?
На уровне языка программирования обычно работа идёт с переменными. Как только ты выровнял начало переменной на нужный размер, то обо всех внутренностях переменной уже можно делать какие-то предположения. Если память выделена динамически, то ты всегда можешь прибавить к указателю нужное значение, чтобы обеспечить его выравненность.

Цитата Сообщение от sys_beginner Посмотреть сообщение
И как понять какое выравнивание требует процессор для кеша(которое как я понял должно быть равно размеру линейки) что бы когда программа запускалась на разных процессорах всегда использовать эффективное выравнивание
У каждого процессора в описании есть размер кэшлайна. У семейства процессоров обычно он не меняется. Вряд ли есть какие-то общие методы типа стандартного заголовочного файла с описанием, потому как такими вещами пользуются сравнительно редко. Можно сделать, например, так (конкретные цифры взял от балды):

C
#if defined __386__
#  define CACHELINE 32
#elif defined __sparc__
#  define CACHELINE 64
#elif defined __arm__
#  define CACHELINE 128
#else
   /* Консервативное значение. Переменная, выровненная на 128 байт
    * автоматически будет выровнена на 16, 32, 64 */
#  define CACHELINE 128
#endif
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.12.2016, 14:10  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
int a[100] __attribute__((aligned(32)));
Не понял что означает эта запись

Цитата Сообщение от Evg Посмотреть сообщение
На уровне языка программирования обычно работа идёт с переменными. Как только ты выровнял начало переменной на нужный размер, то обо всех внутренностях переменной уже можно делать какие-то предположения. Если память выделена динамически, то ты всегда можешь прибавить к указателю нужное значение, чтобы обеспечить его выравненность.
То есть не важно память динамическая или стековая главное что бы при обращении к переменной или ключу массива, адрес переменной/ключа был выровнен так как нам это нужно?

Добавлено через 1 час 11 минут
Цитата Сообщение от sys_beginner Посмотреть сообщение
То есть не важно память динамическая или стековая главное что бы при обращении к переменной или ключу массива, адрес переменной/ключа был выровнен так как нам это нужно?
Скажем мы пишем пул для хранения объектов. Размер каждого объекта 57 байт. Нужно ли выделять место в пуле равное sizeof(object) * objects_count или нужно больше выделять для обеспечения выравнивания? И для каждого объекта добавлять свой padding? И как определить какое нужно выравнивание в конкретном случае?
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
10.12.2016, 14:21
Цитата Сообщение от sys_beginner Посмотреть сообщение
Не понял что означает эта запись
Это означает, что переменная при распределении в память попадёт по адресу, выровненному на 32

Цитата Сообщение от sys_beginner Посмотреть сообщение
То есть не важно память динамическая или стековая главное что бы при обращении к переменной или ключу массива, адрес переменной/ключа был выровнен так как нам это нужно?
Не совсем. Адрес НАЧАЛА нужного куска памяти должен быть выровнен. Т.е. если адрес начала переменной выровнен на 32, то, например, байты номер 32-65 внутри этой переменной гарантированно окажутся внутри одного кэшлайна. Т.е. программист может этим управлять и контролировать. Но если адрес начала выровнен только на 16, то такой гарантии уже не будет

Цитата Сообщение от sys_beginner Посмотреть сообщение
Скажем мы пишем пул для хранения объектов. Размер каждого объекта 57 байт. Нужно ли выделять место в пуле равное sizeof(object) * objects_count или нужно больше выделять для обеспечения выравнивания? И для каждого объекта добавлять свой padding?
Во первый адрес начала пула должен быть выровнен на 32. Далее адрес любого объекта в этом пуле должен быть выровнен на 32. После этого первые 32 байта любого объекта гарантированно будут в одном кэшлайне. То же самое можно сказать и про остаточные 25 байт любого объекта

Цитата Сообщение от sys_beginner Посмотреть сообщение
И как определить какое нужно выравнивание в конкретном случае?
Я вопроса не понимаю. Ты должен определиться, чего хочешь, и исходя из этого распределять объекты в памяти нужным тебе образом
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.12.2016, 14:34  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
Во первый адрес начала пула должен быть выровнен на 32.
Насколько я понимаю, new и malloc для этого не годятся и нужно пользоваться инструментами, которые могут в качестве параметра принимать нужное нам выравнивание? А цифра 32 это условно, в зависимости от размера линеек?
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
10.12.2016, 15:17
Цитата Сообщение от sys_beginner Посмотреть сообщение
Насколько я понимаю, new и malloc для этого не годятся и нужно пользоваться инструментами, которые могут в качестве параметра принимать нужное нам выравнивание?
Годятся, но с доработкой напильником. Допустим, тебе нужно выделить 1024 байта, но всегда выделаешь на 32 байта больше. Таким образом в первых 32 байтах всегда окажется точка, выровненная на 32. А первые несколько и последние несколько байт (в сумме 32) окажутся неиспользованными.

Здесь я говорю именно про кусок памяти, через new массив объектов напрямую, конечно же, так не выделишь. Т.е. через new нужно выделить кусок памяти (грубо говоря, массив char'ов), затем вычислить нужный адрес начала и через placement new натянуть массив объектов на эту память. Каждый объект можно искусственно добить нужным количеством неиспользуемых полей, чтобы размер каждого объекта был кратен 32 байтам

Цитата Сообщение от sys_beginner Посмотреть сообщение
А цифра 32 это условно, в зависимости от размера линеек?
Да. Цифра 32 везде фигурирует в том контексте, о котором я оговаривался в первом абзаце в посте #2
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.12.2016, 15:26  [ТС]
Кажется понял
Цитата Сообщение от Evg Посмотреть сообщение
Каждый объект можно искусственно добить нужным количеством неиспользуемых полей, чтобы размер каждого объекта был кратен 32 байтам
Это слегка муторно Если я все правильно понял, думаю самый нормальный вариант это как ты сказал для каждого объекта в пуле отдельно выделять память, например как массив char или с помощью operator new, размер которых будет равен sizeof объекта + столько байт, что бы размер объекта в пуле был кратен размеру кеш линии.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
10.12.2016, 15:30
Цитата Сообщение от sys_beginner Посмотреть сообщение
Это слегка муторно
Допустим, у тебя в объекте 57 полезных байт. Для простоты я их опишу в виде массива из 57 char'ов. Если ты искусственно добавишь ещё 7 байт (т.е. sizeof станет равным 64), то будет гораздо меньше возни с выравниванием отдельно взятого объекта или с реализацией массива объектов

C
struct MyObj
{
  char my_fields[57];
  char unused_padding[7];
}
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.12.2016, 15:38  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
то будет гораздо меньше возни с выравниванием отдельно взятого объекта или с реализацией массива объектов
Ну если инкапсулировать добавление паддингов в сам пул однотипных объектов и при каждом его расширении (выделении памяти для очередной пачки объектов) просто смотреть если sizeof меньше чем нам нужно, то добавлять нужный паддинг то думаю так будет удобнее. И не придется возиться с паддингами вручную в клиентском коде
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
10.12.2016, 15:41
А... ты в этом смысле. Ну тогда по сути да, надо весь геморрой локализовать в менеджере памяти (или хз как его правильно назвать)
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.12.2016, 16:04  [ТС]
Evg,
Ага
Спасибо тебе, очень помог!

Добавлено через 18 минут
Evg,
Ещё один вопрос назрел
Предположим длина линейки кеша равна 128 а размер объекта хранимого в пуле равен 63. Так как это пул объекты железно следуют друг за дружком(плотно расположены). Если выравнивать до 128 то получится нам нужно будет добавить 65 байт мусора если выравнивать каждый объект по размеру линейки.
Можно анализировать размер кеш линии (если есть такая возможность) и таким образом уместить в одной линейке не один объект, а два, прибавив по одному байту к каждому объекту сделав их размер 64. Затем проц запишет эти 128 байт в кеш и уже два объекта будут закешированы вместо одного. Но тут палка двух концов, насколько я понимаю, если один из этих двух объектов будет изменен, то будет сброшен кеш всей линии
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
10.12.2016, 16:13
Цитата Сообщение от sys_beginner Посмотреть сообщение
Предположим длина линейки кеша равна 128 а размер объекта хранимого в пуле равен 63
Если размер объекта меньше размера кэшлайна, то его надо помещать целиком вовнутрь одного кэшлайна. Т.е. внутри одного кэшлайна может оказаться несколько объектов

Цитата Сообщение от sys_beginner Посмотреть сообщение
Но тут палка двух концов, насколько я понимаю, если один из этих двух объектов будет изменен, то будет сброшен кеш всей линии
Как данные из кэша попадают в память - это отдельная долгая история. При этом сам процесс сброса кэша в память он не тормозит работу процессора. Реальные тормоза появляются только при чтении, т.к. если данные не считаны, то дальнейшая их обработка невозможна (поскольку в регистр ещё не записалось значение). А операция записи в память процессор никогда не тормозит, поскольку процессор отправил запрос на запись и пошёл дальше работать, обработка регистров от этого ведь не страдает
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.12.2016, 16:21  [ТС]
Evg,
Понял, спасибо!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.12.2016, 16:21
Помогаю со студенческими работами здесь

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

Короткое замыкание по линии 12 вольт дополнительного питания процессора
Добрый день.Если я что то упущу,извините.Но я в таком шоке,что нет слов. Материнская плата ASRock ZH77PRO3,вышла из строя,при перепаде...

Форма делится на сектора. Курсором мыши можно рисовать линии. Цвет линии зависит
Народ спасайте. Задача такова " Форма делится на сектора (их количество задает пользователь). Курсором мыши можно рисовать линии. Цвет...

Рисование дополнительной линии под углом к основной линии
Доброго времени суток, всем. Помогите решить вопрос. Есть макрос рисующий линию между двумя координатами. Как изменить макрос,...

Построить линии равного уровня (линии контура)
Ребята нужна строчная помощь нужно построить линии уровня функции Z=100*(x2-x1^3)^2+(1-x1)^2; в интервале x1 x2 Буду по гроб...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru