@@ -266,6 +266,229 @@ TYPED_TEST( Array1DOfArray1DTest, emptyMove )
266266 this ->emptyMove ();
267267}
268268
269+ #if defined(LVARRAY_USE_CHAI) && ( defined(LVARRAY_USE_CUDA) || defined(LVARRAY_USE_HIP) )
270+
271+ class Array1DOfArray1DOfArrayView2DTest : public ::testing::Test
272+ {
273+ public:
274+ using T = double ;
275+ using IndexType = std::ptrdiff_t ;
276+
277+ template < typename U >
278+ using Array1D = Array< U, 1 , RAJA::PERM_I, IndexType, ChaiBuffer >;
279+
280+ template < typename U >
281+ using Array2D = Array< U, 2 , RAJA::PERM_IJ, IndexType, ChaiBuffer >;
282+
283+ template < typename U >
284+ using ArrayView2D = ArrayView< U, 2 , 1 , IndexType, ChaiBuffer >;
285+
286+ using LeafOwners = Array1D< Array1D< Array2D< T > > >;
287+ using NestedViews = Array1D< Array1D< ArrayView2D< T const > > >;
288+ using NestedViewConst = typename NestedViews::NestedViewTypeConst;
289+
290+ static constexpr IndexType OUTER_SIZE = 3 ;
291+
292+ static constexpr IndexType innerSize ( IndexType const i )
293+ { return i + 1 ; }
294+
295+ static constexpr IndexType numRows ( IndexType const i, IndexType const )
296+ { return i + 1 ; }
297+
298+ static constexpr IndexType numCols ( IndexType const , IndexType const j )
299+ { return j + 2 ; }
300+
301+ static LVARRAY_HOST_DEVICE constexpr T initialValue ( IndexType const i,
302+ IndexType const j,
303+ IndexType const r,
304+ IndexType const c )
305+ { return T ( 1000 * i + 100 * j + 10 * r + c ); }
306+
307+ static LVARRAY_HOST_DEVICE constexpr T deviceTouchedValue ( IndexType const i,
308+ IndexType const j,
309+ IndexType const r,
310+ IndexType const c )
311+ { return initialValue ( i, j, r, c ) + T ( 5000 ); }
312+
313+ static LVARRAY_HOST_DEVICE constexpr T hostTouchedValue ( IndexType const i,
314+ IndexType const j,
315+ IndexType const r,
316+ IndexType const c )
317+ { return initialValue ( i, j, r, c ) + T ( 9000 ); }
318+
319+ static void initialize ( LeafOwners & owners, NestedViews & views )
320+ {
321+ owners.resize ( OUTER_SIZE );
322+ views.resize ( OUTER_SIZE );
323+
324+ for ( IndexType i = 0 ; i < OUTER_SIZE; ++i )
325+ {
326+ owners[ i ].resize ( innerSize ( i ) );
327+ views[ i ].resize ( innerSize ( i ) );
328+
329+ for ( IndexType j = 0 ; j < owners[ i ].size (); ++j )
330+ {
331+ owners[ i ][ j ].resize ( numRows ( i, j ), numCols ( i, j ) );
332+
333+ for ( IndexType r = 0 ; r < owners[ i ][ j ].size ( 0 ); ++r )
334+ {
335+ for ( IndexType c = 0 ; c < owners[ i ][ j ].size ( 1 ); ++c )
336+ {
337+ owners[ i ][ j ]( r, c ) = initialValue ( i, j, r, c );
338+ }
339+ }
340+
341+ views[ i ][ j ] = owners[ i ][ j ].toViewConst ();
342+ }
343+ }
344+ }
345+
346+ static void touchLeavesOnDevice ( LeafOwners & owners )
347+ {
348+ for ( IndexType i = 0 ; i < owners.size (); ++i )
349+ {
350+ for ( IndexType j = 0 ; j < owners[ i ].size (); ++j )
351+ {
352+ ArrayView2D< T > const leafView = owners[ i ][ j ].toView ();
353+ forall< parallelDevicePolicy< 32 > >( leafView.size ( 0 ), [leafView, i, j] LVARRAY_HOST_DEVICE ( IndexType const r )
354+ {
355+ for ( IndexType c = 0 ; c < leafView.size ( 1 ); ++c )
356+ {
357+ leafView ( r, c ) = deviceTouchedValue ( i, j, r, c );
358+ }
359+ } );
360+ }
361+ }
362+ }
363+
364+ static void touchLeavesOnHost ( LeafOwners & owners )
365+ {
366+ for ( IndexType i = 0 ; i < owners.size (); ++i )
367+ {
368+ for ( IndexType j = 0 ; j < owners[ i ].size (); ++j )
369+ {
370+ ArrayView2D< T > const leafView = owners[ i ][ j ].toView ();
371+ forall< serialPolicy >( leafView.size ( 0 ), [leafView, i, j] LVARRAY_HOST_DEVICE ( IndexType const r )
372+ {
373+ for ( IndexType c = 0 ; c < leafView.size ( 1 ); ++c )
374+ {
375+ leafView ( r, c ) = hostTouchedValue ( i, j, r, c );
376+ }
377+ } );
378+ }
379+ }
380+ }
381+
382+ static void expectDeviceTouchedValuesInHostKernel ( NestedViewConst const & nestedView )
383+ {
384+ forall< serialPolicy >( nestedView.size (), [nestedView] LVARRAY_HOST_DEVICE ( IndexType const i )
385+ {
386+ for ( IndexType j = 0 ; j < nestedView[ i ].size (); ++j )
387+ {
388+ for ( IndexType r = 0 ; r < nestedView[ i ][ j ].size ( 0 ); ++r )
389+ {
390+ for ( IndexType c = 0 ; c < nestedView[ i ][ j ].size ( 1 ); ++c )
391+ {
392+ PORTABLE_EXPECT_EQ ( nestedView[ i ][ j ]( r, c ), deviceTouchedValue ( i, j, r, c ) );
393+ }
394+ }
395+ }
396+ } );
397+ }
398+
399+ static void expectDeviceTouchedValuesOnHost ( NestedViewConst const & nestedView )
400+ {
401+ for ( IndexType i = 0 ; i < nestedView.size (); ++i )
402+ {
403+ for ( IndexType j = 0 ; j < nestedView[ i ].size (); ++j )
404+ {
405+ for ( IndexType r = 0 ; r < nestedView[ i ][ j ].size ( 0 ); ++r )
406+ {
407+ for ( IndexType c = 0 ; c < nestedView[ i ][ j ].size ( 1 ); ++c )
408+ {
409+ EXPECT_EQ ( nestedView[ i ][ j ]( r, c ), deviceTouchedValue ( i, j, r, c ) );
410+ }
411+ }
412+ }
413+ }
414+ }
415+
416+ static void warmOuterViewOnDevice ( NestedViewConst const & nestedView )
417+ {
418+ forall< parallelDevicePolicy< 32 > >( nestedView.size (), [nestedView] LVARRAY_HOST_DEVICE ( IndexType const i )
419+ {
420+ for ( IndexType j = 0 ; j < nestedView[ i ].size (); ++j )
421+ {
422+ for ( IndexType r = 0 ; r < nestedView[ i ][ j ].size ( 0 ); ++r )
423+ {
424+ for ( IndexType c = 0 ; c < nestedView[ i ][ j ].size ( 1 ); ++c )
425+ {
426+ PORTABLE_EXPECT_EQ ( nestedView[ i ][ j ]( r, c ), initialValue ( i, j, r, c ) );
427+ }
428+ }
429+ }
430+ } );
431+ }
432+
433+ static void expectHostTouchedValuesInDeviceKernel ( NestedViewConst const & nestedView )
434+ {
435+ forall< parallelDevicePolicy< 32 > >( nestedView.size (), [nestedView] LVARRAY_HOST_DEVICE ( IndexType const i )
436+ {
437+ for ( IndexType j = 0 ; j < nestedView[ i ].size (); ++j )
438+ {
439+ for ( IndexType r = 0 ; r < nestedView[ i ][ j ].size ( 0 ); ++r )
440+ {
441+ for ( IndexType c = 0 ; c < nestedView[ i ][ j ].size ( 1 ); ++c )
442+ {
443+ PORTABLE_EXPECT_EQ ( nestedView[ i ][ j ]( r, c ), hostTouchedValue ( i, j, r, c ) );
444+ }
445+ }
446+ }
447+ } );
448+ }
449+ };
450+
451+ TEST_F ( Array1DOfArray1DOfArrayView2DTest, hostCaptureAfterDeviceTouch )
452+ {
453+ LeafOwners owners;
454+ NestedViews views;
455+ initialize ( owners, views );
456+
457+ touchLeavesOnDevice ( owners );
458+
459+ NestedViewConst const & nestedViewConst = views.toNestedViewConst ();
460+ expectDeviceTouchedValuesInHostKernel ( nestedViewConst );
461+ }
462+
463+ TEST_F ( Array1DOfArray1DOfArrayView2DTest, explicitHostMoveAfterDeviceTouch )
464+ {
465+ LeafOwners owners;
466+ NestedViews views;
467+ initialize ( owners, views );
468+
469+ touchLeavesOnDevice ( owners );
470+
471+ NestedViewConst const & nestedViewConst = views.toNestedViewConst ();
472+ nestedViewConst.move ( MemorySpace::host );
473+ expectDeviceTouchedValuesOnHost ( nestedViewConst );
474+ }
475+
476+ TEST_F ( Array1DOfArray1DOfArrayView2DTest, deviceCaptureAfterHostTouchFollowingDeviceUse )
477+ {
478+ LeafOwners owners;
479+ NestedViews views;
480+ initialize ( owners, views );
481+
482+ NestedViewConst const & nestedViewConst = views.toNestedViewConst ();
483+ warmOuterViewOnDevice ( nestedViewConst );
484+
485+ touchLeavesOnHost ( owners );
486+
487+ expectHostTouchedValuesInDeviceKernel ( nestedViewConst );
488+ }
489+
490+ #endif
491+
269492} // namespace testing
270493} // namespace LvArray
271494
0 commit comments