Введенный вами код в основном отличается от (a1+a2+ ... + an)/n
и (a1/n + a2/n + ... + an/n)
. Результат тот же, но во второй версии больше операций (а именно (n-1) больше делений), что замедляет вычисление. Вы утверждали, что во второй версии каждый цикл работает независимо от других. В первом цикле нам нужна следующая информация, чтобы закончить один цикл: total
перед запуском и текущим value
. Во второй версии нам нужна следующая информация для завершения одного цикла: mean
перед запуском, текущие value
и num_of_values
. Как вы видите во второй версии, мы даже зависим от больших значений!
Но как мы можем разделить работу между ядрами (что является целью многопроцессорности)? Мы могли бы просто дать одному ядру первую половину значений, а вторую - вторую половину, т. Е. ((a1+a2+ ... + a(n//2)) + (a(n//2 +1) + ... + a(n))/n)
. Да, работа деления на n не разделяется между ядрами, но это одна инструкция, поэтому нам все равно. Также нам нужно добавить левое общее количество и правое общее количество, которое мы не можем разделить, но опять же это всего лишь одна операция.
Так код, который мы хотим запустить:
def my_sum(values):
total = 0
for value in values:
total += value
return total
Там еще проблема с питоном - обычно можно использовать нити, чтобы сделать вычисления, потому что каждый поток будет использовать одно ядро. Но в этом случае нужно позаботиться о том, чтобы ваша программа не работала в условиях гонки, и сам интерпретатор python также должен позаботиться об этом. CPython решил, что это не стоит и в основном работает только в одном потоке за раз. Основным решением является использование нескольких процессов посредством многопроцессорной обработки.
from multiprocessing import Pool
if __name__ == '__main__':
with Pool(5) as p:
results = p.map(my_sum, [long_list[0:len(long_list)//2], long_list[len(long_list)//2:]))
print(sum(results)/len(long_list)) # add subresults and divide by n
Но, конечно, несколько процессов не предоставляются бесплатно. Вам нужно разблокировать, скопировать материал и т. Д., Чтобы вы не получили ускорение в 2 раза, как можно было бы ожидать. Также самое большое замедление фактически использует сам python, он не оптимизирован для быстрых численных вычислений. Существуют разные способы, но использование numpy, вероятно, является самым простым. Просто используйте:
import numpy
print(numpy.mean(long_list))
Это, вероятно, намного быстрее, чем версия python. Я не думаю, что numpy использует многопроцессорную внутреннюю обработку, поэтому можно добиться повышения, используя несколько процессов и быструю реализацию (numpy или что-то другое, написанное на C), но обычно numpy достаточно быстро.
Что вы имеете в виду с асинхронным? В python asyncio делает async IO, но это на самом деле вам не поможет. Вы хотите ускорить вычисления? Посмотрите на numpy.Если вы хотите запускать на нескольких ядрах, посмотрите на многопроцессорность (потоки python не могут одновременно запускать код python). Ваша вторая версия делает больше работы (каждый раз, когда разделение и дополнение), поэтому я не думаю, что это очень удивительно, что для этого требуется больше времени. – syntonym
@syntonym Извините, я имею в виду параллельно не async, так как это вроде бы работает в нескольких потоках. Как я могу использовать для этого многопроцессор? – ChrisIkeokwu
Ofc второй медленнее. Гораздо больше дивизий! – sascha