Сохранить читабельность кода при оптимизации - PullRequest
18 голосов
/ 04 сентября 2011

Я пишу научную программу на Python и C с некоторыми сложными алгоритмами физического моделирования.После реализации алгоритма я обнаружил, что существует множество возможных оптимизаций для повышения производительности.Распространенными являются предварительные вычисления значений, вывод вычислений из цикла, замена простых матричных алгоритмов более сложными и другие.Но возникает проблема.Неоптимизированный алгоритм намного медленнее, но его логика и связь с теорией выглядят гораздо более понятными и читаемыми.Также сложнее расширять и модифицировать оптимизированный алгоритм.

Итак, вопрос в том, какие методы следует использовать, чтобы сохранить читабельность при одновременном повышении производительности?Сейчас я стараюсь держать как быстрые, так и четкие ветви и развивать их параллельно, но, может быть, есть лучшие методы?

Ответы [ 4 ]

15 голосов
/ 04 сентября 2011

Так же, как общее замечание (я не слишком знаком с Python): я бы посоветовал вам убедиться, что вы можете легко обмениваться медленными частями 'эталонной реализации' с 'оптимизированными' детали (например, используйте что-то вроде шаблона Strategy ).

Это позволит вам провести перекрестную проверку результатов более сложных алгоритмов (чтобы убедиться, что вы не испортили результаты) и сохранит общую структуру алгоритма моделирования прозрачной ( разделение интересов ). Вы можете разместить оптимизированные алгоритмы в отдельных исходных файлах / папках / пакетах и ​​документировать их отдельно, настолько подробно, насколько это необходимо.

Помимо этого, попробуйте избегать обычных ловушек : не делайте преждевременную оптимизацию (проверьте, действительно ли это того стоит, например, с помощью профилировщика), и не изобретайте колесо заново (ищите доступные библиотеки).

3 голосов
/ 05 сентября 2011

Обычно предполагается, что вы должны отказаться от читабельности, чтобы получить производительность.

Это не обязательно так.

Вам нужно выяснить Что именно он тратит на это много времени и почему ?

Обратите внимание, я не говорил, что вам нужно делать измерения.

Вот пример того, что я имею в виду.

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

3 голосов
/ 04 сентября 2011

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

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

Было бы замечательно, если бы я мог поддерживать два параллельных потока кода: наивный способ и более сложный оптимизированный способ.Но мне это никогда не удавалось.

Суть в том, что если я могу писать четкие, полные, лаконичные, точные и актуальные комментарии, это лучшее, что я могу сделать.

Еще одна вещь, которую вы уже знаете: оптимизация, как правило, не означает подкладывание тонны кода в одну строку исходного кода, возможно, путем вызова функции, аргумент которой является другой функцией, аргумент которой является другой функцией, аргумент которой еще не задандругая функция.Я знаю, что некоторые делают это, чтобы избежать временного хранения значения функции.Но это очень мало (как правило, ничего) для ускорения кода, и это сука, чтобы следовать.Нет новостей для тебя, я знаю.

1 голос
/ 05 сентября 2011
def whatYouShouldDo(servings, integration_method=oven):
    """
        Make chicken soup
    """
    # Comments:
    # They are important. With some syntax highlighting, the comments are
    # the first thing a new programmer will look for. Therefore, they should
    # motivate your algorithm, outline it, and break it up into stages.
    # You can MAKE IT FEEL AS IF YOU ARE READING TEXT, interspersing code
    # amongst the text.
    #
    # Algorithm overview:
    # To make chicken soup, we will acquire chicken broth and some noodles.
    # Preprocessing ingredients is done to optimize cooking time. Then we 
    # will output in SOUP format via stdout.
    #
    # BEGIN ALGORITHM
    #
    # Preprocessing:
    # 1. Thaw chicken broth.
    broth = chickenstore.deserialize()

    # 2. Mix with noodles
    if not noodles in cache:
        with begin_transaction(locals=poulty) as t:
            cache[noodles] = t.buy(noodles)  # get from local store
    noodles = cache[noodles]

    # 3. Perform 4th-order Runge-Kutta numerical integration
    import kitchensink import *  # FIXME: poor form, better to from kitchensink import pan at beginning
    result = boilerplate.RK4(broth `semidirect_product` noodles)

    # 4. Serve hot
    log.debug('attempting to serve')
    return result
    log.debug('server successful')

также см. http://en.wikipedia.org/wiki/Literate_programming#Example

Я также слышал, что это то, с чем http://en.wikipedia.org/wiki/Aspect-oriented_programming пытается помочь, хотя я на самом деле не рассматривал это.(Кажется, это просто причудливый способ сказать, что «поместите ваши оптимизации, ваши отладки и другой мусор вне функции, которую вы пишете».)

...