From a0e3dda6fa204c9a848350f36042ec1cbd63580c Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 3 Nov 2026 21:16:16 +0100 Subject: [PATCH 1/4] Release the GIL around oneMKL VM calls On a CPU device oneMKL VM waits on the dependent events and computes on the calling thread. On an in-order queue those events are ordered after the host tasks dpnp submits to keep arguments alive, which acquire the GIL, so a VM call made with the GIL held deadlocks. --- dpnp/libtensor/extensions/vm/abs.cpp | 4 ++ dpnp/libtensor/extensions/vm/acos.cpp | 4 ++ dpnp/libtensor/extensions/vm/acosh.cpp | 4 ++ dpnp/libtensor/extensions/vm/add.cpp | 4 ++ dpnp/libtensor/extensions/vm/arg.cpp | 4 ++ dpnp/libtensor/extensions/vm/asin.cpp | 4 ++ dpnp/libtensor/extensions/vm/asinh.cpp | 4 ++ dpnp/libtensor/extensions/vm/atan.cpp | 4 ++ dpnp/libtensor/extensions/vm/atan2.cpp | 4 ++ dpnp/libtensor/extensions/vm/atanh.cpp | 4 ++ dpnp/libtensor/extensions/vm/cbrt.cpp | 4 ++ dpnp/libtensor/extensions/vm/ceil.cpp | 4 ++ dpnp/libtensor/extensions/vm/conj.cpp | 4 ++ dpnp/libtensor/extensions/vm/copysign.cpp | 4 ++ dpnp/libtensor/extensions/vm/cos.cpp | 4 ++ dpnp/libtensor/extensions/vm/cosh.cpp | 4 ++ dpnp/libtensor/extensions/vm/div.cpp | 4 ++ dpnp/libtensor/extensions/vm/erf_funcs.cpp | 4 ++ dpnp/libtensor/extensions/vm/exp.cpp | 4 ++ dpnp/libtensor/extensions/vm/exp2.cpp | 4 ++ dpnp/libtensor/extensions/vm/expm1.cpp | 4 ++ dpnp/libtensor/extensions/vm/floor.cpp | 4 ++ dpnp/libtensor/extensions/vm/fmax.cpp | 4 ++ dpnp/libtensor/extensions/vm/fmin.cpp | 4 ++ dpnp/libtensor/extensions/vm/fmod.cpp | 4 ++ dpnp/libtensor/extensions/vm/hypot.cpp | 4 ++ dpnp/libtensor/extensions/vm/i0.cpp | 4 ++ dpnp/libtensor/extensions/vm/inv.cpp | 4 ++ dpnp/libtensor/extensions/vm/ln.cpp | 4 ++ dpnp/libtensor/extensions/vm/log10.cpp | 4 ++ dpnp/libtensor/extensions/vm/log1p.cpp | 4 ++ dpnp/libtensor/extensions/vm/log2.cpp | 4 ++ dpnp/libtensor/extensions/vm/modf.cpp | 4 ++ dpnp/libtensor/extensions/vm/mul.cpp | 4 ++ dpnp/libtensor/extensions/vm/nextafter.cpp | 4 ++ dpnp/libtensor/extensions/vm/pow.cpp | 4 ++ dpnp/libtensor/extensions/vm/rint.cpp | 4 ++ dpnp/libtensor/extensions/vm/sin.cpp | 4 ++ dpnp/libtensor/extensions/vm/sinh.cpp | 4 ++ dpnp/libtensor/extensions/vm/sqr.cpp | 4 ++ dpnp/libtensor/extensions/vm/sqrt.cpp | 4 ++ dpnp/libtensor/extensions/vm/sub.cpp | 4 ++ dpnp/libtensor/extensions/vm/tan.cpp | 4 ++ dpnp/libtensor/extensions/vm/tanh.cpp | 4 ++ dpnp/libtensor/extensions/vm/trunc.cpp | 4 ++ dpnp/tests/test_vm_gil.py | 68 ++++++++++++++++++++++ 46 files changed, 248 insertions(+) create mode 100644 dpnp/tests/test_vm_gil.py diff --git a/dpnp/libtensor/extensions/vm/abs.cpp b/dpnp/libtensor/extensions/vm/abs.cpp index 2c2ade041fb..d9786303dc0 100644 --- a/dpnp/libtensor/extensions/vm/abs.cpp +++ b/dpnp/libtensor/extensions/vm/abs.cpp @@ -94,6 +94,10 @@ static sycl::event abs_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::abs(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/acos.cpp b/dpnp/libtensor/extensions/vm/acos.cpp index 5242a01bbf3..5277b419955 100644 --- a/dpnp/libtensor/extensions/vm/acos.cpp +++ b/dpnp/libtensor/extensions/vm/acos.cpp @@ -94,6 +94,10 @@ static sycl::event acos_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::acos(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/acosh.cpp b/dpnp/libtensor/extensions/vm/acosh.cpp index 3518a3ec94e..8d89a626e0f 100644 --- a/dpnp/libtensor/extensions/vm/acosh.cpp +++ b/dpnp/libtensor/extensions/vm/acosh.cpp @@ -94,6 +94,10 @@ static sycl::event acosh_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::acosh(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/add.cpp b/dpnp/libtensor/extensions/vm/add.cpp index 49c0a2faf11..f11e43c6423 100644 --- a/dpnp/libtensor/extensions/vm/add.cpp +++ b/dpnp/libtensor/extensions/vm/add.cpp @@ -113,6 +113,10 @@ static sycl::event add_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::add(exec_q, n, // number of elements to be calculated a, // pointer `a` containing 1st input vector of size n diff --git a/dpnp/libtensor/extensions/vm/arg.cpp b/dpnp/libtensor/extensions/vm/arg.cpp index 75ab640dbf8..b604a2d9fe2 100644 --- a/dpnp/libtensor/extensions/vm/arg.cpp +++ b/dpnp/libtensor/extensions/vm/arg.cpp @@ -92,6 +92,10 @@ static sycl::event arg_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::arg(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/asin.cpp b/dpnp/libtensor/extensions/vm/asin.cpp index 3ad3f42c097..de92971d128 100644 --- a/dpnp/libtensor/extensions/vm/asin.cpp +++ b/dpnp/libtensor/extensions/vm/asin.cpp @@ -94,6 +94,10 @@ static sycl::event asin_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::asin(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/asinh.cpp b/dpnp/libtensor/extensions/vm/asinh.cpp index 7c3788ebebb..f3cf5bea2b1 100644 --- a/dpnp/libtensor/extensions/vm/asinh.cpp +++ b/dpnp/libtensor/extensions/vm/asinh.cpp @@ -94,6 +94,10 @@ static sycl::event asinh_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::asinh(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/atan.cpp b/dpnp/libtensor/extensions/vm/atan.cpp index b8df2c0390d..d25fb0256da 100644 --- a/dpnp/libtensor/extensions/vm/atan.cpp +++ b/dpnp/libtensor/extensions/vm/atan.cpp @@ -94,6 +94,10 @@ static sycl::event atan_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::atan(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/atan2.cpp b/dpnp/libtensor/extensions/vm/atan2.cpp index 643668613fb..5b29eaf582a 100644 --- a/dpnp/libtensor/extensions/vm/atan2.cpp +++ b/dpnp/libtensor/extensions/vm/atan2.cpp @@ -102,6 +102,10 @@ static sycl::event atan2_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::atan2(exec_q, n, // number of elements to be calculated a, // pointer `a` containing 1st input vector of size n diff --git a/dpnp/libtensor/extensions/vm/atanh.cpp b/dpnp/libtensor/extensions/vm/atanh.cpp index 2a71dfcad88..c613752bed9 100644 --- a/dpnp/libtensor/extensions/vm/atanh.cpp +++ b/dpnp/libtensor/extensions/vm/atanh.cpp @@ -94,6 +94,10 @@ static sycl::event atanh_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::atanh(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/cbrt.cpp b/dpnp/libtensor/extensions/vm/cbrt.cpp index 3a37a8f3050..c8bf4022859 100644 --- a/dpnp/libtensor/extensions/vm/cbrt.cpp +++ b/dpnp/libtensor/extensions/vm/cbrt.cpp @@ -91,6 +91,10 @@ static sycl::event cbrt_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::cbrt(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/ceil.cpp b/dpnp/libtensor/extensions/vm/ceil.cpp index 88698445a34..f945a00f056 100644 --- a/dpnp/libtensor/extensions/vm/ceil.cpp +++ b/dpnp/libtensor/extensions/vm/ceil.cpp @@ -91,6 +91,10 @@ static sycl::event ceil_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::ceil(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/conj.cpp b/dpnp/libtensor/extensions/vm/conj.cpp index 3a8e38e6799..7021c7af7d2 100644 --- a/dpnp/libtensor/extensions/vm/conj.cpp +++ b/dpnp/libtensor/extensions/vm/conj.cpp @@ -92,6 +92,10 @@ static sycl::event conj_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::conj(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/copysign.cpp b/dpnp/libtensor/extensions/vm/copysign.cpp index ec5e7d4e23a..ce0a41be841 100644 --- a/dpnp/libtensor/extensions/vm/copysign.cpp +++ b/dpnp/libtensor/extensions/vm/copysign.cpp @@ -102,6 +102,10 @@ static sycl::event copysign_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::copysign( exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/cos.cpp b/dpnp/libtensor/extensions/vm/cos.cpp index 98653c1be01..dd14fd921d6 100644 --- a/dpnp/libtensor/extensions/vm/cos.cpp +++ b/dpnp/libtensor/extensions/vm/cos.cpp @@ -94,6 +94,10 @@ static sycl::event cos_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::cos(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/cosh.cpp b/dpnp/libtensor/extensions/vm/cosh.cpp index d655b2dcc68..07869fd891a 100644 --- a/dpnp/libtensor/extensions/vm/cosh.cpp +++ b/dpnp/libtensor/extensions/vm/cosh.cpp @@ -94,6 +94,10 @@ static sycl::event cosh_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::cosh(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/div.cpp b/dpnp/libtensor/extensions/vm/div.cpp index 68de80960d6..08280a60148 100644 --- a/dpnp/libtensor/extensions/vm/div.cpp +++ b/dpnp/libtensor/extensions/vm/div.cpp @@ -113,6 +113,10 @@ static sycl::event div_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::div(exec_q, n, // number of elements to be calculated a, // pointer `a` containing 1st input vector of size n diff --git a/dpnp/libtensor/extensions/vm/erf_funcs.cpp b/dpnp/libtensor/extensions/vm/erf_funcs.cpp index 38796ae15ff..4cd7985d1ef 100644 --- a/dpnp/libtensor/extensions/vm/erf_funcs.cpp +++ b/dpnp/libtensor/extensions/vm/erf_funcs.cpp @@ -106,6 +106,10 @@ using ew_cmn_ns::unary_contig_impl_fn_ptr_t; using resTy = typename OutputType::value_type; \ resTy *y = reinterpret_cast(out_y); \ \ + /* On a CPU device oneMKL VM waits on `depends` and computes on the */ \ + /* calling thread, so release the GIL for host tasks that need it */ \ + py::gil_scoped_release lock{}; \ + \ return mkl_vm::__name__( \ exec_q, n, /* number of elements to be calculated*/ \ a, /* pointer `a` containing input vector of size n*/ \ diff --git a/dpnp/libtensor/extensions/vm/exp.cpp b/dpnp/libtensor/extensions/vm/exp.cpp index bbcefdc460b..2b0c47390db 100644 --- a/dpnp/libtensor/extensions/vm/exp.cpp +++ b/dpnp/libtensor/extensions/vm/exp.cpp @@ -94,6 +94,10 @@ static sycl::event exp_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::exp(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/exp2.cpp b/dpnp/libtensor/extensions/vm/exp2.cpp index d25e9b89bcd..8206a74abd2 100644 --- a/dpnp/libtensor/extensions/vm/exp2.cpp +++ b/dpnp/libtensor/extensions/vm/exp2.cpp @@ -91,6 +91,10 @@ static sycl::event exp2_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::exp2(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/expm1.cpp b/dpnp/libtensor/extensions/vm/expm1.cpp index 6d62800bc73..47ec6d93b33 100644 --- a/dpnp/libtensor/extensions/vm/expm1.cpp +++ b/dpnp/libtensor/extensions/vm/expm1.cpp @@ -91,6 +91,10 @@ static sycl::event expm1_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::expm1(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/floor.cpp b/dpnp/libtensor/extensions/vm/floor.cpp index 91350e69588..753f35cdf70 100644 --- a/dpnp/libtensor/extensions/vm/floor.cpp +++ b/dpnp/libtensor/extensions/vm/floor.cpp @@ -91,6 +91,10 @@ static sycl::event floor_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::floor(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/fmax.cpp b/dpnp/libtensor/extensions/vm/fmax.cpp index 71000e1392b..d3b7726ebce 100644 --- a/dpnp/libtensor/extensions/vm/fmax.cpp +++ b/dpnp/libtensor/extensions/vm/fmax.cpp @@ -102,6 +102,10 @@ static sycl::event fmax_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::fmax(exec_q, n, // number of elements to be calculated a, // pointer `a` containing 1st input vector of size n diff --git a/dpnp/libtensor/extensions/vm/fmin.cpp b/dpnp/libtensor/extensions/vm/fmin.cpp index 1a8f331125d..36d23c93698 100644 --- a/dpnp/libtensor/extensions/vm/fmin.cpp +++ b/dpnp/libtensor/extensions/vm/fmin.cpp @@ -102,6 +102,10 @@ static sycl::event fmin_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::fmin(exec_q, n, // number of elements to be calculated a, // pointer `a` containing 1st input vector of size n diff --git a/dpnp/libtensor/extensions/vm/fmod.cpp b/dpnp/libtensor/extensions/vm/fmod.cpp index 56481afa5ef..897062b2389 100644 --- a/dpnp/libtensor/extensions/vm/fmod.cpp +++ b/dpnp/libtensor/extensions/vm/fmod.cpp @@ -102,6 +102,10 @@ static sycl::event fmod_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::fmod(exec_q, n, // number of elements to be calculated a, // pointer `a` containing 1st input vector of size n diff --git a/dpnp/libtensor/extensions/vm/hypot.cpp b/dpnp/libtensor/extensions/vm/hypot.cpp index 88195916d32..56a1bfdc029 100644 --- a/dpnp/libtensor/extensions/vm/hypot.cpp +++ b/dpnp/libtensor/extensions/vm/hypot.cpp @@ -102,6 +102,10 @@ static sycl::event hypot_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::hypot(exec_q, n, // number of elements to be calculated a, // pointer `a` containing 1st input vector of size n diff --git a/dpnp/libtensor/extensions/vm/i0.cpp b/dpnp/libtensor/extensions/vm/i0.cpp index 68d3d866064..6b41f6d2012 100644 --- a/dpnp/libtensor/extensions/vm/i0.cpp +++ b/dpnp/libtensor/extensions/vm/i0.cpp @@ -91,6 +91,10 @@ static sycl::event i0_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::i0(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/inv.cpp b/dpnp/libtensor/extensions/vm/inv.cpp index 5575be3cb42..9160f95faf6 100644 --- a/dpnp/libtensor/extensions/vm/inv.cpp +++ b/dpnp/libtensor/extensions/vm/inv.cpp @@ -91,6 +91,10 @@ static sycl::event inv_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::inv(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/ln.cpp b/dpnp/libtensor/extensions/vm/ln.cpp index 8ce83e2c476..b35bfe04b8d 100644 --- a/dpnp/libtensor/extensions/vm/ln.cpp +++ b/dpnp/libtensor/extensions/vm/ln.cpp @@ -94,6 +94,10 @@ static sycl::event ln_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::ln(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/log10.cpp b/dpnp/libtensor/extensions/vm/log10.cpp index b175c336a8c..2adefd63b21 100644 --- a/dpnp/libtensor/extensions/vm/log10.cpp +++ b/dpnp/libtensor/extensions/vm/log10.cpp @@ -94,6 +94,10 @@ static sycl::event log10_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::log10(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/log1p.cpp b/dpnp/libtensor/extensions/vm/log1p.cpp index 336ddb8cbc8..daa33b8ec31 100644 --- a/dpnp/libtensor/extensions/vm/log1p.cpp +++ b/dpnp/libtensor/extensions/vm/log1p.cpp @@ -91,6 +91,10 @@ static sycl::event log1p_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::log1p(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/log2.cpp b/dpnp/libtensor/extensions/vm/log2.cpp index c17f4e19ab1..81105c55a29 100644 --- a/dpnp/libtensor/extensions/vm/log2.cpp +++ b/dpnp/libtensor/extensions/vm/log2.cpp @@ -91,6 +91,10 @@ static sycl::event log2_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::log2(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/modf.cpp b/dpnp/libtensor/extensions/vm/modf.cpp index 68b6f945910..d08ad73f1eb 100644 --- a/dpnp/libtensor/extensions/vm/modf.cpp +++ b/dpnp/libtensor/extensions/vm/modf.cpp @@ -100,6 +100,10 @@ static sycl::event modf_contig_impl(sycl::queue &exec_q, fractT *y = reinterpret_cast(out_y); intT *z = reinterpret_cast(out_z); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::modf(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/mul.cpp b/dpnp/libtensor/extensions/vm/mul.cpp index a25f6794da4..53914aabc5e 100644 --- a/dpnp/libtensor/extensions/vm/mul.cpp +++ b/dpnp/libtensor/extensions/vm/mul.cpp @@ -113,6 +113,10 @@ static sycl::event mul_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::mul(exec_q, n, // number of elements to be calculated a, // pointer `a` containing 1st input vector of size n diff --git a/dpnp/libtensor/extensions/vm/nextafter.cpp b/dpnp/libtensor/extensions/vm/nextafter.cpp index 32e4df5895d..a3e20653b11 100644 --- a/dpnp/libtensor/extensions/vm/nextafter.cpp +++ b/dpnp/libtensor/extensions/vm/nextafter.cpp @@ -103,6 +103,10 @@ static sycl::event using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::nextafter( exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/pow.cpp b/dpnp/libtensor/extensions/vm/pow.cpp index 7aed34fe5fd..bdc9cbadc2a 100644 --- a/dpnp/libtensor/extensions/vm/pow.cpp +++ b/dpnp/libtensor/extensions/vm/pow.cpp @@ -113,6 +113,10 @@ static sycl::event pow_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::pow(exec_q, n, // number of elements to be calculated a, // pointer `a` containing 1st input vector of size n diff --git a/dpnp/libtensor/extensions/vm/rint.cpp b/dpnp/libtensor/extensions/vm/rint.cpp index 5723065c53a..ec461c0dab9 100644 --- a/dpnp/libtensor/extensions/vm/rint.cpp +++ b/dpnp/libtensor/extensions/vm/rint.cpp @@ -91,6 +91,10 @@ static sycl::event rint_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::rint(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/sin.cpp b/dpnp/libtensor/extensions/vm/sin.cpp index 9dec89ad9d6..a92a0b7655f 100644 --- a/dpnp/libtensor/extensions/vm/sin.cpp +++ b/dpnp/libtensor/extensions/vm/sin.cpp @@ -94,6 +94,10 @@ static sycl::event sin_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::sin(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/sinh.cpp b/dpnp/libtensor/extensions/vm/sinh.cpp index ab3d77b9add..06ae106b126 100644 --- a/dpnp/libtensor/extensions/vm/sinh.cpp +++ b/dpnp/libtensor/extensions/vm/sinh.cpp @@ -94,6 +94,10 @@ static sycl::event sinh_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::sinh(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/sqr.cpp b/dpnp/libtensor/extensions/vm/sqr.cpp index 80e30762a0b..4769a31336c 100644 --- a/dpnp/libtensor/extensions/vm/sqr.cpp +++ b/dpnp/libtensor/extensions/vm/sqr.cpp @@ -91,6 +91,10 @@ static sycl::event sqr_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::sqr(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/sqrt.cpp b/dpnp/libtensor/extensions/vm/sqrt.cpp index 2a1bb7f7a99..ee91e2fef24 100644 --- a/dpnp/libtensor/extensions/vm/sqrt.cpp +++ b/dpnp/libtensor/extensions/vm/sqrt.cpp @@ -94,6 +94,10 @@ static sycl::event sqrt_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::sqrt(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/sub.cpp b/dpnp/libtensor/extensions/vm/sub.cpp index 022ec5bfefa..8b974a0fed6 100644 --- a/dpnp/libtensor/extensions/vm/sub.cpp +++ b/dpnp/libtensor/extensions/vm/sub.cpp @@ -113,6 +113,10 @@ static sycl::event sub_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::sub(exec_q, n, // number of elements to be calculated a, // pointer `a` containing 1st input vector of size n diff --git a/dpnp/libtensor/extensions/vm/tan.cpp b/dpnp/libtensor/extensions/vm/tan.cpp index a4ff4842c4a..a546ee64c61 100644 --- a/dpnp/libtensor/extensions/vm/tan.cpp +++ b/dpnp/libtensor/extensions/vm/tan.cpp @@ -94,6 +94,10 @@ static sycl::event tan_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::tan(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/tanh.cpp b/dpnp/libtensor/extensions/vm/tanh.cpp index 9734a2fc718..c6e406c306d 100644 --- a/dpnp/libtensor/extensions/vm/tanh.cpp +++ b/dpnp/libtensor/extensions/vm/tanh.cpp @@ -94,6 +94,10 @@ static sycl::event tanh_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::tanh(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/libtensor/extensions/vm/trunc.cpp b/dpnp/libtensor/extensions/vm/trunc.cpp index 57a749916af..5b94dad2624 100644 --- a/dpnp/libtensor/extensions/vm/trunc.cpp +++ b/dpnp/libtensor/extensions/vm/trunc.cpp @@ -91,6 +91,10 @@ static sycl::event trunc_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); + // On a CPU device oneMKL VM waits on `depends` and computes on the + // calling thread, so release the GIL for host tasks that need it + py::gil_scoped_release lock{}; + return mkl_vm::trunc(exec_q, n, // number of elements to be calculated a, // pointer `a` containing input vector of size n diff --git a/dpnp/tests/test_vm_gil.py b/dpnp/tests/test_vm_gil.py new file mode 100644 index 00000000000..8dccdbbd26b --- /dev/null +++ b/dpnp/tests/test_vm_gil.py @@ -0,0 +1,68 @@ +"""oneMKL VM calls in the VM extension must release the GIL. + +On a CPU device oneMKL VM waits on the dependent events and computes on the +calling thread. On an in-order queue those events are ordered after the host +tasks dpnp submits to keep arguments alive, and these host tasks acquire the +GIL, so a VM call holding the GIL never returns. +""" + +import subprocess +import sys + +import dpctl +import pytest + +import dpnp.libtensor._vm_impl as vmi + +# Prints "novm" if oneMKL VM is not used for the subtraction, or "ok". +_VM_AFTER_HOST_TASKS = """ +import dpctl, dpnp +import dpnp.libtensor._vm_impl as vmi +q = dpctl.SyclQueue("cpu", property="in_order") +xp = dpnp.linspace(10.0, 0.0, 5, sycl_queue=q) +a, b = xp[-1:], xp[:1] +out = dpnp.empty_like(a) +if not vmi._mkl_sub_to_call(q, a.get_array(), b.get_array(), out.get_array()): + print("novm") + raise SystemExit +for _ in range(100): + xs = xp[dpnp.argsort(xp)] # submits host tasks keeping arguments alive + xs[-1:] - xs[:1] +q.wait() +print("ok") +""" + +_TIMEOUT = 120 # seconds, a run takes about one + + +def _cpu_device_with_fp64(): + for dev in dpctl.get_devices(device_type="cpu"): + if dev.has_aspect_fp64: + return dev + return None + + +@pytest.mark.skipif(not vmi._is_available(), reason="requires oneMKL VM") +@pytest.mark.skipif( + _cpu_device_with_fp64() is None, + reason="requires a CPU device with fp64 support", +) +def test_in_order_queue_after_host_tasks(): + try: + res = subprocess.run( + [sys.executable, "-c", _VM_AFTER_HOST_TASKS], + capture_output=True, + text=True, + timeout=_TIMEOUT, + ) + except subprocess.TimeoutExpired: + pytest.fail( + f"no progress in {_TIMEOUT}s: a oneMKL VM call holds the GIL " + "while waiting on events behind host tasks. It needs " + "py::gil_scoped_release." + ) + assert res.returncode == 0, res.stderr + out = res.stdout.strip() + if out == "novm": + pytest.skip("oneMKL VM is not used for the subtraction") + assert out == "ok", out From e863f969c39b6492d447c17a6900ae63b79bff86 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 3 Nov 2026 22:02:02 +0100 Subject: [PATCH 2/4] Add gh-3156 to the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33e1bd4aa64..3b0af504070 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed * Fixed `flags[key]` of `dpnp.ndarray` and `dpnp.tensor.usm_ndarray` to raise `KeyError` for an unknown key [#3141](https://github.com/IntelPython/dpnp/pull/3141) +* Released the GIL around the oneMKL VM calls in the VM extension, which deadlocked on an in-order queue of a CPU device [#3156](https://github.com/IntelPython/dpnp/pull/3156) ### Security From 12ee06a4b5b48d0b71781afafb4fb63173c92774 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 4 Nov 2026 11:38:28 +0100 Subject: [PATCH 3/4] Move the VM GIL release comment into a shared helper alias --- dpnp/libtensor/extensions/vm/abs.cpp | 4 +--- dpnp/libtensor/extensions/vm/acos.cpp | 4 +--- dpnp/libtensor/extensions/vm/acosh.cpp | 4 +--- dpnp/libtensor/extensions/vm/add.cpp | 4 +--- dpnp/libtensor/extensions/vm/arg.cpp | 4 +--- dpnp/libtensor/extensions/vm/asin.cpp | 4 +--- dpnp/libtensor/extensions/vm/asinh.cpp | 4 +--- dpnp/libtensor/extensions/vm/atan.cpp | 4 +--- dpnp/libtensor/extensions/vm/atan2.cpp | 4 +--- dpnp/libtensor/extensions/vm/atanh.cpp | 4 +--- dpnp/libtensor/extensions/vm/cbrt.cpp | 4 +--- dpnp/libtensor/extensions/vm/ceil.cpp | 4 +--- dpnp/libtensor/extensions/vm/common.hpp | 12 ++++++++++-- dpnp/libtensor/extensions/vm/conj.cpp | 4 +--- dpnp/libtensor/extensions/vm/copysign.cpp | 4 +--- dpnp/libtensor/extensions/vm/cos.cpp | 4 +--- dpnp/libtensor/extensions/vm/cosh.cpp | 4 +--- dpnp/libtensor/extensions/vm/div.cpp | 4 +--- dpnp/libtensor/extensions/vm/erf_funcs.cpp | 4 +--- dpnp/libtensor/extensions/vm/exp.cpp | 4 +--- dpnp/libtensor/extensions/vm/exp2.cpp | 4 +--- dpnp/libtensor/extensions/vm/expm1.cpp | 4 +--- dpnp/libtensor/extensions/vm/floor.cpp | 4 +--- dpnp/libtensor/extensions/vm/fmax.cpp | 4 +--- dpnp/libtensor/extensions/vm/fmin.cpp | 4 +--- dpnp/libtensor/extensions/vm/fmod.cpp | 4 +--- dpnp/libtensor/extensions/vm/hypot.cpp | 4 +--- dpnp/libtensor/extensions/vm/i0.cpp | 4 +--- dpnp/libtensor/extensions/vm/inv.cpp | 4 +--- dpnp/libtensor/extensions/vm/ln.cpp | 4 +--- dpnp/libtensor/extensions/vm/log10.cpp | 4 +--- dpnp/libtensor/extensions/vm/log1p.cpp | 4 +--- dpnp/libtensor/extensions/vm/log2.cpp | 4 +--- dpnp/libtensor/extensions/vm/modf.cpp | 4 +--- dpnp/libtensor/extensions/vm/mul.cpp | 4 +--- dpnp/libtensor/extensions/vm/nextafter.cpp | 4 +--- dpnp/libtensor/extensions/vm/pow.cpp | 4 +--- dpnp/libtensor/extensions/vm/rint.cpp | 4 +--- dpnp/libtensor/extensions/vm/sin.cpp | 4 +--- dpnp/libtensor/extensions/vm/sinh.cpp | 4 +--- dpnp/libtensor/extensions/vm/sqr.cpp | 4 +--- dpnp/libtensor/extensions/vm/sqrt.cpp | 4 +--- dpnp/libtensor/extensions/vm/sub.cpp | 4 +--- dpnp/libtensor/extensions/vm/tan.cpp | 4 +--- dpnp/libtensor/extensions/vm/tanh.cpp | 4 +--- dpnp/libtensor/extensions/vm/trunc.cpp | 4 +--- 46 files changed, 55 insertions(+), 137 deletions(-) diff --git a/dpnp/libtensor/extensions/vm/abs.cpp b/dpnp/libtensor/extensions/vm/abs.cpp index d9786303dc0..51e47e23eee 100644 --- a/dpnp/libtensor/extensions/vm/abs.cpp +++ b/dpnp/libtensor/extensions/vm/abs.cpp @@ -94,9 +94,7 @@ static sycl::event abs_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::abs(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/acos.cpp b/dpnp/libtensor/extensions/vm/acos.cpp index 5277b419955..24cdbc83d65 100644 --- a/dpnp/libtensor/extensions/vm/acos.cpp +++ b/dpnp/libtensor/extensions/vm/acos.cpp @@ -94,9 +94,7 @@ static sycl::event acos_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::acos(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/acosh.cpp b/dpnp/libtensor/extensions/vm/acosh.cpp index 8d89a626e0f..8e68b0f4508 100644 --- a/dpnp/libtensor/extensions/vm/acosh.cpp +++ b/dpnp/libtensor/extensions/vm/acosh.cpp @@ -94,9 +94,7 @@ static sycl::event acosh_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::acosh(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/add.cpp b/dpnp/libtensor/extensions/vm/add.cpp index f11e43c6423..2f418b73153 100644 --- a/dpnp/libtensor/extensions/vm/add.cpp +++ b/dpnp/libtensor/extensions/vm/add.cpp @@ -113,9 +113,7 @@ static sycl::event add_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::add(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/arg.cpp b/dpnp/libtensor/extensions/vm/arg.cpp index b604a2d9fe2..42d54dd57b3 100644 --- a/dpnp/libtensor/extensions/vm/arg.cpp +++ b/dpnp/libtensor/extensions/vm/arg.cpp @@ -92,9 +92,7 @@ static sycl::event arg_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::arg(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/asin.cpp b/dpnp/libtensor/extensions/vm/asin.cpp index de92971d128..a3e211ba3f9 100644 --- a/dpnp/libtensor/extensions/vm/asin.cpp +++ b/dpnp/libtensor/extensions/vm/asin.cpp @@ -94,9 +94,7 @@ static sycl::event asin_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::asin(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/asinh.cpp b/dpnp/libtensor/extensions/vm/asinh.cpp index f3cf5bea2b1..4b62f40bc6f 100644 --- a/dpnp/libtensor/extensions/vm/asinh.cpp +++ b/dpnp/libtensor/extensions/vm/asinh.cpp @@ -94,9 +94,7 @@ static sycl::event asinh_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::asinh(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/atan.cpp b/dpnp/libtensor/extensions/vm/atan.cpp index d25fb0256da..cc3c8940cee 100644 --- a/dpnp/libtensor/extensions/vm/atan.cpp +++ b/dpnp/libtensor/extensions/vm/atan.cpp @@ -94,9 +94,7 @@ static sycl::event atan_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::atan(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/atan2.cpp b/dpnp/libtensor/extensions/vm/atan2.cpp index 5b29eaf582a..672f761634c 100644 --- a/dpnp/libtensor/extensions/vm/atan2.cpp +++ b/dpnp/libtensor/extensions/vm/atan2.cpp @@ -102,9 +102,7 @@ static sycl::event atan2_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::atan2(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/atanh.cpp b/dpnp/libtensor/extensions/vm/atanh.cpp index c613752bed9..8aebc141f7f 100644 --- a/dpnp/libtensor/extensions/vm/atanh.cpp +++ b/dpnp/libtensor/extensions/vm/atanh.cpp @@ -94,9 +94,7 @@ static sycl::event atanh_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::atanh(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/cbrt.cpp b/dpnp/libtensor/extensions/vm/cbrt.cpp index c8bf4022859..da7a49c14e7 100644 --- a/dpnp/libtensor/extensions/vm/cbrt.cpp +++ b/dpnp/libtensor/extensions/vm/cbrt.cpp @@ -91,9 +91,7 @@ static sycl::event cbrt_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::cbrt(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/ceil.cpp b/dpnp/libtensor/extensions/vm/ceil.cpp index f945a00f056..1bb59632dd4 100644 --- a/dpnp/libtensor/extensions/vm/ceil.cpp +++ b/dpnp/libtensor/extensions/vm/ceil.cpp @@ -91,9 +91,7 @@ static sycl::event ceil_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::ceil(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/common.hpp b/dpnp/libtensor/extensions/vm/common.hpp index a350013ff24..90fc5f00fed 100644 --- a/dpnp/libtensor/extensions/vm/common.hpp +++ b/dpnp/libtensor/extensions/vm/common.hpp @@ -50,7 +50,14 @@ namespace ext_ns = ext::common; namespace py = pybind11; namespace td_ns = dpnp::tensor::type_dispatch; -namespace dpnp::extensions::vm::py_internal +namespace dpnp::extensions::vm +{ +// Releases the GIL around a oneMKL VM call. On a CPU device VM waits on its +// `depends` and computes on the calling thread, so holding the GIL can +// deadlock with host tasks that need it (e.g. on an in-order queue). +using vm_gil_release = py::gil_scoped_release; + +namespace py_internal { template bool need_to_call_unary_ufunc(sycl::queue &exec_q, @@ -487,4 +494,5 @@ bool need_to_call_binary_ufunc(sycl::queue &exec_q, __name__##_ContigFactory>( \ contig_dispatch_vector); \ }; -} // namespace dpnp::extensions::vm::py_internal +} // namespace py_internal +} // namespace dpnp::extensions::vm diff --git a/dpnp/libtensor/extensions/vm/conj.cpp b/dpnp/libtensor/extensions/vm/conj.cpp index 7021c7af7d2..1ffe557fbf1 100644 --- a/dpnp/libtensor/extensions/vm/conj.cpp +++ b/dpnp/libtensor/extensions/vm/conj.cpp @@ -92,9 +92,7 @@ static sycl::event conj_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::conj(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/copysign.cpp b/dpnp/libtensor/extensions/vm/copysign.cpp index ce0a41be841..dd77b22a2cf 100644 --- a/dpnp/libtensor/extensions/vm/copysign.cpp +++ b/dpnp/libtensor/extensions/vm/copysign.cpp @@ -102,9 +102,7 @@ static sycl::event copysign_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::copysign( exec_q, diff --git a/dpnp/libtensor/extensions/vm/cos.cpp b/dpnp/libtensor/extensions/vm/cos.cpp index dd14fd921d6..308b3b572ab 100644 --- a/dpnp/libtensor/extensions/vm/cos.cpp +++ b/dpnp/libtensor/extensions/vm/cos.cpp @@ -94,9 +94,7 @@ static sycl::event cos_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::cos(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/cosh.cpp b/dpnp/libtensor/extensions/vm/cosh.cpp index 07869fd891a..3e02a9b9179 100644 --- a/dpnp/libtensor/extensions/vm/cosh.cpp +++ b/dpnp/libtensor/extensions/vm/cosh.cpp @@ -94,9 +94,7 @@ static sycl::event cosh_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::cosh(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/div.cpp b/dpnp/libtensor/extensions/vm/div.cpp index 08280a60148..bb9d0f339ff 100644 --- a/dpnp/libtensor/extensions/vm/div.cpp +++ b/dpnp/libtensor/extensions/vm/div.cpp @@ -113,9 +113,7 @@ static sycl::event div_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::div(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/erf_funcs.cpp b/dpnp/libtensor/extensions/vm/erf_funcs.cpp index 4cd7985d1ef..eeabc33a34b 100644 --- a/dpnp/libtensor/extensions/vm/erf_funcs.cpp +++ b/dpnp/libtensor/extensions/vm/erf_funcs.cpp @@ -106,9 +106,7 @@ using ew_cmn_ns::unary_contig_impl_fn_ptr_t; using resTy = typename OutputType::value_type; \ resTy *y = reinterpret_cast(out_y); \ \ - /* On a CPU device oneMKL VM waits on `depends` and computes on the */ \ - /* calling thread, so release the GIL for host tasks that need it */ \ - py::gil_scoped_release lock{}; \ + vm_gil_release lock{}; \ \ return mkl_vm::__name__( \ exec_q, n, /* number of elements to be calculated*/ \ diff --git a/dpnp/libtensor/extensions/vm/exp.cpp b/dpnp/libtensor/extensions/vm/exp.cpp index 2b0c47390db..d9ec198808d 100644 --- a/dpnp/libtensor/extensions/vm/exp.cpp +++ b/dpnp/libtensor/extensions/vm/exp.cpp @@ -94,9 +94,7 @@ static sycl::event exp_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::exp(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/exp2.cpp b/dpnp/libtensor/extensions/vm/exp2.cpp index 8206a74abd2..933b29903ff 100644 --- a/dpnp/libtensor/extensions/vm/exp2.cpp +++ b/dpnp/libtensor/extensions/vm/exp2.cpp @@ -91,9 +91,7 @@ static sycl::event exp2_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::exp2(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/expm1.cpp b/dpnp/libtensor/extensions/vm/expm1.cpp index 47ec6d93b33..ecf5332c443 100644 --- a/dpnp/libtensor/extensions/vm/expm1.cpp +++ b/dpnp/libtensor/extensions/vm/expm1.cpp @@ -91,9 +91,7 @@ static sycl::event expm1_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::expm1(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/floor.cpp b/dpnp/libtensor/extensions/vm/floor.cpp index 753f35cdf70..f5e1f224ace 100644 --- a/dpnp/libtensor/extensions/vm/floor.cpp +++ b/dpnp/libtensor/extensions/vm/floor.cpp @@ -91,9 +91,7 @@ static sycl::event floor_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::floor(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/fmax.cpp b/dpnp/libtensor/extensions/vm/fmax.cpp index d3b7726ebce..e2009107f7e 100644 --- a/dpnp/libtensor/extensions/vm/fmax.cpp +++ b/dpnp/libtensor/extensions/vm/fmax.cpp @@ -102,9 +102,7 @@ static sycl::event fmax_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::fmax(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/fmin.cpp b/dpnp/libtensor/extensions/vm/fmin.cpp index 36d23c93698..050b0d44383 100644 --- a/dpnp/libtensor/extensions/vm/fmin.cpp +++ b/dpnp/libtensor/extensions/vm/fmin.cpp @@ -102,9 +102,7 @@ static sycl::event fmin_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::fmin(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/fmod.cpp b/dpnp/libtensor/extensions/vm/fmod.cpp index 897062b2389..43b0710dbd4 100644 --- a/dpnp/libtensor/extensions/vm/fmod.cpp +++ b/dpnp/libtensor/extensions/vm/fmod.cpp @@ -102,9 +102,7 @@ static sycl::event fmod_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::fmod(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/hypot.cpp b/dpnp/libtensor/extensions/vm/hypot.cpp index 56a1bfdc029..2a63fbeaabd 100644 --- a/dpnp/libtensor/extensions/vm/hypot.cpp +++ b/dpnp/libtensor/extensions/vm/hypot.cpp @@ -102,9 +102,7 @@ static sycl::event hypot_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::hypot(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/i0.cpp b/dpnp/libtensor/extensions/vm/i0.cpp index 6b41f6d2012..8a5d9e1acec 100644 --- a/dpnp/libtensor/extensions/vm/i0.cpp +++ b/dpnp/libtensor/extensions/vm/i0.cpp @@ -91,9 +91,7 @@ static sycl::event i0_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::i0(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/inv.cpp b/dpnp/libtensor/extensions/vm/inv.cpp index 9160f95faf6..3c2a0c61395 100644 --- a/dpnp/libtensor/extensions/vm/inv.cpp +++ b/dpnp/libtensor/extensions/vm/inv.cpp @@ -91,9 +91,7 @@ static sycl::event inv_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::inv(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/ln.cpp b/dpnp/libtensor/extensions/vm/ln.cpp index b35bfe04b8d..f87ea66291f 100644 --- a/dpnp/libtensor/extensions/vm/ln.cpp +++ b/dpnp/libtensor/extensions/vm/ln.cpp @@ -94,9 +94,7 @@ static sycl::event ln_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::ln(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/log10.cpp b/dpnp/libtensor/extensions/vm/log10.cpp index 2adefd63b21..42e2d945f39 100644 --- a/dpnp/libtensor/extensions/vm/log10.cpp +++ b/dpnp/libtensor/extensions/vm/log10.cpp @@ -94,9 +94,7 @@ static sycl::event log10_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::log10(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/log1p.cpp b/dpnp/libtensor/extensions/vm/log1p.cpp index daa33b8ec31..1f46d9eab2c 100644 --- a/dpnp/libtensor/extensions/vm/log1p.cpp +++ b/dpnp/libtensor/extensions/vm/log1p.cpp @@ -91,9 +91,7 @@ static sycl::event log1p_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::log1p(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/log2.cpp b/dpnp/libtensor/extensions/vm/log2.cpp index 81105c55a29..c269f5b50fb 100644 --- a/dpnp/libtensor/extensions/vm/log2.cpp +++ b/dpnp/libtensor/extensions/vm/log2.cpp @@ -91,9 +91,7 @@ static sycl::event log2_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::log2(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/modf.cpp b/dpnp/libtensor/extensions/vm/modf.cpp index d08ad73f1eb..387e2acdbbc 100644 --- a/dpnp/libtensor/extensions/vm/modf.cpp +++ b/dpnp/libtensor/extensions/vm/modf.cpp @@ -100,9 +100,7 @@ static sycl::event modf_contig_impl(sycl::queue &exec_q, fractT *y = reinterpret_cast(out_y); intT *z = reinterpret_cast(out_z); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::modf(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/mul.cpp b/dpnp/libtensor/extensions/vm/mul.cpp index 53914aabc5e..224c9f1f070 100644 --- a/dpnp/libtensor/extensions/vm/mul.cpp +++ b/dpnp/libtensor/extensions/vm/mul.cpp @@ -113,9 +113,7 @@ static sycl::event mul_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::mul(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/nextafter.cpp b/dpnp/libtensor/extensions/vm/nextafter.cpp index a3e20653b11..cc64e33690b 100644 --- a/dpnp/libtensor/extensions/vm/nextafter.cpp +++ b/dpnp/libtensor/extensions/vm/nextafter.cpp @@ -103,9 +103,7 @@ static sycl::event using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::nextafter( exec_q, diff --git a/dpnp/libtensor/extensions/vm/pow.cpp b/dpnp/libtensor/extensions/vm/pow.cpp index bdc9cbadc2a..005458c03ce 100644 --- a/dpnp/libtensor/extensions/vm/pow.cpp +++ b/dpnp/libtensor/extensions/vm/pow.cpp @@ -113,9 +113,7 @@ static sycl::event pow_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::pow(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/rint.cpp b/dpnp/libtensor/extensions/vm/rint.cpp index ec461c0dab9..8410b3e8017 100644 --- a/dpnp/libtensor/extensions/vm/rint.cpp +++ b/dpnp/libtensor/extensions/vm/rint.cpp @@ -91,9 +91,7 @@ static sycl::event rint_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::rint(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/sin.cpp b/dpnp/libtensor/extensions/vm/sin.cpp index a92a0b7655f..1f7d909e675 100644 --- a/dpnp/libtensor/extensions/vm/sin.cpp +++ b/dpnp/libtensor/extensions/vm/sin.cpp @@ -94,9 +94,7 @@ static sycl::event sin_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::sin(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/sinh.cpp b/dpnp/libtensor/extensions/vm/sinh.cpp index 06ae106b126..bc082b573eb 100644 --- a/dpnp/libtensor/extensions/vm/sinh.cpp +++ b/dpnp/libtensor/extensions/vm/sinh.cpp @@ -94,9 +94,7 @@ static sycl::event sinh_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::sinh(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/sqr.cpp b/dpnp/libtensor/extensions/vm/sqr.cpp index 4769a31336c..b711a4d0795 100644 --- a/dpnp/libtensor/extensions/vm/sqr.cpp +++ b/dpnp/libtensor/extensions/vm/sqr.cpp @@ -91,9 +91,7 @@ static sycl::event sqr_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::sqr(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/sqrt.cpp b/dpnp/libtensor/extensions/vm/sqrt.cpp index ee91e2fef24..e388788fe3b 100644 --- a/dpnp/libtensor/extensions/vm/sqrt.cpp +++ b/dpnp/libtensor/extensions/vm/sqrt.cpp @@ -94,9 +94,7 @@ static sycl::event sqrt_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::sqrt(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/sub.cpp b/dpnp/libtensor/extensions/vm/sub.cpp index 8b974a0fed6..63ee87a7183 100644 --- a/dpnp/libtensor/extensions/vm/sub.cpp +++ b/dpnp/libtensor/extensions/vm/sub.cpp @@ -113,9 +113,7 @@ static sycl::event sub_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::sub(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/tan.cpp b/dpnp/libtensor/extensions/vm/tan.cpp index a546ee64c61..df15e73d9e0 100644 --- a/dpnp/libtensor/extensions/vm/tan.cpp +++ b/dpnp/libtensor/extensions/vm/tan.cpp @@ -94,9 +94,7 @@ static sycl::event tan_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::tan(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/tanh.cpp b/dpnp/libtensor/extensions/vm/tanh.cpp index c6e406c306d..9cd25a51e53 100644 --- a/dpnp/libtensor/extensions/vm/tanh.cpp +++ b/dpnp/libtensor/extensions/vm/tanh.cpp @@ -94,9 +94,7 @@ static sycl::event tanh_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::tanh(exec_q, n, // number of elements to be calculated diff --git a/dpnp/libtensor/extensions/vm/trunc.cpp b/dpnp/libtensor/extensions/vm/trunc.cpp index 5b94dad2624..2e572e90d9a 100644 --- a/dpnp/libtensor/extensions/vm/trunc.cpp +++ b/dpnp/libtensor/extensions/vm/trunc.cpp @@ -91,9 +91,7 @@ static sycl::event trunc_contig_impl(sycl::queue &exec_q, using resTy = typename OutputType::value_type; resTy *y = reinterpret_cast(out_y); - // On a CPU device oneMKL VM waits on `depends` and computes on the - // calling thread, so release the GIL for host tasks that need it - py::gil_scoped_release lock{}; + vm_gil_release lock{}; return mkl_vm::trunc(exec_q, n, // number of elements to be calculated From 8cf470ea9fc9d100dc880bb5e11ac6dcc9009db6 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 4 Nov 2026 13:12:01 +0100 Subject: [PATCH 4/4] Retrigger CI