I am trying to find a way to efficiently (with a minimum of copies) transfer externally allocated columns of data (mostly build-in types, integers or floats) into a TTree, and eventually a file. Multiples columns are stored in pinned memory and properly aligned and co-located, for consumption by a GPU. And of course, we need the operations in the opposite direction too.
I was thinking of something conceptually like using a user-allocated fBuffer for the TBasket behind each TBranch, and then let root compress and write the data via the fZipBuffer and write to the file, but did not find the way/interface to do this.
Is this the proper way to attack this problem?
Thanks a lot,
I think we need @pcanal here!
Because in TTree, the buffer is always stored in (compressed) big-endian format, you are likely to need a copy/transformation before getting to the file. RNtuple has a mode where the endianness can match the in-memory format (@jblomer @jalopezg might help) and might be better suited for this task.
Sorry, I skipped over this. Yes, RNTuple offers zero-copy access to the values stored in a column through an
This works for fields that can be directly mapped, i.e., if the endianness matches and the type does not require specific packing requirements (which is the case for fundamental types in little-endian architectures, e.g. x86).
As an example, one can do the following for a field of type
auto ntuple = RNTupleReader::Open("ntuple", "/path/to/file.ntuple");
auto view = ntuple->GetView<float>("field_name");
NTupleSize_t nItems = 0;
const float *buf = view.MapV(0, nItems);
// `nItems` should contain the number of elements in the mapped page. Values may
// be accessed via `buf[i]`.
for (unsigned i = 0; i < nItems; i++)
std::cout << buf[i] << std::endl;