• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IntelPython / dpnp / 24355365981

13 Apr 2026 04:45PM UTC coverage: 81.073% (-1.0%) from 82.034%
24355365981

Pull #2841

github

web-flow
Merge eecf9d6cb into 71d3c2316
Pull Request #2841: Feature sparse linalg solvers

1328 of 2472 branches covered (53.72%)

Branch coverage included in aggregate %.

567 of 952 new or added lines in 7 files covered. (59.56%)

23 existing lines in 1 file now uncovered.

20350 of 24267 relevant lines covered (83.86%)

6728.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.92
/dpnp/backend/extensions/sparse/sparse_py.cpp
1
//*****************************************************************************
2
// Copyright (c) 2025, Intel Corporation
3
// All rights reserved.
4
//
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are met:
7
// - Redistributions of source code must retain the above copyright notice,
8
//   this list of conditions and the following disclaimer.
9
// - Redistributions in binary form must reproduce the above copyright notice,
10
//   this list of conditions and the following disclaimer in the documentation
11
//   and/or other materials provided with the distribution.
12
// - Neither the name of the copyright holder nor the names of its contributors
13
//   may be used to endorse or promote products derived from this software
14
//   without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
// POSSIBILITY OF SUCH DAMAGE.
27
//*****************************************************************************
28

29
#include <cstdint>
30
#include <tuple>
31
#include <vector>
32

33
#include <pybind11/pybind11.h>
34
#include <pybind11/stl.h>
35

36
#include <sycl/sycl.hpp>
37

38
#include <dpctl4pybind11.hpp>
39

40
#include "gemv.hpp"
41

42
namespace py = pybind11;
43

44
using dpnp::extensions::sparse::init_sparse_gemv_dispatch_tables;
45
using dpnp::extensions::sparse::sparse_gemv_compute;
46
using dpnp::extensions::sparse::sparse_gemv_init;
47
using dpnp::extensions::sparse::sparse_gemv_release;
48

49
PYBIND11_MODULE(_sparse_impl, m)
50
{
2✔
51
    init_sparse_gemv_dispatch_tables();
2✔
52

53
    // ------------------------------------------------------------------
54
    // _using_onemath()
55
    //
56
    // Reports whether the module was compiled against the portable
57
    // OneMath interface (USE_ONEMATH) rather than direct oneMKL.
58
    // ------------------------------------------------------------------
59
    m.def("_using_onemath", []() -> bool {
2✔
60
#ifdef USE_ONEMATH
61
        return true;
62
#else
NEW
63
        return false;
×
NEW
64
#endif
×
NEW
65
    });
×
66

67
    // ------------------------------------------------------------------
68
    // _sparse_gemv_init(exec_q, trans, row_ptr, col_ind, values,
69
    //                   num_rows, num_cols, nnz, depends)
70
    //     -> (handle: int, val_type_id: int, event)
71
    //
72
    // Calls init_matrix_handle + set_csr_data + optimize_gemv ONCE.
73
    //
74
    // The returned handle is an opaque uintptr_t; val_type_id is the
75
    // dpctl typenum lookup id of the matrix value dtype and MUST be
76
    // passed back to _sparse_gemv_compute so the C++ layer can verify
77
    // that x and y dtype match the handle.
78
    //
79
    // LIFETIME CONTRACT: the caller must keep row_ptr / col_ind / values
80
    // USM allocations alive until _sparse_gemv_release has been called
81
    // AND its returned event has completed. The handle does not copy
82
    // the CSR arrays.
83
    // ------------------------------------------------------------------
84
    m.def(
2✔
85
        "_sparse_gemv_init",
2✔
86
        [](sycl::queue &exec_q, const int trans,
2✔
87
           const dpctl::tensor::usm_ndarray &row_ptr,
2✔
88
           const dpctl::tensor::usm_ndarray &col_ind,
2✔
89
           const dpctl::tensor::usm_ndarray &values,
2✔
90
           const std::int64_t num_rows, const std::int64_t num_cols,
2✔
91
           const std::int64_t nnz, const std::vector<sycl::event> &depends)
2✔
92
            -> std::tuple<std::uintptr_t, int, sycl::event> {
2✔
NEW
93
            return sparse_gemv_init(exec_q, trans, row_ptr, col_ind, values,
×
NEW
94
                                    num_rows, num_cols, nnz, depends);
×
NEW
95
        },
×
96
        py::arg("exec_q"), py::arg("trans"), py::arg("row_ptr"),
2✔
97
        py::arg("col_ind"), py::arg("values"), py::arg("num_rows"),
2✔
98
        py::arg("num_cols"), py::arg("nnz"), py::arg("depends"),
2✔
99
        "Initialise oneMKL sparse matrix handle "
2✔
100
        "(set_csr_data + optimize_gemv). "
2✔
101
        "Returns (handle_ptr: int, val_type_id: int, event). "
2✔
102
        "Call once per operator.");
2✔
103

104
    // ------------------------------------------------------------------
105
    // _sparse_gemv_compute(exec_q, handle, val_type_id, trans, alpha,
106
    //                     x, beta, y, num_rows, num_cols, depends)
107
    //     -> gemv_event
108
    //
109
    // Fires sparse::gemv using a pre-built handle. Verifies x and y
110
    // dtype match val_type_id from init, and that shapes agree with
111
    // op(A) dimensions (swapped for trans != N).
112
    //
113
    // Only the cheap MKL kernel is dispatched; no analysis overhead.
114
    // No host_task keep-alive is submitted -- pybind11 refcounts the
115
    // usm_ndarrays across the call, and sequencing of subsequent work
116
    // on the same queue happens automatically.
117
    // ------------------------------------------------------------------
118
    m.def(
2✔
119
        "_sparse_gemv_compute",
2✔
120
        [](sycl::queue &exec_q, const std::uintptr_t handle_ptr,
2✔
121
           const int val_type_id, const int trans, const double alpha,
2✔
122
           const dpctl::tensor::usm_ndarray &x, const double beta,
2✔
123
           const dpctl::tensor::usm_ndarray &y, const std::int64_t num_rows,
2✔
124
           const std::int64_t num_cols,
2✔
125
           const std::vector<sycl::event> &depends) -> sycl::event {
2✔
NEW
126
            return sparse_gemv_compute(exec_q, handle_ptr, val_type_id, trans,
×
NEW
127
                                       alpha, x, beta, y, num_rows, num_cols,
×
NEW
128
                                       depends);
×
NEW
129
        },
×
130
        py::arg("exec_q"), py::arg("handle"), py::arg("val_type_id"),
2✔
131
        py::arg("trans"), py::arg("alpha"), py::arg("x"), py::arg("beta"),
2✔
132
        py::arg("y"), py::arg("num_rows"), py::arg("num_cols"),
2✔
133
        py::arg("depends"),
2✔
134
        "Execute sparse::gemv using a pre-built handle. "
2✔
135
        "Returns the gemv event.");
2✔
136

137
    // ------------------------------------------------------------------
138
    // _sparse_gemv_release(exec_q, handle, depends) -> event
139
    //
140
    // Releases the matrix_handle allocated by _sparse_gemv_init.
141
    // Must be called exactly once per handle after all compute calls
142
    // referencing it have completed. The returned event depends on the
143
    // release, so callers can chain CSR buffer deallocation on it.
144
    // ------------------------------------------------------------------
145
    m.def(
2✔
146
        "_sparse_gemv_release",
2✔
147
        [](sycl::queue &exec_q, const std::uintptr_t handle_ptr,
2✔
148
           const std::vector<sycl::event> &depends) -> sycl::event {
2✔
NEW
149
            return sparse_gemv_release(exec_q, handle_ptr, depends);
×
NEW
150
        },
×
151
        py::arg("exec_q"), py::arg("handle"), py::arg("depends"),
2✔
152
        "Release the oneMKL matrix_handle created by _sparse_gemv_init.");
2✔
153
}
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc