python 不使用整个CPU的多处理

2ekbmq32  于 2023-02-18  发布在  Python
关注(0)|答案(1)|浏览(214)

我正在测试python的模块“多重处理”,我正在尝试使用我的12线程ryzen55600,用蒙特卡洛技术来计算pi。
问题是我的cpu没有被完全使用,而是只使用了47%。我把我的代码留在下面,改变n_cpu的值并没有导致太大的内核使用差异,相反,将N增加一个数量级可以将负载增加到77% ...但是我相信N不应该影响进程的数量...请帮助我理解如何正确地并行化我的代码,谢谢。

import random
import math
import numpy as np
import multiprocessing
from multiprocessing import Pool

def sample(n):
    n_inside_circle = 0
    for i in range(n):
        x = random.random()
        y = random.random()
        if x**2 + y**2 < 1.0:
            n_inside_circle += 1
    return n_inside_circle

N_test=1000
N=12*10**4
n_cpu = 12
pi=0

for j in range(N_test):
    part_count=[int(N/n_cpu)] * n_cpu
    pool = Pool(processes=n_cpu)
    results = pool.map(sample, part_count)
    pool.close()
    pi += sum(results)/(N*1.0)*4

print(pi/N_test)
mzillmmw

mzillmmw1#

cpu使用不足是因为您将数据块发送到多个新进程池,而不是一次发送到单个进程池。
简单地使用

pool = Pool(processes=n_cpu)
for j in range(N_test):
    part_count=[int(N/n_cpu)] * n_cpu
    results = pool.map(sample, part_count)
    pi += sum(results)/(N*1.0)*4
pool.close()

应该加快速度
为了进一步优化
我们可以更改作业的拆分方式,以便为单个流程提供更多样本。
我们可以使用Numpy的向量化随机函数,它比random.random()运行得更快。
最后,为了加快速度,我们可以使用numba和线程池来进一步减少开销。

import time
import numpy as np
from multiprocessing.pool import ThreadPool
from numba import jit

@jit(nogil=True, parallel=True, fastmath=True)
def sample(n):
    x = np.random.random(n)
    y = np.random.random(n)
    inside_circle = np.square(x) + np.square(y) < 1.0
    return int(np.sum(inside_circle))

total_samples = int(3e9)
function_limit = int(1e7)
n_cpu = 12
pi=0

assert total_samples%function_limit == 0

start = time.perf_counter()
with ThreadPool(n_cpu) as pool:
    part_count=[function_limit] * (total_samples//function_limit)
    results = pool.map(sample, part_count)
    pi = 4*sum(results)/(total_samples)
end = time.perf_counter()
print(pi)
print(round(end-start,3), "seconds taken")

导致

3.141589756
6.982 seconds taken

相关问题