diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e0d10b060e..8cf9666ada 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -215,6 +215,15 @@ foreach(SUB_DIR ${UNIT_TEST_SUBDIRS_LIST}) endif() endforeach() +# Copy synthetic blocks data files to /tests/synthetic-blocks-data +set(SYNTHETIC_BLOCKS_DATA_DEST "${CMAKE_BINARY_DIR}/tests/synthetic-blocks-data") +file(MAKE_DIRECTORY ${SYNTHETIC_BLOCKS_DATA_DEST}) +file(GLOB SYNTHETIC_BLOCKS_DATA_FILES "${CMAKE_SOURCE_DIR}/tests/data/synthetic-blocks/*") +foreach(SYNTHETIC_BLOCKS_DATA_FILE ${SYNTHETIC_BLOCKS_DATA_FILES}) + get_filename_component(FILE_NAME ${SYNTHETIC_BLOCKS_DATA_FILE} NAME) + configure_file(${SYNTHETIC_BLOCKS_DATA_FILE} ${SYNTHETIC_BLOCKS_DATA_DEST} COPYONLY) +endforeach() + # # Performance Tests # diff --git a/tests/data/synthetic-blocks/synthetic-dataset-blocks.0.json b/tests/data/synthetic-blocks/synthetic-dataset-blocks.0.json new file mode 100644 index 0000000000..26afaaea2c --- /dev/null +++ b/tests/data/synthetic-blocks/synthetic-dataset-blocks.0.json @@ -0,0 +1 @@ +{"metadata":{"type":"LBDatafile","rank":0},"phases":[{"id":0,"tasks":[{"entity":{"home":0,"id":1,"migratable":true,"type":"object"},"node":0,"resource":"cpu","time":0.5,"user_defined":{"shared_id":0,"shared_bytes":9.0,"home_rank":0}},{"entity":{"home":0,"id":3,"migratable":true,"type":"object"},"node":0,"resource":"cpu","time":0.5,"user_defined":{"shared_id":1,"shared_bytes":9.0,"home_rank":0}},{"entity":{"home":0,"id":2,"migratable":true,"type":"object"},"node":0,"resource":"cpu","time":0.5,"user_defined":{"shared_id":1,"shared_bytes":9.0,"home_rank":0}},{"entity":{"home":0,"id":0,"migratable":true,"type":"object"},"node":0,"resource":"cpu","time":1.0,"user_defined":{"shared_id":0,"shared_bytes":9.0,"home_rank":0}}],"communications":[{"type":"SendRecv","to":{"type":"object","id":5},"messages":1,"from":{"type":"object","id":0},"bytes":2.0},{"type":"SendRecv","to":{"type":"object","id":4},"messages":1,"from":{"type":"object","id":1},"bytes":1.0},{"type":"SendRecv","to":{"type":"object","id":2},"messages":1,"from":{"type":"object","id":3},"bytes":1.0},{"type":"SendRecv","to":{"type":"object","id":8},"messages":1,"from":{"type":"object","id":3},"bytes":0.5}]}]} diff --git a/tests/data/synthetic-blocks/synthetic-dataset-blocks.1.json b/tests/data/synthetic-blocks/synthetic-dataset-blocks.1.json new file mode 100644 index 0000000000..160cf422d5 --- /dev/null +++ b/tests/data/synthetic-blocks/synthetic-dataset-blocks.1.json @@ -0,0 +1 @@ +{"metadata":{"type":"LBDatafile","rank":1},"phases":[{"id":0,"tasks":[{"entity":{"home":1,"id":5,"migratable":true,"type":"object"},"node":1,"resource":"cpu","time":2.0,"user_defined":{"shared_id":2,"shared_bytes":9.0,"home_rank":1}},{"entity":{"home":1,"id":4,"migratable":true,"type":"object"},"node":1,"resource":"cpu","time":0.5,"user_defined":{"shared_id":2,"shared_bytes":9.0,"home_rank":1}},{"entity":{"home":1,"id":7,"migratable":true,"type":"object"},"node":1,"resource":"cpu","time":0.5,"user_defined":{"shared_id":3,"shared_bytes":9.0,"home_rank":1}},{"entity":{"home":1,"id":6,"migratable":true,"type":"object"},"node":1,"resource":"cpu","time":1.0,"user_defined":{"shared_id":3,"shared_bytes":9.0,"home_rank":1}}],"communications":[{"type":"SendRecv","to":{"type":"object","id":1},"messages":1,"from":{"type":"object","id":4},"bytes":2.0},{"type":"SendRecv","to":{"type":"object","id":8},"messages":1,"from":{"type":"object","id":5},"bytes":2.0},{"type":"SendRecv","to":{"type":"object","id":6},"messages":1,"from":{"type":"object","id":7},"bytes":1.0}]}]} diff --git a/tests/data/synthetic-blocks/synthetic-dataset-blocks.2.json b/tests/data/synthetic-blocks/synthetic-dataset-blocks.2.json new file mode 100644 index 0000000000..5b1e88a01d --- /dev/null +++ b/tests/data/synthetic-blocks/synthetic-dataset-blocks.2.json @@ -0,0 +1 @@ +{"metadata":{"type":"LBDatafile","rank":2},"phases":[{"id":0,"tasks":[{"entity":{"home":2,"id":8,"migratable":true,"type":"object"},"node":2,"resource":"cpu","time":1.5,"user_defined":{"shared_id":4,"shared_bytes":9.0,"home_rank":2}}],"communications":[{"type":"SendRecv","to":{"type":"object","id":6},"messages":1,"from":{"type":"object","id":8},"bytes":1.5}]}]} diff --git a/tests/data/synthetic-blocks/synthetic-dataset-blocks.3.json b/tests/data/synthetic-blocks/synthetic-dataset-blocks.3.json new file mode 100644 index 0000000000..f2868aa3bd --- /dev/null +++ b/tests/data/synthetic-blocks/synthetic-dataset-blocks.3.json @@ -0,0 +1 @@ +{"metadata":{"type":"LBDatafile","rank":3},"phases":[{"id":0,"tasks":[]}]} diff --git a/tests/unit/lb/test_temperedlb.cc b/tests/unit/lb/test_temperedlb.cc new file mode 100644 index 0000000000..c54a610d5e --- /dev/null +++ b/tests/unit/lb/test_temperedlb.cc @@ -0,0 +1,87 @@ +#include +#include +#include + +#include "test_helpers.h" +#include "test_parallel_harness.h" + +namespace vt { namespace tests { namespace unit { namespace lb { + +#if vt_check_enabled(lblite) + +using TestTemperedLB = TestParallelHarness; + +std::string writeTemperedLBConfig(std::string transfer_strategy, + bool mem_constraints, + double delta = 0.0, + double beta = 0.0, + double gamma = 0.0) { + int this_rank; + MPI_Comm_rank(MPI_COMM_WORLD, &this_rank); + auto config_file = getUniqueFilename(); + if (this_rank == 0) { + std::ofstream cfg_file_{config_file.c_str(), std::ofstream::out | std::ofstream::trunc}; + cfg_file_ << "0 TemperedLB transfer=" << transfer_strategy << + " alpha=1.0" << + " beta=" << beta << + " gamma=" << gamma << + " delta=" << delta; + if (mem_constraints) { + cfg_file_ << " memory_threshold=20.0"; + } + cfg_file_.close(); + } + return config_file; +} + +void runTemperedLBTest(std::string config_file, double expected_imb = 0.0) { + // Set configuration + theConfig()->vt_lb = true; + theConfig()->vt_lb_name = "TemperedLB"; + theConfig()->vt_lb_data_in = true; + theConfig()->vt_lb_file_name = config_file; + theConfig()->vt_lb_data_file_in="synthetic-dataset-blocks.%p.json"; + theConfig()->vt_lb_data_dir_in="synthetic-blocks-data"; + + // Replay load balancing + int initial_phase = 0; + int phases_to_run = 1; + int phase_mod = 0; + vt::vrt::collection::balance::replay::replayWorkloads( + initial_phase, phases_to_run, phase_mod); + + // Get information for the last phase (this problem only has one) + auto phase_info = theLBManager()->getPhaseInfo(); + + // Assert that temperedLB found the correct imbalance + auto imb = (phase_info->max_load / phase_info->avg_load) - 1; + EXPECT_EQ(imb, expected_imb); + + // Clear the LB config ahead of next test + vrt::collection::balance::ReadLBConfig::clear(); +} + +TEST_F(TestTemperedLB, test_load_only) { + auto cfg = writeTemperedLBConfig("Original", false); + runTemperedLBTest(cfg); +} + +TEST_F(TestTemperedLB, test_load_and_memory_swapclusters) { + auto cfg = writeTemperedLBConfig("SwapClusters", true); + runTemperedLBTest(cfg); +} + +TEST_F(TestTemperedLB, test_load_memory_homing_swapclusters) { + auto cfg = writeTemperedLBConfig("SwapClusters", true, 1.0); + runTemperedLBTest(cfg); +} + +TEST_F(TestTemperedLB, test_load_memory_homing_comms) { + auto cfg = writeTemperedLBConfig("SwapClusters", true, 1.0, 1.0); + double expected_imbalance = 0.25; // placeholder for value from MILP + runTemperedLBTest(cfg, expected_imbalance); +} + +#endif + +}}}} /* end namespace vt::tests::unit::lb */