Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • mszczep/aidge_backend_cpu
  • eclipse/aidge/aidge_backend_cpu
  • hrouis/aidge_backend_cpu
  • oantoni/aidge_backend_cpu
  • raphaelmillet/aidge_backend_cpu
  • cguillon/aidge_backend_cpu
  • jeromeh/aidge_backend_cpu
  • axelfarr/aidge_backend_cpu
  • noamzerah/aidge_backend_cpu
  • silvanosky/aidge_backend_cpu
  • maab05/aidge_backend_cpu
  • lucaslopez/aidge_backend_cpu_ll
  • farnez/aidge_backend_cpu
13 results
Show changes
Commits on Source (9)
......@@ -12,19 +12,14 @@ stages:
- deploy
include:
- project: 'eclipse/aidge/gitlab_shared_files'
- project: 'eclipse/aidge/gitlab_shared_files'
ref: 'main'
file:
# choose which jobs to run by including the corresponding files.
file: # choose which jobs to run by including the corresponding files.
- '.gitlab/ci/ubuntu_cpp.gitlab-ci.yml'
- '.gitlab/ci/ubuntu_python.gitlab-ci.yml'
- '.gitlab/ci/release/cibuildwheel_ubuntu.gitlab-ci.yml'
- '.gitlab/ci/release/cibuildwheel_ubuntu.gitlab-ci.yml'
- '.gitlab/ci/windows_cpp.gitlab-ci.yml'
- '.gitlab/ci/windows_python.gitlab-ci.yml'
- '.gitlab/ci/release/cibuildwheel_windows.gitlab-ci.yml'
- '.gitlab/ci/windows_python.gitlab-ci.yml'
- '.gitlab/ci/release/cibuildwheel_windows.gitlab-ci.yml'
......@@ -22,6 +22,9 @@ execute_process(
message(STATUS "Latest git commit: ${GIT_COMMIT_HASH}")
add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
# helper for LSP users
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Note : project name is ${CMAKE_PROJECT_NAME} and python module name is also ${CMAKE_PROJECT_NAME}
set(module_name _${CMAKE_PROJECT_NAME}) # target name
set(pybind_module_name ${CMAKE_PROJECT_NAME}) # name of submodule for python bindings
......
......@@ -40,6 +40,7 @@
#include "aidge/backend/cpu/operator/PowImpl.hpp"
#include "aidge/backend/cpu/operator/ReduceMeanImpl.hpp"
#include "aidge/backend/cpu/operator/ReduceSumImpl.hpp"
#include "aidge/backend/cpu/operator/ResizeImpl.hpp"
#include "aidge/backend/cpu/operator/ReLUImpl.hpp"
#include "aidge/backend/cpu/operator/RoundImpl.hpp"
#include "aidge/backend/cpu/operator/ScalingImpl.hpp"
......
/********************************************************************************
* Copyright (c) 2024 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#ifndef AIDGE_CPU_DATA_INTERPOLATION_H_
#define AIDGE_CPU_DATA_INTERPOLATION_H_
#include <vector>
#include <aidge/data/Interpolation.hpp>
#include <aidge/utils/Types.h>
namespace Aidge {
class InterpolationCPU : public Interpolation {
public:
/*
* @brief Interpolates values given via input in given mode.
*
* Values are contiguously arranged in a "square" shape around the point to
* interpolate. Depending on interpolation mode.
* The point that will be interpolated is located right in the
* middle of all points.
* Immediate neighbours :
* 1D interp : 2D interp :
* . . . . . .
* . . 1 2 . . . . . . . .
* . . 1 2 . .
* . . 3 4 . .
* . . . . . .
* . . . . . .
*
* 2 neighbours :
* 1D interp : 2D interp :
* . . . . . . . .
* . . . . . . . .
* . . 1 2 3 4 . . . . 1 2 3 4 . .
* . . 5 6 7 8 . .
* . . 9 10 11 12 . .
* . . 13 14 15 16 . .
* . . . . . . . .
* . . . . . . . .
*
* @param[in] originalCoords: coord of the point to interpolate in the
* original picture. These coords are generated with
* Interpolation::untransformCoords(coordsInInterpolatedTensor)
* @param[in] points : points to interpolate, arranged in a vector of a
* pairs ((point_coord), value) :
* [[[X1, X2, ..., XN], Xval], ...., [[A1, A2, ..., AN],Aval]].
* With :
* - N: the number of dimensions.
* - A: the number of points of the grid to interpolate.
* - All coordinates expressed in originalTensor frame.
* @param[in] interpMode: interpolation mode
* @return interpolated value
*/
template <typename T>
static T interpolate(const std::vector<float> &coordsToInterpolate,
const std::set<Point<T>> &points,
const Mode interpMode = Interpolation::Mode::Linear);
/**
* @brief performs linear interpolation on given points.
* @param[in] values: values to interpolate, since we only do an average of
* all values, their indexes isn't useful.
* @return interpolated value
*/
template <typename T>
static T linear(const std::vector<float> &originalCoords,
const std::set<Point<T>> &points);
/**
* @brief performs nearest interpolation on given points.
* @note it is a wrapper for linearRecurse() private method
* @param[in] coordsToInterpolate: coordinates to interpolate
* @param[in] points: points to interpolate
* @param[in] interpMode: interpolation method, must be a Nearest...
* otherwise function will throw an error.
* @return interpolated value
*/
template <typename T>
static T nearest(const std::vector<float> &coordsToInterpolate,
const std::set<Point<T>> &points,
const Interpolation::Mode nearestMode);
private:
/**
* @brief actual linear interpolation function.
* will :
* - Split all points along each dimension depending of if their coords at
* idx alongDim are above or under coordsToInterpolate until they are
* 1-to-1.
* - Perform interpolation in 2 leftover points and return interpolated
* point to parent call with a set of size 1.
* - repeat until all dimensions have been interpolated.
* @param[in] coordsToInterpolate: coordinates to interpolate
* @param[in] points: points to interpolate
* @param[in] alongDim: discriminant on along which dimension are being
* segregated.
* @return
*/
template <typename T>
static std::set<Interpolation::Point<T>>
linearRecurse(const std::vector<float> &coordsToInterpolate,
const std::set<Point<T>> &points,
const DimIdx_t alongDim = 0);
};
} // namespace Aidge
#endif // AIDGE_CPU_DATA_INTERPOLATION_H_
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#ifndef AIDGE_CPU_OPERATOR_RESIZEIMPL_H_
#define AIDGE_CPU_OPERATOR_RESIZEIMPL_H_
#include "aidge/backend/cpu/operator/OperatorImpl.hpp"
#include "aidge/operator/Resize.hpp"
#include "aidge/utils/Registrar.hpp"
#include <aidge/data/Interpolation.hpp>
#include <aidge/operator/Pad.hpp>
#include <cstdint>
namespace Aidge {
// Operator implementation entry point for the backend
using ResizeImpl_cpu = OperatorImpl_cpu<
Resize_Op,
void(const void *, // input
const std::vector<DimSize_t> &, // INput dims
const std::vector<DimSize_t> &, // OUTput dims
const Interpolation::CoordinateTransformation, // coord transfo
const Interpolation::Mode, // interpolation mode
const PadBorderType, // padding mode
void *)>; // output
// Implementation entry point registration to Operator
REGISTRAR(Resize_Op, "cpu", Aidge::ResizeImpl_cpu::create);
} // namespace Aidge
#endif /* AIDGE_CPU_OPERATOR_RESIZEIMPL_H_ */
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#ifndef AIDGE_CPU_OPERATOR_RESIZEIMPL_FORWARD_KERNEL_H_
#define AIDGE_CPU_OPERATOR_RESIZEIMPL_FORWARD_KERNEL_H_
#include "aidge/backend/cpu/operator/ResizeImpl.hpp"
#include <aidge/data/Data.hpp>
#include <aidge/data/half.hpp>
#include <aidge/operator/Pad.hpp>
#include <cmath>
#include <cstdint>
#include <numeric>
#include "aidge/backend/cpu/data/Interpolation.hpp"
#include "aidge/data/Interpolation.hpp"
#include "aidge/data/Tensor.hpp"
#include "aidge/utils/Registrar.hpp"
#include "aidge/utils/Types.h"
namespace Aidge {
template <typename IO>
void ResizeImpl_cpu_forward_kernel(
const void *input_,
const std::vector<DimSize_t> &inputDims,
const std::vector<DimSize_t> &outputDims,
const Interpolation::CoordinateTransformation coordTransfoMode,
const Interpolation::Mode interpMode,
const PadBorderType paddingMode,
// const double * /*roi*/,
// const float * /*scales*/,
// const int64_t * /*sizes*/,
void *output_) {
// Seting a data
const IO *input = static_cast<const IO *>(input_);
IO *output = static_cast<IO *>(output_);
const DimSize_t outputLen = std::accumulate(outputDims.cbegin(),
outputDims.cend(),
1,
std::multiplies<DimSize_t>());
std::vector<float> coordInApprox(inputDims.size());
std::vector<std::size_t> coordIn(inputDims.size());
std::vector<DimSize_t> coordOut;
for (DimSize_t idxFlatOut = 0; idxFlatOut < outputLen; ++idxFlatOut) {
coordOut = Tensor::toCoord(outputDims, idxFlatOut);
coordInApprox =
Interpolation::untransformCoordinates(coordOut,
inputDims,
outputDims,
coordTransfoMode);
if ((interpMode == Interpolation::Mode::Ceil) || (interpMode == Interpolation::Mode::Floor) || (interpMode == Interpolation::Mode::RoundPreferCeil) || (interpMode == Interpolation::Mode::RoundPreferFloor)) {
for (std::size_t i = 0; i < coordInApprox.size(); ++i) {
if (interpMode == Interpolation::Mode::Ceil) {
coordInApprox[i] = std::ceil(coordInApprox[i]);
} else if (interpMode == Interpolation::Mode::Floor) {
coordInApprox[i] = std::floor(coordInApprox[i]);
} else if (interpMode == Interpolation::Mode::RoundPreferCeil) {
coordInApprox[i] = std::floor(coordInApprox[i] + 0.5f);
} else { // (interpMode == Interpolation::Mode::RoundPreferFloor)
coordInApprox[i] = std::ceil(coordInApprox[i] - 0.5f);
}
}
if (Tensor::isInBounds<float>(inputDims, coordInApprox)) {
for (std::size_t i = 0; i < coordInApprox.size(); ++i) {
coordIn[i] = static_cast<std::size_t>(coordInApprox[i]);
}
} else {
if (paddingMode == PadBorderType::Edge) {
for (std::size_t i = 0; i < coordInApprox.size(); ++i) {
coordIn[i] = coordInApprox[i] < 0 ? 0 : (coordInApprox[i] >=inputDims[i] ? inputDims[i] - 1 : static_cast<std::size_t>(coordInApprox[i]));
}
} else {
AIDGE_THROW_OR_ABORT(std::runtime_error, "Padding mode not supported");
}
}
output[idxFlatOut] = input[Tensor::toIndex(inputDims, coordIn)];
} else {
std::set<Interpolation::Point<IO>> neighbours =
InterpolationCPU::retrieveNeighbours(input,
inputDims,
coordInApprox,
paddingMode);
output[idxFlatOut] = InterpolationCPU::interpolate(coordInApprox,
neighbours,
interpMode);
}
}
return;
}
// Kernels registration to implementation entry point
REGISTRAR(ResizeImpl_cpu,
{{{DataType::Int16},
{DataType::Float32},
{DataType::Float32},
{DataType::UInt64}},
{DataType::Int16}},
{ProdConso::inPlaceModel,
ResizeImpl_cpu_forward_kernel<int16_t>,
nullptr});
REGISTRAR(ResizeImpl_cpu,
{{{DataType::Int32},
{DataType::Float32},
{DataType::Float32},
{DataType::UInt64}},
{DataType::Int32}},
{ProdConso::inPlaceModel,
ResizeImpl_cpu_forward_kernel<int32_t>,
nullptr});
REGISTRAR(ResizeImpl_cpu,
{{{DataType::Int64},
{DataType::Float32},
{DataType::Float32},
{DataType::Int64}},
{DataType::UInt64}},
{ProdConso::inPlaceModel,
ResizeImpl_cpu_forward_kernel<int64_t>,
nullptr});
REGISTRAR(ResizeImpl_cpu,
{{{DataType::Float16},
{DataType::Float32},
{DataType::Float32},
{DataType::UInt64}},
{DataType::Float16}},
{ProdConso::inPlaceModel,
ResizeImpl_cpu_forward_kernel<half_float::half>,
nullptr});
REGISTRAR(ResizeImpl_cpu,
{{{DataType::Float32},
{DataType::Float32},
{DataType::Float32},
{DataType::UInt64}},
{DataType::Float32}},
{ProdConso::inPlaceModel,
ResizeImpl_cpu_forward_kernel<float>,
nullptr});
REGISTRAR(ResizeImpl_cpu,
{{{DataType::Float64},
{DataType::Float32},
{DataType::Float32},
{DataType::UInt64}},
{DataType::Float64}},
{ProdConso::inPlaceModel,
ResizeImpl_cpu_forward_kernel<double>,
nullptr});
} // namespace Aidge
#endif /* AIDGE_CPU_OPERATOR_RESIZEIMPL_FORWARD_KERNEL_H_ */
/********************************************************************************
* Copyright (c) 2024 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#include "aidge/backend/cpu/data/Interpolation.hpp"
#include <aidge/utils/Log.hpp>
#include <algorithm>
#include <cmath>
#include <cstdint>
#include <iterator>
#include <stdexcept>
#include <utility>
#include <vector>
#include <aidge/data/Interpolation.hpp>
#include <aidge/data/half.hpp>
#include <aidge/utils/ErrorHandling.hpp>
#include <aidge/utils/Types.h>
namespace Aidge {
template <typename T>
std::set<Interpolation::Point<T>>
InterpolationCPU::linearRecurse(const std::vector<float> &coordToInterpolate,
const std::set<Point<T>> &points,
const DimIdx_t alongDim) {
// all points have been discriminated properly along given dimension.
if (points.size() == 1) {
return points;
}
auto extractPtCoords = [](std::set<Point<T>> pts) -> std::set<Coords> {
std::set<Coords> result;
for (const auto &pt : pts) {
result.insert(pt.first);
}
return result;
};
///////////////////
// ERROR CHECKING
if (alongDim > coordToInterpolate.size() || points.size() == 0) {
// retrieving points coords as points values can be in half_float &
// this type is not fmt compatible
std::vector<Coords> pointsCoords;
for (const auto &point : points) {
pointsCoords.push_back(point.first);
}
AIDGE_ASSERT(
alongDim >= coordToInterpolate.size(),
"InterpolationCPU::linearInterpolationRecurse: alongDim value "
"exceeded exceeded number of dimensions of coordsTointerpolate. "
"Interpolation has failed. Input values : \n - "
"coordsToInterpolate {}\n - pointsToInterpolate {}\n - alongDim "
"{}",
coordToInterpolate,
pointsCoords,
alongDim);
AIDGE_ASSERT(
points.size() == 0,
"InterpolationCPU::linearInterpolationRecurse: entering recursive "
"function with 0 points. Interpolation has failed."
"Please file a bug report to aidge_backend_cpu repo: "
"https://gitlab.eclipse.org/eclipse/aidge/aidge_backend_cpu/-/"
"issues."
"\nInput values : \n - "
"coordsToInterpolate {}\n - pointsToInterpolate {}\n - alongDim "
"{}",
coordToInterpolate,
pointsCoords,
alongDim);
}
Log::debug("\nEntering linear recurse with {} points.", points.size());
Log::debug("Points : {}", extractPtCoords(points));
Log::debug("coordsToInterpolate : {}", coordToInterpolate);
Log::debug("alongDim : {}", alongDim);
///////////////////
// COMPUTATION
// split all points along each dimension
// depending on if their coords[alongDim] are above or under
// coords to interpolate values
std::set<Point<T>> lowerPoints;
std::set<Point<T>> upperPoints;
for (const auto &point : points) {
if (point.first[alongDim] <= coordToInterpolate[alongDim]) {
lowerPoints.insert(point);
} else {
upperPoints.insert(point);
}
}
Log::debug("alongDim : {}", alongDim);
Log::debug("lowerPoints : {}", extractPtCoords(lowerPoints));
Log::debug("upperPoints : {}", extractPtCoords(upperPoints));
// Here are 3 cases
// 1. upper/lowerPoints.size() == 0
// Coordinates to interpolate along current dimension are round.
// That would be equivalent to a linear interpolation with a
// ponderation of 1 for lowerPoints & 0 for upperPoints(or the
// opposite idk), hence we will only take lower/upperPoints values
// from there.
//
// Why this happens :
// If coordinates are round, the floor()/ceil() operations called
// in retrieveNeighbours to generate direct neighbours of floating
// coordinates returned the same value.
//
// 2. lower/upperPoints.size() == 1
// All dimensions have been discriminated, we can proceed to
// weighted interpolation
//
// 3. lower/upperPoints.size() > 1
// points have not been all discriminated and must be further split
// so we call linearRecurse()
switch (lowerPoints.size()) {
case 0: {
return linearRecurse(coordToInterpolate, upperPoints, alongDim + 1);
}
case 1: {
break;
}
default: {
lowerPoints =
linearRecurse(coordToInterpolate, lowerPoints, alongDim + 1);
break;
}
}
switch (upperPoints.size()) {
case 0: {
return linearRecurse(coordToInterpolate, lowerPoints, alongDim + 1);
}
case 1: {
break;
}
default: {
upperPoints =
linearRecurse(coordToInterpolate, upperPoints, alongDim + 1);
break;
}
}
// At this point lowerPoints & upperPoints are garanteed to be
// 1 sized arrays
AIDGE_ASSERT(lowerPoints.size() == 1,
"LowerPoints Size = {} != 1",
lowerPoints.size());
AIDGE_ASSERT(upperPoints.size() == 1,
"upperPoints Size = {} != 1",
upperPoints.size());
// ( point[dim] - Pl[dim] )
// t = ------------------------
// ( Pu[dim] - Pl[dim] )
float weight =
(coordToInterpolate[alongDim] - lowerPoints.begin()->first[alongDim]) /
(upperPoints.begin()->first[alongDim] -
lowerPoints.begin()->first[alongDim]);
Point<T> interpolatedPoint = std::make_pair(
lowerPoints.begin()->first,
static_cast<T>((1.F - weight) * lowerPoints.begin()->second +
weight * upperPoints.begin()->second));
// 0 is just a sanity check to ensure later that all dims have been
// interpolate
interpolatedPoint.first[alongDim] = 0;
Log::debug("successfully returned from alongDim : {}", alongDim);
return std::set<Point<T>>({interpolatedPoint});
}
template <typename T>
T InterpolationCPU::linear(const std::vector<float> &coordToInterpolate,
const std::set<Point<T>> &pointsToInterpolate) {
auto result = linearRecurse(coordToInterpolate, pointsToInterpolate, 0);
AIDGE_ASSERT(result.size() == 1,
"Result size is not 1 but {}",
result.size());
// if (!std::all_of(result.begin()->first.begin(),
// result.begin()->first.end(),
// [](DimSize_t coord) -> bool { return coord == 0; })) {
// std::vector<Coords> ptCoords;
// std::transform(pointsToInterpolate.begin(),
// pointsToInterpolate.end(),
// std::back_inserter(ptCoords),
// [](Point<T> pt) { return pt.first; });
// AIDGE_THROW_OR_ABORT(std::runtime_error,
// "Not all dimensions have been interpolated."
// "Input data :"
// "\n\t coord to interpolate : {}"
// "\n\t pointsToInterpolate : {}",
// // "\n\tAll non 0 values show dimensions
// // that were not interpolated : {}",
// coordToInterpolate,
// ptCoords //,
// // result.begin()->first
// );
// }
return result.begin()->second;
}
template <typename T>
T InterpolationCPU::nearest(const std::vector<float> &coordsToInterpolate,
const std::set<Point<T>> &points,
const Interpolation::Mode nearestMode) {
AIDGE_ASSERT(
coordsToInterpolate.size() == points.begin()->first.size(),
"Interpolation::nearest(): dimension mismatch : coordinate "
"to interpolate ({}) have not the same number of dimensions than "
"the points to interpolate({}).",
coordsToInterpolate,
points.begin()->first);
std::function<int64_t(const float &)> updateCoordinates;
switch (nearestMode) {
case Interpolation::Mode::Ceil: {
updateCoordinates = [](const float &coord) -> int64_t {
return ceil(coord);
};
break;
}
case Interpolation::Mode::Floor: {
updateCoordinates = [](const float &coord) -> int64_t {
return floor(coord);
};
break;
}
case Interpolation::Mode::RoundPreferFloor: {
updateCoordinates = [](const float &coord) -> int64_t {
return (coord - floor(coord)) == 0.5 ? floor(coord)
: std::round(coord);
};
break;
}
case Interpolation::Mode::RoundPreferCeil: {
updateCoordinates = [](const float &coord) -> int64_t {
return (coord - floor(coord)) == 0.5 ? ceil(coord)
: std::round(coord);
};
break;
}
default: {
AIDGE_THROW_OR_ABORT(
std::runtime_error,
"Invalid Interpolation mode for "
"InterpolationCPU::interpolateNearest. Accepted modes are : "
"Ceil({}),Floor({}),RoundPreferCeil({}), "
"RoundPreferFloor({}). Got {}.",
static_cast<int>(Ceil),
static_cast<int>(Floor),
static_cast<int>(RoundPreferCeil),
static_cast<int>(RoundPreferFloor),
static_cast<int>(nearestMode));
}
}
Coords nearestCoords;
nearestCoords.reserve(coordsToInterpolate.size());
for (const auto &coord : coordsToInterpolate) {
nearestCoords.push_back(updateCoordinates(coord));
}
auto it = std::find_if(
points.begin(),
points.end(),
[nearestCoords](auto &point) { return nearestCoords == point.first; });
if (it != points.end()) {
return it->second;
} else {
Log::warn("Interpolate::nearest(): did not find a fitting point in "
"the neighbours whose coordinates were {}, returning 0. "
"Available neighbours are at following indexes: ",
coordsToInterpolate);
for (const auto &point : points) {
Log::warn("idx : [{}]\t\tvalue {}", point.first);
}
return static_cast<T>(0);
}
}
template <typename T>
T InterpolationCPU::interpolate(const std::vector<float> &coordsToInterpolate,
const std::set<Point<T>> &points,
const Mode interpMode) {
T result{0};
switch (interpMode) {
case Interpolation::Mode::Cubic: {
AIDGE_THROW_OR_ABORT(
std::runtime_error,
"Unsupported interpolation mode selected : Cubic.");
break;
}
case Interpolation::Mode::Linear: {
return linear(coordsToInterpolate, points);
break;
}
case Interpolation::Mode::Ceil:
case Interpolation::Mode::Floor:
case Interpolation::Mode::RoundPreferFloor:
case Interpolation::Mode::RoundPreferCeil: {
result =
InterpolationCPU::nearest(coordsToInterpolate, points, interpMode);
break;
}
default: {
AIDGE_THROW_OR_ABORT(std::runtime_error,
"InterpolationCPU::Interpolate({}): Unsupported "
"interpolation mode given as input.",
static_cast<int>(interpMode));
break;
}
}
return result;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// TEMPLATE DECLARATION
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////
// INTERPOLATE
template int8_t InterpolationCPU::interpolate<int8_t>(
const std::vector<float> &originalCoords,
const std::set<Point<int8_t>> &points,
const Mode interpMode);
template int16_t InterpolationCPU::interpolate<int16_t>(
const std::vector<float> &originalCoords,
const std::set<Point<int16_t>> &points,
const Mode interpMode);
template int32_t InterpolationCPU::interpolate<int32_t>(
const std::vector<float> &originalCoords,
const std::set<Point<int32_t>> &points,
const Mode interpMode);
template int64_t InterpolationCPU::interpolate<int64_t>(
const std::vector<float> &originalCoords,
const std::set<Point<int64_t>> &points,
const Mode interpMode);
template half_float::half InterpolationCPU::interpolate<half_float::half>(
const std::vector<float> &originalCoords,
const std::set<Point<half_float::half>> &points,
const Mode interpMode);
template float InterpolationCPU::interpolate<float>(
const std::vector<float> &originalCoords,
const std::set<Point<float>> &points,
const Mode interpMode);
template double InterpolationCPU::interpolate<double>(
const std::vector<float> &originalCoords,
const std::set<Point<double>> &points,
const Mode interpMode);
////////////////////////////////////////////////////////////////////
// INTERPOLATE LINEAR (& its associated recursive function)
template int8_t
InterpolationCPU::linear(const std::vector<float> &coordsToInterpolate,
const std::set<Point<int8_t>> &points);
template std::set<Interpolation::Point<int8_t>>
InterpolationCPU::linearRecurse(const std::vector<float> &coordsToInterpolate,
const std::set<Point<int8_t>> &points,
DimIdx_t alongDim);
template int16_t
InterpolationCPU::linear(const std::vector<float> &coordsToInterpolate,
const std::set<Point<int16_t>> &points);
template std::set<Interpolation::Point<int16_t>>
InterpolationCPU::linearRecurse(const std::vector<float> &coordsToInterpolate,
const std::set<Point<int16_t>> &points,
DimIdx_t alongDim);
template int32_t
InterpolationCPU::linear(const std::vector<float> &coordsToInterpolate,
const std::set<Point<int32_t>> &points);
template std::set<Interpolation::Point<int32_t>>
InterpolationCPU::linearRecurse(const std::vector<float> &coordsToInterpolate,
const std::set<Point<int32_t>> &points,
DimIdx_t alongDim);
template half_float::half
InterpolationCPU::linear(const std::vector<float> &coordsToInterpolate,
const std::set<Point<half_float::half>> &points);
template std::set<Interpolation::Point<half_float::half>>
InterpolationCPU::linearRecurse(
const std::vector<float> &coordsToInterpolate,
const std::set<Point<half_float::half>> &points,
DimIdx_t alongDim);
template float
InterpolationCPU::linear(const std::vector<float> &coordsToInterpolate,
const std::set<Point<float>> &points);
template std::set<Interpolation::Point<float>>
InterpolationCPU::linearRecurse(const std::vector<float> &coordsToInterpolate,
const std::set<Point<float>> &points,
DimIdx_t alongDim);
template double
InterpolationCPU::linear(const std::vector<float> &coordsToInterpolate,
const std::set<Point<double>> &points);
template std::set<Interpolation::Point<double>>
InterpolationCPU::linearRecurse(const std::vector<float> &coordsToInterpolate,
const std::set<Point<double>> &points,
DimIdx_t alongDim);
//////////////////////////////////
// INTERPOLATE NEAREST
template int8_t
InterpolationCPU::nearest(const std::vector<float> &originalCoords,
const std::set<Point<int8_t>> &points,
const Interpolation::Mode nearestMode);
template int16_t
InterpolationCPU::nearest(const std::vector<float> &originalCoords,
const std::set<Point<int16_t>> &points,
const Interpolation::Mode nearestMode);
template int32_t
InterpolationCPU::nearest(const std::vector<float> &originalCoords,
const std::set<Point<int32_t>> &points,
const Interpolation::Mode nearestMode);
template half_float::half
InterpolationCPU::nearest(const std::vector<float> &originalCoords,
const std::set<Point<half_float::half>> &points,
const Interpolation::Mode nearestMode);
template float
InterpolationCPU::nearest(const std::vector<float> &originalCoords,
const std::set<Point<float>> &points,
const Interpolation::Mode nearestMode);
template double
InterpolationCPU::nearest(const std::vector<float> &originalCoords,
const std::set<Point<double>> &points,
const Interpolation::Mode nearestMode);
} // namespace Aidge
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#include "aidge/backend/cpu/operator/ResizeImpl.hpp"
#include "aidge/backend/cpu/operator/ResizeImpl_kernels.hpp"
#include "aidge/operator/Resize.hpp"
#include <cassert>
#include <cstdint>
#include <sys/stat.h>
#include "aidge/backend/OperatorImpl.hpp"
#include "aidge/utils/ErrorHandling.hpp"
namespace Aidge {
template <> void ResizeImpl_cpu::forward() {
auto &op = dynamic_cast<const Resize_Op &>(mOp);
/** @brief input #0 */
int8_t idxData = 0;
const bool input0DataPresent =
op.getInput(idxData) && !op.getInput(idxData)->undefined();
///////////////////////////////////////
// CHECKING NODE CONNECTIONS
AIDGE_ASSERT(input0DataPresent, "{}: missing data input #0", op.type());
///////////////////////////////////////
// CALL TO FORWARD
const auto impl =
Registrar<ResizeImpl_cpu>::create(getBestMatch(getRequiredSpec()));
impl.forward(op.getInput(idxData)->getImpl()->rawPtr(),
op.getInput(idxData)->dims(),
op.getOutput(0)->dims(),
op.coordinateTransformationMode(),
op.interpolationMode(),
op.paddingMode(),
op.getOutput(0)->getImpl()->rawPtr() // output pointer
);
}
template <> void Aidge::ResizeImpl_cpu::backward() {
AIDGE_THROW_OR_ABORT(
std::runtime_error,
"Backward not yet implemented for Slice_Op on backend cpu");
}
} // namespace Aidge
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#include <aidge/backend/cpu/data/Interpolation.hpp>
#include <aidge/data/Interpolation.hpp>
#include <aidge/data/Tensor.hpp>
#include <aidge/filler/Filler.hpp>
#include <aidge/utils/Types.h>
#include <catch2/catch_test_macros.hpp>
#include <limits>
#include "aidge/backend/cpu/data/Interpolation.hpp"
namespace Aidge {
TEST_CASE("Interpolation", "[Interpolation][Data]") {
SECTION("Linear") {
std::set<Interpolation::Point<int>> pointsToInterpolateInt;
std::set<Interpolation::Point<float>> pointsToInterpolateFloat;
SECTION("1D") {
pointsToInterpolateInt =
std::set<Interpolation::Point<int>>({{{0}, 10}, {{1}, 20}});
CHECK(abs(InterpolationCPU::linear({0.5}, pointsToInterpolateInt) -
15) <= std::numeric_limits<int>::epsilon());
pointsToInterpolateFloat = std::set<Interpolation::Point<float>>(
{{{0}, .0F}, {{1}, 0.2F}});
CHECK(fabs(InterpolationCPU::linear({0.3},
pointsToInterpolateFloat) -
.06F) <= 1e-5);
}
SECTION("2D") {
// example taken from
// https://en.wikipedia.org/wiki/Bilinear_interpolation
pointsToInterpolateFloat = {{{14, 20}, 91.F},
{{14, 21}, 162.F},
{{15, 20}, 210.F},
{{15, 21}, 95.F}};
CHECK(fabs(InterpolationCPU::linear<float>(
{14.5F, 20.2F},
pointsToInterpolateFloat) -
146.1) < 1e-5);
// pointsToInterpolateFloat = {{{0, 0}, .10F},
// {{0, 1}, .20F},
// {{1, 0}, .30F},
// {{1, 1}, .40F}};
// CHECK(abs(InterpolationCPU::linear<float>({1.5, 0.5},
// pointsToInterpolateInt)
// -
// 25) < std::numeric_limits<int>::epsilon());
// pointsToInterpolateFloat = std::vector({0.1F, 0.2F, 0.3F,
// 0.4F}); CHECK(InterpolationCPU::linear(pointsToInterpolateFloat)
// == .25f);
}
SECTION("3D") {
pointsToInterpolateFloat = {{{0, 0, 0}, .1F},
{{0, 0, 1}, .2F},
{{0, 1, 0}, .3F},
{{0, 1, 1}, .4F},
{{1, 0, 0}, .5F},
{{1, 0, 1}, .6F},
{{1, 1, 0}, .7F},
{{1, 1, 1}, .8F}};
CHECK(fabs(InterpolationCPU::linear({.5, .5, .5},
pointsToInterpolateFloat) -
.45f) < 1e-5);
}
SECTION("4D") {
SECTION("Casual") {
pointsToInterpolateFloat = {{{0, 0, 0, 0}, .1F},
{{0, 0, 0, 1}, .2F},
{{0, 0, 1, 0}, .3F},
{{0, 0, 1, 1}, .4F},
{{0, 1, 0, 0}, .5F},
{{0, 1, 0, 1}, .6F},
{{0, 1, 1, 0}, .7F},
{{0, 1, 1, 1}, .8F},
{{1, 0, 0, 0}, .9F},
{{1, 0, 0, 1}, 1.F},
{{1, 0, 1, 0}, 1.1F},
{{1, 0, 1, 1}, 1.2F},
{{1, 1, 0, 0}, 1.3F},
{{1, 1, 0, 1}, 1.4F},
{{1, 1, 1, 0}, 1.5F},
{{1, 1, 1, 1}, 1.6F}};
CHECK(fabs(InterpolationCPU::linear<float>(
{.5, .5, .5, .5},
pointsToInterpolateFloat) -
.85f) < 0.0001);
}
}
SECTION("Some of the coords to interpolate were round") {
// In this case retrieveNeighbours()
// only retrieved the neighbours against not round dimensions
auto tensor =
std::make_shared<Tensor>(std::vector<DimSize_t>({10, 10}));
tensor->setDataType(DataType::Float32);
tensor->setBackend("cpu");
Aidge::constantFiller(tensor, 1337.F);
std::set<Interpolation::Point<float>> expectedResult = {
{{0, 0, -1, -1}, 0.F},
{{0, 0, 0, -1}, 0.F},
{{0, 0, -1, 0}, 0.F},
{{0, 0, 0, 0}, 1337.F}};
pointsToInterpolateFloat = Interpolation::retrieveNeighbours(
reinterpret_cast<float *>(tensor->getImpl()->rawPtr()),
tensor->dims(),
std::vector<float>({0.F, 0.F, -0.25F, -0.25F}));
pointsToInterpolateFloat = {{{0, 0, -1, -1}, 1337.F},
{{0, 0, 0, -1}, 1337.F},
{{0, 0, -1, 0}, 1337.F},
{{0, 0, 0, 0}, 1337.F}};
}
}
SECTION("Nearest") {
std::set<Interpolation::Point<float>> pointsToInterpolate;
std::vector<float> coordToInterpolate;
SECTION("1D") {
coordToInterpolate = {0.5F};
pointsToInterpolate =
std::set<Interpolation::Point<float>>{{{0}, 1.0F},
{{1}, 2.0F},
{{2}, 3.0F},
{{3}, 4.0F},
{{4}, 5.0F}};
SECTION("Floor") {
CHECK(InterpolationCPU::nearest(
coordToInterpolate,
pointsToInterpolate,
Interpolation::Mode::Floor) == 1);
}
SECTION("Ceil") {
CHECK(InterpolationCPU::nearest(
coordToInterpolate,
pointsToInterpolate,
Interpolation::Mode::Ceil) == 2);
}
SECTION("RoundPreferFloor") {
CHECK(InterpolationCPU::nearest(
coordToInterpolate,
pointsToInterpolate,
Interpolation::Mode::RoundPreferFloor) == 1);
}
SECTION("RoundPreferCeil") {
CHECK(InterpolationCPU::nearest(
coordToInterpolate,
pointsToInterpolate,
Interpolation::Mode::RoundPreferCeil) == 2);
}
}
SECTION("2D") {
coordToInterpolate = {2.5F, 3.97F};
pointsToInterpolate = {{{0, 0}, 10.0},
{{1, 1}, 20.0},
{{2, 3}, 30.0},
{{2, 4}, 40.0},
{{3, 3}, 50.0},
{{3, 4}, 60.0}};
SECTION("Floor") {
CHECK(InterpolationCPU::nearest(
coordToInterpolate,
pointsToInterpolate,
Interpolation::Mode::Floor) == 30.);
}
SECTION("Ceil") {
CHECK(InterpolationCPU::nearest(
coordToInterpolate,
pointsToInterpolate,
Interpolation::Mode::Ceil) == 60.);
}
SECTION("RoundPreferFloor") {
CHECK(InterpolationCPU::nearest(
coordToInterpolate,
pointsToInterpolate,
Interpolation::Mode::RoundPreferFloor) ==
40.);
}
SECTION("RoundPreferCeil") {
CHECK(InterpolationCPU::nearest(
coordToInterpolate,
pointsToInterpolate,
Interpolation::Mode::RoundPreferCeil) == 60.);
}
}
SECTION("3D") {
coordToInterpolate = {1.9, 2.1, 3.6};
pointsToInterpolate = {{{0, 0, 0}, 5.0},
{{1, 2, 3}, 10.0},
{{2, 1, 4}, 20.0},
{{2, 2, 4}, 30.0},
{{2, 3, 3}, 40.0},
{{2, 3, 4}, 50.0},
{{3, 3, 4}, 60.0}};
SECTION("Floor") {
CHECK(InterpolationCPU::nearest(
coordToInterpolate,
pointsToInterpolate,
Interpolation::Mode::Floor) == 10.);
}
SECTION("Ceil") {
CHECK(InterpolationCPU::nearest(
coordToInterpolate,
pointsToInterpolate,
Interpolation::Mode::Ceil) == 50.);
}
SECTION("RoundPreferFloor") {
CHECK(InterpolationCPU::nearest(
coordToInterpolate,
pointsToInterpolate,
Interpolation::Mode::RoundPreferFloor) ==
30.);
}
SECTION("RoundPreferCeil") {
CHECK(InterpolationCPU::nearest(
coordToInterpolate,
pointsToInterpolate,
Interpolation::Mode::RoundPreferCeil) == 30.);
}
}
}
}
} // namespace Aidge
......@@ -25,7 +25,7 @@
namespace Aidge {
TEST_CASE("Test addition of Tensors","[TensorImpl][Add]") {
TEST_CASE("Test addition of Tensors","[TensorImpl][Add][Data]") {
constexpr std::uint16_t NBTRIALS = 10;
// Create a random number generator
std::random_device rd;
......
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#include <cstdint>
#include <memory>
#include <aidge/data/Data.hpp>
#include <aidge/data/Interpolation.hpp>
#include <aidge/data/half.hpp>
#include <aidge/operator/Pad.hpp>
#include <aidge/utils/ArrayHelpers.hpp>
#include <catch2/catch_test_macros.hpp>
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/OperatorTensor.hpp"
#include "aidge/operator/Resize.hpp"
#include "aidge/utils/TensorUtils.hpp"
namespace Aidge {
TEST_CASE("[cpu/operator] Resize(forward)", "[Resize][CPU]") {
Log::setConsoleLevel(Log::Level::Debug);
SECTION("Nearest") {
SECTION("Ceil") {
std::shared_ptr<Tensor> input_tensor = std::make_shared<Tensor>(Array4D<std::int32_t, 1, 1, 2, 2>{{
{
{
{ 1, 2},
{ 3, 4}
}
}
}});
Tensor expected_out_tensor = Tensor(Array4D<std::int32_t, 1, 1, 4, 4>{{
{
{
{ 1, 1, 1, 2},
{ 1, 1, 1, 2},
{ 1, 1, 1, 2},
{ 3, 3, 3, 4}
}
}
}});
std::vector<float> scales = {1.0f, 1.0f, 2.0f, 2.0f};
auto resize_node = Resize(scales, {}, Interpolation::CoordinateTransformation::HalfPixel, Interpolation::Mode::Floor);
auto op = std::static_pointer_cast<Resize_Op>(resize_node->getOperator());
op->associateInput(0, input_tensor);
op->setDataType(DataType::Int32);
op->setBackend("cpu");
op->forwardDims(true);
op->forward();
op->getOutput(0)->print();
expected_out_tensor.print();
CHECK(*(op->getOutput(0)) == expected_out_tensor);
}
}
SECTION("1-sized input tensor (upscaling)") {
std::shared_ptr<Tensor> input_tensor = std::make_shared<Tensor>(Array4D<float, 1, 1, 1, 1>{{{{{0.417022}}}}});
std::vector<std::size_t> sizes = {1, 1, 2, 2};
auto resize_node = Resize({}, sizes, Interpolation::CoordinateTransformation::HalfPixel, Interpolation::Mode::Linear);
auto op = std::static_pointer_cast<Resize_Op>(resize_node->getOperator());
op->associateInput(0, input_tensor);
op->setDataType(DataType::Float32);
op->setBackend("cpu");
op->forwardDims(true);
op->forward();
std::shared_ptr<Tensor> expectedOutput = std::make_shared<Tensor>(Array4D<float, 1, 1, 2, 2>{
{{{{0.417022, 0.417022}, {0.417022, 0.417022}}}}});
op->getOutput(0)->print();
CHECK(approxEq<float>(*op->getOutput(0), *expectedOutput) == true);
}
SECTION("Upscaling from 5x5 to 10x10 (linear)") {
std::shared_ptr<Tensor> input_tensor = std::make_shared<Tensor>(
Array4D<float, 1, 1, 5, 5>{{{{{7.20324516e-01,
1.14374816e-04,
3.02332580e-01,
1.46755889e-01,
9.23385918e-02},
{1.86260208e-01,
3.45560730e-01,
3.96767467e-01,
5.38816750e-01,
4.19194520e-01},
{6.85219526e-01,
2.04452246e-01,
8.78117442e-01,
2.73875929e-02,
6.70467496e-01},
{4.17304814e-01,
5.58689833e-01,
1.40386939e-01,
1.98101491e-01,
8.00744593e-01},
{9.68261600e-01,
3.13424170e-01,
6.92322612e-01,
8.76389146e-01,
8.94606650e-01}}}}}
);
std::vector<std::size_t> sizes = {1, 1, 10, 10};
auto resize_node = Resize({}, sizes, Interpolation::CoordinateTransformation::Asymmetric, Interpolation::Mode::Linear);
auto op = std::static_pointer_cast<Resize_Op>(resize_node->getOperator());
op->associateInput(0, input_tensor);
op->setDataType(DataType::Float32);
op->setBackend("cpu");
op->forwardDims(true);
op->forward();
std::shared_ptr<Tensor> expectedOutput = std::make_shared<Tensor>(
Array4D<float, 1, 1, 10, 10>{{{{{7.20324516e-01,
3.60219449e-01,
1.14374816e-04,
1.51223481e-01,
3.02332580e-01,
2.24544227e-01,
1.46755889e-01,
1.19547240e-01,
9.23385918e-02,
9.23385918e-02},
{4.53292370e-01,
3.13064963e-01,
1.72837555e-01,
2.61193782e-01,
3.49550009e-01,
3.46168160e-01,
3.42786312e-01,
2.99276441e-01,
2.55766571e-01,
2.55766571e-01},
{1.86260208e-01,
2.65910476e-01,
3.45560730e-01,
3.71164083e-01,
3.96767467e-01,
4.67792094e-01,
5.38816750e-01,
4.79005635e-01,
4.19194520e-01,
4.19194520e-01},
{4.35739875e-01,
3.55373204e-01,
2.75006473e-01,
4.56224471e-01,
6.37442470e-01,
4.60272312e-01,
2.83102185e-01,
4.13966596e-01,
5.44831038e-01,
5.44831038e-01},
{6.85219526e-01,
4.44835901e-01,
2.04452246e-01,
5.41284859e-01,
8.78117442e-01,
4.52752531e-01,
2.73875929e-02,
3.48927557e-01,
6.70467496e-01,
6.70467496e-01},
{5.51262140e-01,
4.66416597e-01,
3.81571054e-01,
4.45411623e-01,
5.09252191e-01,
3.10998380e-01,
1.12744540e-01,
4.24175322e-01,
7.35606015e-01,
7.35606015e-01},
{4.17304814e-01,
4.87997323e-01,
5.58689833e-01,
3.49538386e-01,
1.40386939e-01,
1.69244215e-01,
1.98101491e-01,
4.99423027e-01,
8.00744593e-01,
8.00744593e-01},
{6.92783237e-01,
5.64420104e-01,
4.36057001e-01,
4.26205903e-01,
4.16354775e-01,
4.76800054e-01,
5.37245333e-01,
6.92460477e-01,
8.47675622e-01,
8.47675622e-01},
{9.68261600e-01,
6.40842915e-01,
3.13424170e-01,
5.02873421e-01,
6.92322612e-01,
7.84355879e-01,
8.76389146e-01,
8.85497928e-01,
8.94606650e-01,
8.94606650e-01},
{9.68261600e-01,
6.40842915e-01,
3.13424170e-01,
5.02873421e-01,
6.92322612e-01,
7.84355879e-01,
8.76389146e-01,
8.85497928e-01,
8.94606650e-01,
8.94606650e-01}}}}});
Log::notice("Expected result : dims = {}", expectedOutput->dims());
expectedOutput->print();
Log::notice("\nActual result: dims = {}", op->getOutput(0)->dims());
op->getOutput(0)->print();
CHECK(approxEq<float>(*op->getOutput(0),
*expectedOutput,
1e-5f,
1e-5f) == true);
}
}
} // namespace Aidge