miniCBF: read the sweep's rotation angles on several threads

Opening a sweep parses the header of every file to get its start angle, and one
header is two dozen std::regex searches: measured at 0.33 ms on a 16 Mpx sweep
and 1.0 ms on one with a longer header, so a 7200-frame sweep spent 7.2 s on one
thread before it read an image. The files are independent, so the scan is shared
out over up to eight of them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
leonarski_fandClaude Opus 5 committed 2026-09-09 20:14:04 +02:00
1 parent ffbdaa71e4
commit 10435ef588
1 file changed
+16 -3
+16 -3
View File
@@ -8,8 +8,10 @@
#include <cstring>
#include <filesystem>
#include <array>
#include <future>
#include <map>
#include <optional>
#include <thread>
#include "../common/JFJochException.h"
#include "../common/Logger.h"
@@ -258,10 +260,21 @@ void JFJochCBFReader::ReadFiles(const std::string &path) {
std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::duration<double>(header0_.exposure_s)));
// The rotation angle of every image, from its own header.
// The rotation angle of every image, from its own header. Parsing one costs a few hundred
// microseconds - it is two dozen regular expressions - so on a sweep of several thousand frames
// this is seconds of startup before a single image is read, and the files are independent.
std::vector<double> angles(files_.size());
for (size_t i = 0; i < files_.size(); i++)
angles[i] = minicbf::ReadHeader(files_[i]).start_angle_deg;
{
const size_t nthreads = std::min<size_t>(std::max(1u, std::thread::hardware_concurrency()), 8);
std::vector<std::future<void>> futures;
for (size_t t = 0; t < nthreads; t++)
futures.push_back(std::async(std::launch::async, [&, t] {
for (size_t i = t; i < files_.size(); i += nthreads)
angles[i] = minicbf::ReadHeader(files_[i]).start_angle_deg;
}));
for (auto &f : futures)
f.get();
}
double increment = header0_.angle_increment_deg;
if (files_.size() > 1) {