简单 CPU/GPU 上的最大并行进程数
Maximum number of parallel processes on a simple CPU/GPU
我正在尝试 运行 具有 3000 个独立粒子的 particle filter。更具体地说,我想运行同时并行进行3000次(简单)计算,以便计算时间保持较短。
此任务是为实验室设备上的实验应用而设计的,因此必须 运行 在本地笔记本电脑上进行。我不能依赖远处的计算机集群,而且将要使用的计算机不太可能配备花哨的 Nvidia 显卡。例如,我目前使用的计算机有一个 Intel Core i7-8650U CPU 和一个 Intel UHD Graphics 620 GPU。
使用 multiprocessing
Python 库中的 mp.cpu_count()
告诉我我有 8 个处理器,这对我的问题来说太少了(我需要 运行 几个数千个进程并行)。因此,我着眼于基于 GPU 的解决方案,尤其是 PyOpenCL。 Intel UHD Graphics 620 GPU 应该只有 24 个处理器,这是否意味着我只能使用它来 运行 同时并行处理 24 个进程?
更一般地说,我的问题(运行使用 Python 在一台简单的笔记本电脑上并行处理 3000 个进程)是否现实,如果是,您会推荐哪种软件解决方案?
编辑
这是我的伪代码。在每个时间步骤 i
,我都在调用函数 posterior_update
。这个函数使用了 3000 次并且独立地(每个粒子一次)函数 approx_likelihood
,这似乎很难向量化。理想情况下,我希望这 3000 次调用独立且并行进行。
import numpy as np
import scipy.stats
from collections import Counter
import random
import matplotlib.pyplot as plt
import os
import time
# User's inputs ##############################################################
# Numbers of particles
M_out = 3000
# Defines a bunch of functions ###############################################
def approx_likelihood(i,j,theta_bar,N_range,q_range,sigma_range,e,xi,M_in):
return sum(scipy.stats.norm.pdf(e[i],loc=q_range[theta_bar[j,2]]*kk,scale=sigma_range[theta_bar[j,3]])* \
xi[nn,kk]/M_in for kk in range(int(N_range[theta_bar[j,0]]+1)) for nn in range(int(N_range[theta_bar[j,0]]+1)))
def posterior_update(i,T,e,M_out,M_in,theta,N_range,p_range,q_range,sigma_range,tau_range,X,delta_t,ML):
theta_bar = np.zeros([M_out,5], dtype=int)
x_bar = np.zeros([M_out,M_in,2], dtype=int)
u = np.zeros(M_out)
x_tilde = np.zeros([M_out,M_in,2], dtype=int)
w = np.zeros(M_out)
# Loop over the outer particles
for j in range(M_out):
# Computes the approximate likelihood u
u[j] = approx_likelihood(i,j,theta_bar,N_range,q_range,sigma_range,e,xi,M_in)
ML[i,:] = theta_bar[np.argmax(u),:]
# Compute the normalized weights w
w = u/sum(u)
# Resample
X[i,:,:,:],theta[i,:,:] = resample(M_out,w,x_tilde,theta_bar)
return X, theta, ML
# Loop over time #############################################################
for i in range(T):
print('Progress {0}%'.format(round((i/T)*100,1)))
X, theta, ML = posterior_update(i,T,e,M_out,M_in,theta,N_range,p_range,q_range,sigma_range,tau_range,X,delta_t,ML)
这些是一些想法,不是您问题的答案:
您主要关心的是如何确定您可以 运行 的并行进程数,并不是那么简单。基本上,您可以认为您的计算机 运行 并行处理的进程与您拥有的 CPU 个内核一样多。但这最终取决于操作系统、计算机当前的工作负载等。此外,您可以将数据分块发送到您的进程,而不必一次发送一个项目。或者您可以将数据划分为您拥有的流程,例如6 个流程,每个流程有 500 个项目 = 3000 个项目。最佳组合需要反复试验。
另一方面,GPU 拥有大量可用的工作人员。如果您安装了 Nvidia 驱动程序和 OpenCL,请在终端中发出命令 clinfo
以了解硬件的功能。
我发现在您的代码中使用 GPU 的一个问题是您需要使用 C 语言将指令传递给您的设备。您的 approx_likelihood
函数包含依赖于库的代码,这在 C 中很难复制。
但是,如果您估计您正在使用这些库来执行您可以用 C 编写的代码,请尝试一下。您也可以考虑使用 Numba。
我将从使用 python 的 multiprocessing
开始。这些行中的内容:
import multiprocessing as mp
def f(j):
return approx_likelihood(i, j, theta_bar, N_range, q_range, sigma_range, e, xi, M_in)
with mp.Pool() as pool:
u = pool.map(f, range(M_out), chunksize=50)
我正在尝试 运行 具有 3000 个独立粒子的 particle filter。更具体地说,我想运行同时并行进行3000次(简单)计算,以便计算时间保持较短。
此任务是为实验室设备上的实验应用而设计的,因此必须 运行 在本地笔记本电脑上进行。我不能依赖远处的计算机集群,而且将要使用的计算机不太可能配备花哨的 Nvidia 显卡。例如,我目前使用的计算机有一个 Intel Core i7-8650U CPU 和一个 Intel UHD Graphics 620 GPU。
使用 multiprocessing
Python 库中的 mp.cpu_count()
告诉我我有 8 个处理器,这对我的问题来说太少了(我需要 运行 几个数千个进程并行)。因此,我着眼于基于 GPU 的解决方案,尤其是 PyOpenCL。 Intel UHD Graphics 620 GPU 应该只有 24 个处理器,这是否意味着我只能使用它来 运行 同时并行处理 24 个进程?
更一般地说,我的问题(运行使用 Python 在一台简单的笔记本电脑上并行处理 3000 个进程)是否现实,如果是,您会推荐哪种软件解决方案?
编辑
这是我的伪代码。在每个时间步骤 i
,我都在调用函数 posterior_update
。这个函数使用了 3000 次并且独立地(每个粒子一次)函数 approx_likelihood
,这似乎很难向量化。理想情况下,我希望这 3000 次调用独立且并行进行。
import numpy as np
import scipy.stats
from collections import Counter
import random
import matplotlib.pyplot as plt
import os
import time
# User's inputs ##############################################################
# Numbers of particles
M_out = 3000
# Defines a bunch of functions ###############################################
def approx_likelihood(i,j,theta_bar,N_range,q_range,sigma_range,e,xi,M_in):
return sum(scipy.stats.norm.pdf(e[i],loc=q_range[theta_bar[j,2]]*kk,scale=sigma_range[theta_bar[j,3]])* \
xi[nn,kk]/M_in for kk in range(int(N_range[theta_bar[j,0]]+1)) for nn in range(int(N_range[theta_bar[j,0]]+1)))
def posterior_update(i,T,e,M_out,M_in,theta,N_range,p_range,q_range,sigma_range,tau_range,X,delta_t,ML):
theta_bar = np.zeros([M_out,5], dtype=int)
x_bar = np.zeros([M_out,M_in,2], dtype=int)
u = np.zeros(M_out)
x_tilde = np.zeros([M_out,M_in,2], dtype=int)
w = np.zeros(M_out)
# Loop over the outer particles
for j in range(M_out):
# Computes the approximate likelihood u
u[j] = approx_likelihood(i,j,theta_bar,N_range,q_range,sigma_range,e,xi,M_in)
ML[i,:] = theta_bar[np.argmax(u),:]
# Compute the normalized weights w
w = u/sum(u)
# Resample
X[i,:,:,:],theta[i,:,:] = resample(M_out,w,x_tilde,theta_bar)
return X, theta, ML
# Loop over time #############################################################
for i in range(T):
print('Progress {0}%'.format(round((i/T)*100,1)))
X, theta, ML = posterior_update(i,T,e,M_out,M_in,theta,N_range,p_range,q_range,sigma_range,tau_range,X,delta_t,ML)
这些是一些想法,不是您问题的答案:
您主要关心的是如何确定您可以 运行 的并行进程数,并不是那么简单。基本上,您可以认为您的计算机 运行 并行处理的进程与您拥有的 CPU 个内核一样多。但这最终取决于操作系统、计算机当前的工作负载等。此外,您可以将数据分块发送到您的进程,而不必一次发送一个项目。或者您可以将数据划分为您拥有的流程,例如6 个流程,每个流程有 500 个项目 = 3000 个项目。最佳组合需要反复试验。
另一方面,GPU 拥有大量可用的工作人员。如果您安装了 Nvidia 驱动程序和 OpenCL,请在终端中发出命令
clinfo
以了解硬件的功能。我发现在您的代码中使用 GPU 的一个问题是您需要使用 C 语言将指令传递给您的设备。您的
approx_likelihood
函数包含依赖于库的代码,这在 C 中很难复制。但是,如果您估计您正在使用这些库来执行您可以用 C 编写的代码,请尝试一下。您也可以考虑使用 Numba。
我将从使用 python 的
multiprocessing
开始。这些行中的内容:
import multiprocessing as mp
def f(j):
return approx_likelihood(i, j, theta_bar, N_range, q_range, sigma_range, e, xi, M_in)
with mp.Pool() as pool:
u = pool.map(f, range(M_out), chunksize=50)