-
Notifications
You must be signed in to change notification settings - Fork 171
Replaced SpMV with SpMVOp in PDHG for double precision #1226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
cccace9
dd12e1a
2439f92
86be5b2
81b8f77
c5f8db2
583da59
4f041f1
2a1360d
96a524a
6b8e78a
a85b10f
68922b0
1880f23
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,8 @@ | |
|
|
||
| #include <cusparse_v2.h> | ||
|
|
||
| #define CUDA_VER_13_2_UP (CUDART_VERSION >= 13020) | ||
|
|
||
| namespace cuopt::linear_programming::detail { | ||
|
|
||
| template <typename i_t, typename f_t> | ||
|
|
@@ -79,6 +81,54 @@ class cusparse_dn_mat_descr_wrapper_t { | |
| bool need_destruction_; | ||
| }; | ||
|
|
||
| #if CUDA_VER_13_2_UP | ||
| class cusparse_spmvop_descr_wrapper_t { | ||
| public: | ||
| cusparse_spmvop_descr_wrapper_t(); | ||
| ~cusparse_spmvop_descr_wrapper_t(); | ||
|
|
||
| cusparse_spmvop_descr_wrapper_t(const cusparse_spmvop_descr_wrapper_t& other); | ||
| cusparse_spmvop_descr_wrapper_t& operator=(cusparse_spmvop_descr_wrapper_t&& other); | ||
| cusparse_spmvop_descr_wrapper_t& operator=(const cusparse_spmvop_descr_wrapper_t& other) = delete; | ||
|
|
||
| void create(cusparseHandle_t handle, | ||
| cusparseOperation_t opA, | ||
| cusparseSpMatDescr_t matA, | ||
| cusparseDnVecDescr_t vecX, | ||
| cusparseDnVecDescr_t vecY, | ||
| cusparseDnVecDescr_t vecZ, | ||
| cudaDataType computeType, | ||
| void* buffer); | ||
|
|
||
| operator cusparseSpMVOpDescr_t() const; | ||
|
|
||
| private: | ||
| cusparseSpMVOpDescr_t descr_; | ||
| bool need_destruction_; | ||
| }; | ||
|
|
||
| class cusparse_spmvop_plan_wrapper_t { | ||
| public: | ||
| cusparse_spmvop_plan_wrapper_t(); | ||
| ~cusparse_spmvop_plan_wrapper_t(); | ||
|
|
||
| cusparse_spmvop_plan_wrapper_t(const cusparse_spmvop_plan_wrapper_t& other); | ||
| cusparse_spmvop_plan_wrapper_t& operator=(cusparse_spmvop_plan_wrapper_t&& other); | ||
| cusparse_spmvop_plan_wrapper_t& operator=(const cusparse_spmvop_plan_wrapper_t& other) = delete; | ||
|
|
||
| void create(cusparseHandle_t handle, | ||
| cusparseSpMVOpDescr_t descr, | ||
| char* lto_buffer, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Passing around raw pointers and sizes are a bad code smell. Please document what these are used for and who owns the memory. On first glance it seems like we always pass
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right, I will fix it |
||
| size_t lto_buffer_size); | ||
|
|
||
| operator cusparseSpMVOpPlan_t() const; | ||
|
|
||
| private: | ||
| cusparseSpMVOpPlan_t plan_; | ||
| bool need_destruction_; | ||
| }; | ||
| #endif | ||
|
|
||
| template <typename i_t, typename f_t> | ||
| class cusparse_view_t { | ||
| public: | ||
|
|
@@ -172,6 +222,17 @@ class cusparse_view_t { | |
| rmm::device_uvector<uint8_t> buffer_non_transpose; | ||
| rmm::device_uvector<uint8_t> buffer_transpose; | ||
|
|
||
| // SpMVOp buffers for A and A_T | ||
| rmm::device_uvector<uint8_t> buffer_non_transpose_spmvop{0, handle_ptr_->get_stream()}; | ||
| rmm::device_uvector<uint8_t> buffer_transpose_spmvop{0, handle_ptr_->get_stream()}; | ||
|
|
||
| #if CUDA_VER_13_2_UP | ||
| // SpMVOp descriptors and plans for A and A_T (descr before plan so dtor destroys plan first) | ||
| cusparse_spmvop_descr_wrapper_t spmv_op_descr_A_; | ||
| cusparse_spmvop_plan_wrapper_t spmv_op_plan_A_; | ||
| cusparse_spmvop_descr_wrapper_t spmv_op_descr_A_t_; | ||
| cusparse_spmvop_plan_wrapper_t spmv_op_plan_A_t_; | ||
| #endif | ||
| // reuse buffers for cusparse spmm | ||
| rmm::device_uvector<uint8_t> buffer_transpose_batch; | ||
| rmm::device_uvector<uint8_t> buffer_non_transpose_batch; | ||
|
|
@@ -212,6 +273,8 @@ class cusparse_view_t { | |
| // Redirects the cuSPARSE CSR structure pointers from op_problem_scaled_ to the original problem | ||
| // so the duplicated row/column buffers can be freed. | ||
| void redirect_cusparse_csr_structure_pointers(const problem_t<i_t, f_t>& original_problem); | ||
| // Creates SpMVOp plans. Must be called after scale_problem() so plans use the scaled matrix. | ||
| void create_spmv_op_plans(bool is_reflected); | ||
| }; | ||
|
|
||
| // Mixed precision SpMV: FP32 matrix with FP64 vectors and FP64 compute type | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 786
Add compile-time guard to enforce double-only instantiation.
The
create_spmv_op_plansmethod is templated onf_tand can be instantiated withfloat(line 1344 of cusparse_view.cu), but hardcodesCUDA_R_64Fat lines 1294, 1304, 1321, and 1331. Since the feature is "double precision only," add a compile-time check:This prevents incorrect behavior if a float instantiation is created and calls this method.
🤖 Prompt for AI Agents