#include <Cabana_Parallel.hpp> #include <Cabana_ExecutionPolicy.hpp> #include <Cabana_AoSoA.hpp> #include <boost/test/unit_test.hpp> //---------------------------------------------------------------------------// // Check the data given a set of values. template<class aosoa_type> void checkDataMembers( aosoa_type aosoa, const float fval, const double dval, const int ival, const std::size_t dim_1, const std::size_t dim_2, const std::size_t dim_3, const std::size_t dim_4 ) { for ( auto idx = aosoa.begin(); idx != aosoa.end(); ++idx ) { // Member 0. for ( std::size_t i = 0; i < dim_1; ++i ) for ( std::size_t j = 0; j < dim_2; ++j ) for ( std::size_t k = 0; k < dim_3; ++k ) BOOST_CHECK( aosoa.template get<0>( idx, i, j, k ) == fval * (i+j+k) ); // Member 1. BOOST_CHECK( aosoa.template get<1>( idx ) == ival ); // Member 2. for ( std::size_t i = 0; i < dim_1; ++i ) for ( std::size_t j = 0; j < dim_2; ++j ) for ( std::size_t k = 0; k < dim_3; ++k ) for ( std::size_t l = 0; l < dim_4; ++l ) BOOST_CHECK( aosoa.template get<2>( idx, i, j, k, l ) == fval * (i+j+k+l) ); // Member 3. for ( std::size_t i = 0; i < dim_1; ++i ) BOOST_CHECK( aosoa.template get<3>( idx, i ) == dval * i ); // Member 4. for ( std::size_t i = 0; i < dim_1; ++i ) for ( std::size_t j = 0; j < dim_2; ++j ) BOOST_CHECK( aosoa.template get<4>( idx, i, j ) == dval * (i+j) ); } } //---------------------------------------------------------------------------// // TESTS //---------------------------------------------------------------------------// BOOST_AUTO_TEST_CASE( parallel_for_test ) { // Manually set the inner array size. using inner_array_size = Cabana::InnerArraySize<10>; // Data dimensions. const std::size_t dim_1 = 3; const std::size_t dim_2 = 2; const std::size_t dim_3 = 4; const std::size_t dim_4 = 3; // Declare data types. using DataTypes = Cabana::MemberDataTypes<float[dim_1][dim_2][dim_3], int, float[dim_1][dim_2][dim_3][dim_4], double[dim_1], double[dim_1][dim_2] >; // Declare the AoSoA type. using AoSoA_t = Cabana::AoSoA<DataTypes,inner_array_size,TEST_MEMSPACE>; // Create an AoSoA. std::size_t num_data = 155; AoSoA_t aosoa( num_data ); // Create an execution policy. Cabana::IndexRangePolicy<TEST_EXECSPACE> range_policy( aosoa.begin(), aosoa.end() ); // Write a functor to operate on. float fval = 3.4; double dval = 1.23; int ival = 1; auto func_1 = KOKKOS_LAMBDA( const Cabana::Index idx ) { // Member 0. for ( std::size_t i = 0; i < dim_1; ++i ) for ( std::size_t j = 0; j < dim_2; ++j ) for ( std::size_t k = 0; k < dim_3; ++k ) aosoa.get<0>( idx, i, j, k ) = fval * (i+j+k); // Member 1. aosoa.get<1>( idx ) = ival; // Member 2. for ( std::size_t i = 0; i < dim_1; ++i ) for ( std::size_t j = 0; j < dim_2; ++j ) for ( std::size_t k = 0; k < dim_3; ++k ) for ( std::size_t l = 0; l < dim_4; ++l ) aosoa.get<2>( idx, i, j, k, l ) = fval * (i+j+k+l); // Member 3. for ( std::size_t i = 0; i < dim_1; ++i ) aosoa.get<3>( idx, i ) = dval * i; // Member 4. for ( std::size_t i = 0; i < dim_1; ++i ) for ( std::size_t j = 0; j < dim_2; ++j ) aosoa.get<4>( idx, i, j ) = dval * (i+j); }; // Loop in parallel using 1D struct parallelism. Cabana::parallel_for( range_policy, func_1, Cabana::StructParallelTag() ); // Check data members for proper initialization. checkDataMembers( aosoa, fval, dval, ival, dim_1, dim_2, dim_3, dim_4 ); // Change values and write a second functor. fval = 93.4; dval = 12.1; ival = 4; auto func_2 = KOKKOS_LAMBDA( const Cabana::Index idx ) { // Member 0. for ( std::size_t i = 0; i < dim_1; ++i ) for ( std::size_t j = 0; j < dim_2; ++j ) for ( std::size_t k = 0; k < dim_3; ++k ) aosoa.get<0>( idx, i, j, k ) = fval * (i+j+k); // Member 1. aosoa.get<1>( idx ) = ival; // Member 2. for ( std::size_t i = 0; i < dim_1; ++i ) for ( std::size_t j = 0; j < dim_2; ++j ) for ( std::size_t k = 0; k < dim_3; ++k ) for ( std::size_t l = 0; l < dim_4; ++l ) aosoa.get<2>( idx, i, j, k, l ) = fval * (i+j+k+l); // Member 3. for ( std::size_t i = 0; i < dim_1; ++i ) aosoa.get<3>( idx, i ) = dval * i; // Member 4. for ( std::size_t i = 0; i < dim_1; ++i ) for ( std::size_t j = 0; j < dim_2; ++j ) aosoa.get<4>( idx, i, j ) = dval * (i+j); }; // Loop in parallel using 1D array parallelism. Cabana::parallel_for( range_policy, func_2, Cabana::ArrayParallelTag() ); // Check data members for proper initialization. checkDataMembers( aosoa, fval, dval, ival, dim_1, dim_2, dim_3, dim_4 ); // Change values and write a third functor. fval = 7.7; dval = 3.2; ival = 9; auto func_3 = KOKKOS_LAMBDA( const Cabana::Index idx ) { // Member 0. for ( std::size_t i = 0; i < dim_1; ++i ) for ( std::size_t j = 0; j < dim_2; ++j ) for ( std::size_t k = 0; k < dim_3; ++k ) aosoa.get<0>( idx, i, j, k ) = fval * (i+j+k); // Member 1. aosoa.get<1>( idx ) = ival; // Member 2. for ( std::size_t i = 0; i < dim_1; ++i ) for ( std::size_t j = 0; j < dim_2; ++j ) for ( std::size_t k = 0; k < dim_3; ++k ) for ( std::size_t l = 0; l < dim_4; ++l ) aosoa.get<2>( idx, i, j, k, l ) = fval * (i+j+k+l); // Member 3. for ( std::size_t i = 0; i < dim_1; ++i ) aosoa.get<3>( idx, i ) = dval * i; // Member 4. for ( std::size_t i = 0; i < dim_1; ++i ) for ( std::size_t j = 0; j < dim_2; ++j ) aosoa.get<4>( idx, i, j ) = dval * (i+j); }; // Loop in parallel using 2D struct and array parallelism. Cabana::parallel_for( range_policy, func_3, Cabana::StructAndArrayParallelTag() ); // Check data members for proper initialization. checkDataMembers( aosoa, fval, dval, ival, dim_1, dim_2, dim_3, dim_4 ); }