Проект сравнивает производительность нескольких реализаций обработки PNG-изображений на C++.
Реализованы две задачи:
- вычисление суммы абсолютных разностей между соседними пикселями;
- преобразование изображения из RGB(A) в YUV.
Для каждой задачи есть три варианта реализации:
- наивный;
- векторизованный с использованием AVX2-интринсиков;
- многопоточный на основе собственного
ThreadPool.
Для измерения производительности используется google/benchmark.
Пример входного изображения:
main.cppсобирает список PNG-файлов, регистрирует бенчмарки и запускает их.inc/task.h,src/task.cppсодержат загрузку PNG и реализацииsimple8,intrinsic8,threads8,simple11,intrinsic11,threads11.inc/threadpool.h,src/threadpool.cppсодержат реализацию пула потоков.images/содержит входные изображения.scripts/plot_benchmarks.pyстроит графики поbuild/results.json.scripts/run_benchmarks.shиспользует существующийbuild/results.jsonдля построения графиков, а если файла нет, сначала запускает бенчмарк.
- Программа получает путь к папке с PNG-файлами.
- Для каждого изображения регистрируются бенчмарки для всех реализаций.
- Для многопоточных реализаций параметр
nменяется от 2 до 6. google/benchmarkизмеряет время выполнения и пропускную способность.- Результаты можно сохранить в JSON и затем построить по ним графики.
Для сборки нужны:
- компилятор C++ с поддержкой C++17;
cmake3.14 или новее;libpng;git;- доступ в интернет при первой сборке, так как
google benchmarkзагружается черезFetchContent; - процессор с поддержкой
AVX2.
Для построения графиков нужны Python-библиотеки:
pandas;matplotlib;numpy.
Пример установки зависимостей на Ubuntu/Debian:
sudo apt update
sudo apt install build-essential cmake libpng-dev git python3 python3-pip python3-venvРекомендуется создать виртуальное окружение:
python3 -m venv .venv
source .venv/bin/activate
pip install pandas matplotlib numpyСкрипты scripts/run_benchmarks.sh и scripts/plot_benchmarks.py автоматически пытаются использовать .venv или venv, если такое окружение есть в корне проекта.
Из корня проекта:
cmake -S . -B build
cmake --build buildИсполняемый файл:
./build/labЗапуск на тестовых изображениях:
./build/lab ./imagesЗапуск с сохранением результатов:
./build/lab ./images --benchmark_out=build/results.json --benchmark_out_format=json --benchmark_time_unit=msЕсли папка не существует или в ней нет PNG-файлов, программа завершится с ошибкой.
Если build/results.json уже существует и он корректный:
python3 scripts/plot_benchmarks.py build/results.jsonСкрипт:
- нормализует время в миллисекунды;
- автоматически делит изображения на группы
smallиlarge; - сохраняет графики времени и пропускной способности в корень проекта.
Создаются файлы:
time_8_small.pngtime_8_large.pngtime_11_small.pngtime_11_large.pngthroughput_8_small.pngthroughput_8_large.pngthroughput_11_small.pngthroughput_11_large.png
Если build/results.json поврежден или обрезан, скрипт сообщит об этом и попросит пересоздать файл.
Команда:
bash scripts/run_benchmarks.shПоведение:
- если
build/results.jsonуже есть и он валидный, скрипт только строит графики; - если
build/results.jsonнет, скрипт ожидает путь к папке с PNG и сначала запускает бенчмарк; - если
build/results.jsonповрежден, скрипт завершится с сообщением об ошибке.
Запуск с автоматическим созданием results.json, если его нет:
bash scripts/run_benchmarks.sh ./imagessimple8() последовательно считает сумму абсолютных разностей по RGB-каналам:
- между соседними пикселями по горизонтали;
- между соседними пикселями по вертикали.
intrinsic8() выполняет те же вычисления с помощью AVX2.
threads8() делит изображение на части по строкам и распределяет вычисления через ThreadPool.
simple11() поэлементно преобразует каждый пиксель из RGB в YUV.
intrinsic11() выполняет ту же операцию векторно с использованием AVX2.
threads11() делит массив пикселей на части и выполняет преобразование параллельно.
- PNG-файлы загружаются через
libpngи приводятся к формату RGBA. - Размер пула потоков выбирается автоматически по числу доступных аппаратных потоков, но не более 6.
- Бенчмарки используют
bytes_per_secondиreal_time, которые затем читаются Python-скриптом.
cmake -S . -B build
cmake --build build
python3 -m venv .venv
source .venv/bin/activate
pip install pandas matplotlib numpy
./build/lab ./images --benchmark_out=build/results.json --benchmark_out_format=json --benchmark_time_unit=ms
python3 scripts/plot_benchmarks.py build/results.json