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>
61 lines
3.4 KiB
C++
61 lines
3.4 KiB
C++
// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#pragma once
|
|
|
|
#include <memory>
|
|
|
|
#include "ImagePreprocessor.h"
|
|
#include "BSLZ4DecoderGPU.h"
|
|
#include "../indexing/CUDAMemHelpers.h"
|
|
#include "../indexing/CudaSharedTables.h"
|
|
|
|
class ImagePreprocessorGPU : public ImagePreprocessor {
|
|
std::shared_ptr<CudaStream> stream;
|
|
const bool copy_image_to_host;
|
|
int threads;
|
|
int blocks;
|
|
// Geometry-only, so one copy per GPU shared with every other engine on it (CudaSharedTables.h).
|
|
std::shared_ptr<CudaDevicePtr<uint8_t>> gpu_mask;
|
|
// Landing buffer for the HOST-upload path only. The device-decode path un-transposes straight
|
|
// into the preprocessed image, so it never needs this - and at 4 bytes per pixel it is worth a
|
|
// frame per worker, so it is allocated on first use rather than always.
|
|
CudaDevicePtr<uint8_t> gpu_decompressed_image;
|
|
CudaDevicePtr<ImageStatistics> gpu_stats;
|
|
|
|
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;
|
|
|
|
// Built on first use: a decoder that can serve this engine's images, sized to the frame.
|
|
std::unique_ptr<BSLZ4DecoderGPU> bslz4_decoder;
|
|
|
|
template <class T> ImageStatistics Analyze(ImagePreprocessorBuffer &processed_image, const uint8_t *input, T err_value, T sat_value);
|
|
// Preprocess an image already sitting in gpu_decompressed_image (the host-upload path).
|
|
template <class T> ImageStatistics AnalyzeOnDevice(ImagePreprocessorBuffer &processed_image, T err_value, T sat_value);
|
|
// Preprocess straight out of the bitshuffled bytes (the device-decode path). Same per-pixel
|
|
// decision and same statistics as AnalyzeOnDevice, with the un-transpose folded in.
|
|
template <class T, int ES> ImageStatistics UntransposeAndAnalyze(ImagePreprocessorBuffer &processed_image,
|
|
const BSLZ4ShuffledImage &shuffled,
|
|
T err_value, T sat_value);
|
|
public:
|
|
// copy_image_to_host copies the preprocessed image back after every frame. It is only needed when
|
|
// something on the CPU reads it - the GPU engines all work off the device buffer - and at 4 bytes
|
|
// 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;
|
|
};
|
|
|