- PVSM.RU - https://www.pvsm.ru -
В 47 мои увлечения стали Си, Radare2 , Биты, Логика, Память. Изучая память зацепился за адреса. На адрес 0x7ffe10b284 можно смотреть бесконечно долго. Трудно сказать с ходу насколько удачно ваши данные легли в память. Влезают они в одну кеш-линию или размазаны по двум. Чтоб не заниматься битовой арифметикой в уме, я написал утилиту на Си для Linux и Termux. Она раскладывает младшие 12 бит адреса на 4 строки визуализации. Теперь сразу видно, попали мы в "Голову" или застряли в "Хвосте" кеш-линии.
Утилита максимально легковесная. Вам не нужны сложные дебаггеры, достаточно gcc. Работает, как на десктопном Linux, так и в Termux на Android. Можно проверить выравнивание даже лёжа на диване.
В современных процессорах (х86_64, ARM) память нарезана на блоки по 64 байта - это и есть кеш-линия. Процессор не умеет забирать из памяти один байт, он всегда тянет всю линию целиком.
Если ваша структура данных (например 16 интов) начинается в начале этой линии (адрес кратен размеру данных 64), она ложится в ее "Голове". Если же адрес смещен к концу блока (ближе к 63-му биты), данные попадают в хвост.
Представьте вашу структуру массив на 16 интов (это как раз 64 байта размер кеш-линии). И вы не расположили так, что 8 интов лежат в конце одной кеш-линии в "Хвосте" , в остальные 8 в начале следующей.
РЕЗУЛЬТАТ: Процессору придётся выкачивать две линии вместо одной. Поход в память это дорого. Процессору в этом случае приходится ждать заряд, разряд конденсаторов.
ИТОГИ: Лишние такты, посадка производительности, не эффективное использование кеш L1.
АККУМУЛЯТОР: Каждая лишняя активная линия это мизерный но реальный ток. В масштабах миллионов операций в секунду это превращается в повышенный расход АКБ. Что особенно критично для мобильных устройств.
Я новичок мой код скорее всего кривой и косой. Я хочу визуализировать адрес памяти.
Логика простая: мы берём адрес переменной, разглаживает на биты и смотрим карту где мы находимся. Смещение страницы, кеш, номер набора и все остальное.
#include <stdio.h>
#include <stdint.h>
#define RAZR 12 //колличество разрядов выводим на печать
#define GEL "33[1;33m"
#define RED "33[1;31m"
#define GRIN "33[1;32m"
#define ROZ "33[1;35m"
#define SIN "33[1;34m"
#define RES "33[0m"
void hex_dec_nom_raz()
{
printf("nn");
int dec = 1; // строка десятичное представление двоичного числа dec
for (int i = 0; i < RAZR; i ++)
{
printf(GRIN "%8d" RES , dec);
dec = dec << 1;
}
printf("nn");
for (int i = 0; i < RAZR; i ++) // строка для вычисления номера индекса номер набора
{
printf(ROZ "%8d" RES ,1 << (i % 6));
}
printf("nn");
for (int j = 0; j < RAZR; j ++) // строка для номер разряда
{
printf(SIN "%8d" RES , j);
}
printf("nn");
}
int bin_addr (uint64_t addr) //функция двоичного вида адреса
{
int bin, offset_kech, mask = 63;
for (int i = 0; i < RAZR; i ++)
{
bin = (addr >> i) & 1; // для цветного вывода единиц
if (bin == 1)
{
printf(RED "%8d" RES, bin);
}
else
{
printf("%8d", bin);
}
}
offset_kech = addr & mask; // смотрим смещение в КЭШ линии
if ( offset_kech != 0 )
{
printf(GEL "nРасстояние до головы КЕШ линии > %d < байт n" RES, offset_kech);
}
else
{
printf(GEL "nТы попал в головуn" RES);
}
printf("n");
return 0;
}
int main ()
{
uint64_t addr_mem;
hex_dec_nom_raz ();
while (1)
{
if (scanf("%li", &addr_mem) == 1)
{
bin_addr (addr_mem);
}
else
{
break;
}
}
return 0;
Сравним два адреса. Чтоб окончательно убедиться в пользе визуализатор, я сравниваю два случая.
Пишем две маленькие программы. В каждой программе массив, один случайный, другой выровненный по кеш-линии. И нам нужно вывести адреса нулевых элементов.
Массив со случайным адресом < vim mas_random.c>
Массив выровненный по кеш-линии <vim mas_alig.c>
gcc mas_alig.c -o mas_alig
gcc mas_random.c -o mas_random
./mas_alig
./mas_random
./bin_analiz_addt
Адрес жёлтого цвета это выровненный массив по кеш-линии
Адрес красного цвета это адрес случайного массива

ЗЕЛЁНАЯ ЛИНИЯ: Десятичное представление двоичного числа.
РОЗОВАЯ ЛИНИЯ: Номер набора.
СИНЯЯ ЛИНИЯ: Номер разряда.
БЕЛЫЕ ЛИНИИ: Двоичное представление адреса памяти.
Первый адрес заканчивается на 0х80 это выровненный массив по кеш-линии. Единица в 7 разряде. Мы положили свои 16 интов в одну кеш-линию. ( Потом мы можем прочитать смещение страницы нам до "Головы" 128 байт. 4096 - 128 полученная цифра расстояние до "Хвоста" (до конца страницы). Номер набора 2 розовая линия с 6 по 11 разряды.
Второй адрес заканчивается 0х7с это адрес случайного массива. Две кеш-линии не избежны. Мы находимся в средине страницы сложи 1024+512+256+64+32+16+8+4. Номер набора 1 +4+8+16.
Здесь на самом деле много информации
Мы можем управлять разрядностью #define RAZ.
Вводить сколько угодно адресов.
DEC or HEX
Выход из программы любой символ я применяю стандарт " q ".
Можно выводить множество сообщений где ты находишься в кеш, на странице, можем расписать тэги.
Автор: DataViz
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/kesh/450192
Ссылки в тексте:
[1] https://github.com/Data7Viz/addr_bit: https://github.com/Data7Viz/addr_bit
[2] Источник: https://habr.com/ru/articles/1026430/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1026430
Нажмите здесь для печати.