Skip to content

Commit 31c4187

Browse files
committed
Proper testing
1 parent 9624ac2 commit 31c4187

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
@@ -1766,4 +1766,161 @@ TEST_CASE("unavailable_backend", "[core][parallel]")
17661766
}
17671767
#endif
17681768
}
1769+
1770+
void joined_dim(std::string const &ext)
1771+
{
1772+
using type = float;
1773+
using patchType = uint64_t;
1774+
constexpr size_t patches_per_rank = 5;
1775+
constexpr size_t length_of_patch = 10;
1776+
1777+
int size{-1};
1778+
int rank{-1};
1779+
MPI_Comm_size(MPI_COMM_WORLD, &size);
1780+
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1781+
1782+
{
1783+
Series s(
1784+
"../samples/joinedDimParallel." + ext,
1785+
Access::CREATE,
1786+
MPI_COMM_WORLD);
1787+
std::vector<UniquePtrWithLambda<type>> writeFrom(patches_per_rank);
1788+
1789+
auto it = s.writeIterations()[100];
1790+
1791+
Dataset numParticlesDS(determineDatatype<patchType>(), {1});
1792+
numParticlesDS.joinedDimension = 0;
1793+
auto numParticles =
1794+
it.particles["e"]
1795+
.particlePatches["numParticles"][RecordComponent::SCALAR];
1796+
auto numParticlesOffset =
1797+
it.particles["e"]
1798+
.particlePatches["numParticlesOffset"][RecordComponent::SCALAR];
1799+
numParticles.resetDataset(numParticlesDS);
1800+
numParticlesOffset.resetDataset(numParticlesDS);
1801+
1802+
auto patchOffset = it.particles["e"].particlePatches["offset"]["x"];
1803+
auto patchExtent = it.particles["e"].particlePatches["extent"]["x"];
1804+
Dataset particlePatchesDS(determineDatatype<float>(), {1});
1805+
particlePatchesDS.joinedDimension = 0;
1806+
patchOffset.resetDataset(particlePatchesDS);
1807+
patchExtent.resetDataset(particlePatchesDS);
1808+
1809+
float start_value = rank * patches_per_rank * length_of_patch;
1810+
for (size_t i = 0; i < 5; ++i)
1811+
{
1812+
writeFrom[i] = UniquePtrWithLambda<type>(
1813+
new type[length_of_patch],
1814+
[](auto const *ptr) { delete[] ptr; });
1815+
std::iota(
1816+
writeFrom[i].get(),
1817+
writeFrom[i].get() + 10,
1818+
start_value + length_of_patch * i);
1819+
patchOffset.store<type>(start_value + length_of_patch * i);
1820+
}
1821+
1822+
auto epx = it.particles["e"]["position"]["x"];
1823+
Dataset ds(determineDatatype<type>(), {1});
1824+
ds.joinedDimension = 0;
1825+
epx.resetDataset(ds);
1826+
1827+
size_t counter = 0;
1828+
for (auto &chunk : writeFrom)
1829+
{
1830+
epx.storeChunk(std::move(chunk), {}, {length_of_patch});
1831+
numParticles.store<patchType>(length_of_patch);
1832+
/*
1833+
* For the sake of the test case, we know that the
1834+
* numParticlesOffset has this value. In general, the purpose of the
1835+
* joined array is that we don't need to know these values, so the
1836+
* specification of particle patches is somewhat difficult.
1837+
*/
1838+
numParticlesOffset.store<patchType>(
1839+
start_value + counter++ * length_of_patch);
1840+
patchExtent.store<type>(10);
1841+
}
1842+
writeFrom.clear();
1843+
it.close();
1844+
s.close();
1845+
}
1846+
1847+
{
1848+
Series s(
1849+
"../samples/joinedDimParallel." + ext,
1850+
Access::READ_ONLY,
1851+
MPI_COMM_WORLD);
1852+
auto it = s.iterations[100];
1853+
auto e = it.particles["e"];
1854+
1855+
auto particleData = e["position"]["x"].loadChunk<type>();
1856+
auto numParticles =
1857+
e.particlePatches["numParticles"][RecordComponent::SCALAR]
1858+
.load<patchType>();
1859+
auto numParticlesOffset =
1860+
e.particlePatches["numParticlesOffset"][RecordComponent::SCALAR]
1861+
.load<patchType>();
1862+
auto patchOffset = e.particlePatches["offset"]["x"].load<type>();
1863+
auto patchExtent = e.particlePatches["extent"]["x"].load<type>();
1864+
1865+
it.close();
1866+
1867+
// check validity of particle patches
1868+
auto numPatches =
1869+
e.particlePatches["numParticlesOffset"][RecordComponent::SCALAR]
1870+
.getExtent()[0];
1871+
REQUIRE(
1872+
e.particlePatches["numParticles"][RecordComponent::SCALAR]
1873+
.getExtent()[0] == numPatches);
1874+
for (size_t i = 0; i < numPatches; ++i)
1875+
{
1876+
for (size_t j = 0; j < numParticles.get()[i]; ++j)
1877+
{
1878+
REQUIRE(
1879+
patchOffset.get()[i] <=
1880+
particleData.get()[numParticlesOffset.get()[i] + j]);
1881+
REQUIRE(
1882+
particleData.get()[numParticlesOffset.get()[i] + j] <
1883+
patchOffset.get()[i] + patchExtent.get()[i]);
1884+
}
1885+
}
1886+
1887+
/*
1888+
* Check that joined array joins early writes before later writes from
1889+
* the same rank
1890+
*/
1891+
for (size_t i = 0; i < size * length_of_patch * patches_per_rank; ++i)
1892+
{
1893+
REQUIRE(float(i) == particleData.get()[i]);
1894+
}
1895+
for (size_t i = 0; i < size * patches_per_rank; ++i)
1896+
{
1897+
REQUIRE(length_of_patch * i == numParticlesOffset.get()[i]);
1898+
REQUIRE(type(length_of_patch * i) == patchOffset.get()[i]);
1899+
}
1900+
}
1901+
}
1902+
1903+
TEST_CASE("joined_dim", "[serial]")
1904+
{
1905+
#if 100000000 * ADIOS2_VERSION_MAJOR + 1000000 * ADIOS2_VERSION_MINOR + \
1906+
10000 * ADIOS2_VERSION_PATCH + 100 * ADIOS2_VERSION_TWEAK >= \
1907+
209000000
1908+
constexpr char const *supportsJoinedDims[] = {"bp", "bp4", "bp5"};
1909+
#else
1910+
// no zero-size arrays
1911+
std::vector<char const *> supportsJoinedDims;
1912+
#endif
1913+
for (auto const &t : testedFileExtensions())
1914+
{
1915+
for (auto const supported : supportsJoinedDims)
1916+
{
1917+
if (t == supported)
1918+
{
1919+
joined_dim(t);
1920+
break;
1921+
}
1922+
}
1923+
}
1924+
}
1925+
17691926
#endif // openPMD_HAVE_ADIOS2 && openPMD_HAVE_MPI

test/SerialIOTest.cpp

Lines changed: 112 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7219,28 +7219,123 @@ TEST_CASE("groupbased_read_write", "[serial]")
72197219
void joined_dim(std::string const &ext)
72207220
{
72217221
using type = float;
7222-
Series s("../samples/joinedDim." + ext, Access::CREATE);
7223-
std::vector<UniquePtrWithLambda<type>> writeFrom(5);
7224-
for (size_t i = 0; i < 5; ++i)
7222+
using patchType = uint64_t;
7223+
constexpr size_t patches_per_rank = 5;
7224+
constexpr size_t length_of_patch = 10;
7225+
72257226
{
7226-
writeFrom[i] = UniquePtrWithLambda<type>(
7227-
new type[10], [](auto const *ptr) { delete[] ptr; });
7228-
std::iota(writeFrom[i].get(), writeFrom[i].get() + 10, 10 * i);
7229-
}
7227+
Series s("../samples/joinedDimParallel." + ext, Access::CREATE);
7228+
std::vector<UniquePtrWithLambda<type>> writeFrom(patches_per_rank);
72307229

7231-
auto it = s.writeIterations()[100];
7232-
auto epx = it.particles["e"]["position"]["x"];
7233-
Dataset ds(determineDatatype<type>(), {1});
7234-
ds.joinedDimension = 0;
7235-
epx.resetDataset(ds);
7230+
auto it = s.writeIterations()[100];
7231+
7232+
Dataset numParticlesDS(determineDatatype<patchType>(), {1});
7233+
numParticlesDS.joinedDimension = 0;
7234+
auto numParticles =
7235+
it.particles["e"]
7236+
.particlePatches["numParticles"][RecordComponent::SCALAR];
7237+
auto numParticlesOffset =
7238+
it.particles["e"]
7239+
.particlePatches["numParticlesOffset"][RecordComponent::SCALAR];
7240+
numParticles.resetDataset(numParticlesDS);
7241+
numParticlesOffset.resetDataset(numParticlesDS);
7242+
7243+
auto patchOffset = it.particles["e"].particlePatches["offset"]["x"];
7244+
auto patchExtent = it.particles["e"].particlePatches["extent"]["x"];
7245+
Dataset particlePatchesDS(determineDatatype<float>(), {1});
7246+
particlePatchesDS.joinedDimension = 0;
7247+
patchOffset.resetDataset(particlePatchesDS);
7248+
patchExtent.resetDataset(particlePatchesDS);
7249+
7250+
for (size_t i = 0; i < 5; ++i)
7251+
{
7252+
writeFrom[i] = UniquePtrWithLambda<type>(
7253+
new type[length_of_patch],
7254+
[](auto const *ptr) { delete[] ptr; });
7255+
std::iota(
7256+
writeFrom[i].get(),
7257+
writeFrom[i].get() + 10,
7258+
length_of_patch * i);
7259+
patchOffset.store<type>(length_of_patch * i);
7260+
}
7261+
7262+
auto epx = it.particles["e"]["position"]["x"];
7263+
Dataset ds(determineDatatype<type>(), {1});
7264+
ds.joinedDimension = 0;
7265+
epx.resetDataset(ds);
7266+
7267+
size_t counter = 0;
7268+
for (auto &chunk : writeFrom)
7269+
{
7270+
epx.storeChunk(std::move(chunk), {}, {length_of_patch});
7271+
numParticles.store<patchType>(length_of_patch);
7272+
/*
7273+
* For the sake of the test case, we know that the
7274+
* numParticlesOffset has this value. In general, the purpose of the
7275+
* joined array is that we don't need to know these values, so the
7276+
* specification of particle patches is somewhat difficult.
7277+
*/
7278+
numParticlesOffset.store<patchType>(counter++ * length_of_patch);
7279+
patchExtent.store<type>(10);
7280+
}
7281+
writeFrom.clear();
7282+
it.close();
7283+
s.close();
7284+
}
72367285

7237-
for (auto &chunk : writeFrom)
72387286
{
7239-
epx.storeChunk(std::move(chunk), {}, {10});
7287+
Series s("../samples/joinedDimParallel." + ext, Access::READ_ONLY);
7288+
auto it = s.iterations[100];
7289+
auto e = it.particles["e"];
7290+
7291+
auto particleData = e["position"]["x"].loadChunk<type>();
7292+
auto numParticles =
7293+
e.particlePatches["numParticles"][RecordComponent::SCALAR]
7294+
.load<patchType>();
7295+
auto numParticlesOffset =
7296+
e.particlePatches["numParticlesOffset"][RecordComponent::SCALAR]
7297+
.load<patchType>();
7298+
auto patchOffset = e.particlePatches["offset"]["x"].load<type>();
7299+
auto patchExtent = e.particlePatches["extent"]["x"].load<type>();
7300+
7301+
it.close();
7302+
7303+
// check validity of particle patches
7304+
auto numPatches =
7305+
e.particlePatches["numParticlesOffset"][RecordComponent::SCALAR]
7306+
.getExtent()[0];
7307+
REQUIRE(
7308+
e.particlePatches["numParticles"][RecordComponent::SCALAR]
7309+
.getExtent()[0] == numPatches);
7310+
for (size_t i = 0; i < numPatches; ++i)
7311+
{
7312+
for (size_t j = 0; j < numParticles.get()[i]; ++j)
7313+
{
7314+
REQUIRE(
7315+
patchOffset.get()[i] <=
7316+
particleData.get()[numParticlesOffset.get()[i] + j]);
7317+
REQUIRE(
7318+
particleData.get()[numParticlesOffset.get()[i] + j] <
7319+
patchOffset.get()[i] + patchExtent.get()[i]);
7320+
}
7321+
}
7322+
7323+
/*
7324+
* Check that:
7325+
* 1. Joined array joins writes from lower ranks before higher ranks
7326+
* 2. Joined array joins early writes before later writes from the same
7327+
* rank
7328+
*/
7329+
for (size_t i = 0; i < length_of_patch * patches_per_rank; ++i)
7330+
{
7331+
REQUIRE(float(i) == particleData.get()[i]);
7332+
}
7333+
for (size_t i = 0; i < patches_per_rank; ++i)
7334+
{
7335+
REQUIRE(length_of_patch * i == numParticlesOffset.get()[i]);
7336+
REQUIRE(type(length_of_patch * i) == patchOffset.get()[i]);
7337+
}
72407338
}
7241-
writeFrom.clear();
7242-
it.close();
7243-
s.close();
72447339
}
72457340

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

0 commit comments

Comments
 (0)