- PVSM.RU - https://www.pvsm.ru -

Визуализатор структуры адреса на Си для Linux и Termux: Попасть в «Голову» кеш-линии

В 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

  • Утилита после запуска

    Утилита после запуска

    Адрес жёлтого цвета это выровненный массив по кеш-линии

  • Адрес красного цвета это адрес случайного массива

Визуализатор структуры адреса на Си для Linux и Termux: Попасть в «Голову» кеш-линии - 5

ЗЕЛЁНАЯ ЛИНИЯ: Десятичное представление двоичного числа.

  • РОЗОВАЯ ЛИНИЯ: Номер набора.

  • СИНЯЯ ЛИНИЯ: Номер разряда.

  • БЕЛЫЕ ЛИНИИ: Двоичное представление адреса памяти.

Первый адрес заканчивается на 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 ".

  • Можно выводить множество сообщений где ты находишься в кеш, на странице, можем расписать тэги.

Ссылка на GitHub

https://github.com/Data7Viz/addr_bit [1]

Автор: 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