Иногда есть 1% кода, который является достаточно интенсивным в вычислительном отношении и требует самого тяжелого вида низкоуровневой оптимизации. Примерами являются обработка видео, обработка изображений и все виды обработки сигналов в целом.
Цель состоит в том, чтобы документировать и обучать методам оптимизации, чтобы код не становился неуправляемым и не склонным к удалению новыми разработчиками. (*)
(*) Несмотря на возможность того, что конкретная оптимизация совершенно бесполезна в некоторых непредвиденных будущих процессорах, так что код все равно будет удален.
Учитывая, что программные предложения (коммерческие или с открытым исходным кодом) сохраняют свои конкурентные преимущества благодаря наличию самого быстрого кода и использованию новейшей архитектуры ЦП, разработчикам программного обеспечения часто приходится настраивать свой код, чтобы он работал быстрее, получая при этом тот же результат для определенного задание, whlist допускает небольшое количество ошибок округления.
Как правило, разработчик программного обеспечения может хранить множество версий функции в виде документации каждой перезаписи оптимизации / алгоритма, которая имеет место. Как сделать эти версии доступными для других, чтобы изучить их методы оптимизации?
Связанные с:
Ответы:
Краткий ответ
Сохраняйте оптимизации локальными, делайте их очевидными, хорошо документируйте их и упростите сравнение оптимизированных версий друг с другом и с неоптимизированной версией как с точки зрения исходного кода, так и с точки зрения производительности во время выполнения.
Полный ответ
Если такая оптимизация действительно так важна для вашего продукта, вам нужно не только знать, почему оптимизации были полезны раньше, но и предоставлять достаточно информации, чтобы помочь разработчикам понять, будут ли они полезны в будущем.
В идеале вам необходимо включить тестирование производительности в процесс сборки, чтобы вы могли узнать, когда новые технологии делают недействительными старые оптимизации.
Помнить:
Для того, чтобы узнать, настало ли сейчас время, требуется бенчмаркинг и тестирование.
Как вы упоминаете, самая большая проблема с высокооптимизированным кодом заключается в том, что его трудно поддерживать, поэтому, насколько это возможно, вы должны держать оптимизированные части отдельно от неоптимизированных частей. Делаете ли вы это через компиляцию во время компиляции, вызовы виртуальных функций во время выполнения или что-то среднее между ними, не должно иметь значения. Важно иметь в виду, что когда вы запускаете свои тесты, вы хотите иметь возможность протестировать все версии, которые вас интересуют.
Я был бы склонен построить систему таким образом, чтобы базовая неоптимизированная версия производственного кода всегда могла использоваться для понимания цели кода, а затем создавать различные оптимизированные модули наряду с этим, содержащим оптимизированную версию или версии, явно документируя где бы то ни было оптимизированная версия отличается от базовой линии. Когда вы запускаете свои тесты (модуль и интеграция), вы запускаете его на неоптимизированной версии и на всех текущих оптимизированных модулях.
пример
Например, допустим, у вас есть функция быстрого преобразования Фурье . Может быть, у вас есть базовая алгоритмическая реализация
fft.c
и тесты вfft_tests.c
.Затем приходит Pentium, и вы решаете реализовать версию
fft_mmx.c
с фиксированной запятой, используя инструкции MMX . Позже Пентиум 3 приходит и вы решили добавить версию , которая использует Streaming SIMD Extensions вfft_sse.c
.Теперь вы хотите добавить CUDA , поэтому вы добавляете
fft_cuda.c
, но обнаруживаете, что с набором тестовых данных, который вы использовали годами, версия CUDA медленнее, чем версия SSE! Вы делаете некоторый анализ и в итоге добавляете набор данных, который в 100 раз больше, и вы получаете ускорение, которое вы ожидаете, но теперь вы знаете, что время установки для использования версии CUDA является значительным и что с небольшими наборами данных вы должны использовать Алгоритм без этой стоимости установки.В каждом из этих случаев вы реализуете один и тот же алгоритм, все должны вести себя одинаково, но будут работать с разной эффективностью и скоростью на разных архитектурах (если они вообще будут работать). Однако с точки зрения кода вы можете сравнить любую пару исходных файлов, чтобы выяснить, почему один и тот же интерфейс реализован по-разному, и, как правило, самый простой способ - вернуться к исходной неоптимизированной версии.
Все то же самое относится к реализации ООП, где базовый класс, который реализует неоптимизированный алгоритм, и производные классы реализуют различные оптимизации.
Важно сохранять одинаковые вещи одинаковыми , чтобы различия были очевидны .
источник
В частности, поскольку вы взяли пример обработки видео и изображений, можно сохранить код как часть той же версии, но активным или неактивным в зависимости от контекста.
Пока вы не упомянули, я предполагаю
C
здесь.Самый простой способ в
C
коде - оптимизировать (а также применять при попытке сделать вещи переносимыми) - это сохранитьКогда вы включаете
#define OPTIMIZATION_XYZ_ENABLE
во время компиляции в Makefile, все работает соответственно.Обычно, сокращение нескольких строк кода в середине функций может стать грязным, если оптимизировано слишком много функций. Следовательно, в этом случае определяются разные указатели функций для выполнения определенной функции.
основной код всегда выполняется через указатель на функцию, например
Но указатели функций определяются в зависимости от типа примера (например, здесь функция idct оптимизирована для другой архитектуры ЦП.
вы должны увидеть код libjpeg и код libmpeg2 и, возможно, использовать ffmpeg для таких методов.
источник
Как исследователь я заканчиваю тем, что пишу довольно много кода "узкого места". Однако, как только он будет запущен в производство, ответственность за его интеграцию в продукт и последующую поддержку ложится на разработчиков. Как вы можете себе представить, четкое информирование о том, что и как должна работать программа, имеет первостепенное значение.
Я обнаружил, что есть три основных ингредиента для успешного завершения этого шага
Для первого шага я всегда пишу краткий технический документ, который документирует алгоритм. Цель здесь состоит в том, чтобы фактически написать это так, чтобы другой человек мог реализовать это с нуля, используя только технический документ. Если это хорошо известный, опубликованный алгоритм, достаточно дать ссылки и повторить ключевые уравнения. Если это оригинальная работа, вам нужно быть немного более явным. Это скажет вам, что код должен делать .
Фактическая реализация, которая передается в разработку, должна быть задокументирована таким образом, чтобы все тонкости были явными. Если вы получаете блокировки в определенном порядке, чтобы избежать тупика, добавьте комментарий. Если вы выполняете итерации по столбцам, а не по строкам матрицы из-за проблем с согласованием кэша, добавьте комментарий. Если вы делаете что-то даже немного умное, прокомментируйте это. Если вы можете гарантировать, что технический документ и код никогда не будут разделены (через VCS или аналогичную систему), вы можете обратиться к техническому документу. Результатом может быть более 50% комментариев. Все в порядке. Это скажет вам, почему код делает то, что делает.
Наконец, вы должны быть в состоянии гарантировать правильность перед лицом изменений. К счастью, мы удобный инструмент для автоматизированного тестирования и непрерывной интеграции платформ. Они скажут вам, что на самом деле делает код .
Моя самая сердечная рекомендация - не экономить ни на одном из шагов. Они вам понадобятся позже;)
источник
Я считаю, что это лучше всего решить путем всестороннего комментирования кода до такой степени, что каждый значимый блок кода имеет предварительное комментирующее комментирование.
Комментарии должны включать ссылки на спецификации или аппаратный справочный материал.
При необходимости используйте общеотраслевую терминологию и имена алгоритмов - например, «архитектура X генерирует прерывания ЦП для не выровненных чтений, поэтому это устройство Даффа заполняет до следующей границы выравнивания».
Я бы использовал именование переменных in-your-face, чтобы избежать недопонимания происходящего. Не венгерский, но такие вещи, как «шаг», чтобы описать расстояние в байтах между двумя вертикальными пикселями.
Я также дополнил бы это коротким, удобочитаемым документом, который имеет диаграммы высокого уровня и блочный дизайн.
источник