Dear ROOT experts,
There are several cases where I need to open a large number of files to check that they are not corrupt and contain a specific object like a tree or histogram (e.g. for job output), or to count the total number of entries in the TTree per file. The final result should be a map/dictionary between the file name and the number of events (negative if corrupt).
This is typically quite a light & fast task, but often the number of files is large, O(100)–O(1000), and sometimes opening remote files on GRID (via XRootD) can be slow. I would like to speed up this task by parallelizing in a simple C++ macro, which in the end is called from python via ROOT.
I naively implemented a macro using TThreadExecutor
, roughly as follows:
auto workItem = [&](const std::string& filename) {
return getNEventsFromFile(filename, treename);
};
std::map<std::string, int> nevtsMap;
std::vector<int> results = pool.Map(workItem,filenames);
for (size_t i = 0; i < filenames.size(); ++i) {
nevtsMap[filenames[i]] = results[i];
}
Attached to this post is a minimal reproducible example. This naive implementation seems to work as expected, however am wondering if I can optimize the threading. For example, one might want to change the number of files per chunk, depending on the number of files, or whether the file are local (fast) or remote (slow).
Could you give some advice on the following points, please?
- The worker items only opens/closes a ROOT file and return a single integer. It does not need to port ROOT objects, so is using
TThreadExecutor
still “okay” for this task, or would it better to use standard C++ tools for multithreading? - How does
TThreadExecutor::Map
decide the number of chunks by default? Is it the number of available cores, or the number of passed arguments? - Is there a good way to control the chunk granularity with
TThreadExecutor
in this use case? I naively tried to useMapReduce
which allows the user to set the number of chunks, but it requires a reduction function while I still need each integer of each filename. - To overcome the last point above, is there a thread-safe method to fill a map with the integers in the worker item or reduction function?
Thanks!
Izaak
Minimal reproducible example:
- getNEventsFromFiles.C (2.6 KB)
- getNEventsFromFiles.py (1.7 KB)
ROOT Version: ROOT 6.30/04
Platform: Built for macosxarm64 on Feb 10 2024, 14:55:51
Compiler: Apple clang version 15.0.0 (clang-1500.1.0.2.5)