Автор: Дмитрий Чудаков

Редактура: Александр Гончаренко

Введение

В жизни каждого DL-инженера рано или поздно появляется задача ужать нейронку. В самом простом случае проблема связана с нехваткой памяти видеокарты. Например, на этапе обучения мы используем изображения небольшого размера, но на инференсе приходится обрабатывать огромные изображения, которые нельзя разбить на части (как в задачах Image2Image или Depth Estimation). Иногда цель более сложная — ускорить время инференса сети. И в такие моменты появляется идея использовать другие типы чисел с меньшей разрядностью. Давайте разберёмся, как это делается и с какими трудностями здесь можно столкнуться.

Что такое floats?

Floats нужны для удобного представления чисел в широком диапазоне: от 0.00034 до 100000342.12. Начнём с простого примера — посмотрим, как выглядит число 33 в целочисленном формате. В двоичной системе оно представляется таким образом:

$$ 00000000 \ 00000000 \ 00000000 \ 00100001 $$

Формула для расчёта:

$$ 2^{31} + 0 ⋅ 2^{30} + … + 1 ⋅ 2^5 + 0 ⋅ 2^4 + … + 1 ⋅ 2^0 = 33 $$

С числами с плавающей запятой всё немного сложнее. Они состоят из трёх частей: знака, экспоненты и мантиссы. Формула выглядит таким образом:

$$ x = (-1)^S ⋅ (1.M) ⋅ 2^{E-127} $$

Где:

Пример: число 33 в формате float

Двоичное представление:

$$ 0 \ 10000100 \ 00000100000000000000000 $$

  1. Структура:
  2. Расчёт: