によるとHPR-LP-Cが1位になっていました。
COPT Barrier Solverの評価ライセンスがもうすぐ終わるので、後継を考察しておきます。GPUを使うことを前提にすれば、First Order系の進歩が著しいので、可能性が出てきました。前にPDLP-CのCPU版を見たときは、使えないと判断しましたが、精度向上と速度向上により将来の可能性は高まりました。Cuoptのライブラリを使っているとWindows Portが実質的に困難ですが、その点は問題なさそうです。
<PDLP-Cとの違い>
2つをリポジトリで確認した結果をまとめます。cuPDLP-Cの実質的な後継であるcuPDLPx(MIT Lu Lab)も、比較のために並べておきます。
| 項目 | HPR-LP-C | cuPDLP-C | (参考)cuPDLPx |
|---|---|---|---|
| アルゴリズム | Halpern Peaceman–Rachford(HPR) | PDHG+適応ステップ+KKTリスタート | Halpern PDHG+PID制御の重み調整 |
| 既定の精度 | 1e-6 | 1e-4(primal / dual / gap それぞれ) | 1e-4程度 |
| 実行不能・非有界の判定 | なし(OPTIMAL / 時間制限 / 反復制限 / エラーのみ) | あり(INFEASIBLE / UNBOUNDED) | あり |
| 初期解(warm start) | なし | 公開APIにはなし | あり(set_start_values) |
| presolve | GPU-Presolver-C(folding付き)またはPSLP | HiGHSのpresolve | PSLP |
| GPUなしでの実行 | 不可 | CPU版をビルドできる | 不可(AMD GPU / ROCmには対応) |
| 高速化の工夫 | 行列構造に合わせた専用SpMVカーネル、CUDA Graph、反復中の行・列の縮約 | cuSPARSEの標準的な呼び出し | cuSPARSE / hipSPARSE |
| バッチ求解 | あり(行列Aが共通の問題群) | なし | なし |
| 制約の書き方 | AL ≤ Ax ≤ AU(範囲制約をそのまま書ける) | Ax=b と Gx≥h(範囲制約は変換が必要) | l ≤ Ax ≤ u |
| 外部依存 | CUDAとzlibのみ | HiGHS 1.6とCUDA 12.3 | CUDA(またはROCm) |
| Windows | 未対応(forkなどの修正が必要) | _WIN32 分岐が一部にあり、比較的移しやすい | 未確認 |
| 開発状況 | 活発(v0.1.3、2026年) | 2024年12月で更新停止 | 活発(2026年9月まで更新) |
| ライセンス | MIT | MIT | Apache 2.0 |
<Windows Portの可能性>
結論から言うと、Windowsへのポートは可能で、ポート不能な箇所は見当たりませんでした。リポジトリ(main、全41コミットの履歴を含む)を確認しましたが、cuOptのライブラリは使われていません(cuopt / RAFT / RMM への参照はゼロ)。依存しているのは CUDA Toolkit 標準の cuSPARSE・cuBLAS・cuSOLVER・Thrust/CUB と、同梱の PSLP、GPU-Presolver-C、zlib、HDF5(任意)だけです。これらはすべてWindows版があります。
cuOptを使っていたら、確かに厳しいところでした。cuOptは公式にはLinux専用なので(Windowsで動かすにはWSL2経由)、ネイティブ移植の障害になっていたはずです。
ただしLinux前提の書き方をしている箇所がいくつかあり、手を入れる必要があります。
要修正(コード)
src/presolve/pslp_integration.cpp:いちばん大きな作業です。PSLPのpresolveをfork()とpipe()で子プロセスに隔離して実行し、waitpidで後始末しています(<unistd.h>,<sys/wait.h>)。直し方は2通りです。- 簡単な方法:同じプロセス内で直接呼ぶ。隔離はなくなるので、PSLPがクラッシュすると全体が落ちます。
- 同じ挙動を保つ方法:
CreateProcessと匿名パイプで作り直す。ただしforkはメモリを丸ごと引き継ぐので、Windowsでは入力モデルをシリアライズして子プロセスに渡す処理が必要になります。
GPU-Presolver-C/.../presolve_structs.hpp:__builtin_huge_val()がGCC拡張です。std::numeric_limits<double>::infinity()に置き換えれば済みます。- PSLP本体:
_WIN32分岐が最初からあるので、Timer と thread はそのまま通ります。
要修正(ビルド系)
CMakeLists.txt:g++-12/11 を探してホストコンパイラにし、-Xcompiler -fPICや-D_GLIBCXX_USE_CXX11_ABI=0、-O3 -wといったGCC専用フラグを付けています。MSVC(Visual Studio)用の分岐が必要です。- GPUアーキテクチャの自動検出:
scripts/detect_cuda_arch.shをbashで呼んでいます。Windowsでは-DCMAKE_CUDA_ARCHITECTURES=89のように明示的に指定するのが簡単です。 - Makefile:Linux専用なので、CMakeだけを使います。
- zlib / HDF5:vcpkgで入れられます。HDF5はなくてもビルドできます。
確認が必要な点
- CUDA 13.3以上では実験的API
cusparseSpMVOpが使われます。Windows版cuSPARSEにこのAPIがあるかは確認していません。もしなくても、旧来のcusparseSpMVに切り替わる仕組みがあるので、ビルドは通るはずです。 - CUDA Graph、cuSPARSE、cuBLASなどはWindowsでも普通に動きます。
- READMEの動作要件は「Linux x86-64」としか書かれていません。Windowsはテストされていないので、動作確認は自分でやる必要があります。
作業量の目安としては、ビルド系の修正と fork の置き換えがほとんどで、数百行程度の変更で収まると思います。まず動かしたいだけなら、WSL2上でLinux版をそのままビルドするのが一番早いです(GPUもそのまま使えます)。
0 件のコメント:
コメントを投稿