Solvers¶
CVXPYlayers supports multiple solver backends for different use cases.
Available Solvers¶
Solver |
Type |
Best For |
|---|---|---|
diffcp w/ SCS (default) |
CPU |
General use, most problem types |
diffcp w/ Clarabel |
CPU |
Higher accuracy |
Moreau |
CPU/GPU |
Best performance |
MPAX* |
CPU |
LPs/QPs |
CuClarabel w/ diffqcp |
GPU |
Large problems on NVIDIA GPUs |
* Gradient support is currently broken.
Specifying a Solver¶
At Construction¶
import cvxpy as cp
from cvxpylayers.torch import CvxpyLayer
layer = CvxpyLayer(
problem,
parameters=[A, b],
variables=[x],
solver=cp.DIFFCP,
solver_args={'solver': cp.CLARABEL} # Use Clarabel
)
At Call Time¶
# Use default solver
(x,) = layer(A_tensor, b_tensor)
# Override with different solver
(x,) = layer(A_tensor, b_tensor, solver_args={"solver": cp.SCS})
Solver Arguments¶
Pass solver-specific settings via solver_args:
# At construction (defaults for all calls)
layer = CvxpyLayer(
problem,
parameters=[A, b],
variables=[x],
solver_args={"max_iters": 5000, "eps": 1e-8}
)
# At call time (override for this call)
(x,) = layer(A_tensor, b_tensor, solver_args={"max_iters": 10000})
Common Arguments¶
Argument |
Solver |
Description |
|---|---|---|
|
SCS, Clarabel |
Convergence tolerance |
|
All |
Maximum iterations |
|
All |
Print solver output |
|
SCS |
Anderson acceleration window |
SCS Tuning¶
SCS is robust but may need tuning for difficult problems:
# Recommended settings for convergence issues
solver_args = {
"eps": 1e-8, # Tighter tolerance
"max_iters": 10000, # More iterations
"acceleration_lookback": 0 # Disable acceleration (more stable)
}
(x,) = layer(A_tensor, b_tensor, solver_args=solver_args)
If SCS still struggles, try Clarabel:
# Clarabel for better cone support
layer = CvxpyLayer(problem, parameters=[A, b], variables=[x], solver=cp.CLARABEL)
GPU Acceleration with CuClarabel¶
For NVIDIA GPUs, CuClarabel keeps all data on the GPU:
Setup¶
See Installation for CuClarabel installation.
Usage (PyTorch)¶
import cvxpy as cp
import torch
from cvxpylayers.torch import CvxpyLayer
device = torch.device("cuda")
layer = CvxpyLayer(
problem,
parameters=[A, b],
variables=[x],
solver=cp.CUCLARABEL
).to(device)
# Parameters must be on GPU
A_gpu = torch.randn(m, n, device=device, requires_grad=True)
b_gpu = torch.randn(m, device=device, requires_grad=True)
(x_gpu,) = layer(A_gpu, b_gpu)
x_gpu.sum().backward() # Gradients computed on GPU
When to Use CuClarabel¶
CuClarabel is beneficial when:
Problems are large (1000+ variables/constraints)
You’re already using GPU tensors
Batch sizes are large
You want to avoid CPU-GPU transfers
For small problems, CPU solvers may be faster due to GPU overhead.
Solver Comparison¶
import time
import cvxpy as cp
import torch
from cvxpylayers.torch import CvxpyLayer
# Create problem
n = 100
x = cp.Variable(n)
A = cp.Parameter((n, n))
b = cp.Parameter(n)
problem = cp.Problem(cp.Minimize(cp.sum_squares(A @ x - b)))
# Benchmark different solvers
A_t = torch.randn(n, n)
b_t = torch.randn(n)
for solver in [None, cp.CLARABEL, cp.SCS]:
layer = CvxpyLayer(problem, parameters=[A, b], variables=[x], solver=solver)
start = time.time()
for _ in range(10):
(x_sol,) = layer(A_t, b_t)
elapsed = time.time() - start
solver_name = solver if solver else "diffcp (default)"
print(f"{solver_name}: {elapsed:.3f}s for 10 solves")
Troubleshooting¶
Solver Failed¶
SolverError: Solver 'SCS' failed. Try another solver or adjust solver settings.
Solutions:
Try a different solver
Increase
max_itersLoosen tolerance (
eps)Check problem feasibility
Numerical Issues¶
Warning: Solution may be inaccurate.
Solutions:
Scale your data (normalize matrices)
Use tighter tolerance
Try Clarabel (often more numerically stable)
Slow Convergence¶
Solutions:
Warm-starting (if supported)
Problem reformulation
Use CuClarabel for large problems