• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

IntelPython / dpnp / 28865922541

07 Jul 2026 12:25PM UTC coverage: 77.681% (-0.4%) from 78.11%
28865922541

Pull #2841

github

web-flow
Merge 1c7d63d18 into 1b76e0600
Pull Request #2841: Feature sparse linalg solvers

1539 of 2916 branches covered (52.78%)

Branch coverage included in aggregate %.

820 of 1220 new or added lines in 11 files covered. (67.21%)

26823 of 33595 relevant lines covered (79.84%)

8347.19 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) 2026, 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 <utility>
35
#include <vector>
36

37
#include "gemv.hpp"
38

39
namespace py = pybind11;
40

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

46
PYBIND11_MODULE(_sparse_impl, m)
47
{
1✔
48
    init_sparse_gemv_dispatch_tables();
1✔
49

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

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

101
    // ------------------------------------------------------------------
102
    // _sparse_gemv_compute(exec_q, handle, val_type_id, trans, alpha,
103
    //                     x, beta, y, num_rows, num_cols, depends)
104
    //     -> gemv_event
105
    //
106
    // Fires sparse::gemv using a pre-built handle. Verifies x and y
107
    // dtype match val_type_id from init, and that shapes agree with
108
    // op(A) dimensions (swapped for trans != N).
109
    //
110
    // Returns (host_task_event, gemv_event); the host_task_event keeps
111
    // x / y alive until the gemv kernel completes.
112
    // ------------------------------------------------------------------
113
    m.def(
1✔
114
        "_sparse_gemv_compute",
1✔
115
        [](sycl::queue &exec_q, const std::uintptr_t handle_ptr,
1✔
116
           const int val_type_id, const int trans, const double alpha,
1✔
117
           const dpnp::tensor::usm_ndarray &x, const double beta,
1✔
118
           const dpnp::tensor::usm_ndarray &y, const std::int64_t num_rows,
1✔
119
           const std::int64_t num_cols, const std::vector<sycl::event> &depends)
1✔
120
            -> std::pair<sycl::event, sycl::event> {
1✔
NEW
121
            return sparse_gemv_compute(exec_q, handle_ptr, val_type_id, trans,
×
NEW
122
                                       alpha, x, beta, y, num_rows, num_cols,
×
NEW
123
                                       depends);
×
NEW
124
        },
×
125
        py::arg("exec_q"), py::arg("handle"), py::arg("val_type_id"),
1✔
126
        py::arg("trans"), py::arg("alpha"), py::arg("x"), py::arg("beta"),
1✔
127
        py::arg("y"), py::arg("num_rows"), py::arg("num_cols"),
1✔
128
        py::arg("depends"),
1✔
129
        "Execute sparse::gemv using a pre-built handle. "
1✔
130
        "Returns (host_task_event, gemv_event).");
1✔
131

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

© 2026 Coveralls, Inc