Python运行函数并行

Python运行函数并行,python,function,concurrency,Python,Function,Concurrency,我想运行一个“main”函数n次。此函数在运行时启动其他函数。 “main”函数称为“repeat”,当它运行时,它首先启动函数“copula\u sim”,从那里我得到一个称为“total\u summe\u liste”的输出。该列表将被添加到“mega_summe_列表”中,该列表将保护n次运行的所有输出。排序后的“汇总列表”将被安全地保存为“RM\u列表”,它是“VaR\u func”、“CVaR\u func”和“power\u func”函数的输入,所有这些函数都会生成一个输出,该输

我想运行一个“main”函数n次。此函数在运行时启动其他函数。 “main”函数称为“repeat”,当它运行时,它首先启动函数“copula\u sim”,从那里我得到一个称为“total\u summe\u liste”的输出。该列表将被添加到“mega_summe_列表”中,该列表将保护n次运行的所有输出。排序后的“汇总列表”将被安全地保存为“RM\u列表”,它是“VaR\u func”、“CVaR\u func”和“power\u func”函数的输入,所有这些函数都会生成一个输出,该输出在特定列表“RM\u VaR\u列表”、“RM\u CVaR\u列表”或“RM\u PSRM\u列表”中排序。之后,在下一次运行开始之前,将清除“RM_列表”和“total_summe_liste”

最后我得到了“mega_summe_list”、“RM_VaR_list”、“RM_CVaR_list”和“RM_PSRM_list”,它们将用于生成绘图和数据帧

现在我想并行运行“repeat”函数。例如,当我想运行这个函数n=10次时,我想同时在10个cpu核上运行它。原因是“copula_sim”是一个蒙特卡罗模拟,当我做一个大的模拟时需要一段时间

我所拥有的是:

total_summe_liste = []
RM_VaR_list = []
RM_CVaR_list = []
RM_PSRM_list = []
mega_summe_list = []

def repeat():
    global RM_list
    global total_summe_liste
    global RM_VaR_list
    global RM_CVaR_list
    global RM_PSRM_list
    global mega_summe_list

    copula_sim(runs_sim, rand_x, rand_y, mu, full_log=False)
    mega_summe_list += total_summe_liste
    RM_list = sorted(total_summe_liste)    
    VaR_func(alpha)
    RM_VaR_list.append(VaR)    
    CVaR_func(alpha)
    RM_CVaR_list.append(CVaR)
    power_func(gamma)
    RM_PSRM_list.append(risk)
    RM_list = []
    total_summe_liste = []

n = 10

for i in range(0,n):
    repeat()
到目前为止,这是有效的

我试着:

if __name__ == '__main__':
    jobs = []
    for i in range(0,10):
        p = mp.Process(target=repeat)
        jobs.append(p)
        p.start()
但是当我运行这个时,“超级汇总列表”是空的。。当我添加“print(VaR)”以重复时,它会在完成时显示所有10个VaR。因此,到目前为止,并行任务正在工作

有什么问题吗?

您应该使用,然后可以执行以下操作:

p = Pool(10)
p.map(repeat, range(10))
您应该使用,然后可以执行以下操作:

p = Pool(10)
p.map(repeat, range(10))

出现此问题的原因是,进程之间不共享列表
mega\u summe\u list

在python中调用并行处理时,所有函数和变量都将导入并在不同的进程中独立运行

例如,当您启动5个进程时,这些变量的5个不同副本被导入并独立运行。因此,当您在main中访问
mega\u summe\u列表时,它仍然为空,因为在此进程中它为空

要启用进程之间的同步,可以使用多处理程序包中的列表代理。 多处理管理器维护一个独立的服务器进程,在这些python对象中保存这些进程

下面是用于创建多处理管理器列表的代码

from multiprocessing import Manager
mega_summe_list = Manager().List()
在使用多处理时,可以使用上述代码代替
mega\u summe\u list=[]

下面是一个例子

from multiprocessing.pool import Pool
from multiprocessing import Manager


def repeat_test(_):
    global b, mp_list
    a = [1,2,3]
    b += a
    mp_list += a # Multiprocessing Manager List
    a = []

if __name__ == "__main__":
    b = []
    mp_list = Manager().list()

    p = Pool(5)
    p.map(repeat_test, range(5))
    print("a: {0}, \n mp_list: {1}".format(b, mp_list))
输出:

b: [],
 mp_list: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

希望这能解决您的问题。

出现此问题的原因是,进程之间不共享列表

在python中调用并行处理时,所有函数和变量都将导入并在不同的进程中独立运行

例如,当您启动5个进程时,这些变量的5个不同副本被导入并独立运行。因此,当您在main中访问
mega\u summe\u列表时,它仍然为空,因为在此进程中它为空

要启用进程之间的同步,可以使用多处理程序包中的列表代理。 多处理管理器维护一个独立的服务器进程,在这些python对象中保存这些进程

下面是用于创建多处理管理器列表的代码

from multiprocessing import Manager
mega_summe_list = Manager().List()
在使用多处理时,可以使用上述代码代替
mega\u summe\u list=[]

下面是一个例子

from multiprocessing.pool import Pool
from multiprocessing import Manager


def repeat_test(_):
    global b, mp_list
    a = [1,2,3]
    b += a
    mp_list += a # Multiprocessing Manager List
    a = []

if __name__ == "__main__":
    b = []
    mp_list = Manager().list()

    p = Pool(5)
    p.map(repeat_test, range(5))
    print("a: {0}, \n mp_list: {1}".format(b, mp_list))
输出:

b: [],
 mp_list: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

希望这能解决您的问题。

我是这样解决问题的:

此函数是我要并行重复n次的函数:

from multiprocessing import Process
from multiprocessing import Manager
from multiprocessing.pool import Pool

def repeat(shared_list, VaR_list, CVaR_list, PSRM_list, i):
    global RM_list
    global total_summe_liste

    copula_sim(runs_sim, rand_x, rand_y, mu, full_log=False)
    shared_list += total_summe_liste
    RM_list = sorted(total_summe_liste)    
    VaR_func(alpha)
    VaR_list.append(VaR)    
    CVaR_func(alpha)
    CVaR_list.append(CVaR)
    power_func(gamma)
    PSRM_list.append(risk)
    RM_list = []
    total_summe_liste = []
这部分管理共享列表并进行并行处理。谢谢@noufel13

RM_VaR_list = []
RM_CVaR_list = []
RM_PSRM_list = []
mega_summe_list = []

if __name__ == "__main__":
    with Manager() as manager:
        shared_list = manager.list()
        VaR_list = manager.list()
        CVaR_list = manager.list()
        PSRM_list = manager.list()
        processes = []
        for i in range(12):
            p = Process(target=repeat, args=(shared_list, VaR_list, CVaR_list, PSRM_list, i))  # Passing the list
            p.start()
            processes.append(p)
        for p in processes:
            p.join()
        RM_VaR_list += VaR_list
        RM_CVaR_list += CVaR_list
        RM_PSRM_list += PSRM_list
        mega_summe_list += shared_list

    RM_frame_func()
    plotty_func()
谢谢大家!


剩下的唯一问题是我如何处理大型阵列?有没有一种方法可以有效地做到这一点?12个共享列表中的一个可以包含超过100000.000.000项,因此mega_summe_列表总共包含大约1200.000.000项…

我通过以下方式解决了问题:

此函数是我要并行重复n次的函数:

from multiprocessing import Process
from multiprocessing import Manager
from multiprocessing.pool import Pool

def repeat(shared_list, VaR_list, CVaR_list, PSRM_list, i):
    global RM_list
    global total_summe_liste

    copula_sim(runs_sim, rand_x, rand_y, mu, full_log=False)
    shared_list += total_summe_liste
    RM_list = sorted(total_summe_liste)    
    VaR_func(alpha)
    VaR_list.append(VaR)    
    CVaR_func(alpha)
    CVaR_list.append(CVaR)
    power_func(gamma)
    PSRM_list.append(risk)
    RM_list = []
    total_summe_liste = []
这部分管理共享列表并进行并行处理。谢谢@noufel13

RM_VaR_list = []
RM_CVaR_list = []
RM_PSRM_list = []
mega_summe_list = []

if __name__ == "__main__":
    with Manager() as manager:
        shared_list = manager.list()
        VaR_list = manager.list()
        CVaR_list = manager.list()
        PSRM_list = manager.list()
        processes = []
        for i in range(12):
            p = Process(target=repeat, args=(shared_list, VaR_list, CVaR_list, PSRM_list, i))  # Passing the list
            p.start()
            processes.append(p)
        for p in processes:
            p.join()
        RM_VaR_list += VaR_list
        RM_CVaR_list += CVaR_list
        RM_PSRM_list += PSRM_list
        mega_summe_list += shared_list

    RM_frame_func()
    plotty_func()
谢谢大家!


剩下的唯一问题是我如何处理大数组?有没有一种方法可以有效地做到这一点?12个共享列表中的一个可以有超过100000.000.000个项目,因此mega_summe_列表总共有大约1200.000.000个项目…

当我运行我尝试的代码时,它会生成每次运行时所需的输出。但它不能保证全局安全st.“if name=='main':”后面的代码似乎在10个tak完成之前执行..当我运行我尝试的代码时,它正在生成每次运行所需的输出。但它不能将其安全地保存到全局列表中。它还像“if name=='main'”后面的代码:“在10德克完成之前执行..谢谢!但是我运行这个有问题。当我复制代码b时,没有定义mp_列表。当我定义b=[]和mp_list=[]时,它会运行,但输出是一个空列表。我想我已经找到了答案。我将在未来几天发布我的代码。还有一件事:如何处理非常大的阵列?在我做“test_mega+=shared_list”的时候,但是“shared_list”已经进入了1.000.000个条目,我得到了10个条目,我将它们添加到了“test_mega”中。这比现在的模拟需要更长的时间。。。有没有更有效的方法?谢谢!但是我运行这个有问题。当我复制代码b时,没有定义mp_列表。当我定义b=[]和mp_list=[]时,它会运行,但输出是一个空列表。我想我已经找到了答案。我将在未来几天发布我的代码。还有一件事:如何处理非常大的阵列?在我做“test_mega+=shared_list”的时候,但是“shared_list”已经进入了1.000.000个条目,我得到了10个条目,我将它们添加到了“test_mega”中。这比现在的模拟需要更长的时间。。。有没有更有效的方法?