You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Windows下CVXPY多进程凸优化任务卡住问题求助

看起来你遇到了Windows和Linux下多进程优化的兼容性问题,我来帮你拆解原因并给出修复方案:

首先,核心问题出在Windows和Linux多进程的启动机制差异

  • Linux采用fork模式,子进程会直接继承父进程的内存空间,包括你已经定义好的CVXPY问题、参数和变量,因此可以直接复用;
  • Windows默认使用spawn模式,子进程会重新执行整个脚本,而且CVXPY的核心对象(比如ProblemParameter)无法跨进程序列化传递,再加上你没有做进程隔离处理,导致代码卡在pool.map步骤,根本无法进入子进程的get_x函数。

另外你代码里那个全局的for val in gamma_vals:循环其实没有实际作用,只是给gamma赋值但没执行求解逻辑,可以直接删掉。


修复方案1:让子进程独立初始化CVXPY问题

把问题初始化逻辑放到get_x函数内部,同时用if __name__ == '__main__':包裹主程序逻辑——这是Windows下多进程编程的强制要求,能防止子进程无限递归创建:

import cvxpy as cp
import numpy
from multiprocessing import Pool

def get_x(gamma_value):
    print("E")
    # 每个子进程独立创建问题,用固定随机种子保证A/b与主进程一致
    n = 15
    m = 10
    numpy.random.seed(1)
    A = numpy.random.randn(n, m)
    b = numpy.random.randn(n)
    
    gamma = cp.Parameter(nonneg=True)
    x = cp.Variable(m)
    error = cp.sum_squares(A @ x - b)
    obj = cp.Minimize(error + gamma*cp.norm(x, 1))
    prob = cp.Problem(obj)
    
    gamma.value = gamma_value
    result = prob.solve()
    print("F")
    return x.value

if __name__ == '__main__':
    print("A")
    gamma_vals = numpy.logspace(-4,6, num = 6400)
    print("B")
    
    # 可根据CPU核心数调整进程数
    pool = Pool(processes = 4)
    print("D")
    x_values = pool.map(get_x, gamma_vals)
    print(x_values[-1])
    # 记得关闭进程池释放资源
    pool.close()
    pool.join()

修复方案2:预生成A/b并传递给子进程(更高效)

如果不想每个子进程都重复生成A/b,可以在主进程中预生成后打包成参数传递给get_x,numpy数组是可以安全跨进程传递的:

import cvxpy as cp
import numpy
from multiprocessing import Pool

def get_x(args):
    gamma_value, A, b = args
    print("E")
    m = A.shape[1]
    
    gamma = cp.Parameter(nonneg=True)
    x = cp.Variable(m)
    error = cp.sum_squares(A @ x - b)
    obj = cp.Minimize(error + gamma*cp.norm(x, 1))
    prob = cp.Problem(obj)
    
    gamma.value = gamma_value
    result = prob.solve()
    print("F")
    return x.value

if __name__ == '__main__':
    # 主进程仅生成一次A/b
    n = 15
    m = 10
    numpy.random.seed(1)
    A = numpy.random.randn(n, m)
    b = numpy.random.randn(n)
    
    print("A")
    gamma_vals = numpy.logspace(-4,6, num = 6400)
    print("B")
    
    # 构造包含gamma值、A、b的参数元组列表
    args_list = [(val, A, b) for val in gamma_vals]
    
    pool = Pool(processes = 4)
    print("D")
    x_values = pool.map(get_x, args_list)
    print(x_values[-1])
    pool.close()
    pool.join()

为什么Linux能正常运行而Windows不行?

Linux的fork模式会直接复制父进程的内存快照,子进程拿到的是已经初始化完成的CVXPY对象,不需要重新创建也不用序列化传递;但Windows的spawn模式是从头启动子进程,你的全局变量会被重新初始化,且CVXPY对象无法被pickle序列化,导致子进程无法正确执行逻辑,最终出现卡顿无进展的情况。

内容的提问来源于stack exchange,提问作者pcalc

火山引擎 最新活动