python код работает медленнее после многопроцессорной функции - PullRequest
0 голосов
/ 02 августа 2020

Я вычисляю сложный, и некоторые процедуры этой функции медленные. Поэтому я использовал Фортран и многопроцессорность вместе, чтобы ускорить свой код.

Например, эта функция (без многопроцессорности) выглядит так:

from fortran_module import fortran_func1, fortran_func2

def test():
    # some codes...   [A]

    res1 = fortran_func1(...)

    # some codes...   [B]
    
    res2 = fortran_func2(res1, ...)

    return res2

fortran_module скомпилирован из f2py.

И если я использовал line_profiler для анализа этого кода, он сказал мне, что коды части [A] стоят 100 мс, fortran_func1 стоят 300000 мс, [B] стоят 1000 мс и fortran_func2 стоимость 100000мс.

Я хочу ускорить fortran_func1, поэтому переписал (исходная версия рассчитывается в 3-х мерном пространстве, а новая версия рассчитывается только в 2-х мерном пространстве), и вместе с многопроцессорностью:

from multiprocessing import Pool
from fortran_module import fortran_func1_new, fortran_func2

def fortran_func1_new_wrapper(...):
    """in order to make it picklable, so can be used in multiprocessing"""
    return fortran_func1_new(...)

def func1_pool(...):
    args = ...    # create a list of `fortran_func1_wrapper` arguments
    pool = Pool()
    res_list = pool.starmap(fortran_func1_new_wrapper, args)
    return np.stack(res_list, axis=-1)

def test():
    # some codes...   [A]             # -- speed of this part doesn't change

    res1 = func1_pool(...)            # -- speed of this is FASTER comparing to the old version

    # some codes...   [B]             # -- speed of this part is SLOWER than the old version
    
    res2 = fortran_func2(res1, ...)   # -- speed of this is SLOWER than the old version

    return res2

Результат идентичен предыдущему. Но line_profiler сказал мне кое-что странное. В этой новой версии коды части [A] стоят почти 100 мс, func1_pool стоят 200000 мс, [B] стоят 2000 мс, а fortran_func2 стоят 200000 мс.

Другими словами, хотя скорость func1_pool выше, чем в старой версии, ВСЕ коды ПОСЛЕ func_pool на МЕДЛЕННО , чем в старой версии. И все коды после func1_pool точно такие же, как и в старой версии.

Я не знаком с multiprocessing. Кто-нибудь знает, что случилось? Ожидается, что func1_pool быстрее, чем в старой версии, но почему коды после func1_pool медленнее? И как мне избежать этой проблемы?

Большое спасибо!

...