Skip to content

Commit 9ace516

Browse files
committed
Proper testing
1 parent 67a28cb commit 9ace516

File tree

2 files changed

+269
-17
lines changed

2 files changed

+269
-17
lines changed

test/ParallelIOTest.cpp

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,4 +1865,161 @@ TEST_CASE("unavailable_backend", "[core][parallel]")
18651865
}
18661866
#endif
18671867
}
1868+
1869+
void joined_dim(std::string const &ext)
1870+
{
1871+
using type = float;
1872+
using patchType = uint64_t;
1873+
constexpr size_t patches_per_rank = 5;
1874+
constexpr size_t length_of_patch = 10;
1875+
1876+
int size{-1};
1877+
int rank{-1};
1878+
MPI_Comm_size(MPI_COMM_WORLD, &size);
1879+
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1880+
1881+
{
1882+
Series s(
1883+
"../samples/joinedDimParallel." + ext,
1884+
Access::CREATE,
1885+
MPI_COMM_WORLD);
1886+
std::vector<UniquePtrWithLambda<type>> writeFrom(patches_per_rank);
1887+
1888+
auto it = s.writeIterations()[100];
1889+
1890+
Dataset numParticlesDS(determineDatatype<patchType>(), {1});
1891+
numParticlesDS.joinedDimension = 0;
1892+
auto numParticles =
1893+
it.particles["e"]
1894+
.particlePatches["numParticles"][RecordComponent::SCALAR];
1895+
auto numParticlesOffset =
1896+
it.particles["e"]
1897+
.particlePatches["numParticlesOffset"][RecordComponent::SCALAR];
1898+
numParticles.resetDataset(numParticlesDS);
1899+
numParticlesOffset.resetDataset(numParticlesDS);
1900+
1901+
auto patchOffset = it.particles["e"].particlePatches["offset"]["x"];
1902+
auto patchExtent = it.particles["e"].particlePatches["extent"]["x"];
1903+
Dataset particlePatchesDS(determineDatatype<float>(), {1});
1904+
particlePatchesDS.joinedDimension = 0;
1905+
patchOffset.resetDataset(particlePatchesDS);
1906+
patchExtent.resetDataset(particlePatchesDS);
1907+
1908+
float start_value = rank * patches_per_rank * length_of_patch;
1909+
for (size_t i = 0; i < 5; ++i)
1910+
{
1911+
writeFrom[i] = UniquePtrWithLambda<type>(
1912+
new type[length_of_patch],
1913+
[](auto const *ptr) { delete[] ptr; });
1914+
std::iota(
1915+
writeFrom[i].get(),
1916+
writeFrom[i].get() + 10,
1917+
start_value + length_of_patch * i);
1918+
patchOffset.store<type>(start_value + length_of_patch * i);
1919+
}
1920+
1921+
auto epx = it.particles["e"]["position"]["x"];
1922+
Dataset ds(determineDatatype<type>(), {1});
1923+
ds.joinedDimension = 0;
1924+
epx.resetDataset(ds);
1925+
1926+
size_t counter = 0;
1927+
for (auto &chunk : writeFrom)
1928+
{
1929+
epx.storeChunk(std::move(chunk), {}, {length_of_patch});
1930+
numParticles.store<patchType>(length_of_patch);
1931+
/*
1932+
* For the sake of the test case, we know that the
1933+
* numParticlesOffset has this value. In general, the purpose of the
1934+
* joined array is that we don't need to know these values, so the
1935+
* specification of particle patches is somewhat difficult.
1936+
*/
1937+
numParticlesOffset.store<patchType>(
1938+
start_value + counter++ * length_of_patch);
1939+
patchExtent.store<type>(10);
1940+
}
1941+
writeFrom.clear();
1942+
it.close();
1943+
s.close();
1944+
}
1945+
1946+
{
1947+
Series s(
1948+
"../samples/joinedDimParallel." + ext,
1949+
Access::READ_ONLY,
1950+
MPI_COMM_WORLD);
1951+
auto it = s.iterations[100];
1952+
auto e = it.particles["e"];
1953+
1954+
auto particleData = e["position"]["x"].loadChunk<type>();
1955+
auto numParticles =
1956+
e.particlePatches["numParticles"][RecordComponent::SCALAR]
1957+
.load<patchType>();
1958+
auto numParticlesOffset =
1959+
e.particlePatches["numParticlesOffset"][RecordComponent::SCALAR]
1960+
.load<patchType>();
1961+
auto patchOffset = e.particlePatches["offset"]["x"].load<type>();
1962+
auto patchExtent = e.particlePatches["extent"]["x"].load<type>();
1963+
1964+
it.close();
1965+
1966+
// check validity of particle patches
1967+
auto numPatches =
1968+
e.particlePatches["numParticlesOffset"][RecordComponent::SCALAR]
1969+
.getExtent()[0];
1970+
REQUIRE(
1971+
e.particlePatches["numParticles"][RecordComponent::SCALAR]
1972+
.getExtent()[0] == numPatches);
1973+
for (size_t i = 0; i < numPatches; ++i)
1974+
{
1975+
for (size_t j = 0; j < numParticles.get()[i]; ++j)
1976+
{
1977+
REQUIRE(
1978+
patchOffset.get()[i] <=
1979+
particleData.get()[numParticlesOffset.get()[i] + j]);
1980+
REQUIRE(
1981+
particleData.get()[numParticlesOffset.get()[i] + j] <
1982+
patchOffset.get()[i] + patchExtent.get()[i]);
1983+
}
1984+
}
1985+
1986+
/*
1987+
* Check that joined array joins early writes before later writes from
1988+
* the same rank
1989+
*/
1990+
for (size_t i = 0; i < size * length_of_patch * patches_per_rank; ++i)
1991+
{
1992+
REQUIRE(float(i) == particleData.get()[i]);
1993+
}
1994+
for (size_t i = 0; i < size * patches_per_rank; ++i)
1995+
{
1996+
REQUIRE(length_of_patch * i == numParticlesOffset.get()[i]);
1997+
REQUIRE(type(length_of_patch * i) == patchOffset.get()[i]);
1998+
}
1999+
}
2000+
}
2001+
2002+
TEST_CASE("joined_dim", "[serial]")
2003+
{
2004+
#if 100000000 * ADIOS2_VERSION_MAJOR + 1000000 * ADIOS2_VERSION_MINOR + \
2005+
10000 * ADIOS2_VERSION_PATCH + 100 * ADIOS2_VERSION_TWEAK >= \
2006+
209000000
2007+
constexpr char const *supportsJoinedDims[] = {"bp", "bp4", "bp5"};
2008+
#else
2009+
// no zero-size arrays
2010+
std::vector<char const *> supportsJoinedDims;
2011+
#endif
2012+
for (auto const &t : testedFileExtensions())
2013+
{
2014+
for (auto const supported : supportsJoinedDims)
2015+
{
2016+
if (t == supported)
2017+
{
2018+
joined_dim(t);
2019+
break;
2020+
}
2021+
}
2022+
}
2023+
}
2024+
18682025
#endif // openPMD_HAVE_ADIOS2 && openPMD_HAVE_MPI

test/SerialIOTest.cpp

Lines changed: 112 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7258,28 +7258,123 @@ TEST_CASE("groupbased_read_write", "[serial]")
72587258
void joined_dim(std::string const &ext)
72597259
{
72607260
using type = float;
7261-
Series s("../samples/joinedDim." + ext, Access::CREATE);
7262-
std::vector<UniquePtrWithLambda<type>> writeFrom(5);
7263-
for (size_t i = 0; i < 5; ++i)
7261+
using patchType = uint64_t;
7262+
constexpr size_t patches_per_rank = 5;
7263+
constexpr size_t length_of_patch = 10;
7264+
72647265
{
7265-
writeFrom[i] = UniquePtrWithLambda<type>(
7266-
new type[10], [](auto const *ptr) { delete[] ptr; });
7267-
std::iota(writeFrom[i].get(), writeFrom[i].get() + 10, 10 * i);
7268-
}
7266+
Series s("../samples/joinedDimParallel." + ext, Access::CREATE);
7267+
std::vector<UniquePtrWithLambda<type>> writeFrom(patches_per_rank);
72697268

7270-
auto it = s.writeIterations()[100];
7271-
auto epx = it.particles["e"]["position"]["x"];
7272-
Dataset ds(determineDatatype<type>(), {1});
7273-
ds.joinedDimension = 0;
7274-
epx.resetDataset(ds);
7269+
auto it = s.writeIterations()[100];
7270+
7271+
Dataset numParticlesDS(determineDatatype<patchType>(), {1});
7272+
numParticlesDS.joinedDimension = 0;
7273+
auto numParticles =
7274+
it.particles["e"]
7275+
.particlePatches["numParticles"][RecordComponent::SCALAR];
7276+
auto numParticlesOffset =
7277+
it.particles["e"]
7278+
.particlePatches["numParticlesOffset"][RecordComponent::SCALAR];
7279+
numParticles.resetDataset(numParticlesDS);
7280+
numParticlesOffset.resetDataset(numParticlesDS);
7281+
7282+
auto patchOffset = it.particles["e"].particlePatches["offset"]["x"];
7283+
auto patchExtent = it.particles["e"].particlePatches["extent"]["x"];
7284+
Dataset particlePatchesDS(determineDatatype<float>(), {1});
7285+
particlePatchesDS.joinedDimension = 0;
7286+
patchOffset.resetDataset(particlePatchesDS);
7287+
patchExtent.resetDataset(particlePatchesDS);
7288+
7289+
for (size_t i = 0; i < 5; ++i)
7290+
{
7291+
writeFrom[i] = UniquePtrWithLambda<type>(
7292+
new type[length_of_patch],
7293+
[](auto const *ptr) { delete[] ptr; });
7294+
std::iota(
7295+
writeFrom[i].get(),
7296+
writeFrom[i].get() + 10,
7297+
length_of_patch * i);
7298+
patchOffset.store<type>(length_of_patch * i);
7299+
}
7300+
7301+
auto epx = it.particles["e"]["position"]["x"];
7302+
Dataset ds(determineDatatype<type>(), {1});
7303+
ds.joinedDimension = 0;
7304+
epx.resetDataset(ds);
7305+
7306+
size_t counter = 0;
7307+
for (auto &chunk : writeFrom)
7308+
{
7309+
epx.storeChunk(std::move(chunk), {}, {length_of_patch});
7310+
numParticles.store<patchType>(length_of_patch);
7311+
/*
7312+
* For the sake of the test case, we know that the
7313+
* numParticlesOffset has this value. In general, the purpose of the
7314+
* joined array is that we don't need to know these values, so the
7315+
* specification of particle patches is somewhat difficult.
7316+
*/
7317+
numParticlesOffset.store<patchType>(counter++ * length_of_patch);
7318+
patchExtent.store<type>(10);
7319+
}
7320+
writeFrom.clear();
7321+
it.close();
7322+
s.close();
7323+
}
72757324

7276-
for (auto &chunk : writeFrom)
72777325
{
7278-
epx.storeChunk(std::move(chunk), {}, {10});
7326+
Series s("../samples/joinedDimParallel." + ext, Access::READ_ONLY);
7327+
auto it = s.iterations[100];
7328+
auto e = it.particles["e"];
7329+
7330+
auto particleData = e["position"]["x"].loadChunk<type>();
7331+
auto numParticles =
7332+
e.particlePatches["numParticles"][RecordComponent::SCALAR]
7333+
.load<patchType>();
7334+
auto numParticlesOffset =
7335+
e.particlePatches["numParticlesOffset"][RecordComponent::SCALAR]
7336+
.load<patchType>();
7337+
auto patchOffset = e.particlePatches["offset"]["x"].load<type>();
7338+
auto patchExtent = e.particlePatches["extent"]["x"].load<type>();
7339+
7340+
it.close();
7341+
7342+
// check validity of particle patches
7343+
auto numPatches =
7344+
e.particlePatches["numParticlesOffset"][RecordComponent::SCALAR]
7345+
.getExtent()[0];
7346+
REQUIRE(
7347+
e.particlePatches["numParticles"][RecordComponent::SCALAR]
7348+
.getExtent()[0] == numPatches);
7349+
for (size_t i = 0; i < numPatches; ++i)
7350+
{
7351+
for (size_t j = 0; j < numParticles.get()[i]; ++j)
7352+
{
7353+
REQUIRE(
7354+
patchOffset.get()[i] <=
7355+
particleData.get()[numParticlesOffset.get()[i] + j]);
7356+
REQUIRE(
7357+
particleData.get()[numParticlesOffset.get()[i] + j] <
7358+
patchOffset.get()[i] + patchExtent.get()[i]);
7359+
}
7360+
}
7361+
7362+
/*
7363+
* Check that:
7364+
* 1. Joined array joins writes from lower ranks before higher ranks
7365+
* 2. Joined array joins early writes before later writes from the same
7366+
* rank
7367+
*/
7368+
for (size_t i = 0; i < length_of_patch * patches_per_rank; ++i)
7369+
{
7370+
REQUIRE(float(i) == particleData.get()[i]);
7371+
}
7372+
for (size_t i = 0; i < patches_per_rank; ++i)
7373+
{
7374+
REQUIRE(length_of_patch * i == numParticlesOffset.get()[i]);
7375+
REQUIRE(type(length_of_patch * i) == patchOffset.get()[i]);
7376+
}
72797377
}
7280-
writeFrom.clear();
7281-
it.close();
7282-
s.close();
72837378
}
72847379

72857380
TEST_CASE("joined_dim", "[serial]")

0 commit comments

Comments
 (0)