Я играю с concurrent.future в python, чтобы понять несколько простых реализаций, использующих многопроцессорность.Однако я столкнулся с очень неожиданным результатом.Прежде чем начать, вот мои системные данные:
Тип компьютера: ноутбук с Windows 10 Оперативная память: 8,00 ГБ Процессор: Intel (R) Core(TM) i7-6600U @ 2.60 ГГц Базовая скорость: 2,80 ГГц Сокеты: 1 Ядра: 2 Логические процессоры: 4 Кэш-память L1:128 КБ кэш L2: 512 КБ кэш L3: 4,0 МБ
Возьмите следующий геометрический ряд, который вычисляет среднее значение n
числа:
С учетом этой идеи я создаю функцию, которая вычисляет среднее значение целых чисел между нижней границей a
(включительно) и верхней границей b
(эксклюзив).Затем я запускаю тест с и без многопроцессорной обработки в диапазоне 500 миллионов целых чисел:
import time
import concurrent.futures
def mean(a, b):
total_sum = 0
for next_int in range(a, b):
total_sum += next_int
return total_sum / (b - a)
if __name__ == '__main__':
n = 500000000 # 500 Million
wall_time = time.time()
base_ans = mean(0, n) # From 0 to n-1.
print("Single Thread Time: " + str(time.time() - wall_time) + " sec.")
work = [(0, int(n/2)), (int(n/2), n)]
num_workers = 2 # One process per core!
test_ans = 0
wall_time = time.time()
with concurrent.futures.ProcessPoolExecutor(max_workers=num_workers) as executor:
future_tasks = {executor.submit(mean, job[0], job[1]): job for job in work}
for future in concurrent.futures.as_completed(future_tasks):
test_ans += future.result()
print("Multiprocessing Time: " + str(time.time() - wall_time) + " sec.")
print(str(base_ans) + " == " + str(test_ans / num_workers) + " => " + str(base_ans == (test_ans / num_workers)))
Следующее выдает следующий вывод:
Single Thread Time: 41.0769419670105 sec. # CPU Utilization ≈ 35% (from task manager)
Multiprocessing Time: 24.71605634689331 sec. # CPU Utilization ≈ 70% (from task manager)
Как мы можем ясно видеть, наблюдалось значительное ускорение ( примерно 1,66x ).Однако, если я создаю 4 рабочих, а не 2, я получаю еще большую скорость:
work = [(0, int(n/4)), (int(n/4), int(n/2)), (int(n/2), int(3*n/4)), (int(3*n/4), n)]
num_workers = 4
# ...
Single Thread Time: 41.51883292198181 sec. # CPU Utilization ≈ 35% (from task manager)
Multiprocessing Time: 18.18532919883728 sec. # CPU Utilization = 100% (from task manager)
Здесь можно увидеть еще большее увеличение скорости ( примерно 2,28x ) иэто даже состоит из многих пробегов!
- Поскольку в этой двух (физической) базовой системе одновременно могут работать только два процесса, является причиной эффективности планировщика Window причиной этого дальнейшего ускорения?
- Как я могу выбрать
max_worker
номер, который обеспечивает самое быстрое время выполнения?Сколько еще процессов я должен добавить после числа физических ядер? - И, наконец, влияет ли добавление большего числа процессов после числа физических ядер на потоки (в многопоточности) в каждом процессе от эффективности работы?