Пример #1
0
def prof_sparse_qp(trial, nz, nbatch, cons, cuda=True):
    trials = []

    npr.seed(trial)

    A = sparse.random(nz, nz, density=.01) + \
        sparse.eye(nz)
    A_rows, A_cols = A.nonzero()

    G = sparse.random(nz, nz, density=.01) + \
        sparse.eye(nz)
    G_rows, G_cols = G.nonzero()
    Q = sparse.eye(nz)

    xs = npr.randn(nbatch, nz)
    p = npr.randn(nbatch, nz)
    b = np.array([A @ xs[i] for i in range(nbatch)])
    h = np.array([G @ xs[i] for i in range(nbatch)])

    def convert(A):
        A = [A.todense() for _ in range(nbatch)]
        return torch.from_numpy(np.array(A)).double().requires_grad_()

    Q_tch, A_tch, G_tch = [convert(mat) for mat in [Q, A, G]]

    p_tch, b_tch, h_tch = [
        torch.from_numpy(x).double().requires_grad_()
        for x in [p, b, h]
    ]

    if cuda:
        p_tch, Q_tch, G_tch, h_tch, A_tch, b_tch = [
            x.cuda() for x in [p_tch, Q_tch, G_tch, h_tch, A_tch, b_tch]]

    torch.cuda.synchronize()
    torch.cuda.synchronize()
    start = time.time()
    x = QPFunction(verbose=False, eps=1e-8, notImprovedLim=5,
                   maxIter=1000)(Q_tch, p_tch, G_tch, h_tch, A_tch, b_tch)
    torch.cuda.synchronize()
    t = time.time() - start
    trials.append({
        'trial': trial,
        'nz': nz,
        'nbatch': nbatch,
        'cuda': cuda,
        'mode': 'qpth',
        'direction': 'forward',
        'time': t,
        'qp': 'sparse'
    })

    y = x.sum()
    start = time.time()
    y.backward()
    t = time.time() - start
    trials.append({
        'trial': trial,
        'nz': nz,
        'nbatch': nbatch,
        'cuda': cuda,
        'mode': 'qpth',
        'direction': 'backward',
        'time': t,
        'qp': 'sparse'
    })

    _p = cp.Parameter((nz, 1))
    _b = cp.Parameter((nz, 1))
    _h = cp.Parameter((nz, 1))

    _z = cp.Variable((nz, 1))

    obj = cp.Minimize(0.5 * cp.sum_squares(_z) + _p.T @ _z)
    cons = [G @ _z <= _h,
            A @ _z == _b]
    prob = cp.Problem(obj, cons)

    p_tch, b_tch, h_tch = [torch.from_numpy(x).unsqueeze(-1).requires_grad_()
                           for x in [p, b, h]]

    solver_args = {
        'mode': 'lsqr',
        'verbose': False,
        'max_iters': 1000,
        'eps': 1e-6,
        'use_indirect': False,
        'gpu': False,
        'n_jobs_forward': -1,
        'n_jobs_backward': -1
    }
    solve = CvxpyLayer(prob, [_p, _b, _h], [_z])

    start = time.time()
    z, = solve(p_tch, b_tch, h_tch, solver_args=solver_args)
    t = time.time() - start
    trials.append({
        'trial': trial,
        'nz': nz,
        'nbatch': nbatch,
        'cuda': cuda,
        'mode': 'cvxpylayers',
        'direction': 'forward',
        'time': t,
        'qp': 'sparse',
        'canon_time': solve.info.get("canon_time")
    })

    y = z.sum()
    start = time.time()
    y.backward()
    t = time.time() - start
    trials.append({
        'trial': trial,
        'nz': nz,
        'nbatch': nbatch,
        'cuda': cuda,
        'mode': 'cvxpylayers',
        'direction': 'backward',
        'time': t,
        'qp': 'sparse',
        'dcanon_time': solve.info.get("dcanon_time")
    })
    return trials
Пример #2
0
def prof_dense_qp(trial, nz, nbatch, cons, cuda=True):
    trials = []

    npr.seed(trial)

    L = npr.rand(nbatch, nz, nz)
    Q = np.matmul(L, L.transpose((0, 2, 1))) + 1e-3 * np.eye(nz, nz)
    p = npr.randn(nbatch, nz)

    if cons == 'dense':
        nineq = nz
        G = npr.randn(nbatch, nineq, nz)
        z0 = npr.randn(nbatch, nz)
        s0 = npr.rand(nbatch, nineq)
        h = np.matmul(G, np.expand_dims(z0, axis=(2))).squeeze(2) + s0
    elif cons == 'box':
        nineq = 2 * nz
        G = np.concatenate((-np.eye(nz), np.eye(nz)))
        G = np.stack([G] * nbatch)
        h = np.ones((nbatch, 2 * nz))
    else:
        raise NotImplementedError

    p_tch, Q_tch, G_tch, h_tch = [
        torch.from_numpy(x).double().requires_grad_()
        for x in [p, Q, G, h]
    ]
    if cuda:
        p_tch, Q_tch, G_tch, h_tch = [x.cuda()
                                      for x in [p_tch, Q_tch, G_tch, h_tch]]

    e = torch.Tensor()

    torch.cuda.synchronize()
    torch.cuda.synchronize()
    start = time.time()
    x = QPFunction(verbose=False, eps=1e-8, notImprovedLim=5,
                   maxIter=1000)(Q_tch, p_tch, G_tch, h_tch, e, e)
    torch.cuda.synchronize()
    t = time.time() - start
    trials.append({
        'trial': trial,
        'nz': nz,
        'nbatch': nbatch,
        'cuda': cuda,
        'mode': 'qpth',
        'direction': 'forward',
        'time': t,
        'qp': 'dense'
    })

    y = x.sum()
    start = time.time()
    y.backward()
    t = time.time() - start
    trials.append({
        'trial': trial,
        'nz': nz,
        'nbatch': nbatch,
        'cuda': cuda,
        'mode': 'qpth',
        'direction': 'backward',
        'time': t,
        'qp': 'dense'
    })

    _Q_sqrt = cp.Parameter((nz, nz))
    _p = cp.Parameter((nz, 1))
    _G = cp.Parameter((nineq, nz))
    _h = cp.Parameter((nineq, 1))
    _z = cp.Variable((nz, 1))
    obj = cp.Minimize(0.5 * cp.sum_squares(_Q_sqrt @ _z) + _p.T @ _z)
    cons = [_G @ _z <= _h]
    prob = cp.Problem(obj, cons)

    Q_sqrt = np.array([sqrtm(q) for q in Q])
    Q_sqrt_tch, p_tch, G_tch, h_tch = [
        torch.from_numpy(x).double().requires_grad_()
        for x in [Q_sqrt, p, G, h]]

    solver_args = {
        'mode': 'dense',
        'verbose': False,
        'max_iters': 1000,
        'eps': 1e-6,
        'use_indirect': False,
        'gpu': False,
        'n_jobs_forward': 12,
        'n_jobs_backward': 12
    }
    solve = CvxpyLayer(prob, [_Q_sqrt, _p, _G, _h], [_z])

    start = time.time()
    z, = solve(
        Q_sqrt_tch, p_tch.unsqueeze(-1), G_tch, h_tch.unsqueeze(-1),
        solver_args=solver_args
    )
    t = time.time() - start
    trials.append({
        'trial': trial,
        'nz': nz,
        'nbatch': nbatch,
        'cuda': cuda,
        'mode': f'cvxpylayers',
        'direction': 'forward',
        'time': t,
        'qp': 'dense',
        'canon_time': solve.info.get("canon_time")
    })

    y = z.sum()
    start = time.time()
    y.backward()
    t = time.time() - start
    trials.append({
        'trial': trial,
        'nz': nz,
        'nbatch': nbatch,
        'cuda': cuda,
        'mode': f'cvxpylayers',
        'direction': 'backward',
        'time': t,
        'qp': 'dense',
        'dcanon_time': solve.info.get("dcanon_time")
    })

    return trials