|
4 | 4 | #include "openPMD/auxiliary/Environment.hpp" |
5 | 5 | #include "openPMD/auxiliary/Filesystem.hpp" |
6 | 6 | #include "openPMD/openPMD.hpp" |
| 7 | +// @todo change includes |
| 8 | +#include "openPMD/benchmark/mpi/OneDimensionalBlockSlicer.hpp" |
7 | 9 | #include <catch2/catch.hpp> |
8 | 10 |
|
9 | 11 | #if openPMD_HAVE_MPI |
@@ -1108,4 +1110,150 @@ TEST_CASE( "adios2_ssc", "[parallel][adios2]" ) |
1108 | 1110 | { |
1109 | 1111 | adios2_ssc(); |
1110 | 1112 | } |
1111 | | -#endif |
| 1113 | + |
| 1114 | +void adios2_chunk_distribution() |
| 1115 | +{ |
| 1116 | + int mpi_size{ -1 }; |
| 1117 | + int mpi_rank{ -1 }; |
| 1118 | + MPI_Comm_size( MPI_COMM_WORLD, &mpi_size ); |
| 1119 | + MPI_Comm_rank( MPI_COMM_WORLD, &mpi_rank ); |
| 1120 | + |
| 1121 | + chunk_assignment::RankMeta writingRanksHostnames, readingRanksHostnames; |
| 1122 | + for( int i = 0; i < mpi_size; ++i ) |
| 1123 | + { |
| 1124 | + // 0, 0, 1, 1, 2, 2, 3, 3 ... |
| 1125 | + writingRanksHostnames[ i ] = "node" + std::to_string( i / 2 ); |
| 1126 | + // 0, 0, 0, 0, 2, 2, 2, 2 ... |
| 1127 | + readingRanksHostnames[ i ] = "node" + std::to_string( i / 4 * 2 ); |
| 1128 | + } |
| 1129 | + |
| 1130 | + std::string filename = "../samples/adios2_chunk_distribution.bp"; |
| 1131 | + // simulate a stream |
| 1132 | + std::stringstream parameters; |
| 1133 | + parameters << R"END( |
| 1134 | +{ |
| 1135 | + "adios2": |
| 1136 | + { |
| 1137 | + "engine": |
| 1138 | + { |
| 1139 | + "type": "bp4", |
| 1140 | + "parameters": |
| 1141 | + { |
| 1142 | + "NumAggregators":)END" |
| 1143 | + << "\"" << std::to_string( mpi_size ) << "\"" |
| 1144 | + << R"END( |
| 1145 | + } |
| 1146 | + } |
| 1147 | + } |
| 1148 | +} |
| 1149 | +)END"; |
| 1150 | + |
| 1151 | + auto printAssignment = [ mpi_rank ]( |
| 1152 | + std::string const & strategyName, |
| 1153 | + ChunkTable const & table, |
| 1154 | + chunk_assignment::RankMeta const & meta ) |
| 1155 | + { |
| 1156 | + if( mpi_rank != 0 ) |
| 1157 | + { |
| 1158 | + return; |
| 1159 | + } |
| 1160 | + std::cout << "WITH STRATEGY '" << strategyName << "':\n"; |
| 1161 | + for( auto const & chunk : table ) |
| 1162 | + { |
| 1163 | + std::cout << "[HOST: " << meta.at( chunk.sourceID ) |
| 1164 | + << ",\tRank: " << chunk.sourceID << ",\tOffset: "; |
| 1165 | + for( auto offset : chunk.offset ) |
| 1166 | + { |
| 1167 | + std::cout << offset << ", "; |
| 1168 | + } |
| 1169 | + std::cout << "\tExtent: "; |
| 1170 | + for( auto extent : chunk.extent ) |
| 1171 | + { |
| 1172 | + std::cout << extent << ", "; |
| 1173 | + } |
| 1174 | + std::cout << "]" << std::endl; |
| 1175 | + } |
| 1176 | + }; |
| 1177 | + |
| 1178 | + { |
| 1179 | + Series series( |
| 1180 | + filename, |
| 1181 | + openPMD::Access::CREATE, |
| 1182 | + MPI_COMM_WORLD, |
| 1183 | + parameters.str() ); |
| 1184 | + series.setMpiRanksMetaInfo( writingRanksHostnames.at( mpi_rank ) ); |
| 1185 | + |
| 1186 | + auto E_x = series.iterations[ 0 ].meshes[ "E" ][ "x" ]; |
| 1187 | + openPMD::Dataset ds( |
| 1188 | + openPMD::Datatype::INT, { unsigned( mpi_size ), 10 } ); |
| 1189 | + E_x.resetDataset( ds ); |
| 1190 | + std::vector< int > data( 10, 0 ); |
| 1191 | + std::iota( data.begin(), data.end(), 0 ); |
| 1192 | + E_x.storeChunk( data, { unsigned( mpi_rank ), 0 }, { 1, 10 } ); |
| 1193 | + series.flush(); |
| 1194 | + } |
| 1195 | + |
| 1196 | + { |
| 1197 | + Series series( filename, openPMD::Access::READ_ONLY, MPI_COMM_WORLD ); |
| 1198 | + auto rankMetaIn = series.mpiRanksMetaInfo(); |
| 1199 | + REQUIRE( rankMetaIn == writingRanksHostnames ); |
| 1200 | + |
| 1201 | + auto E_x = series.iterations[ 0 ].meshes[ "E" ][ "x" ]; |
| 1202 | + auto const chunkTable = E_x.availableChunks(); |
| 1203 | + |
| 1204 | + printAssignment( "INPUT", chunkTable, rankMetaIn ); |
| 1205 | + |
| 1206 | + using namespace chunk_assignment; |
| 1207 | + |
| 1208 | + RoundRobin roundRobinStrategy; |
| 1209 | + auto roundRobinAssignment = assignChunks( |
| 1210 | + chunkTable, rankMetaIn, readingRanksHostnames, roundRobinStrategy ); |
| 1211 | + printAssignment( |
| 1212 | + "ROUND ROBIN", roundRobinAssignment, readingRanksHostnames ); |
| 1213 | + |
| 1214 | + ByHostname byHostname( |
| 1215 | + std::make_unique< BinPacking >( /* splitAlongDimension = */ 1 ) ); |
| 1216 | + auto byHostnamePartialAssignment = assignChunks( |
| 1217 | + chunkTable, rankMetaIn, readingRanksHostnames, byHostname ); |
| 1218 | + printAssignment( |
| 1219 | + "HOSTNAME, ASSIGNED", |
| 1220 | + byHostnamePartialAssignment.assigned, |
| 1221 | + readingRanksHostnames ); |
| 1222 | + printAssignment( |
| 1223 | + "HOSTNAME, LEFTOVER", |
| 1224 | + byHostnamePartialAssignment.notAssigned, |
| 1225 | + rankMetaIn ); |
| 1226 | + |
| 1227 | + FromPartialStrategy fromPartialStrategy( |
| 1228 | + std::make_unique< ByHostname >( std::move( byHostname ) ), |
| 1229 | + std::make_unique< BinPacking >( /* splitAlongDimension = */ 1 ) ); |
| 1230 | + auto fromPartialAssignment = assignChunks( |
| 1231 | + chunkTable, |
| 1232 | + rankMetaIn, |
| 1233 | + readingRanksHostnames, |
| 1234 | + fromPartialStrategy ); |
| 1235 | + printAssignment( |
| 1236 | + "HOSTNAME WITH SECOND PASS", |
| 1237 | + fromPartialAssignment, |
| 1238 | + readingRanksHostnames ); |
| 1239 | + |
| 1240 | + ByCuboidSlice cuboidSliceStrategy( |
| 1241 | + std::make_unique< OneDimensionalBlockSlicer >( 1 ), |
| 1242 | + E_x.getExtent(), |
| 1243 | + mpi_rank, |
| 1244 | + mpi_size ); |
| 1245 | + auto cuboidSliceAssignment = assignChunks( |
| 1246 | + chunkTable, |
| 1247 | + rankMetaIn, |
| 1248 | + readingRanksHostnames, |
| 1249 | + cuboidSliceStrategy ); |
| 1250 | + printAssignment( |
| 1251 | + "CUBOID SLICE", cuboidSliceAssignment, readingRanksHostnames ); |
| 1252 | + } |
| 1253 | +} |
| 1254 | + |
| 1255 | +TEST_CASE( "adios2_chunk_distribution", "[parallel][adios2]" ) |
| 1256 | +{ |
| 1257 | + adios2_chunk_distribution(); |
| 1258 | +} |
| 1259 | +#endif // openPMD_HAVE_ADIOS2 && openPMD_HAVE_MPI |
0 commit comments