Pull to refresh

Comments 19

Так нужна-то автору была очередь или кольцевой буфер? Какой смысл обсуждать производительность, если это разные вещи по смыслу?

Нужна была FIFO очередь аудиоданных. Изначальна она работала на std::deque, но затем я заменил ее на кольцевой буфер boost::circular_buffer - естесственный выбор для аудио, тем более что ALSA сама использует кольцевой буфер. Семантика не изменилась, поэтому сравнение корректно; неожиданно, кольцевой буфер оказался значительно медленнее.

Как же семантика не изменилась, если кольцевой буфер закольцован? Его назначение - вытеснять старые блоки.

Закольцованность - это организация памяти, а вытеснение - лишь политика при переполнении. У меня запись шла только при наличии места, поэтому буфер оставался обычно ограниченной FIFO очередью.

Ну так и получили оверхед на поддержке ненужного вам вытеснения.

просто boost::circular_buffer это плохой буфер, полно более хороших реализаций

Похоже на то - по крайней мере в моем сценарии boost::circular_buffer значительно проиграл std::deque. Если можете посоветовать конкретную реализацию, было бы интересно сравнить.

Кольцевой буфер (непотокобезопасный, с фиксированным размером) довольно простая структура, под вашу задачу пилится за 2-3 часа в 200-400 строк кода. Плюс самописной реализации в том, что вы можете подогнать ее под ваши требования и выжать максимум.

Смысл своего велосипеда есть только если тебе нужны специфичные гарантии по latency, которых нет в стд

Странно, программируя на C++, так бояться велосипедов. Структура в пару сотен строк с примитивной логикой и уже тащить стороннюю библиотеку? Если так в себе не уверены, зачем вообще прогать на плюсах, есть питон, где все из коробки. Структуры STL носят универсальный характер и обязаны давать кучу гарантий из-за чего не могут быть максимально производительны для конкретной задачи, могут быть приемлимы.

Автор пилит аудиоочередь, где оптимальным был бы кольцевой буфер, вместо deque, так как кеш-френдли, выравнивание по 64 байт для avx512 и т.д. Но его не устроила усложненная реализация boost, которая опять же универсальна.

Я (условно я) пытаюсь написать обработку аудио, а не кольцевой буфер. Зачем мне писать кольцевой буфер?

Потому что кольцо будет ядром вашей обработки аудио, вы же хотите, чтобы пользователи были рады быстрой обработке, отсутствию фризов при аллокациях.

Вы лучше скажите зачем вам этого не делать, кроме экономии пары часов времени? Еще не известно, может на поиск подходящей библиотеки и ее внедрение в проект вы потратите больше. Я пока ни одного аргумента не услышал.

жиза жизовая) в поисках тонкого места иногда можно набрести на вообще неожиданные места

а еще во многих языках програмирования некторые веши оптимизированы асм-вставками под популярные процессоры и потому на реальных тестах может оказатся что "не оптимальный" алгоритм работы на самом деле оптимальнее чем "сделаный правильно"

Да, живой код регулярно ломает красивые теории :)

Поэтому профилировщик всегда должен быть открыт раньше, чем документация по структурам данных

Кольцевой буфер на то и кольцевой, что при чтении блоками всегда будет проблема перехода через границу массива)

А кто им мешал сделать это через две быстрые операции: чтение до конца массива и чтение от начала и до нужного индекса? Там же, наверное, не побайтное чтение?

Ну да, в boost есть части как достаточно оптимизированные на скорость, так и заточенные на “красоту” реализации. Например boost.crc32 - жуткий тормоз.

там еще ж нельзя просто в лоб написать memcpy, нужно смотреть что у тебя за тип T и можно ли с ним такое выделывать

и еще и от объемов данных зависит, на небольших объемах поэлементное копирование может быть быстрее

короче, не так просто реализовать такого рода оптимизацию корректно

Sign up to leave a comment.

Articles