Отсутствие масштабирования для многопроцессорного пула Python - PullRequest
0 голосов
/ 18 декабря 2018

Я пишу простой скрипт на python, который мне нужно масштабировать для множества потоков.Для простоты я заменил фактическую функцию, которую мне нужно использовать, на матричную матрицу умножения.У меня возникают проблемы с масштабированием моего кода в зависимости от количества процессоров.Любой совет, который поможет мне получить правильное ускорение, будет полезен!Мой код и результаты следующие:

import numpy as np
import time
import math
from multiprocessing.dummy import Pool

res = 4

#we must iterate over all of these values
wavektests = np.linspace(.1,2.5,res)
omegaratios = np.linspace(.1,2.5,res)
wavekmat,omegamat = np.meshgrid(wavektests,omegaratios)

def solve_for_omegaratio( ind ):
    #obtain the indices for this run
    x_ind = ind % res
    y_ind = math.floor(ind / res)
    #obtain the value for this run
    wavek = wavektests[x_ind]
    omega = omegaratios[y_ind]
    #do some work ( I have replaced the real function with this)
    randmat = np.random.rand(4000,4000)
    nop = np.linalg.matrix_power(randmat,3)
    #obtain a scalar value
    value = x_ind + y_ind**2.0
    return value

list_ind = range(res**2)

#Serial code execution

t0_proc = time.clock()
t0_wall = time.time()

threads = 0
dispersion = map( solve_for_omegaratio , list_ind)
displist = list(dispersion)

t1_proc = time.clock()
t1_wall = time.time()


print('serial execution')
print('wall clock time = ',t1_wall-t0_wall)
print('processor clock time = ',t1_proc-t0_proc)
print('------------------------------------------------')



#Using pool defaults
t0_proc = time.clock()
t0_wall = time.time()

if __name__ == '__main__':
    pool = Pool()
    dispersion = pool.map( solve_for_omegaratio , list_ind)

displist = list(dispersion)
t1_proc = time.clock()
t1_wall = time.time()

pool.close
print('num of threads  = default')
print('wall clock time = ',t1_wall-t0_wall)
print('processor clock time = ',t1_proc-t0_proc)
print('------------------------------------------------')




# Using 4 threads
t0_proc = time.clock()
t0_wall = time.time()

threads = 4
if __name__ == '__main__':
    pool = Pool(threads)
    dispersion = pool.map( solve_for_omegaratio , list_ind)

displist = list(dispersion)
t1_proc = time.clock()
t1_wall = time.time()

pool.close
print('num of threads  = ' + str(threads))
print('wall clock time = ',t1_wall-t0_wall)
print('processor clock time = ',t1_proc-t0_proc)
print('------------------------------------------------')

Результаты:

serial execution
wall clock time =  66.1561758518219
processor clock time =  129.16376499999998
------------------------------------------------
num of threads  = default
wall clock time =  81.86436200141907
processor clock time =  263.45369
------------------------------------------------
num of threads  = 4
wall clock time =  77.63390111923218
processor clock time =  260.66285300000004
------------------------------------------------

1 Ответ

0 голосов
/ 18 декабря 2018

Поскольку python имеет GIL https://wiki.python.org/moin/GlobalInterpreterLock, «нативные» python-потоки не могут выполняться по-настоящему параллельно и, следовательно, не могут повысить производительность задач, связанных с ЦП, таких как математика.Их можно использовать для эффективного распараллеливания задач, связанных с вводом-выводом (например, вызовы API, которые тратят почти все свое время на ожидание сетевого ввода-вывода).Формирование отдельных процессов с multiprocessing, а не с dummy реализацией с поддержкой потоков создаст несколько процессов, а не потоков, которые смогут работать одновременно (за счет значительных накладных расходов памяти).

...