Skip to content

Commit 0e9d0be

Browse files
authored
Fix simd reshape lazy view (#2930)
Fix: #2929 `provides_simd_interface` now also requires the storage to expose lvalue references, so lazybacked strided views fall back to the scalar assign path. Container-backed views keep their SIMD path unchanged. --------- Co-authored-by: Alexis Placet <2400067+Alex-PLACET@users.noreply.github.com>
1 parent 37f1372 commit 0e9d0be

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

include/xtensor/views/xstrided_view.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,13 @@ namespace xt
179179
using simd_value_type = xt_simd::simd_type<value_type>;
180180
using bool_load_type = typename base_type::bool_load_type;
181181

182+
// load_simd/store_simd take the address of the flat storage, which requires the
183+
// storage to expose lvalue references (not the case for lazy expressions wrapped
184+
// in a flat_expression_adaptor).
182185
static constexpr bool provides_simd_interface = has_simd_interface<xexpression_type>::value
183-
&& L != layout_type::dynamic;
186+
&& L != layout_type::dynamic
187+
&& std::is_lvalue_reference_v<
188+
decltype(std::declval<const storage_type&>()[0])>;
184189

185190
template <class CTA, class SA>
186191
xstrided_view(CTA&& e, SA&& shape, strides_type&& strides, std::size_t offset, layout_type layout) noexcept;

test/test_xstrided_view.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,29 @@ namespace xt
723723
EXPECT_TRUE(std::equal(nv.shape().begin(), nv.shape().end(), expected_shape.begin()));
724724
}
725725

726+
TEST(xstrided_view, reshape_view_lazy_expression)
727+
{
728+
const std::size_t G = 8, N = 4;
729+
xtensor<double, 1> w = xt::arange<double>(G) + 1.0;
730+
xtensor<double, 2> Phi = 3.0 * xt::ones<double>({G, N});
731+
732+
// reshape_view over a lazy expression must not enable the SIMD assign path,
733+
// which takes the address of the (computed) flat storage.
734+
auto col = xt::reshape_view(w * w, {G, std::size_t(1)});
735+
xtensor<double, 2> out = Phi * col;
736+
737+
#if XTENSOR_USE_XSIMD
738+
using lazy_traits = xassign_traits<xtensor<double, 2>, decltype(Phi * col)>;
739+
EXPECT_FALSE(lazy_traits::simd_linear_assign());
740+
741+
auto colc = xt::reshape_view(w, {G, std::size_t(1)});
742+
using cont_traits = xassign_traits<xtensor<double, 2>, decltype(Phi * colc)>;
743+
EXPECT_TRUE(cont_traits::simd_linear_assign());
744+
#endif
745+
746+
EXPECT_EQ(108.0, out(5, 2));
747+
}
748+
726749
TEST(xstrided_view, reshape_view_assign)
727750
{
728751
xarray<int, layout_type::column_major> xa = {{1, 2, 3}, {4, 5, 6}};

0 commit comments

Comments
 (0)