FLOPs
FLOPs — это количество операций с плавающей точкой, необходимых модели для одного прямого прохода, и стандартная мера вычислительной стоимости. Как подсчитывать, сравнивать и сокращать их количество.
FLOPs (операции с плавающей точкой) — это количество арифметических операций, которые выполняет нейронная сеть для обработки одного входного элемента, например изображения или токена. В основном это умножения и сложения внутри слоёв сети. Эта величина характеризует вычислительную сложность модели независимо от оборудования, на котором она работает, поэтому её стандартно используют для сравнения ресурсоёмкости разных архитектур. Для моделей компьютерного зрения обычно указывают GFLOPs (миллиарды операций) для заданного размера входных данных; общее количество вычислений при обучении большой модели также измеряют во FLOPs.
FLOPs, FLOPS и MACs#
Эти три похожих термина легко перепутать:
- FLOPs (строчная s): количество операций с плавающей точкой; зависит от модели и размера входных данных. Показывает объём необходимых вычислений.
- FLOPS (заглавная S): количество операций с плавающей точкой в секунду; характеристика оборудования, например GPU. Показывает скорость вычислений, а деление FLOPs модели на пиковое значение FLOPS устройства даёт минимально возможное время выполнения.
- MACs: операции умножения с накоплением. Одна MAC — это одно умножение и одно сложение, поэтому одна MAC равна двум FLOPs. В некоторых статьях и инструментах MACs указывают под названием FLOPs, из-за чего значения оказываются вдвое меньше.
Как подсчитывают FLOPs#
Основная часть FLOPs сети приходится на умножения матриц и свёртки. Полносвязный слой с n входами и m выходами требует около 2 × n × m FLOPs для одного входного элемента. Свёртка вычисляет скалярное произведение для каждого выходного значения, поэтому её стоимость составляет 2 × C_in × k × k × C_out × H_out × W_out, где k — размер ядра, а H_out × W_out — разрешение выходных данных. Функции активации, нормализация и сложение добавляют сравнительно мало вычислений. Пример ниже рассчитывает стоимость одной свёртки по формуле и проверяет её с помощью встроенного счётчика FLOPs в PyTorch:
import torch
from torch.utils.flop_counter import FlopCounterMode
# A 3x3 convolution mapping 64 channels to 128 on an 80x80 feature map
conv = torch.nn.Conv2d(64, 128, kernel_size=3, padding=1, bias=False)
x = torch.randn(1, 64, 80, 80)
# Each output value needs 64*3*3 multiply-accumulates (MACs); 1 MAC = 2 FLOPs
macs = 128 * 80 * 80 * 64 * 3 * 3
print(f"By formula: {2 * macs / 1e9:.3f} GFLOPs ({macs / 1e9:.3f} GMACs)")
# PyTorch's FLOP counter traces the real forward pass
with FlopCounterMode(display=False) as counter:
conv(x)
print(f"Counted: {counter.get_total_flops() / 1e9:.3f} GFLOPs")Обе строки выводят 0,944 GFLOPs, а в строке с формулой тот же слой представлен как 0,472 GMACs — вдвое меньше, чем значение FLOPs. Для трансформеров прямой проход требует около 2 FLOPs на параметр и токен, а обучение — около 6. Это эмпирическое правило из исследований законов масштабирования, позволяющее оценить общие вычислительные затраты на обучение как 6 × количество параметров × количество обучающих токенов.
FLOPs и реальная скорость#
FLOPs лишь приблизительно предсказывают скорость. Задержка также зависит от трафика памяти, степени распараллеливания каждой операции и наличия на оборудовании оптимизированных ядер для неё. В статье о ShuffleNet V2 показано, что сети с сопоставимыми FLOPs могут заметно различаться по скорости на одном устройстве, а глубинные свёртки, требующие мало FLOPs, часто ограничены пропускной способностью памяти, а не вычислениями. Оптимизации тоже воздействуют на разные факторы. Прореживание модели и уменьшение размера входных данных сокращают число операций, а квантование модели не меняет их число, но делает каждую операцию дешевле за счёт вычислений с 8-битными целыми числами. Поэтому FLOPs лучше всего использовать для первичного отбора перед измерением задержки инференса на целевом устройстве, например в режиме бенчмаркинга Ultralytics:
FLOPs при выборе модели#
Семейства моделей выпускаются в нескольких размерах, чтобы команды могли обменивать точность на вычислительную мощность; этот выбор подробно разбирается в уроке Ultralytics Academy о размере модели. Ultralytics YOLO26 требует от 5,5 GFLOPs для YOLO26n до 194,4 GFLOPs для YOLO26x при входном размере 640×640, а model.info() выводит GFLOPs любой загруженной модели. Дроны и телефоны с батарейным питанием используют самые компактные варианты, а облачные серверы могут позволить себе самые крупные. Поскольку вычислительная стоимость свёрточной сети зависит от числа пикселей, размер входных данных влияет на FLOPs не меньше, чем размер модели:
from ultralytics import YOLO
from ultralytics.utils.torch_utils import get_flops
# Load the smallest YOLO26 detection model and fuse its layers, as for inference
model = YOLO("yolo26n.pt")
model.fuse()
# Count GFLOPs for the same model at three input resolutions
for imgsz in [320, 640, 1280]:
print(f"{imgsz}px: {get_flops(model.model, imgsz):.1f} GFLOPs")Цикл выводит 1,3, 5,5 и 23,4 GFLOPs: каждое удвоение стороны входного изображения примерно учетверяет это значение. Поэтому запуск YOLO26n при разрешении 1280 пикселей требует больше вычислений, чем 20,9 GFLOPs у YOLO26s с вчетверо большим количеством параметров при разрешении 640.










