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

IntelPython / dpnp / 24789581352

22 Apr 2026 04:19PM UTC coverage: 77.826% (-0.5%) from 78.298%
24789581352

Pull #2841

github

web-flow
Merge 555e54791 into 58eaa1ef5
Pull Request #2841: Feature sparse linalg solvers

1573 of 2960 branches covered (53.14%)

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.

26829 of 33534 relevant lines covered (80.01%)

7895.36 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 <pybind11/pybind11.h>
30
#include <pybind11/stl.h>
31

32
#include <cstdint>
33
#include <tuple>
34
#include <vector>
35

36
#include "gemv.hpp"
37

38
namespace py = pybind11;
39

40
using dpnp::extensions::sparse::init_sparse_gemv_dispatch_tables;
41
using dpnp::extensions::sparse::sparse_gemv_compute;
42
using dpnp::extensions::sparse::sparse_gemv_init;
43
using dpnp::extensions::sparse::sparse_gemv_release;
44

45
PYBIND11_MODULE(_sparse_impl, m)
46
{
4✔
47
    init_sparse_gemv_dispatch_tables();
4✔
48

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

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

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

133
    // ------------------------------------------------------------------
134
    // _sparse_gemv_release(exec_q, handle, depends) -> event
135
    //
136
    // Releases the matrix_handle allocated by _sparse_gemv_init.
137
    // Must be called exactly once per handle after all compute calls
138
    // referencing it have completed. The returned event depends on the
139
    // release, so callers can chain CSR buffer deallocation on it.
140
    // ------------------------------------------------------------------
141
    m.def(
4✔
142
        "_sparse_gemv_release",
4✔
143
        [](sycl::queue &exec_q, const std::uintptr_t handle_ptr,
4✔
144
           const std::vector<sycl::event> &depends) -> sycl::event {
4✔
NEW
145
            return sparse_gemv_release(exec_q, handle_ptr, depends);
×
NEW
146
        },
×
147
        py::arg("exec_q"), py::arg("handle"), py::arg("depends"),
4✔
148
        "Release the oneMKL matrix_handle created by _sparse_gemv_init.");
4✔
149
}
4✔
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