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

IntelPython / dpnp / 18463977845

13 Oct 2025 11:15AM UTC coverage: 72.021% (+0.006%) from 72.015%
18463977845

Pull #2616

github

web-flow
Merge 4683c32d6 into 800f642c9
Pull Request #2616: Add `dpnp.exceptions` submodule to aggregate generic exceptions

5067 of 10224 branches covered (49.56%)

Branch coverage included in aggregate %.

8 of 8 new or added lines in 2 files covered. (100.0%)

2041 existing lines in 130 files now uncovered.

18659 of 22719 relevant lines covered (82.13%)

18876.68 hits per line

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

79.2
/dpnp/backend/extensions/lapack/heevd_batch.cpp
1
//*****************************************************************************
2
// Copyright (c) 2024, 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
26
// THE POSSIBILITY OF SUCH DAMAGE.
27
//*****************************************************************************
28

29
#include <stdexcept>
30

31
#include <pybind11/stl.h>
32

33
#include "common_helpers.hpp"
34
#include "evd_batch_common.hpp"
35
#include "heevd_batch.hpp"
36

37
// utils extension header
38
#include "ext/common.hpp"
39

40
// dpctl tensor headers
41
#include "utils/type_utils.hpp"
42

43
namespace dpnp::extensions::lapack
44
{
45
namespace mkl_lapack = oneapi::mkl::lapack;
46
namespace type_utils = dpctl::tensor::type_utils;
47

48
using ext::common::init_dispatch_table;
49

50
template <typename T, typename RealT>
51
static sycl::event heevd_batch_impl(sycl::queue &exec_q,
52
                                    const oneapi::mkl::job jobz,
53
                                    const oneapi::mkl::uplo upper_lower,
54
                                    const std::int64_t batch_size,
55
                                    const std::int64_t n,
56
                                    char *in_a,
57
                                    char *out_w,
58
                                    const std::vector<sycl::event> &depends)
59
{
24✔
60
    type_utils::validate_type_for_device<T>(exec_q);
24✔
61
    type_utils::validate_type_for_device<RealT>(exec_q);
24✔
62

63
    T *a = reinterpret_cast<T *>(in_a);
24✔
64
    RealT *w = reinterpret_cast<RealT *>(out_w);
24✔
65

66
    const std::int64_t a_size = n * n;
24✔
67
    const std::int64_t w_size = n;
24✔
68

69
    const std::int64_t lda = std::max<size_t>(1UL, n);
24✔
70

71
    // Get the number of independent linear streams
72
    const std::int64_t n_linear_streams =
24✔
73
        (batch_size > 16) ? 4 : ((batch_size > 4 ? 2 : 1));
24!
74

75
    const std::int64_t scratchpad_size =
24✔
76
        mkl_lapack::heevd_scratchpad_size<T>(exec_q, jobz, upper_lower, n, lda);
24✔
77

78
    T *scratchpad = helper::alloc_scratchpad_batch<T>(scratchpad_size,
24✔
79
                                                      n_linear_streams, exec_q);
24✔
80

81
    // Computation events to manage dependencies for each linear stream
82
    std::vector<std::vector<sycl::event>> comp_evs(n_linear_streams, depends);
24✔
83

84
    std::stringstream error_msg;
24✔
85
    std::int64_t info = 0;
24✔
86

87
    // Release GIL to avoid serialization of host task
88
    // submissions to the same queue in OneMKL
89
    py::gil_scoped_release release;
24✔
90

91
    for (std::int64_t batch_id = 0; batch_id < batch_size; ++batch_id) {
88✔
92
        T *a_batch = a + batch_id * a_size;
64✔
93
        RealT *w_batch = w + batch_id * w_size;
64✔
94

95
        std::int64_t stream_id = (batch_id % n_linear_streams);
64✔
96

97
        T *current_scratch_heevd = scratchpad + stream_id * scratchpad_size;
64✔
98

99
        // Get the event dependencies for the current stream
100
        const auto &current_dep = comp_evs[stream_id];
64✔
101

102
        sycl::event heevd_event;
64✔
103
        try {
64✔
104
            heevd_event = mkl_lapack::heevd(
64✔
105
                exec_q,
64✔
106
                jobz, // 'jobz == job::vec' means eigenvalues and eigenvectors
64✔
107
                      // are computed.
108
                upper_lower, // 'upper_lower == job::upper' means the upper
64✔
109
                             // triangular part of A, or the lower triangular
110
                             // otherwise
111
                n,           // The order of the matrix A (0 <= n)
64✔
112
                a_batch,     // Pointer to the square A (n x n)
64✔
113
                             // If 'jobz == job::vec', then on exit it will
114
                             // contain the eigenvectors of A
115
                lda, // The leading dimension of A, must be at least max(1, n)
64✔
116
                w_batch, // Pointer to array of size at least n, it will contain
64✔
117
                         // the eigenvalues of A in ascending order
118
                current_scratch_heevd, // Pointer to scratchpad memory to be
64✔
119
                                       // used by MKL routine for storing
120
                                       // intermediate results
121
                scratchpad_size, current_dep);
64✔
122
        } catch (mkl_lapack::exception const &e) {
64✔
123
            error_msg << "Unexpected MKL exception caught during heevd() "
×
124
                         "call:\nreason: "
×
125
                      << e.what() << "\ninfo: " << e.info();
×
126
            info = e.info();
×
127
        } catch (sycl::exception const &e) {
×
128
            error_msg
×
129
                << "Unexpected SYCL exception caught during heevd() call:\n"
×
UNCOV
130
                << e.what();
×
UNCOV
131
            info = -1;
×
UNCOV
132
        }
×
133

134
        // Update the event dependencies for the current stream
135
        comp_evs[stream_id] = {heevd_event};
64✔
136
    }
64✔
137

138
    if (info != 0) // an unexpected error occurs
24!
139
    {
×
140
        if (scratchpad != nullptr) {
×
141
            dpctl::tensor::alloc_utils::sycl_free_noexcept(scratchpad, exec_q);
×
UNCOV
142
        }
×
UNCOV
143
        throw std::runtime_error(error_msg.str());
×
UNCOV
144
    }
×
145

146
    sycl::event ht_ev = exec_q.submit([&](sycl::handler &cgh) {
24✔
147
        for (const auto &ev : comp_evs) {
24✔
148
            cgh.depends_on(ev);
24✔
149
        }
24✔
150
        auto ctx = exec_q.get_context();
24✔
151
        cgh.host_task([ctx, scratchpad]() {
24✔
152
            dpctl::tensor::alloc_utils::sycl_free_noexcept(scratchpad, ctx);
24✔
153
        });
24✔
154
    });
24✔
155

156
    return ht_ev;
24✔
157
}
24✔
158

159
template <typename fnT, typename T, typename RealT>
160
struct HeevdBatchContigFactory
161
{
162
    fnT get()
163
    {
392✔
164
        if constexpr (types::HeevdTypePairSupportFactory<T, RealT>::is_defined)
165
        {
4✔
166
            return heevd_batch_impl<T, RealT>;
4✔
167
        }
168
        else {
388✔
169
            return nullptr;
388✔
170
        }
388✔
171
    }
392✔
172
};
173

174
using evd::evd_batch_impl_fn_ptr_t;
175

176
void init_heevd_batch(py::module_ m)
177
{
2✔
178
    using arrayT = dpctl::tensor::usm_ndarray;
2✔
179
    using event_vecT = std::vector<sycl::event>;
2✔
180

181
    static evd_batch_impl_fn_ptr_t
2✔
182
        heevd_batch_dispatch_table[dpctl_td_ns::num_types]
2✔
183
                                  [dpctl_td_ns::num_types];
2✔
184

185
    {
2✔
186
        init_dispatch_table<evd_batch_impl_fn_ptr_t, HeevdBatchContigFactory>(
2✔
187
            heevd_batch_dispatch_table);
2✔
188

189
        auto heevd_batch_pyapi =
2✔
190
            [&](sycl::queue &exec_q, const std::int8_t jobz,
2✔
191
                const std::int8_t upper_lower, const arrayT &eig_vecs,
2✔
192
                const arrayT &eig_vals, const event_vecT &depends = {}) {
24✔
193
                return evd::evd_batch_func(exec_q, jobz, upper_lower, eig_vecs,
24✔
194
                                           eig_vals, depends,
24✔
195
                                           heevd_batch_dispatch_table);
24✔
196
            };
24✔
197
        m.def(
2✔
198
            "_heevd_batch", heevd_batch_pyapi,
2✔
199
            "Call `heevd` from OneMKL LAPACK library in a loop to return "
2✔
200
            "the eigenvalues and eigenvectors of a batch of complex Hermitian "
2✔
201
            "matrices",
2✔
202
            py::arg("sycl_queue"), py::arg("jobz"), py::arg("upper_lower"),
2✔
203
            py::arg("eig_vecs"), py::arg("eig_vals"),
2✔
204
            py::arg("depends") = py::list());
2✔
205
    }
2✔
206
}
2✔
207
} // namespace dpnp::extensions::lapack
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