Skip to content
Snippets Groups Projects
Commit 713c5024 authored by Jerome Hue's avatar Jerome Hue
Browse files

Add BitErrorRate operator implementation for CPU backend

parent fd321fc0
No related branches found
No related tags found
No related merge requests found
......@@ -23,6 +23,7 @@
#include "aidge/backend/cpu/operator/AvgPoolingImpl.hpp"
#include "aidge/backend/cpu/operator/MaxPoolingImpl.hpp"
#include "aidge/backend/cpu/operator/BatchNormImpl.hpp"
#include "aidge/backend/cpu/operator/BitErrorRateImpl.hpp"
#include "aidge/backend/cpu/operator/BitShiftImpl.hpp"
#include "aidge/backend/cpu/operator/ClipImpl.hpp"
#include "aidge/backend/cpu/operator/ConvDepthWiseImpl.hpp"
......
/********************************************************************************
* Copyright (c) 2025 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_BITERRORRATEIMPL_H_
#define AIDGE_CPU_OPERATOR_BITERRORRATEIMPL_H_
#include <memory>
#include <tuple>
#include <vector>
#include "aidge/backend/cpu/operator/OperatorImpl.hpp"
#include "aidge/operator/BitErrorRate.hpp"
#include "aidge/utils/Registrar.hpp"
#include "aidge/utils/Types.h"
#include "aidge/backend/cpu/data/GetCPUPtr.h"
namespace Aidge {
// Operator implementation entry point for the backend
using BitErrorRateImpl_Cpu = OperatorImpl_cpu<BitErrorRate_Op,
void(const void *,
void *,
std::size_t,
float)>;
// Implementation entry point registration to Operator
REGISTRAR(BitErrorRate_Op, "cpu", Aidge::BitErrorRateImpl_Cpu::create);
} // namespace Aidge
#endif /* AIDGE_CPU_OPERATOR_BITERRORRATEIMPL_H */
/********************************************************************************
* Copyright (c) 2025 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_NBITFLIPIMPL_KERNELS_H_
#define AIDGE_CPU_OPERATOR_NBITFLIPIMPL_KERNELS_H_
#include <algorithm>
#include <random>
#include "aidge/backend/cpu/operator/BitErrorRateImpl.hpp"
#include "aidge/utils/Registrar.hpp"
namespace Aidge {
template<typename T2, typename T1>
struct BitCastHelper {
static constexpr bool isValid =
sizeof(T1) == sizeof(T2) and
std::is_trivially_copyable<T1>::value and
std::is_trivially_copyable<T2>::value and
std::is_trivially_constructible<T2>::value;
};
template<typename T2, typename T1>
typename std::enable_if<BitCastHelper<T2, T1>::isValid, T2>::type
bitCast(const T1& src) {
T2 dst;
std::memcpy(&dst, &src, sizeof(T2));
return dst;
}
template<typename T>
typename std::enable_if<sizeof(T) == 4>::type
flipSingleBit(T& value, std::size_t bitToFlip)
{
std::uint32_t intRepresentation = bitCast<std::uint32_t>(value);
intRepresentation ^= (1u << bitToFlip);
value = bitCast<T>(intRepresentation);
}
template<typename T>
typename std::enable_if<sizeof(T) == 8>::type
flipSingleBit(T& value, std::size_t bitToFlip)
{
std::uint64_t intRepresentation = bitCast<std::uint64_t>(value);
intRepresentation ^= (1ull << bitToFlip);
value = bitCast<T>(intRepresentation);
}
template<typename T>
typename std::enable_if<(sizeof(T) != 4 and sizeof(T) != 8)>::type
flipSingleBit(T& vlaue, std::size_t bitToFlip)
{
AIDGE_THROW_OR_ABORT(std::runtime_error,
"BitFlip error not implemented for this type of data.");
}
template <class I, class O>
void BitErrorRateImpl_cpu_forward_kernel(const void* input_,
void* output_,
std::size_t inputLength,
float ber) {
const I* input = static_cast<const I*>(input_);
O* output = static_cast<O*>(output_);
std::copy(input, input + inputLength, output);
// Compute the total number of bits in the tensor.
std::size_t totalBits = inputLength * sizeof(O) * 8;
// Determine the number of bits to flip using the bit error rate (rounded to the nearest integer).
std::size_t nBitToFlip = static_cast<std::size_t>(std::round(ber * totalBits));
if(nBitToFlip == 0) {
return;
}
Log::info("Performing {} bit flips on tensor, length is {}", nBitToFlip, inputLength);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<size_t> dist(0, inputLength - 1);
std::uniform_int_distribution<size_t> bitDist(0, sizeof(O) * 8 - 1);
for(auto i = 0U; i < nBitToFlip; ++i) {
auto randomIndex = dist(gen);
auto bitToFlip = bitDist(gen);
O oldValue = output[randomIndex];
flipSingleBit(output[randomIndex], bitToFlip);
O newValue = output[randomIndex];
Log::notice("\t Flipping bit {} of weight {}.\tFrom {} to {}",
bitToFlip,
randomIndex,
oldValue,
newValue);
}
}
// Kernels registration to implementation entry point
REGISTRAR(BitErrorRateImpl_Cpu,
{DataType::Float32},
{ProdConso::inPlaceModel,
Aidge::BitErrorRateImpl_cpu_forward_kernel<float, float>,
nullptr});
REGISTRAR(BitErrorRateImpl_Cpu,
{DataType::Float64},
{ProdConso::inPlaceModel,
Aidge::BitErrorRateImpl_cpu_forward_kernel<double, double>,
nullptr});
REGISTRAR(BitErrorRateImpl_Cpu,
{DataType::Int32},
{ProdConso::inPlaceModel,
Aidge::BitErrorRateImpl_cpu_forward_kernel<std::uint32_t, std::uint32_t>,
nullptr});
} // namespace Aidge
#endif
......@@ -23,7 +23,7 @@ namespace Aidge {
template<typename T2, typename T1>
struct BitCastHelper {
static constexpr bool isValid =
static constexpr bool isValid =
sizeof(T1) == sizeof(T2) and
std::is_trivially_copyable<T1>::value and
std::is_trivially_copyable<T2>::value and
......@@ -61,7 +61,7 @@ template<typename T>
typename std::enable_if<(sizeof(T) != 4 and sizeof(T) != 8)>::type
flipSingleBit(T& vlaue, std::size_t bitToFlip)
{
AIDGE_THROW_OR_ABORT(std::runtime_error,
AIDGE_THROW_OR_ABORT(std::runtime_error,
"BitFlip error not implemented for this type of data.");
}
......@@ -71,7 +71,7 @@ void NBitFlipImpl_cpu_forward_kernel(const void* input_,
std::size_t inputLength,
std::uint32_t nBitToFlip) {
const I* input = static_cast<const I*>(input_);
O* output = static_cast<O*>(output_);
......@@ -81,7 +81,7 @@ void NBitFlipImpl_cpu_forward_kernel(const void* input_,
return;
}
Log::info("Performing {} bit flips on tensor", nBitToFlip);
Log::info("Performing {} bit flips on tensor, length is {}", nBitToFlip, inputLength);
std::random_device rd;
std::mt19937 gen(rd());
......@@ -97,7 +97,7 @@ void NBitFlipImpl_cpu_forward_kernel(const void* input_,
O oldValue = output[randomIndex];
flipSingleBit(output[randomIndex], bitToFlip);
O newValue = output[randomIndex];
Log::notice("\t Flipping bit {} of weight {}.\tFrom {} to {}",
bitToFlip,
randomIndex,
......@@ -111,20 +111,19 @@ void NBitFlipImpl_cpu_forward_kernel(const void* input_,
// Kernels registration to implementation entry point
REGISTRAR(NBitFlipImpl_cpu,
{DataType::Float32},
{ProdConso::inPlaceModel,
Aidge::NBitFlipImpl_cpu_forward_kernel<float, float>,
{ProdConso::inPlaceModel,
Aidge::NBitFlipImpl_cpu_forward_kernel<float, float>,
nullptr});
REGISTRAR(NBitFlipImpl_cpu,
{DataType::Float64},
{ProdConso::inPlaceModel,
Aidge::NBitFlipImpl_cpu_forward_kernel<double, double>,
{ProdConso::inPlaceModel,
Aidge::NBitFlipImpl_cpu_forward_kernel<double, double>,
nullptr});
REGISTRAR(NBitFlipImpl_cpu,
{DataType::Int32},
{ProdConso::inPlaceModel,
Aidge::NBitFlipImpl_cpu_forward_kernel<std::uint32_t, std::uint32_t>,
{ProdConso::inPlaceModel,
Aidge::NBitFlipImpl_cpu_forward_kernel<std::uint32_t, std::uint32_t>,
nullptr});
} // namespace Aidge
#endif
......@@ -6,6 +6,6 @@ static constexpr const int PROJECT_VERSION_MAJOR = 0;
static constexpr const int PROJECT_VERSION_MINOR = 6;
static constexpr const int PROJECT_VERSION_PATCH = 1;
static constexpr const char * PROJECT_VERSION = "0.6.1";
static constexpr const char * PROJECT_GIT_HASH = "ae873a1";
static constexpr const char * PROJECT_GIT_HASH = "fd321fc";
}
#endif // VERSION_H
/********************************************************************************
* Copyright (c) 2025 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/NBitFlipImpl.hpp"
#include <stdexcept>
#include <vector>
#include "aidge/backend/cpu/data/GetCPUPtr.h"
#include "aidge/backend/cpu/operator/BitErrorRateImpl_kernels.hpp"
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/BitErrorRate.hpp"
#include "aidge/utils/ErrorHandling.hpp"
#include "aidge/utils/Log.hpp"
#include "aidge/utils/Types.h"
#include "aidge/utils/Registrar.hpp"
template <>
void Aidge::BitErrorRateImpl_Cpu::forward() {
const BitErrorRate_Op& op_ = dynamic_cast<const BitErrorRate_Op&>(mOp);
std::shared_ptr<Tensor> in0 = op_.getInput(0);
std::shared_ptr<Tensor> out0 = op_.getOutput(0);
AIDGE_ASSERT(in0, "missing input #0");
// Find the correct kernel type
const auto impl = Registrar<BitErrorRateImpl_Cpu>::create(getBestMatch(getRequiredSpec()));
// Call kernel
impl.forward(
getCPUPtr(mOp.getRawInput(0)),
getCPUPtr(mOp.getRawOutput(0)),
in0->size(),
op_.ber());
}
template <>
void Aidge::BitErrorRateImpl_Cpu::backward() {
AIDGE_THROW_OR_ABORT(std::runtime_error, "Not implemented yet");
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment