Skip to content

Commit 04afc1a

Browse files
Merge master into use_gesv_solve
2 parents 15814c5 + 5584348 commit 04afc1a

File tree

13 files changed

+786
-153
lines changed

13 files changed

+786
-153
lines changed

.github/workflows/openssf-scorecard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,6 @@ jobs:
6969

7070
# Upload the results to GitHub's code scanning dashboard.
7171
- name: "Upload to code-scanning"
72-
uses: github/codeql-action/upload-sarif@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.9
72+
uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11
7373
with:
7474
sarif_file: results.sarif

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3434
* Replaced `ci` section in `.pre-commit-config.yaml` with a new GitHub workflow with scheduled run to autoupdate the `pre-commit` configuration [#2542](https://github.com/IntelPython/dpnp/pull/2542)
3535
* FFT module is updated to perform in-place FFT in intermediate steps of ND FFT [#2543](https://github.com/IntelPython/dpnp/pull/2543)
3636
* Reused dpctl tensor include to enable experimental SYCL namespace for complex types [#2546](https://github.com/IntelPython/dpnp/pull/2546)
37+
* Changed Windows-specific logic in dpnp initialization [#2553](https://github.com/IntelPython/dpnp/pull/2553)
3738
* Refactored backend implementation of `dpnp.linalg.solve` to use oneMKL LAPACK `gesv` directly [#2558](https://github.com/IntelPython/dpnp/pull/2558)
3839

3940
### Deprecated

doc/reference/linalg.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Decompositions
4343
dpnp.linalg.cholesky
4444
dpnp.linalg.outer
4545
dpnp.linalg.qr
46+
dpnp.linalg.lu_factor
4647
dpnp.linalg.svd
4748
dpnp.linalg.svdvals
4849

dpnp/__init__.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,13 @@
4040
# where to search for DLLs towards both DPNP backend and DPCTL Sycl interface,
4141
# otherwise DPNP import will be failing. This is because the libraries
4242
# are not installed under any of default paths where Python is searching.
43-
from platform import system
44-
45-
if system() == "Windows": # pragma: no cover
46-
if hasattr(os, "add_dll_directory"):
47-
os.add_dll_directory(mypath)
48-
os.add_dll_directory(dpctlpath)
4943

44+
if sys.platform == "win32": # pragma: no cover
45+
os.add_dll_directory(mypath)
46+
os.add_dll_directory(dpctlpath)
5047
os.environ["PATH"] = os.pathsep.join(
5148
[os.getenv("PATH", ""), mypath, dpctlpath]
5249
)
53-
5450
# For virtual environments on Windows, add folder with DPC++ libraries
5551
# to the DLL search path
5652
if sys.base_exec_prefix != sys.exec_prefix and os.path.isfile(

dpnp/backend/extensions/lapack/getrf.cpp

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ namespace py = pybind11;
4444
namespace type_utils = dpctl::tensor::type_utils;
4545

4646
typedef sycl::event (*getrf_impl_fn_ptr_t)(sycl::queue &,
47+
const std::int64_t,
4748
const std::int64_t,
4849
char *,
4950
std::int64_t,
@@ -56,6 +57,7 @@ static getrf_impl_fn_ptr_t getrf_dispatch_vector[dpctl_td_ns::num_types];
5657

5758
template <typename T>
5859
static sycl::event getrf_impl(sycl::queue &exec_q,
60+
const std::int64_t m,
5961
const std::int64_t n,
6062
char *in_a,
6163
std::int64_t lda,
@@ -69,7 +71,7 @@ static sycl::event getrf_impl(sycl::queue &exec_q,
6971
T *a = reinterpret_cast<T *>(in_a);
7072

7173
const std::int64_t scratchpad_size =
72-
mkl_lapack::getrf_scratchpad_size<T>(exec_q, n, n, lda);
74+
mkl_lapack::getrf_scratchpad_size<T>(exec_q, m, n, lda);
7375
T *scratchpad = nullptr;
7476

7577
std::stringstream error_msg;
@@ -82,13 +84,13 @@ static sycl::event getrf_impl(sycl::queue &exec_q,
8284

8385
getrf_event = mkl_lapack::getrf(
8486
exec_q,
85-
n, // The order of the square matrix A (0 ≤ n).
87+
m, // The number of rows in the input matrix A (0 ≤ m).
8688
// It must be a non-negative integer.
87-
n, // The number of columns in the square matrix A (0 ≤ n).
89+
n, // The number of columns in the input matrix A (0 ≤ n).
8890
// It must be a non-negative integer.
89-
a, // Pointer to the square matrix A (n x n).
91+
a, // Pointer to the input matrix A (m x n).
9092
lda, // The leading dimension of matrix A.
91-
// It must be at least max(1, n).
93+
// It must be at least max(1, m).
9294
ipiv, // Pointer to the output array of pivot indices.
9395
scratchpad, // Pointer to scratchpad memory to be used by MKL
9496
// routine for storing intermediate results.
@@ -99,7 +101,7 @@ static sycl::event getrf_impl(sycl::queue &exec_q,
99101

100102
if (info < 0) {
101103
error_msg << "Parameter number " << -info
102-
<< " had an illegal value.";
104+
<< " had an illegal value";
103105
}
104106
else if (info == scratchpad_size && e.detail() != 0) {
105107
error_msg
@@ -168,13 +170,13 @@ std::pair<sycl::event, sycl::event>
168170
if (a_array_nd != 2) {
169171
throw py::value_error(
170172
"The input array has ndim=" + std::to_string(a_array_nd) +
171-
", but a 2-dimensional array is expected.");
173+
", but a 2-dimensional array is expected");
172174
}
173175

174176
if (ipiv_array_nd != 1) {
175177
throw py::value_error("The array of pivot indices has ndim=" +
176178
std::to_string(ipiv_array_nd) +
177-
", but a 1-dimensional array is expected.");
179+
", but a 1-dimensional array is expected");
178180
}
179181

180182
// check compatibility of execution queue and allocation queue
@@ -190,10 +192,11 @@ std::pair<sycl::event, sycl::event>
190192
}
191193

192194
bool is_a_array_c_contig = a_array.is_c_contiguous();
195+
bool is_a_array_f_contig = a_array.is_f_contiguous();
193196
bool is_ipiv_array_c_contig = ipiv_array.is_c_contiguous();
194-
if (!is_a_array_c_contig) {
197+
if (!is_a_array_c_contig && !is_a_array_f_contig) {
195198
throw py::value_error("The input array "
196-
"must be C-contiguous");
199+
"must be contiguous");
197200
}
198201
if (!is_ipiv_array_c_contig) {
199202
throw py::value_error("The array of pivot indices "
@@ -208,27 +211,33 @@ std::pair<sycl::event, sycl::event>
208211
if (getrf_fn == nullptr) {
209212
throw py::value_error(
210213
"No getrf implementation defined for the provided type "
211-
"of the input matrix.");
214+
"of the input matrix");
212215
}
213216

214217
auto ipiv_types = dpctl_td_ns::usm_ndarray_types();
215218
int ipiv_array_type_id =
216219
ipiv_types.typenum_to_lookup_id(ipiv_array.get_typenum());
217220

218221
if (ipiv_array_type_id != static_cast<int>(dpctl_td_ns::typenum_t::INT64)) {
219-
throw py::value_error("The type of 'ipiv_array' must be int64.");
222+
throw py::value_error("The type of 'ipiv_array' must be int64");
220223
}
221224

222-
const std::int64_t n = a_array.get_shape_raw()[0];
225+
const py::ssize_t *a_array_shape = a_array.get_shape_raw();
226+
const std::int64_t m = a_array_shape[0];
227+
const std::int64_t n = a_array_shape[1];
228+
const std::int64_t lda = std::max<size_t>(1UL, m);
229+
230+
if (ipiv_array.get_size() != std::min(m, n)) {
231+
throw py::value_error("The size of 'ipiv_array' must be min(m, n)");
232+
}
223233

224234
char *a_array_data = a_array.get_data();
225-
const std::int64_t lda = std::max<size_t>(1UL, n);
226235

227236
char *ipiv_array_data = ipiv_array.get_data();
228237
std::int64_t *d_ipiv = reinterpret_cast<std::int64_t *>(ipiv_array_data);
229238

230239
std::vector<sycl::event> host_task_events;
231-
sycl::event getrf_ev = getrf_fn(exec_q, n, a_array_data, lda, d_ipiv,
240+
sycl::event getrf_ev = getrf_fn(exec_q, m, n, a_array_data, lda, d_ipiv,
232241
dev_info, host_task_events, depends);
233242

234243
sycl::event args_ev = dpctl::utils::keep_args_alive(

dpnp/backend/extensions/lapack/getrf.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ extern std::pair<sycl::event, sycl::event>
4444
const dpctl::tensor::usm_ndarray &a_array,
4545
const dpctl::tensor::usm_ndarray &ipiv_array,
4646
py::list dev_info,
47+
std::int64_t m,
4748
std::int64_t n,
4849
std::int64_t stride_a,
4950
std::int64_t stride_ipiv,

dpnp/backend/extensions/lapack/getrf_batch.cpp

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ namespace type_utils = dpctl::tensor::type_utils;
4646
typedef sycl::event (*getrf_batch_impl_fn_ptr_t)(
4747
sycl::queue &,
4848
std::int64_t,
49+
std::int64_t,
4950
char *,
5051
std::int64_t,
5152
std::int64_t,
@@ -61,6 +62,7 @@ static getrf_batch_impl_fn_ptr_t
6162

6263
template <typename T>
6364
static sycl::event getrf_batch_impl(sycl::queue &exec_q,
65+
std::int64_t m,
6466
std::int64_t n,
6567
char *in_a,
6668
std::int64_t lda,
@@ -77,7 +79,7 @@ static sycl::event getrf_batch_impl(sycl::queue &exec_q,
7779
T *a = reinterpret_cast<T *>(in_a);
7880

7981
const std::int64_t scratchpad_size =
80-
mkl_lapack::getrf_batch_scratchpad_size<T>(exec_q, n, n, lda, stride_a,
82+
mkl_lapack::getrf_batch_scratchpad_size<T>(exec_q, m, n, lda, stride_a,
8183
stride_ipiv, batch_size);
8284
T *scratchpad = nullptr;
8385

@@ -91,11 +93,11 @@ static sycl::event getrf_batch_impl(sycl::queue &exec_q,
9193

9294
getrf_batch_event = mkl_lapack::getrf_batch(
9395
exec_q,
94-
n, // The order of each square matrix in the batch; (0 ≤ n).
96+
m, // The number of rows in each matrix in the batch; (0 ≤ m).
9597
// It must be a non-negative integer.
9698
n, // The number of columns in each matrix in the batch; (0 ≤ n).
9799
// It must be a non-negative integer.
98-
a, // Pointer to the batch of square matrices, each of size (n x n).
100+
a, // Pointer to the batch of input matrices, each of size (m x n).
99101
lda, // The leading dimension of each matrix in the batch.
100102
stride_a, // Stride between consecutive matrices in the batch.
101103
ipiv, // Pointer to the array of pivot indices for each matrix in
@@ -179,6 +181,7 @@ std::pair<sycl::event, sycl::event>
179181
const dpctl::tensor::usm_ndarray &a_array,
180182
const dpctl::tensor::usm_ndarray &ipiv_array,
181183
py::list dev_info,
184+
std::int64_t m,
182185
std::int64_t n,
183186
std::int64_t stride_a,
184187
std::int64_t stride_ipiv,
@@ -191,21 +194,21 @@ std::pair<sycl::event, sycl::event>
191194
if (a_array_nd < 3) {
192195
throw py::value_error(
193196
"The input array has ndim=" + std::to_string(a_array_nd) +
194-
", but an array with ndim >= 3 is expected.");
197+
", but an array with ndim >= 3 is expected");
195198
}
196199

197200
if (ipiv_array_nd != 2) {
198201
throw py::value_error("The array of pivot indices has ndim=" +
199202
std::to_string(ipiv_array_nd) +
200-
", but a 2-dimensional array is expected.");
203+
", but a 2-dimensional array is expected");
201204
}
202205

203206
const int dev_info_size = py::len(dev_info);
204207
if (dev_info_size != batch_size) {
205208
throw py::value_error("The size of 'dev_info' (" +
206209
std::to_string(dev_info_size) +
207210
") does not match the expected batch size (" +
208-
std::to_string(batch_size) + ").");
211+
std::to_string(batch_size) + ")");
209212
}
210213

211214
// check compatibility of execution queue and allocation queue
@@ -221,10 +224,11 @@ std::pair<sycl::event, sycl::event>
221224
}
222225

223226
bool is_a_array_c_contig = a_array.is_c_contiguous();
227+
bool is_a_array_f_contig = a_array.is_f_contiguous();
224228
bool is_ipiv_array_c_contig = ipiv_array.is_c_contiguous();
225-
if (!is_a_array_c_contig) {
229+
if (!is_a_array_c_contig && !is_a_array_f_contig) {
226230
throw py::value_error("The input array "
227-
"must be C-contiguous");
231+
"must be must contiguous");
228232
}
229233
if (!is_ipiv_array_c_contig) {
230234
throw py::value_error("The array of pivot indices "
@@ -240,27 +244,34 @@ std::pair<sycl::event, sycl::event>
240244
if (getrf_batch_fn == nullptr) {
241245
throw py::value_error(
242246
"No getrf_batch implementation defined for the provided type "
243-
"of the input matrix.");
247+
"of the input matrix");
244248
}
245249

246250
auto ipiv_types = dpctl_td_ns::usm_ndarray_types();
247251
int ipiv_array_type_id =
248252
ipiv_types.typenum_to_lookup_id(ipiv_array.get_typenum());
249253

250254
if (ipiv_array_type_id != static_cast<int>(dpctl_td_ns::typenum_t::INT64)) {
251-
throw py::value_error("The type of 'ipiv_array' must be int64.");
255+
throw py::value_error("The type of 'ipiv_array' must be int64");
256+
}
257+
258+
const py::ssize_t *ipiv_array_shape = ipiv_array.get_shape_raw();
259+
if (ipiv_array_shape[0] != batch_size ||
260+
ipiv_array_shape[1] != std::min(m, n)) {
261+
throw py::value_error(
262+
"The shape of 'ipiv_array' must be (batch_size, min(m, n))");
252263
}
253264

254265
char *a_array_data = a_array.get_data();
255-
const std::int64_t lda = std::max<size_t>(1UL, n);
266+
const std::int64_t lda = std::max<size_t>(1UL, m);
256267

257268
char *ipiv_array_data = ipiv_array.get_data();
258269
std::int64_t *d_ipiv = reinterpret_cast<std::int64_t *>(ipiv_array_data);
259270

260271
std::vector<sycl::event> host_task_events;
261272
sycl::event getrf_batch_ev = getrf_batch_fn(
262-
exec_q, n, a_array_data, lda, stride_a, d_ipiv, stride_ipiv, batch_size,
263-
dev_info, host_task_events, depends);
273+
exec_q, m, n, a_array_data, lda, stride_a, d_ipiv, stride_ipiv,
274+
batch_size, dev_info, host_task_events, depends);
264275

265276
sycl::event args_ev = dpctl::utils::keep_args_alive(
266277
exec_q, {a_array, ipiv_array}, host_task_events);

dpnp/backend/extensions/lapack/lapack_py.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,16 @@ PYBIND11_MODULE(_lapack_impl, m)
135135

136136
m.def("_getrf", &lapack_ext::getrf,
137137
"Call `getrf` from OneMKL LAPACK library to return "
138-
"the LU factorization of a general n x n matrix",
138+
"the LU factorization of a general m x n matrix",
139139
py::arg("sycl_queue"), py::arg("a_array"), py::arg("ipiv_array"),
140140
py::arg("dev_info"), py::arg("depends") = py::list());
141141

142142
m.def("_getrf_batch", &lapack_ext::getrf_batch,
143143
"Call `getrf_batch` from OneMKL LAPACK library to return "
144-
"the LU factorization of a batch of general n x n matrices",
144+
"the LU factorization of a batch of general m x n matrices",
145145
py::arg("sycl_queue"), py::arg("a_array"), py::arg("ipiv_array"),
146-
py::arg("dev_info_array"), py::arg("n"), py::arg("stride_a"),
147-
py::arg("stride_ipiv"), py::arg("batch_size"),
146+
py::arg("dev_info_array"), py::arg("m"), py::arg("n"),
147+
py::arg("stride_a"), py::arg("stride_ipiv"), py::arg("batch_size"),
148148
py::arg("depends") = py::list());
149149

150150
m.def("_getri_batch", &lapack_ext::getri_batch,

0 commit comments

Comments
 (0)