Skip to content

Commit 43b6a6d

Browse files
committed
[ntuple] optimize bulk read for array of PoD
1 parent b0b5e30 commit 43b6a6d

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

tree/ntuple/inc/ROOT/RField/RFieldSequenceContainer.hxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ protected:
7070
std::size_t AppendImpl(const void *from) final;
7171
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
7272
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final;
73+
std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final;
7374

7475
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
7576

tree/ntuple/src/RFieldSequenceContainer.cxx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@ void ROOT::RArrayField::ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to
7575
}
7676
}
7777

78+
std::size_t ROOT::RArrayField::ReadBulkImpl(const RBulkSpec &bulkSpec)
79+
{
80+
if (!fSubfields[0]->IsSimple())
81+
return RFieldBase::ReadBulkImpl(bulkSpec);
82+
83+
GetPrincipalColumnOf(*fSubfields[0])
84+
->ReadV(bulkSpec.fFirstIndex * fArrayLength, bulkSpec.fCount * fArrayLength, bulkSpec.fValues);
85+
return RBulkSpec::kAllSet;
86+
}
87+
7888
void ROOT::RArrayField::ReconcileOnDiskField(const RNTupleDescriptor &desc)
7989
{
8090
static const std::vector<std::string> prefixes = {"std::array<"};

tree/ntuple/test/ntuple_bulk.cxx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,55 @@ TEST(RNTupleBulk, RVec)
208208
}
209209
}
210210

211+
TEST(RNTupleBulk, Array)
212+
{
213+
FileRaii fileGuard("test_ntuple_bulk_array.root");
214+
{
215+
auto model = RNTupleModel::Create();
216+
auto fldArrI = model->MakeField<std::array<int, 2>>("aint");
217+
auto fld2DArrI = model->MakeField<std::array<std::array<int, 2>, 2>>("2daint");
218+
auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
219+
for (int i = 0; i < 3; ++i) {
220+
fldArrI->at(0) = 2 * i;
221+
fldArrI->at(1) = 2 * i + 1;
222+
223+
fld2DArrI->at(0).at(0) = 4 * i;
224+
fld2DArrI->at(0).at(1) = 4 * i + 1;
225+
fld2DArrI->at(1).at(0) = 4 * i + 2;
226+
fld2DArrI->at(1).at(1) = 4 * i + 3;
227+
228+
writer->Fill();
229+
}
230+
}
231+
232+
auto reader = RNTupleReader::Open("ntpl", fileGuard.GetPath());
233+
const auto &model = reader->GetModel();
234+
235+
RFieldBase::RBulkValues bulkI = model.CreateBulk("aint");
236+
RFieldBase::RBulkValues bulk2DI = model.CreateBulk("2daint");
237+
238+
auto mask = std::make_unique<bool[]>(3);
239+
mask[0] = true;
240+
mask[1] = false; // the std::array<simple type, ...> field optimization should ignore the mask
241+
mask[2] = true;
242+
243+
auto iArr = static_cast<std::array<int, 2> *>(bulkI.ReadBulk(RNTupleLocalIndex(0, 0), mask.get(), 3));
244+
auto i2DArr =
245+
static_cast<std::array<std::array<int, 2>, 2> *>(bulk2DI.ReadBulk(RNTupleLocalIndex(0, 0), mask.get(), 3));
246+
247+
for (int i = 0; i < 3; ++i) {
248+
EXPECT_EQ(2 * i, iArr[i][0]);
249+
EXPECT_EQ(2 * i + 1, iArr[i][1]);
250+
251+
if (mask[i]) {
252+
EXPECT_EQ(4 * i, i2DArr[i][0][0]);
253+
EXPECT_EQ(4 * i + 1, i2DArr[i][0][1]);
254+
EXPECT_EQ(4 * i + 2, i2DArr[i][1][0]);
255+
EXPECT_EQ(4 * i + 3, i2DArr[i][1][1]);
256+
}
257+
}
258+
}
259+
211260
TEST(RNTupleBulk, Adopted)
212261
{
213262
FileRaii fileGuard("test_ntuple_bulk_adopted.root");

0 commit comments

Comments
 (0)