GEOS-DEV/LvArray

MultiView

corbett5 opened this issue · 3 comments

Make something similar to the RAJA MultiView. Here's what I imagine it would look like.

template< int NARRAYS, typename T, int NDIM, int USD, typename INDEX_TYPE, template< typename > class BUFFER_TYPE >
class MultiView
{
public:
  MultiView( CArray< ArrayView< T, NDIM, USD, INDEX_TYPE, BUFFER_TYPE > > && views ):
    m_dims{ views[ 0 ].m_dims },
    m_strides{ views[ 0 ].m_strides }
  {
    // Error checking

    for( int i = 0; i < NARRAYS; ++i )
    {
      m_dataBuffers[ i ] = std::move( views[ i ].m_dataBuffer );
    }
  }

  inline LVARRAY_HOST_DEVICE constexpr
  ArraySlice< T, NDIM, USD, INDEX_TYPE >
  toSlice( int const i ) const & noexcept
  { return ArraySlice< T, NDIM, USD, INDEX_TYPE >( m_dataBuffers[ i ].data(), m_dims.data, m_strides.data ); }

private:
  CArray< INDEX_TYPE, NDIM > m_dims;
  CArray< INDEX_TYPE, NDIM > m_strides;
  CArray< BUFFER_TYPE< T >, NARRAYS > m_dataBuffers;
};

Would need to be a bit more complicated to ensure the same copy-semantics as ArrayView.

With a little work it could be extended to support views with different types, which would be necessary if you want to mix T with T const.

Usage would look something like

void foo( ArrayView2d< int > const & xIn, ArrayView2d< int > const & yIn )
{
  MultiView2d< 2, int > const multiView( { xIn, yIn } );

  forAll< POLICY >( xIn.size( 0 ), [multiView] ( int const i )
  {
    ArraySlice2d< int > const x = multiView.toSlice( 0 );
    ArraySlice2d< int > const y = multiView.toSlice( 1 );

    bar( x, y );
  } );
}
for( int i = 0; i < NDIM; ++i )
{
  m_dataBuffers[ i ] = std::move( views[ i ].m_dataBuffer );
}

}

That should be??

for( int i = 0; i < NARRAYS; ++i )
{
  m_dataBuffers[ i ] = std::move( views[ i ].m_dataBuffer );
}

Looks pretty straight forward. The combination of different T would be essential to general usage....which would make it much less straight forward I guess.

Nice catch, fixed.

Yeah internally it would be a bit more complicated using a tuple instead of an array for m_dataBuffers. The usage would be pretty much the same. You'd have to call toSlice< 0 >() instead of toSlice( 0 ), but that's fine. As for construction we could create a

template< int NDIM, int USD, typename INDEX_TYPE, template< typename > class BUFFER_TYPE, typename ... TYPES >
MultiView<...> createMultiView( ArrayView< TYPES, NDIM, USD, INDEX_TYPE, BUFFER_TYPE > const & ... views );

So that users could just do

void foo( ArrayView2d< int > const & xIn, ArrayView2d< double > const & yIn )
{
  auto const multiView = createMultiView( x, y );
  ...
}

OK. that looks nice. I guess we don't need anything to help with the creation of the multi view as the createMultiView is pretty simple...but we can add a variadic macro to ease the definition of all the slices.