Reductions in an interior-point solve: a worked solution¶

The worked solution to the first exercise of tutorial 1. Attempt it there first.

Three per-iteration quantities of an interior-point solver, each a single mapreduce over the device, with no temporary array: the primal infeasibility maximum |c|, the complementarity max |x_i z_i|, and the fraction-to-boundary step, the largest α keeping x + α dx positive.

In [1]:
using CUDA

c = CUDA.randn(Float64, 10^5)
xv = CUDA.rand(Float64, 10^5) .+ 0.1
zv = CUDA.rand(Float64, 10^5) .+ 0.1
dx = CUDA.randn(Float64, 10^5)

inf_pr = mapreduce(abs, max, c)

# mapreduce takes several arrays and walks them together
compl = mapreduce((x, z) -> abs(x * z), max, xv, zv)

# Inf for entries that do not constrain the step: the identity for min
alpha_max = mapreduce((x, d) -> d < 0 ? -x / d : Inf, min, xv, dx)

(inf_pr = inf_pr, complementarity = compl, alpha_max = alpha_max)
Out[1]:
(inf_pr = 4.790118053726513, complementarity = 1.2048985717299163, alpha_max = 0.033370771696594755)

Each is one pass over the device, and none of them builds an intermediate array. This is how a GPU-resident interior-point method keeps its work on the device: the iterates never come back to the host, and the scalars that steer the algorithm are computed where the data already is.


This notebook was generated using Literate.jl.