Commit a01047da authored by Alejandro Homs Puron's avatar Alejandro Homs Puron Committed by Generic Bliss account for Control Software
Browse files

[PROC] Add OpenCL average (16-bit) implementation

parent f206996d
// Copyright (C) 2020 Alejandro Homs Puron, ESRF.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#pragma once
#include <limits>
#include <lima/logging.hpp>
#include <lima/processing/fai/opencl.hpp>
#include <lima/processing/fai/enums.hpp>
#include <lima/processing/fai/typedefs.hpp>
namespace lima
{
namespace processing::fai
{
using ave_ret_t = std::size_t;
inline auto make_average(bcl::context& context, //
std::size_t width, std::size_t height, //
std::size_t start_frame, // First frame to average
std::size_t nb_frames, // Number of frames to average
bcl::command_queue& queue) //
{
// Preconditions
if (nb_frames == 0)
LIMA_THROW_EXCEPTION(lima::invalid_argument("Invalid null average number of frames"));
else if (nb_frames > std::numeric_limits<unsigned int>::max())
LIMA_THROW_EXCEPTION(lima::invalid_argument("Average number of frames too large"));
else if (width * height > std::numeric_limits<unsigned int>::max())
LIMA_THROW_EXCEPTION(lima::invalid_argument("Number of pixels too large"));
const unsigned int nb_pixels = width * height;
bcl::vector<unsigned long> acc_d(nb_pixels, context); //!< Accumulation buffer
bcl::vector<float> res_d(nb_pixels, context); //!< Average result
// Memory fill pattern >= 8 bytes not supported by CUDA: initialize in GPU
const unsigned long init_val = 0;
BOOST_COMPUTE_CLOSURE(unsigned long, init_acc, (unsigned long unused), (init_val), { return init_val; });
bcl::transform(acc_d.begin(), acc_d.end(), acc_d.begin(), init_acc, queue);
unsigned int curr_acc_frames = 0;
return [=, //
acc = std::move(acc_d), res = std::move(res_d),
to_skip = start_frame](bcl::command_queue& queue, //
vector<std::uint16_t> const& raw, // Input
vector<float>& ave, // Output average
bool force_ave) mutable -> ave_ret_t {
// Skip the first & last frames
if (to_skip > 0) {
--to_skip;
return 0;
} else if (curr_acc_frames == nb_frames)
return 0;
int dummy_capture = 0;
BOOST_COMPUTE_CLOSURE(unsigned long, acc_frame, (unsigned long acc, unsigned int raw), (dummy_capture),
{ return acc + raw; });
bcl::transform(acc.begin(), acc.end(), raw.begin(), acc.begin(), acc_frame, queue);
++curr_acc_frames;
if ((curr_acc_frames < nb_frames) && !force_ave)
return 0;
BOOST_COMPUTE_CLOSURE(float, calc_ave, (unsigned long acc), (curr_acc_frames),
{ return ((float) acc) / curr_acc_frames; });
bcl::transform(acc.begin(), acc.end(), res.begin(), calc_ave, queue);
bcl::copy(res.begin(), res.end(), ave.begin(), queue);
return curr_acc_frames;
};
};
using average = std::function<ave_ret_t(bcl::command_queue&, //
vector<std::uint16_t> const&, // Input
vector<float>&, // Output average
bool // Force output average
)>;
} // namespace processing::fai
} // namespace lima
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment