From b531104721d2d8a3fe119df875a615d22f89a74e Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 21 May 2019 12:05:15 -0400 Subject: [PATCH] added test to reproduce SST BP compression bug --- testing/adios2/engine/sst/CMakeLists.txt | 6 + .../engine/sst/TestSstBpCompressionLarge.cpp | 358 ++++++++++++++++++ 2 files changed, 364 insertions(+) create mode 100644 testing/adios2/engine/sst/TestSstBpCompressionLarge.cpp diff --git a/testing/adios2/engine/sst/CMakeLists.txt b/testing/adios2/engine/sst/CMakeLists.txt index 9e548e0cfe..07f839feea 100644 --- a/testing/adios2/engine/sst/CMakeLists.txt +++ b/testing/adios2/engine/sst/CMakeLists.txt @@ -19,3 +19,9 @@ if(ADIOS2_HAVE_MPI) target_link_libraries(TestSstParamFails MPI::MPI_C) target_link_libraries(TestSstWriterFails MPI::MPI_C) endif() + +if(ADIOS2_HAVE_MPI) + add_executable(TestSstBpCompressionLarge TestSstBpCompressionLarge.cpp) + target_link_libraries(TestSstBpCompressionLarge adios2 gtest MPI::MPI_C) + add_test(NAME TestSstBpCompressionLarge COMMAND "mpirun" "-n" "8" $) +endif() diff --git a/testing/adios2/engine/sst/TestSstBpCompressionLarge.cpp b/testing/adios2/engine/sst/TestSstBpCompressionLarge.cpp new file mode 100644 index 0000000000..9519cb6711 --- /dev/null +++ b/testing/adios2/engine/sst/TestSstBpCompressionLarge.cpp @@ -0,0 +1,358 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ + +#include +#include +#ifdef ADIOS2_HAVE_MPI +#include +#endif +#include +#include + +using namespace adios2; +int mpiRank = 0; +int mpiSize = 1; +MPI_Comm mpiComm; +size_t print_lines = 0; + +char runMode; + +class SstEngineTest : public ::testing::Test +{ +public: + SstEngineTest() = default; +}; + +template +void PrintData(const T *data, const size_t step, const Dims &start, + const Dims &count) +{ + size_t size = std::accumulate(count.begin(), count.end(), 1, + std::multiplies()); + std::cout << "Rank: " << mpiRank << " Step: " << step << " Size:" << size + << "\n"; + size_t printsize = 128; + + if (size < printsize) + { + printsize = size; + } + int s = 0; + for (size_t i = 0; i < printsize; ++i) + { + ++s; + std::cout << data[i] << " "; + if (s == count[1]) + { + std::cout << std::endl; + s = 0; + } + } + + std::cout << "]" << std::endl; +} + +template +void GenData(std::vector &data, const size_t step, const Dims &start, + const Dims &count, const Dims &shape) +{ + if (start.size() == 2) + { + for (size_t i = 0; i < count[0]; ++i) + { + for (size_t j = 0; j < count[1]; ++j) + { + data[i * count[1] + j] = + (i + start[1]) * shape[1] + j + start[0] + step; + } + } + } +} + +template +void VerifyData(const std::complex *data, size_t step, const Dims &start, + const Dims &count, const Dims &shape) +{ + size_t size = std::accumulate(count.begin(), count.end(), 1, + std::multiplies()); + std::vector> tmpdata(size); + GenData(tmpdata, step, start, count, shape); + for (size_t i = 0; i < size; ++i) + { + ASSERT_EQ(data[i], tmpdata[i]); + } + if (print_lines < 100) + { + PrintData(data, step, start, count); + ++print_lines; + } +} + +template +void VerifyData(const T *data, size_t step, const Dims &start, + const Dims &count, const Dims &shape) +{ + size_t size = std::accumulate(count.begin(), count.end(), 1, + std::multiplies()); + bool compressed = false; + std::vector tmpdata(size); + if (print_lines < 100) + { + PrintData(data, step, start, count); + ++print_lines; + } + GenData(tmpdata, step, start, count, shape); + for (size_t i = 0; i < size; ++i) + { + if (!compressed) + { + ASSERT_EQ(data[i], tmpdata[i]); + } + } +} + +void Writer(const Dims &shape, const Dims &start, const Dims &count, + const size_t steps, const adios2::Params &engineParams, + const std::string &name) +{ + size_t datasize = std::accumulate(count.begin(), count.end(), 1, + std::multiplies()); + adios2::ADIOS adios(mpiComm, adios2::DebugON); + adios2::IO dataManIO = adios.DeclareIO("WAN"); + dataManIO.SetEngine("sst"); + dataManIO.SetParameters(engineParams); + std::vector myChars(datasize); + std::vector myUChars(datasize); + std::vector myShorts(datasize); + std::vector myUShorts(datasize); + std::vector myInts(datasize); + std::vector myUInts(datasize); + std::vector myFloats(datasize); + std::vector myDoubles(datasize); + std::vector> myComplexes(datasize); + std::vector> myDComplexes(datasize); + auto bpChars = + dataManIO.DefineVariable("bpChars", shape, start, count); + auto bpUChars = dataManIO.DefineVariable("bpUChars", shape, + start, count); + auto bpShorts = + dataManIO.DefineVariable("bpShorts", shape, start, count); + auto bpUShorts = dataManIO.DefineVariable( + "bpUShorts", shape, start, count); + auto bpInts = dataManIO.DefineVariable("bpInts", shape, start, count); + auto bpUInts = + dataManIO.DefineVariable("bpUInts", shape, start, count); + auto bpFloats = + dataManIO.DefineVariable("bpFloats", shape, start, count); + auto bpDoubles = + dataManIO.DefineVariable("bpDoubles", shape, start, count); + auto bpComplexes = dataManIO.DefineVariable>( + "bpComplexes", shape, start, count); + auto bpDComplexes = dataManIO.DefineVariable>( + "bpDComplexes", shape, start, count); + + adios2::Operator ZfpOp = adios.DefineOperator("zfpCompressor", "zfp"); + bpFloats.AddOperation(ZfpOp, {{"rate", "20"}}); + + dataManIO.DefineAttribute("AttInt", 110); + adios2::Engine dataManWriter = dataManIO.Open(name, adios2::Mode::Write); + for (int i = 0; i < steps; ++i) + { + dataManWriter.BeginStep(); + GenData(myChars, i, start, count, shape); + GenData(myUChars, i, start, count, shape); + GenData(myShorts, i, start, count, shape); + GenData(myUShorts, i, start, count, shape); + GenData(myInts, i, start, count, shape); + GenData(myUInts, i, start, count, shape); + GenData(myFloats, i, start, count, shape); + GenData(myDoubles, i, start, count, shape); + GenData(myComplexes, i, start, count, shape); + GenData(myDComplexes, i, start, count, shape); + dataManWriter.Put(bpChars, myChars.data(), adios2::Mode::Sync); + dataManWriter.Put(bpUChars, myUChars.data(), adios2::Mode::Sync); + dataManWriter.Put(bpShorts, myShorts.data(), adios2::Mode::Sync); + dataManWriter.Put(bpUShorts, myUShorts.data(), adios2::Mode::Sync); + dataManWriter.Put(bpInts, myInts.data(), adios2::Mode::Sync); + dataManWriter.Put(bpUInts, myUInts.data(), adios2::Mode::Sync); + dataManWriter.Put(bpFloats, myFloats.data(), adios2::Mode::Sync); + dataManWriter.Put(bpDoubles, myDoubles.data(), adios2::Mode::Sync); + dataManWriter.Put(bpComplexes, myComplexes.data(), adios2::Mode::Sync); + dataManWriter.Put(bpDComplexes, myDComplexes.data(), + adios2::Mode::Sync); + dataManWriter.EndStep(); + } + dataManWriter.Close(); +} + +void Reader(const Dims &shape, const Dims &start, const Dims &count, + const size_t steps, const adios2::Params &engineParams, + const std::string &name) +{ + adios2::ADIOS adios(mpiComm, adios2::DebugON); + adios2::IO dataManIO = adios.DeclareIO("Test"); + dataManIO.SetEngine("sst"); + dataManIO.SetParameters(engineParams); + adios2::Engine dataManReader = dataManIO.Open(name, adios2::Mode::Read); + + size_t datasize = std::accumulate(count.begin(), count.end(), 1, + std::multiplies()); + std::vector myChars(datasize); + std::vector myUChars(datasize); + std::vector myShorts(datasize); + std::vector myUShorts(datasize); + std::vector myInts(datasize); + std::vector myUInts(datasize); + std::vector myFloats(datasize); + std::vector myDoubles(datasize); + std::vector> myComplexes(datasize); + std::vector> myDComplexes(datasize); + + bool received_steps = false; + size_t i; + for (i = 0; i < steps; ++i) + { + + adios2::StepStatus status = + dataManReader.BeginStep(StepMode::NextAvailable, 5); + + if (status == adios2::StepStatus::OK) + { + received_steps = true; + const auto &vars = dataManIO.AvailableVariables(); + if (print_lines == 0) + { + std::cout << "All available variables : "; + for (const auto &var : vars) + { + std::cout << var.first << ", "; + } + std::cout << std::endl; + } + ASSERT_EQ(vars.size(), 10); + size_t currentStep = dataManReader.CurrentStep(); + // ASSERT_EQ(i, currentStep); + adios2::Variable bpChars = + dataManIO.InquireVariable("bpChars"); + adios2::Variable bpUChars = + dataManIO.InquireVariable("bpUChars"); + adios2::Variable bpShorts = + dataManIO.InquireVariable("bpShorts"); + adios2::Variable bpUShorts = + dataManIO.InquireVariable("bpUShorts"); + adios2::Variable bpInts = + dataManIO.InquireVariable("bpInts"); + adios2::Variable bpUInts = + dataManIO.InquireVariable("bpUInts"); + adios2::Variable bpFloats = + dataManIO.InquireVariable("bpFloats"); + adios2::Variable bpDoubles = + dataManIO.InquireVariable("bpDoubles"); + adios2::Variable> bpComplexes = + dataManIO.InquireVariable>("bpComplexes"); + adios2::Variable> bpDComplexes = + dataManIO.InquireVariable>("bpDComplexes"); + auto charsBlocksInfo = dataManReader.AllStepsBlocksInfo(bpChars); + + bpChars.SetSelection({start, count}); + bpUChars.SetSelection({start, count}); + bpShorts.SetSelection({start, count}); + bpUShorts.SetSelection({start, count}); + bpInts.SetSelection({start, count}); + bpUInts.SetSelection({start, count}); + bpFloats.SetSelection({start, count}); + bpDoubles.SetSelection({start, count}); + bpComplexes.SetSelection({start, count}); + bpDComplexes.SetSelection({start, count}); + + dataManReader.Get(bpChars, myChars.data(), adios2::Mode::Sync); + dataManReader.Get(bpUChars, myUChars.data(), adios2::Mode::Sync); + dataManReader.Get(bpShorts, myShorts.data(), adios2::Mode::Sync); + dataManReader.Get(bpUShorts, myUShorts.data(), adios2::Mode::Sync); + dataManReader.Get(bpInts, myInts.data(), adios2::Mode::Sync); + dataManReader.Get(bpUInts, myUInts.data(), adios2::Mode::Sync); + dataManReader.Get(bpFloats, myFloats.data(), adios2::Mode::Sync); + dataManReader.Get(bpDoubles, myDoubles.data(), adios2::Mode::Sync); + dataManReader.Get(bpComplexes, myComplexes.data(), + adios2::Mode::Sync); + dataManReader.Get(bpDComplexes, myDComplexes.data(), + adios2::Mode::Sync); + VerifyData(myChars.data(), currentStep, start, count, shape); + VerifyData(myUChars.data(), currentStep, start, count, shape); + VerifyData(myShorts.data(), currentStep, start, count, shape); + VerifyData(myUShorts.data(), currentStep, start, count, shape); + VerifyData(myInts.data(), currentStep, start, count, shape); + VerifyData(myUInts.data(), currentStep, start, count, shape); + VerifyData(myFloats.data(), currentStep, start, count, shape); + VerifyData(myDoubles.data(), currentStep, start, count, shape); + VerifyData(myComplexes.data(), currentStep, start, count, shape); + VerifyData(myDComplexes.data(), currentStep, start, count, shape); + dataManReader.EndStep(); + } + else if (status == adios2::StepStatus::EndOfStream) + { + std::cout << "[Rank " + std::to_string(mpiRank) + + "] SstTest reader end of stream!" + << std::endl; + break; + } + } + if (received_steps) + { + auto attInt = dataManIO.InquireAttribute("AttInt"); + std::cout << "[Rank " + std::to_string(mpiRank) + + "] Attribute received " + << attInt.Data()[0] << ", expected 110" << std::endl; + ASSERT_EQ(110, attInt.Data()[0]); + ASSERT_NE(111, attInt.Data()[0]); + } + dataManReader.Close(); + print_lines = 0; +} + +TEST_F(SstEngineTest, SstBpCompressionLarge) +{ + int worldRank, worldSize; + MPI_Comm_rank(MPI_COMM_WORLD, &worldRank); + MPI_Comm_size(MPI_COMM_WORLD, &worldSize); + int mpiGroup = worldRank / (worldSize / 2); + MPI_Comm_split(MPI_COMM_WORLD, mpiGroup, worldRank, &mpiComm); + + MPI_Comm_rank(mpiComm, &mpiRank); + MPI_Comm_size(mpiComm, &mpiSize); + + Dims shape = {100000, (size_t)mpiSize * 2}; + Dims start = {0, (size_t)mpiRank * 2}; + Dims count = {100000, 2}; + + std::string filename = "SstBpCompression"; + + if (mpiGroup == 0) + { + Writer(shape, start, count, 10, Params(), filename); + } + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + if (mpiGroup == 1) + { + Reader(shape, start, count, 10, Params(), filename); + } + + MPI_Barrier(MPI_COMM_WORLD); +} + +int main(int argc, char **argv) +{ + MPI_Init(&argc, &argv); + int worldRank, worldSize; + MPI_Comm_rank(MPI_COMM_WORLD, &worldRank); + MPI_Comm_size(MPI_COMM_WORLD, &worldSize); + ::testing::InitGoogleTest(&argc, argv); + int result = RUN_ALL_TESTS(); + + MPI_Finalize(); + return result; +}