镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

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

Description

@qinixw

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}}, 

Activity

  1. spectre-ns commented on Dec 22, 2024

    @spectre-ns
    Contributor

    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions