preprocessing: page-lock the reader's bytes for an uncompressed image

PinInputBuffer() page-locks the buffer an image is decompressed into, which an
uncompressed image never uses: it is read straight out of the reader's own
buffer, so the upload came from pageable memory. Measured on this card, 72.6 MB
crosses at 5.6 GB/s pageable and 14.6 GB/s registered - 12.9 ms against 5.0 ms,
on every image of a sweep that stores its frames uncompressed.

PinInputRegion() page-locks a region the caller owns and remembers it, so a
worker that reads every frame into the same buffer registers it once. The
registration is dropped with the engine, so the three workers that build one
declare their raw image before it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-09 20:14:04 +02:00
co-authored by Claude Opus 5
parent 391736425f
commit ffbdaa71e4
5 changed files with 46 additions and 5 deletions
@@ -26,6 +26,9 @@ class ImagePreprocessorGPU : public ImagePreprocessor {
std::vector<ImageStatistics> cpu_stats;
CudaRegisteredVector<ImageStatistics> cpu_stats_reg;
CudaRegisteredVector<uint8_t> input_reg; // page-locks the caller's decompression buffer
// The uncompressed-image counterpart of input_reg: the region PinInputRegion last page-locked.
const void *pinned_input = nullptr;
size_t pinned_input_bytes = 0;
std::vector<int32_t> cpu_image;
@@ -46,10 +49,12 @@ public:
// per pixel it is the single largest transfer in the pipeline, so the caller says whether it wants it.
ImagePreprocessorGPU(const DiffractionExperiment &experiment, const PixelMask &mask, std::shared_ptr<CudaStream> stream,
bool copy_image_to_host = true);
~ImagePreprocessorGPU() override;
ImageStatistics Analyze(ImagePreprocessorBuffer &processed_image, const uint8_t *decompressed_image, CompressedImageMode image_mode) override;
bool AnalyzeCompressed(ImagePreprocessorBuffer &processed_image, const CompressedImage &image,
ImageStatistics &stats) override;
[[nodiscard]] float GetLastDecompressionTime_s() const override;
void PinInputBuffer(std::vector<uint8_t> &buffer, size_t size) override;
void PinInputRegion(const void *ptr, size_t bytes) override;
};