Код с промежуточными вычислениями — какой стиль более эффективен?

#python #performance

#python #Производительность

Вопрос:

У меня есть функция, которая выполняет ряд вычислений для переменной массива. Код будет выполняться на дешевом одноплатном компьютере с низкой производительностью (например, Raspberry Pi, я не знаю точную плату в настоящее время). Эта функция является основной функцией всей программы. Я требую, чтобы программа работала быстро даже с большими данными, присутствующими в переменной массива. Я беспокоюсь об управлении памятью и общей скорости программы. Я думаю о двух способах для этого.

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

Вариант 1:

 def function_1(a):
    #some code
    b = computation_1(a)
    #some code
    c = computation_2(b)
    #some code
    d = computation_3(c)
    #some code
    return d
  

Вариант 2:

 def function_2(a):
    #some code
    a = computation_1(a)
    #some code
    a = computation_2(a)
    #some code
    a = computation_3(a)
    #some code
    return a
  

Примечание: я знаю об этом стиле кодирования:

 computation_2(computation_1(a))
...
  

Однако из-за разной природы различных функций мне нужно выполнить некоторую предварительную обработку перед отправкой им, представленную «#some code»

Комментарии:

1. Протестируйте обе версии и узнайте?

2. @AndrewHenle Я не знаю или у меня сейчас нет SBC, и моя программа может позже использоваться на разных платформах. Отсюда мой вопрос

3. @TransistorOverlord Бенчмарк на ПК. Использование памяти и относительная производительность будут одинаковыми на ПК и SBC.

4. Обязательно ли вам использовать Python? Обычно потребление памяти и эффективность процессора скомпилированного языка, такого как Rust или C , будут лучше. (Но попробуйте и посмотрите — получите RasPi и прототип на нем)

Ответ №1:

Обычно разница во времени процессора будет незначительной.

Однако вариант 1 создает b и c, и только когда он вернется, b и c будут доступны для сборки мусора. Вариант 2 не позволяет промежуточным результатам висеть так долго. Если промежуточные данные малы, это также не имеет значения. Но если это объекты, занимающие десятки или сотни мегабайт (на Pi с объемом оперативной памяти всего 512 МБ или 1 ГБ), это может иметь значение между программой, которая переключается или вылетает из-за нехватки оперативной памяти, и программой, которая этого не делает.

Поэтому используйте вариант 2, при условии, что промежуточные элементы бесполезны в момент завершения следующего шага.

Ответ №2:

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