使用python多处理计算Monte Carlo模拟中的平均值

使用python多处理计算Monte Carlo模拟中的平均值,python,multiprocessing,Python,Multiprocessing,我一直在阅读Python中的多处理技术(例如,我已经阅读了and等;我还阅读/观看了不同的网站/视频,如and等),但我仍然对如何将多处理技术应用于我的特定问题感到困惑。我编写了一个简单的示例代码,用于使用蒙特卡罗模拟计算随机生成的整数的平均值(我将随机整数存储在一个名为integers的变量中,以便最终计算平均值;我还将生成随机numpy.ndarray,并将其存储在一个名为array的变量中,因为我以后还需要对这些数组进行一些后处理): 现在我想利用我机器上的所有16个核,这样随机数/数组就

我一直在阅读Python中的多处理技术(例如,我已经阅读了and等;我还阅读/观看了不同的网站/视频,如and等),但我仍然对如何将多处理技术应用于我的特定问题感到困惑。我编写了一个简单的示例代码,用于使用蒙特卡罗模拟计算随机生成的整数的平均值(我将随机整数存储在一个名为
integers
的变量中,以便最终计算平均值;我还将生成随机numpy.ndarray,并将其存储在一个名为
array
的变量中,因为我以后还需要对这些数组进行一些后处理):

现在我想利用我机器上的所有16个核,这样随机数/数组就不会按顺序生成,我可以加快这个过程。根据我学到的知识,我认识到我需要存储每个蒙特卡罗模拟的结果(即生成的随机整数和随机numpy.ndarray)然后使用进程间通信,以便以后将所有结果存储在一个列表中。我编写了不同的代码,但不幸的是,其中没有一个可以工作。例如,当我编写类似以下内容时:

import numpy as np
import multiprocessing

nMCS = 10 ** 6

integers = []
arrays = []

def monte_carlo():
    a = np.random.randint(0,10)
    b = np.random.rand(10,2)

if __name__ == '__main__':
    __spec__ = "ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>)" # this is because I am using Spyder!

    p1 = multiprocessing.Process(target = monte_carlo)

    p1.start()

    p1.join()

    for i in range(nMCS):

        integers.append(a)
        arrays.append(b)
将numpy导入为np
导入多处理
nMCS=10**6
整数=[]
数组=[]
def monte_carlo():
a=np.random.randint(0,10)
b=np.rand.rand(10,2)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
__这是因为我使用的是Spyder!
p1=多处理过程(目标=蒙特卡罗)
p1.开始()
p1.join()
对于范围内的i(nMCS):
整数。追加(a)
数组。追加(b)
我得到错误“名称“a”未定义。因此,请任何人帮助我,并告诉我如何同时生成尽可能多的随机整数/数组,然后将它们全部添加到列表中进行进一步处理?

简单错误

a和b是在函数中创建的 它们不存在于您的主作用域中。您需要从函数返回它们

def monte_carlo():
    a = np.random.randint(0,10)
    b = np.random.rand(10,2)
    #create a return statement here. It may help if you put them into an array so you can return 2 value

if __name__ == '__main__':
__spec__ = "ModuleSpec(name='builtins', loader=<class 
    '_frozen_importlib.BuiltinImporter'>)" # this is because I am using Spyder!

    p1 = multiprocessing.Process(target = monte_carlo)

    p1.start()

    p1.join()
    #Call your function here and save the return to something
    for i in range(nMCS):

      integers.append(a) # paste here
      arrays.append(b) # and here

由于返回大量结果会导致进程之间的传播时间,因此我建议将任务分成几个部分,并在返回之前对其进行处理

n = 4
def monte_carlo():
    raw_result = []
    for j in range(10**4 / n):
        a = np.random.randint(0,10)
        b = np.random.rand(10,2)
        raw_result .append([a,b])
    result = processResult(raw_result) 
    #Your method to reduce the result return, 
    #let's assume the return value is [avg(a),reformed_array(b)]
    return result

if __name__ == '__main__':
    __spec__ = "ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>)" # this is because I am using Spyder!

    pool = Pool(processes=4) 
    #you can control how many processes here, for example multiprocessing.cpu_count()-1 to avoid completely blocking

    multiple_results = [pool.apply_async(monte_carlo, (i,)) for i in range(n)]

    data = [res.get() for res in multiple_results]
    #OR
    data = pool.map(monte_carlo, [i for i in range(n)])
    #Both return you a list of [avg(a),reformed_array(b)]
n=4
def monte_carlo():
原始结果=[]
对于范围内的j(10**4/n):
a=np.random.randint(0,10)
b=np.rand.rand(10,2)
原始结果追加([a,b])
结果=处理结果(原始结果)
#您减少结果返回的方法,
#假设返回值为[avg(a),数组(b)]
返回结果
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
__这是因为我使用的是Spyder!
池=池(进程=4)
#您可以控制此处的进程数,例如multiprocessing.cpu\u count()-1,以避免完全阻塞
多个_结果=[pool.apply_async(monte_carlo,(i,))用于范围(n)内的i]
data=[res.get()表示多个_结果中的res]
#或
data=pool.map(蒙特卡罗[i代表范围(n)])
#两者都会返回[avg(a)和[u数组(b)]

我在底部的代码中标记了它。他可以在他的函数中为a和b创建返回语句。我感谢你的回答,但你的代码不起作用。就像它给我空列表一样!我编辑了一些东西希望能帮助你。我也测试了它,在我的代码版本中,列表不是空的。非常感谢你对于你的答案。在我真正的问题-这是一个大问题,这开始使用我的整个100%的CPU(这是完全有道理的),这使我无法在代码运行时使用其他应用程序。那么,您能告诉我如何将CPU使用率限制在50%以内吗?@Antonio,您是指没有任何MP的应用程序,对吗?在您的原始版本中,我似乎无法控制函数monte_carlo?的多进程执行次数函数您正在执行该函数10**6次only@Antonio,部分正确,我使用
map()
更新了一个版本,似乎它在许多任务情况下工作得更好。您可以测试它,如果您提供更多任务,MP方法最终会更快。@Antonio,我没有您提到的问题(注意,我有输入错误,应该是
返回[a,b]
)。另外,第一种方法是在我的计算机中10**6后MP更快。可能我们应该在房间里讨论,
import numpy as np
import multiprocessing

nMCS = 10 ** 6

integers = []
arrays = []

def monte_carlo():
    a = np.random.randint(0,10)
    b = np.random.rand(10,2)
    temp = [a,b]
    return temp

if __name__ == '__main__':
__spec__ = "ModuleSpec(name='builtins', loader=<class 
'_frozen_importlib.BuiltinImporter'>)" # this is because I am using Spyder!

    p1 = multiprocessing.Process(target = monte_carlo())#added the extra brackets here

    p1.start()

    p1.join()

    for i in range(nMCS):
        array = monte_carlo()
        integers.append(array[0])
        arrays.append(array[1])
Process Process-6:
Traceback (most recent call last):
  File"c:\users\lunar\appdata\local\continuum\anaconda3\lib\multiprocessing\process.py", line 252, in _bootstrap
    self.run()
  File "c:\users\lunar\appdata\local\continuum\anaconda3\lib\multiprocessing\process.py", line 93, in run
    self._target(*self._args, **self._kwargs)
TypeError: 'list' object is not callable
n = 4
def monte_carlo():
    raw_result = []
    for j in range(10**4 / n):
        a = np.random.randint(0,10)
        b = np.random.rand(10,2)
        raw_result .append([a,b])
    result = processResult(raw_result) 
    #Your method to reduce the result return, 
    #let's assume the return value is [avg(a),reformed_array(b)]
    return result

if __name__ == '__main__':
    __spec__ = "ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>)" # this is because I am using Spyder!

    pool = Pool(processes=4) 
    #you can control how many processes here, for example multiprocessing.cpu_count()-1 to avoid completely blocking

    multiple_results = [pool.apply_async(monte_carlo, (i,)) for i in range(n)]

    data = [res.get() for res in multiple_results]
    #OR
    data = pool.map(monte_carlo, [i for i in range(n)])
    #Both return you a list of [avg(a),reformed_array(b)]