Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

copy a view with non-trivial strides along with its underlying container #2803

Open
qinixw opened this issue Aug 21, 2024 · 1 comment
Open

Comments

@qinixw
Copy link

qinixw commented Aug 21, 2024

I have a need to copy a view along with its underlying container. Could someone show me the right way to do it?

My current code doesn't propagate the strides info to the view expression. The code crashed when I printed the new view out.

template <class T, class... S>
auto copy_view_to_new_container(const xt::xview<T, S...>& view) {
  const auto& container = view.expression();

  auto new_container = xt::eval(container);

  auto slices = view.slices();

  auto new_view = xt::view(new_container, std::get<S>(slices)...);

  return std::make_pair(std::move(new_container), std::move(new_view));
}

TEST(gpu_proxy, dtype_float_view1) {
  xt::xarray<double> array = xt::arange<double>(100).reshape({10, 10});
  auto view = xt::view(array, xt::range(2, 8), xt::range(3, 7));

  auto [new_container, new_view] = copy_view_to_new_container(view);

  std::cout << new_container << "\n"; 
  std::cout << new_view << "\n";   // core dump here.
}

The above code crashed at xview.hpp at the function of compute_strides_impl(). When I printed out xview's m_e, I noticed that m_strides and m_backstrides are not properly initialized. It seems to be the case that the view does not have trivial_strides, so the initialization of m_strides are skipped in xview constructor.

        static static_layout = xt::layout_type::row_major}, <xt::xaccessible<xt::xarray_container<xt::uvector<double, std::allocator<double> >, (xt::layout_type)1, xt::svector<unsigned long, 4ul, std::allocator<unsigned long>, true>, xt::xtensor_expression_tag> >> = {<xt::xconst_accessible<xt::xarray_container<xt::uvector<double, std::allocator<double> >, (xt::layout_type)1, xt::svector<unsigned long, 4ul, std::allocator<unsigned long>, true>, xt::xtensor_expression_tag> >> = {<No data fields>}, <No data fields>}, 
      static static_layout = xt::layout_type::row_major, static contiguous_layout = true}, 
     m_shape = {
      static alignment = 8, 
      m_allocator = {<__gnu_cxx::new_allocator<unsigned long>> = {<No data fields>}, <No data fields>}, 
      m_begin = 0xffffffff000003e8, m_end = 0x4b00000003, m_capacity = 0x0, m_data = {0, 0, 
        140737337425920, 9}}, 
      m_strides = {static alignment = 8, 
      m_allocator = {<__gnu_cxx::new_allocator<long>> = {<No data fields>}, <No data fields>}, 
      m_begin = 0x0, m_end = 0x0, m_capacity = 0x0, m_data = {0, 0, 0, 6}}, 
     m_backstrides = {
      static alignment = 8, 
      m_allocator = {<__gnu_cxx::new_allocator<long>> = {<No data fields>}, <No data fields>}, 
      m_begin = 0x1, m_end = 0x0, m_capacity = 0x4b00000003, m_data = {-4294966296, 36, 0, 
        140737488342728}}, 
@spectre-ns
Copy link
Contributor

spectre-ns commented Dec 22, 2024

You code does not compile. I had to update it to the following:

    template <class T, class... S, size_t... I>
    auto copy_view_to_new_container(const xt::xview<T, S...>& view, std::index_sequence<I...>) {
        const auto& container = view.expression();

        xt::xarray<float> new_container = xt::eval(container);

        auto slices = view.slices();

        auto new_view = xt::view(new_container, std::get<I>(slices)...);

        return std::make_pair(std::move(new_container), std::move(new_view));
    }


    TEST(gpu_proxy, dtype_float_view1) {
        xt::xarray<double> array = xt::arange<double>(100);
        array.reshape({10, 10});
        auto view = xt::view(array, xt::range(2, 8), xt::range(3, 7));

        auto [new_container, new_view] = copy_view_to_new_container(view, std::make_index_sequence<2>());

        std::cout << new_container << "\n"; 
        std::cout << new_view << "\n";   // core dump here.
    }

The issue you're encountering here is new_container is captured by reference. It's life time is bound to the code of copy_view_to_new_container you then move new_container this means that new_view now has a dangling reference which when called results in a segmentation fault.

I'm not really sure what you're trying to accomplish to be honest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants