Pull to refresh

Ускорить сложные вычисления с минимальной загрузкой RAM

Reading time 2 min
Views 4.5K
В процессе освоения ML, СNN, NN на Python новичок почти всегда сталкивается с проблемой скорости вычислений, а иногда и нехватки оперативной памяти.

Особенно это заметно с большими базами, которые по размеру больше 50% свободной RAM. Мысли о покупке более достойного железа всего лишь одно из возможных решений.

Иной вариант использовать одну из возможностей в Python — итерации по самой функции.

Простой и наглядный пример. Допустим Вам необходимо возвести в 200 000 степень ряд чисел от 1 до 10 и сложить их сумму. В итоге вы должны получить число длинной 200 тыс знаков. это в 2 раза больше чем google)

Вот простой код такой функции:

from time import time # импорт модуля времени
# простая функция возведения в степень
def power_1(x):
    power_1 = 0 
    start = time()
    power_1 = x**200000
    end = time()
    total_1 = end - start
    return round(total_1,6)
# простые операции сложения, для того что бы посчитать отдельно время операции
power_1(1) + power_1(2) + power_1(3) + power_1(4) + power_1(5) + power_1(6) + power_1(7) + power_1(8) \
+ power_1(9) + power_1(10)

В итоге мы получаем достаточно «затратную» операцию для вашего компа, и например у моего это занимает более 13 мс. А что если таких операций может быть много? Тогда все усложняется, а возможно Вам просто не хватит RAM.

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

Вот код такого простого решения, той же самой функции:

from time import time #получаем модуль времени 
# функция итерации
def power_2():
    for i in range(11):
        yield i
# функции возведения в степень 
for i in power_2():
    if i < 11:
        d = 0
        total_2 = 0
        start = time()
        d += i**200000
        end = time()
        total_2 += end - start
        print('Ineration {} lasts {}'.format(i, round(total_2, 6)))
        if i == 10:
            print('    \n End with total time {} \n'.format(round(total_2,3))) 

Временные затраты на моем компе



Разница 0,13 — 0,024 = 0,106 мс!


Если к этому огромному числу обычным способом просто добавить 1, то этой займет больше времени, чем само возведение в 200000 степень. То есть, преимущества такого способа очевидны.

def add_one(x):
    total_3 = 0
    start = time()
    s = x + 1
    end = time()
    total_3 +=  end - start
    print('Time to do add 1 to BIG number: {} \n'.format(total_3))
    return print('Difference in time {}\n'.format(round(total_2 - total_3 ,3)))
add_one(d)
print('The size of the number {}!!!'.format(len(str(d))))

Результат такой:



Почему так? Насколько, мне известно, при итерации по функции Python не создает временные объекты в памяти, что в свою очередь существенно ускоряет любой процесс вычислений. Поэтому, переписав таким образом функцию — вы экономите время и нервы.

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

Надеюсь, это поможет кому-то не потерять драгоценные минуты или не потратится на дополнительное, быстро устаревающее железо.

Навеяно по лекции
Tags:
Hubs:
+4
Comments 10
Comments Comments 10

Articles