Scaling Decision Optimization to 100 Million Variables and Beyond with mPDLP in NVIDIA cuOpt
https://developer.nvidia.com/blog/scaling-decision-optimization-to-100-million-variables-and-beyond-with-mpdlp-in-nvidia-cuopt/📌 NVIDIA cuOpt 用多 GPU 解上億變數的線性規劃
TL;DR:NVIDIA cuOpt 新推出 mPDLP 多 GPU 求解器,靠 min-cut 分割減少跨 GPU 通訊,單卡記憶體用量最多省 6 倍。
有一道叫 zib03 的線性規劃測試題,2008 年由 Thorsten Koch 提出,光是矩陣裡的非零元素就超過 1 億零 400 萬個。十幾年來它一直是演算法與硬體進步的試金石,而 NVIDIA 剛把這道題的求解速度,又往前推了一大步。
🤔 一道考驗了十幾年的超大規模 LP 問題
供應鏈問題正跨越更多 SKU、運輸路線與限制條件,電力網也要即時平衡更多分散式電源——這些都需要在有限的規劃時間窗內評估更大規模的模型與更多不確定性。NVIDIA cuOpt 在單 GPU 上已能比 CPU solver 快 10 倍以上,但今日最大型的規劃問題仍可能需要數小時才能收斂,或直接超出單一 GPU 的記憶體容量,成為業務決策流程的瓶頸。這次 cuOpt 把 zib03 搬到多 GPU 上用新的 mPDLP 求解,解題速率比一年前快了將近 10 倍。
🧩 PDLP:靠兩次矩陣向量乘法反覆逼近答案
cuOpt 採用的 PDLP(Primal-Dual hybrid gradient method)是一階梯度下降類方法,天生高度可平行化、對 GPU 友善。整個演算法的熱點迴圈是稀疏矩陣向量乘法(SpMV)加上幾個逐元素的映射運算,疊代對象是兩個向量:primal 解 x 與 dual 解 y,限制條件則抽象成一個矩陣 A(以及它的轉置)。每一輪疊代大致分兩步:先用上一輪的 dual 解 y,結合 A 的轉置與成本向量,算出新的 primal 解 x,並投影回變數的上下界範圍內;再用更新後的 x,結合 A 本身與限制式右手邊的常數,算出新的 dual 解 y。扣掉可平行化的逐元素運算後,真正需要跨裝置溝通的只剩下這兩次 SpMV,而且彼此依賴對方的輸出。
把 SpMV 分散到多 GPU 時,由於它是一個受記憶體頻寬限制的運算,增加 GPU 數量等於直接疊加可用頻寬,但代價是要壓低兩種分散式開銷:等待其他 GPU 傳資料的通訊開銷,以及工作分配不均造成的閒置。硬體上,NVIDIA 用 NVLink 負責兩張 GPU 間的高速交換,NVSwitch 負責協調多張 GPU 之間的通訊;軟體上則靠 NCCL 函式庫提供 GPU 直連的點對點與集合通訊操作(如 AllReduce、AllGather、Broadcast),原生吃滿 NVLink 與 NVSwitch 的頻寬。
💡 從各自獨立到聯合分割:少掉不必要的跨卡對話
先前的多 GPU 方案 D-PDLP 採用「2D 分割」:先重新排序矩陣改善負載平衡,再沿著行與列把矩陣切成多個子區塊分散到各 GPU,原始矩陣的 SpMV 由每個子區塊各自計算後,再把對應到同一列的部分結果加總還原。這個方法可行,但它把兩次 SpMV 當成互相獨立的運算來處理。
cuOpt 的 mPDLP 改用「min-cut 分割」:既然同一輪疊代中的兩次 SpMV 透過 x 與 y 向量彼此依賴,就該聯合考慮這兩次運算,而不是各自獨立分割。做法是依據矩陣 A 的稀疏模式,盡量把輸入與輸出向量之間連結緊密的部分留在同一張 GPU 上——因為矩陣稀疏,計算某個 y 值時往往根本用不到完整的 x 向量,只需要對應非零項的那幾個分量。透過這種依賴關係的二分圖分析找出切割點,就能大幅減少連續兩次 SpMV 之間必須跨 GPU 傳輸的資料量。
📊 記憶體省 6 倍,速度一年快 10 倍
在 zib03 這道超過 1 億零 400 萬非零元素的基準問題上,cuOpt mPDLP 用多 GPU 求解,解題速率比一年前的版本快了將近 10 倍。相較於單 GPU 版本的 PDLP,mPDLP 在非零元素上限 21 億的 LP 問題上,單卡峰值記憶體用量最多可降低 6 倍。這套方法也已應用在合作夥伴的實際場景:Kinaxis 用於全球性限制條件下的供應與生產規劃,PSR 則用於大型能源系統的產能擴張模型。
🎯 實務啟示
如果團隊手上的 LP 問題已經逼近小時級的收斂時間,或開始撞上單 GPU 記憶體上限,而基礎設施已經有 NVLink 互連的多 GPU 叢集,mPDLP 這種善用疊代依賴關係而非天真平行切分的設計,值得作為下一步擴大求解規模的參考方向。
🔗 來源
- 標題:Scaling Decision Optimization to 100 Million Variables and Beyond with mPDLP in NVIDIA cuOpt
- 作者/機構:Tanya Lenz(NVIDIA Developer Blog)
- 連結:https://developer.nvidia.com/blog/scaling-decision-optimization-to-100-million-variables-and-beyond-with-mpdlp-in-nvidia-cuopt/
#LinearProgramming #GPUComputing #NVIDIA #cuOpt #HPC #NVLink #NCCL #DecisionOptimization #SupplyChain #ParallelComputing
原始資料 NVIDIA Developer · 收集於 2026-10-07
摘要原文
Supply chain problems are expanding across more SKUs, lanes, and constraints than ever before, while energy grids are balancing more distributed sources in real time. To meet these challenges, teams need to evaluate larger models and more uncertainty within a practical planning window. NVIDIA cuOpt GPU-accelerated decision optimization can already deliver speedups of more than 10x over CPU solvers on a single GPU for large-scale linear programming (LP) problems. However, today’s largest planning problems can take hours to converge or exceed the memory capacity of a single GPU. These constraints cause a bottleneck for the workflows that drive business decisions. Historically, large and notoriously challenging LP problems have been a consistent subject of interest for researchers and practitioners. One such problem, zib03 , introduced by Thorsten Koch in 2008 and featuring over 104 million nonzeros, has become a widely studied benchmark for new algorithms and solvers. Figure 1 shows how much progress has been achieved in the field with new algorithms and new hardware for solving this problem. cuOpt is now pushing the limits even further by solving the problem on multiple GPUs with mPDLP, achieving a solve rate nearly 10x faster than a year before. Figure 1. Progression of solve times by linear programming solvers on problem zib03 This post introduces the new cuOpt Multi-GPU Primal-Dual hybrid gradient for Linear Programming (mPDLP) solver. It distributes LP problems across NVLink -connected GPUs, enabling two major outcomes: Reducing solve time for large problems that are impractical to solve within the time window available for a planner Up to 6x lower peak memory usage per GPU compared to single-GPU PDLP (with LP problems capped at 2.1B nonzeros) The post also highlights the benefits of this approach through two partner applications: Kinaxis in globally constrained supply and production planning, and PSR in large-scale energy-system capacity-expansion models. How does the PDLP algorithm solve LPs? Solving an LP consists in finding \(x\) for the following equation: \begin{aligned} \min_{x} \quad & c^\top x \\ \text{s.t.} \quad & Ax = b \\ & l \leq x \leq u \end{aligned} Primal-Dual hybrid gradient for LP (PDLP) is a first order method for solving LPs. It is based on a gradient-descent-like method, making it highly parallelizable and GPU-friendly, enabling significant speedups. The hot loop of the algorithm is a Sparse Matrix-Vector Multiplication (SpMV) , followed by several map operations. This method iterates on two vectors: Primal solution (\(x\)) Dual solution (\(y\)) The constraints of the LP are abstracted as a matrix (\(A\)). This is the matrix that is used in the SpMV loop. There is also the transpose of this matrix (\(A\) T ). The iterative algorithm consists of these operations: \begin{aligned} x^{k+1} &= \text{proj}_{[l,\, u]}\!\left(x^k – \tau(c – A^\top y^k)\right) \\ y^{k+1} &= y^k + \sigma\left(b – A(2x^{k+1} – x^k)\right) \end{aligned} Here, τ and σ are the primal and dual step lengths, proj [l,u] denotes projection onto the variable bounds \(l ≤ x ≤ u\), \(b\) is the right-hand side of the linear equality constraints and \(c\) is the cost vector of the objective function we are trying to minimize. This algorithm is primarily composed of element-wise operations: projections and basic arithmetic. These operations are trivial to distribute on multiple GPUs, so they can be ignored while developing the distributed algorithm. Stripped down to its nontrivial communication steps, the algorithm is: \begin{aligned} x^{k+1} &= A^\top y^k \\ y^{k+1} &= Ax^{k+1} \end{aligned} The last value of \(y\) is used to compute the next \(x\) with a SpMV, and the last value of \(x\) is used to compute the next \(y\) with another SpMV. Distributing PDLP The only nontrivial task to distribute in PDLP is the SpMV, which is a memory-bound operation. This means that increasing the available bandwidth increases the speed of the operation. To increase the bandwidth, you can choose to either wait for the next generation of NVIDIA GPUs to be released or use more GPUs, effectively multiplying the total available bandwidth by the number of GPUs. This, however, comes with the costs associated with distributed algorithms. When distributing an algorithm, two main overheads must be minimized: Communication overhead : Time spent waiting on information from other GPUs Load imbalance : Uneven distribution of work across GPUs, causing some GPUs to wait for others NVIDIA provides the communication tools needed for efficient distributed computation for both the hardware and software stack. For the hardware stack, NVLink and NVSwitch provide the computation backbone. NVLink enables fast, optimized data exchanges between two GPUs, while the NVSwitch efficiently orchestrates the communication among several GPUs. For the software stack, NCCL is a C/C++ library that gives access to GPU-direct point-to-point communication and collective operations (AllReduce, AllGather, Broadcast) among GPUs. These operations natively use the NVLink and NVSwitch to their full capacity. With NVLink, NVSwitch, and NCCL together, multiple distinct GPUs become one fast shared machine. Data moves between devices at high bandwidth and low overhead, so distributed algorithms can scale without leaving the GPU. 2D partitioned D-PDLP Previous efforts to distribute PDLP across multiple GPUs include D-PDLP . First, the matrix can be reordered to improve load balancing. It is then partitioned along its rows and columns into several sub-blocks, which are distributed across the GPUs. Finally, the SpMV of the original matrix is computed by performing an SpMV on each sub-block and summing the resulting partial outputs corresponding to the same row to reconstruct the final result. This means each result of the output vector needs to be constructed from communication among multiple GPUs. This technique works well and D-PDLP used it to demonstrate the potential of multi-GPU acceleration. However, 2D partitioning in D-PDLP computes each SpMV independently, while cuOpt mPDLP exploits the fact that consecutive SpMVs share dependencies through the \(x\) and \(y\) vectors. Min-cut-partitioned PDLP Min-cut-partitioning leverages the dependencies shared between the two SpMVs performed in each PDLP iteration. Unlike the 2D partitioning approach, which treats the SpMVs independently, min-cut partitioning considers both operations jointly when determining how to distribute the constraint matrix across GPUs. The key idea is to partition the matrix so that tightly connected dependencies between the input and output vectors are kept on the same GPU whenever possible. Minimizing the communication across consecutive SpMVs by exploiting the sparsity pattern of \(A\). Figure 2. Example Sparse-Matrix-Vector multiplication between the constraint matrix \(A\) and the primal solution \(x\) , yielding \(y\) When performing \(y^{k+1} = Ax^{k+1}\) the underlying operations are: \begin{aligned} y_1 &= 1x_1 + 2x_2 + 4x_3 + \textcolor{gray}{0x_4} \\ y_2 &= 3x_1 + 6x_2 + \textcolor{gray}{0x_3} + \textcolor{gray}{0x_4} \\ y_3 &= \textcolor{gray}{0x_1} + 7x_2 + 1x_3 + 2x_4 \\ y_4 &= \textcolor{gray}{0x_1} + \textcolor{gray}{0x_2} + 3x_3 + 4x_4 \end{aligned} When computing \(y\), it’s unnecessary to use the full vector \(x\) for the different components \(y\)1, \(y\)2, \(y\)3, \(y\)4 in \(y\). This is due to the sparsity of \(A\). When performing the operations to compute \(y\)1: \(x\)4 is not necessary. For \(y\)2: \(x\)3 and \(x\)4 are not necessary. This is illustrated in the bipartite graph in Figure 3. Figure 3. Bipartite dependency graph linking primal variables \(x\) to dual variables \(y\) based on matrix sparsity Figure 3 shows a general overview of what data is needed to compute each row (this graph also represents the dependencies on SpMV for A T if read from right to left).
由 claude-code/sonnet 自動生成