Skip to content

Conversation

@ZedongPeng
Copy link
Collaborator

Desciption

This PR adds the Julia interface for cuPDLPx, a GPU-accelerated first-order LP solver.

A JLL package has already been created and merged into Yggdrasil.
The next step is to build the C API wrapper using Clang.jl, which is still a work in progress due to several CUDA header dependencies.

Below is an example output from the current code generation workflow.
Any feedback or suggestions from the Julia or JuMP community would be greatly appreciated. @odow @blegat

julia> include("gen/generate.jl")
[ Info: Found dependent header: /home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/struct.h
[ Info: Found dependent header: /orcd/home/002/zdpeng/github/cuPDLPx.jl/gen/clang_stub/cusparse.h
[ Info: Found dependent header: /orcd/home/002/zdpeng/github/cuPDLPx.jl/gen/clang_stub/cublas_v2.h
[ Info: Found dependent header: /home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/utils.h
[ Info: Found dependent header: /orcd/home/002/zdpeng/github/cuPDLPx.jl/gen/clang_stub/cuda_runtime.h
[ Info: Found dependent header: /home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/io.h
[ Info: Found dependent header: /home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/solver.h
[ Info: Parsing headers...
/home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/cupdlpx.h:17:9: warning: #pragma once in main file [-Wpragma-once-outside-header]
/home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/struct.h:187:2: error: unknown type name 'cusparseSpMatDescr_t'
/home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/struct.h:188:2: error: unknown type name 'cusparseSpMatDescr_t'
/home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/struct.h:189:2: error: unknown type name 'cusparseDnVecDescr_t'
/home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/struct.h:190:2: error: unknown type name 'cusparseDnVecDescr_t'
/home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/struct.h:191:2: error: unknown type name 'cusparseDnVecDescr_t'
/home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/struct.h:192:2: error: unknown type name 'cusparseDnVecDescr_t'
[ Info] artifact_include_dir = /home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include
[ Info] cuda_include_dir     = /home/zdpeng/.julia/artifacts/4ae4e34b836b22e0abe84f78191e8f25385f3c1c/cuda/include
[ Info] stub_dir             = /orcd/home/002/zdpeng/github/cuPDLPx.jl/gen/clang_stub
[ Info] clang args:
    -isystem/home/zdpeng/.julia/artifacts/305c8b171016c46dfbb8ca234a543a99b6e3d045/lib/gcc/x86_64-linux-gnu/4.8.5/include
    -isystem/home/zdpeng/.julia/artifacts/305c8b171016c46dfbb8ca234a543a99b6e3d045/lib/gcc/x86_64-linux-gnu/4.8.5/include-fixed
    -isystem/home/zdpeng/.julia/artifacts/305c8b171016c46dfbb8ca234a543a99b6e3d045/x86_64-linux-gnu/include
    -isystem/home/zdpeng/.julia/artifacts/305c8b171016c46dfbb8ca234a543a99b6e3d045/x86_64-linux-gnu/sys-root/usr/include
    --target=x86_64-unknown-linux-gnu
    -I/orcd/home/002/zdpeng/github/cuPDLPx.jl/gen/clang_stub
    -I/home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include
    -I/home/zdpeng/.julia/artifacts/4ae4e34b836b22e0abe84f78191e8f25385f3c1c/cuda/include
    -D__thread=
    -D__device__=
    -D__host__=
    -D__forceinline__=
    -D__global__=
    -D__shared__=
    -D__inline__=
    -D__attribute__(x)=
    -D__declspec(x)=
    -D__location__=
    -Dgrid_constant=
    -Dconstant=
    -Dmanaged=
    -D__CDPRT_DEPRECATED(x)=
    -D__CUDART_API_PTSZ(x)=x
    -D__device_builtin__=__attribute__((unused))
    -x
    c++
    -std=c++14
    -nostdinc
[ Info] Building lib bindings from /home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/cupdlpx.h ...
[ Info: Processing header: /home/zdpeng/.julia/artifacts/4e7858c9e3bf6559c126b7a9bb92c59c3608b926/include/cupdlpx.h
[ Info: Building the DAG...
[ Info: Emit Julia expressions...
[ Info: [ProloguePrinter]: print to ../src/LibcuPDLPx.jl
[ Info: [GeneralPrinter]: print to ../src/LibcuPDLPx.jl
[ Info: [EpiloguePrinter]: print to ../src/LibcuPDLPx.jl
[ Info: Done!
[ Info] Generation complete.
[ Info] Cleaning up generated bindings at /orcd/home/002/zdpeng/github/cuPDLPx.jl/gen/../src/LibcuPDLPx.jl ...
[ Info] Cleanup complete. Removed 4 bytes.
[ ✅ Done] Bindings generated successfully!

julia> Pkg.precompile()
Precompiling project...
  1 dependency successfully precompiled in 9 seconds. 74 already precompiled.

@ZedongPeng ZedongPeng requested a review from blegat November 2, 2025 00:21
@ZedongPeng ZedongPeng marked this pull request as draft November 2, 2025 02:11
@odow
Copy link

odow commented Nov 2, 2025

There's a lot of stuff there. You should wrap only the public C API.

What functions is the user expected to call?

reflection_coefficient::Cdouble
end

struct pdhg_solver_state_t
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, I assume the user shouldn't need access to this struct

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it.

f === :csc && return Ptr{var"##Ctag#234"}(x + 0)
f === :coo && return Ptr{var"##Ctag#235"}(x + 0)
return getfield(x, f)
end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I don't know what this function is


function safe_malloc(size)
ccall((:safe_malloc, libcupdlpx), Ptr{Cvoid}, (Csize_t,), size)
end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this should almost certainly not be exposed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it.

end

function read_mps_file(filename)
ccall((:read_mps_file, libcupdlpx), Ptr{lp_problem_t}, (Ptr{Cchar},), filename)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But stuff like this should be

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m a bit confused here. Since the goal of this API is to interact with JuMP, do we still need this functionality, given that JuMP already provides the read_from_file function?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This falls into the question of "what is your public API?"

People might want to interact with cuPDLPx directly, from Julia, and without JuMP.

Something like:

using cuPDLPx
model = cuPDLPx.read_mps_file(filename)
cuPDLPx.optimize(model)
x = cuPDLPx.get_solution(model)

(Or whatever, I don't know the C API functions)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the input, @odow. That’s a good point — we may need to reorganize the C API functions in cuPDLPx.

@ZedongPeng
Copy link
Collaborator Author

Thank you so much for the suggestion, @odow. I wasn’t very familiar with Clang.jl before — I’ll make sure to wrap only the public C API.

There's a lot of stuff there. You should wrap only the public C API.

What functions is the user expected to call?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants