Иногда у вас просто есть алгоритмы, которые не могут быть лучше линейного времени, для которого все еще существует высокий спрос на производительность.
Примером является обработка видео, когда вы не можете сделать изображение / кадр более ярким в качестве базового примера без циклического прохождения каждого пикселя (ну, я полагаю, вы можете с некоторой иерархической структурой, указывающей свойства, унаследованные дочерними элементами, которые в конечном итоге спускаются в фрагменты изображения для конечных узлов, но тогда вы откладываете на рендереру более высокую стоимость зацикливания каждого пикселя, и код, вероятно, будет сложнее поддерживать, чем даже самый микрооптимизированный фильтр изображений).
В моей области много таких случаев. Я склонен делать больше циклов линейной сложности, которые должны касаться всего или читать все, чем те, которые извлекают выгоду из какой-либо сложной структуры данных или алгоритма. Там нет работы, которая может быть пропущена, когда все должны быть затронуты. Таким образом, в этот момент, если вы неизбежно имеете дело с линейной сложностью, вы должны сделать работу, выполняемую за итерацию, все дешевле и дешевле.
Поэтому в моем случае наиболее важными и распространенными оптимизациями часто являются представления данных и макеты памяти, многопоточность и SIMD (обычно в таком порядке, причем представление данных является наиболее важным, поскольку оно влияет на способность выполнять последние два). Я не сталкиваюсь с таким количеством проблем, которые решаются с помощью деревьев, хеш-таблиц, алгоритмов сортировки и тому подобного. Мой ежедневный код больше похож на то, что "для каждой вещи, сделай что-нибудь".
Конечно, это другой случай, когда нужно говорить о необходимости оптимизации (и, что более важно, когда ее нет), микро или алгоритмической. Но в моем конкретном случае, если критический путь выполнения требует оптимизации, выигрыш в скорости 10x + часто достигается за счет оптимизаций на микроуровне, таких как многопоточность, SIMD и переупорядочение схем памяти и шаблонов доступа для улучшения местоположения ссылки. Я не так часто, скажем, заменяю пузырьковую сортировку на интросортную или радикальную сортировку или обнаружение столкновений квадратичной сложности с помощью BVH настолько, насколько нахожу горячие точки, которые, скажем, выигрывают от расщепления горячих / холодных полей.
Теперь в моем случае моя область настолько критична к производительности (трассировка лучей, физические движки и т. Д.), Что медленный, но совершенно правильный трассировщик лучей, для визуализации которого требуется 10 часов, часто считается бесполезным или более быстрым, полностью интерактивным, но выводит самые уродливые изображения с лучами, протекающими повсюду из-за отсутствия пересечения водонепроницаемых лучей / три. Скорость, возможно, является основной метрикой качества такого программного обеспечения, возможно, даже больше, чем корректность в какой-то момент (поскольку «правильность» - это нечеткая идея с трассировкой лучей, поскольку все приближается, пока оно не дает сбой или что-то в этом роде). И когда это так, если я не думаю об эффективности заранее, я нахожу, что мне действительно нужно изменить код на самом дорогом уровне проектирования, чтобы обрабатывать более эффективные проекты. Так что, если я не
Игры - это еще одно поле, похожее на мое. Неважно, насколько правильна ваша игровая логика или насколько удобна и блестяще спроектирована ваша кодовая база, если ваша игра работает со скоростью 1 кадр в секунду, как слайд-шоу. В некоторых областях отсутствие скорости может фактически сделать приложение бесполезным для его пользователей. В отличие от игр, в таких областях, как трассировка лучей, нет «достаточно хорошей» метрики. Пользователи всегда хотят большей скорости, а промышленная конкуренция состоит в основном в поиске более быстрых решений. Он никогда не будет достаточно хорош до реального времени, когда игры будут использовать трассировщики пути. И тогда это, вероятно, все еще не будет достаточно хорошо для VFX, с тех пор художники могли бы хотеть загружать миллиарды полигонов и имитировать частицы с самовоздействием среди миллиардов частиц при 30 + FPS.
Теперь, если это удобно, несмотря на это, я все еще пишу около 90% кода на языке сценариев (Lua), не заботясь о производительности. Но у меня есть необычайно большой объем кода, который действительно должен проходить через миллионы и миллиарды вещей, и когда вы перебираете миллионы и миллиарды вещей, вы начинаете замечать грандиозную разницу между наивным однопоточным кодом, который вызывает ошибку кэша при каждой итерации или, скажем, векторизованном коде, работающем в параллельном доступе к смежным блокам, где в строку кэша не загружаются ненужные данные.