编辑:我更改了立方体函数,而是定义了我注意到这个问题的实际优化问题。我还根据收到的评论改变了块的生成方式。
我正在尝试并行化一些代码以减少计算时间,但执行代码的并行化版本需要比非并行版本更长的时间。我将展示一个简单的例子:
import multiprocessing as mp
import time
import numpy as np
from cvxpy import *
import functools
from sklearn.datasets import load_boston
boston = load_boston()
x = boston.data
y = boston.target
def lm_l_solver(x, y, lambda1):
n = x.shape[0]
m = x.shape[1]
lambda_param = Parameter(sign="positive")
beta_var = Variable(m)
lasso_penalization = lambda_param * norm(beta_var, 1)
lm_penalization = (1/n) * sum_squares(y - x * beta_var)
objective = Minimize(lm_penalization + lasso_penalization)
problem = Problem(objective)
# Solve optimization problem
beta_sol_matrix = np.zeros((len(lambda1), 1, m))
for i in range(len(lambda1)):
lambda_param.value = lambda1[i]
problem.solve(solver=CVXOPT)
beta_sol = np.asarray(np.row_stack([b.value for b in beta_var])).flatten()
beta_sol_matrix[i, :] = beta_sol
beta_sol_matrix[np.abs(beta_sol_matrix) < 1e-4] = 0
# Generate response
response = dict(solution=beta_sol_matrix, lambda1=lambda1)
return response
if __name__ == '__main__':
vector = np.arange(1, 100, 1)
start_time = time.time()
chunks = np.array_split(vector, mp.cpu_count())
pool = mp.Pool(processes=mp.cpu_count())
results = pool.map(functools.partial(lm_l_solver, x, y), chunks)
pool.close()
pool.join()
end_time_1 = time.time()
results2 = lm_l_solver(x, y, vector)
end_time_2 = time.time()
print('Parallel programming took {} seconds'.format(round(end_time_1-start_time, 2)))
print('Non parallel programming took {} seconds'.format(round(end_time_2 - end_time_1, 2)))
函数lm_l_solver接收数据矩阵x,响应向量y和可能的lambda值向量,并为每个lambda值求解一个惩罚线性模型。
执行这段代码会生成以下输出:
Parallel programming took 5.28 seconds
Non parallel programming took 0.4 seconds
为什么会出现这样的差异? &#34; lm_l_solver&#34;的并行化版本比非并行版本长13倍。我在这里做错了吗?
答案 0 :(得分:2)
要精确地复制它有点困难,因为它取决于群集的配置。就我而言,无论我使用自己的4核CPU还是小型的24核服务器,并行化行为都不会差很多。
无论如何,罪魁祸首是使用BLAS的求解器CVXOPT已经是多线程的。通过尝试并行化代码,您正在与该线性代数库竞争。 为了证明我的观点,我强迫BLAS仅使用一个线程。在这种情况下,多处理可以显示出一些优势:
$ python solver.py
Parallel programming took 2.0 seconds
Non parallel programming took 2.73 seconds
$ OMP_NUM_THREADS=1 python solver.py
Parallel programming took 0.57 seconds
Non parallel programming took 2.73 seconds
设置OMP_NUM_THREADS = 1基本上会关闭OpenMP多线程,因此您的每个Python进程都保持单线程。 BLAS也使用一个线程。
对于您的应用程序,您必须平衡线程数(具有OMP_NUM_THREADS)和进程数(例如,在mp.Pool(processes=24)
中)。
阅读参考书
可重复性
requirements.txt
(使用Python 2.7.5):
numpy
cvxpy==0.4.11
sklearn
cvxopt
答案 1 :(得分:0)
多重处理用于CPU绑定功能。 您不能真正对单个过程持续 0.5 秒的任务进行性能比较。您的测试方案需要更新。
与单进程相比,使用多进程时会有很多开销。 Python需要产生新流程,移交任务,传达结果,等等。
Numpy 实际上在幕后执行了外部C代码,这是经过优化的。这意味着它将在单个CPU上非常快速地串行执行。
调度开销支配了您问题中的实际计算时间 。
您应该增加数据输入,因此Numpy大约需要1-2分钟才能完成一个过程,然后转到多处理过程进行比较。
除此之外,如果顺序不重要,那么如果使用imap_unordered
而不是map
,则可以在多处理中获得更好的结果。
有一个不错的blogpost,它在多线程和多处理之间进行了一些比较,并且也解决了Numpy操作。我认为您可能会觉得有帮助。