Skip to content
Snippets Groups Projects
Commit c9700bee authored by Houssem ROUIS's avatar Houssem ROUIS
Browse files

add And Op

parent 102f1995
No related branches found
No related tags found
2 merge requests!93Release v0.3.0,!75Learning backend cuda
......@@ -13,6 +13,7 @@
#define AIDGE_CPU_IMPORTS_H_
#include "aidge/backend/cpu/operator/AddImpl.hpp"
#include "aidge/backend/cpu/operator/AndImpl.hpp"
#include "aidge/backend/cpu/operator/ArgMaxImpl.hpp"
#include "aidge/backend/cpu/operator/AvgPoolingImpl.hpp"
#include "aidge/backend/cpu/operator/MaxPoolingImpl.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_OPERATOR_ANDIMPL_H_
#define AIDGE_CPU_OPERATOR_ANDIMPL_H_
#include "aidge/backend/OperatorImpl.hpp"
#include "aidge/operator/And.hpp"
#include "aidge/utils/Registrar.hpp"
#include "aidge/utils/Types.h"
#include "aidge/backend/cpu/data/GetCPUPtr.h"
#include <memory>
#include <vector>
namespace Aidge {
// compute kernel registry for forward and backward
class AndImplForward_cpu
: public Registrable<AndImplForward_cpu, std::tuple<DataType, DataType, DataType>, void(const std::vector<std::size_t>&, const std::vector<std::size_t>&, const std::vector<std::size_t>&, const void*, const void*,void*)> {
};
class AndImplBackward_cpu
: public Registrable<AndImplBackward_cpu, std::tuple<DataType, DataType, DataType>, void(const std::vector<std::size_t>&, const std::vector<std::size_t>&, const std::vector<std::size_t>&, const void*, const void*, void*)> {
};
class AndImpl_cpu : public OperatorImpl {
public:
AndImpl_cpu(const And_Op& op) : OperatorImpl(op, "cpu") {}
static std::unique_ptr<AndImpl_cpu> create(const And_Op& op) {
return std::make_unique<AndImpl_cpu>(op);
}
Elts_t getNbRequiredProtected(const IOIndex_t inputIdx) const override final;
void forward() override;
};
namespace {
static Registrar<And_Op> registrarAndImpl_cpu("cpu", Aidge::AndImpl_cpu::create);
}
} // namespace Aidge
#endif /* AIDGE_CPU_OPERATOR_ANDIMPL_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
*
********************************************************************************/
#ifndef AIDGE_CPU_OPERATOR_ANDIMPL_FORWARD_KERNEL_H_
#define AIDGE_CPU_OPERATOR_ANDIMPL_FORWARD_KERNEL_H_
#include "aidge/backend/cpu/data/Broadcasting.hpp"
#include "aidge/backend/cpu/operator/AndImpl.hpp"
#include "aidge/utils/Registrar.hpp"
namespace Aidge {
template <class I1, class I2, class O>
void AndImpl_cpu_forward_kernel(const std::vector<std::size_t>& input1Dims,
const std::vector<std::size_t>& input2Dims,
const std::vector<std::size_t>& outputDims,
const void* input1_,
const void* input2_,
void* output_) {
const I1* input_1 = static_cast<const I1*>(input1_);
const I2* input_2 = static_cast<const I2*>(input2_);
O* output = static_cast<O*>(output_);
size_t totalElements = 1;
for (size_t dimSize : outputDims) {
totalElements *= dimSize;
}
for (std::size_t oIndex = 0; oIndex < totalElements; ++oIndex)
{
std::vector<size_t> indexes = getMultiDimIndices(outputDims, oIndex);
std::size_t idx1 = getFlattenedIndex(input1Dims, indexes);
std::size_t idx2 = getFlattenedIndex(input2Dims, indexes);
output[oIndex] = static_cast<O>(input_1[idx1] == input_2[idx2]);
}
}
namespace {
static Registrar<AndImplForward_cpu> registrarAndImplForward_cpu_Float32(
{DataType::Float32, DataType::Float32, DataType::Float32},
Aidge::AndImpl_cpu_forward_kernel<float, float, float>);
static Registrar<AndImplForward_cpu> registrarAndImplForward_cpu_Float64(
{DataType::Float64, DataType::Float64, DataType::Float64},
Aidge::AndImpl_cpu_forward_kernel<double, double, double>);
static Registrar<AndImplForward_cpu> registrarAndImplForward_cpu_Int32(
{DataType::Int32, DataType::Int32, DataType::Int32},
Aidge::AndImpl_cpu_forward_kernel<std::int32_t, std::int32_t, std::int32_t>);
static Registrar<AndImplForward_cpu> registrarAndImplForward_cpu_Int64(
{DataType::Int64, DataType::Int64, DataType::Int64},
Aidge::AndImpl_cpu_forward_kernel<std::int64_t, std::int64_t, std::int64_t>);
} // namespace
} // namespace Aidge
#endif /* AIDGE_CPU_OPERATOR_ANDIMPL_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 <cassert>
#include <chrono> // std::chrono::milliseconds
#include <numeric> // std::accumulate
#include <thread> // std::this_thread::sleep_for
#include <vector>
#include "aidge/operator/And.hpp"
#include "aidge/utils/Types.h"
#include "aidge/backend/cpu/data/Broadcasting.hpp"
#include "aidge/backend/cpu/data/GetCPUPtr.h"
#include "aidge/backend/cpu/operator/AndImpl.hpp"
#include "aidge/backend/cpu/operator/AndImpl_forward_kernels.hpp"
Aidge::Elts_t Aidge::AndImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const {
// this implementation can be in-place
return Elts_t::DataElts(0);
}
void Aidge::AndImpl_cpu::forward() {
// Find the correct kernel type
auto kernelFunc = Registrar<AndImplForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(1))->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()});
const std::vector<std::size_t> inputDims0 = getBroadcastedDims(std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dims());
const std::vector<std::size_t> inputDims1 = getBroadcastedDims(std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(1))->dims());
// Call kernel
kernelFunc(inputDims0,
inputDims1,
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dims(),
getCPUPtr(mOp.getRawInput(0)),
getCPUPtr(mOp.getRawInput(1)),
getCPUPtr(mOp.getRawOutput(0)));
}
/********************************************************************************
* 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 <catch2/catch_test_macros.hpp>
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/And.hpp"
#include "aidge/backend/cpu.hpp"
using namespace Aidge;
TEST_CASE("[cpu/operator] And(forward)", "[And][CPU]") {
SECTION("Same size inputs") {
std::shared_ptr<Tensor> input1 = std::make_shared<Tensor>(Array4D<int,3,3,3,2> {
{ //
{ //
{{20, 15},{31, 11},{22, 49}}, //
{{41, 10},{24, 51},{27, 52}}, //
{{26, 53},{27, 54},{28, 55}} //
}, //
{ //
{{29, 56},{30, 57},{31, 58}}, //
{{32, 59},{33, 60},{34, 61}}, //
{{35, 62},{36, 63},{37, 64}} //
}, //
{ //
{{38, 65},{39, 66},{40, 67}}, //
{{41, 68},{42, 69},{43, 70}}, //
{{44, 71},{45, 72},{46, 73}} //
} //
} //
}); //
std::shared_ptr<Tensor> input2 = std::make_shared<Tensor>(Array4D<int,3,3,3,2> {
{ //
{ //
{{20, 47},{21, 48},{22, 49}}, //
{{23, 50},{24, 51},{25, 52}}, //
{{17, 53},{27, 26},{14, 33}} //
}, //
{ //
{{29, 56},{30, 57},{31, 58}}, //
{{72, 44},{33, 20},{27, 55}}, //
{{35, 24},{25, 63},{28, 64}} //
}, //
{ //
{{32, 65},{39, 66},{40, 70}}, //
{{41, 53},{42, 60},{34, 70}}, //
{{44, 71},{30, 12},{46, 73}} //
} //
} //
}); //
std::shared_ptr<Tensor> expectedOutput = std::make_shared<Tensor>(Array4D<int,3,3,3,2> {
{
{
{{1, 0},{0, 0},{1, 1}},
{{0, 0},{1, 1},{0, 1}},
{{0, 1},{1, 0},{0, 0}}
},
{
{{1, 1},{1, 1},{1, 1}},
{{0, 0},{1, 0},{0, 0}},
{{1, 0},{0, 1},{0, 1}}
},
{
{{0, 1},{1, 1},{1, 0}},
{{1, 0},{1, 0},{0, 1}},
{{1, 1},{0, 0},{1, 1}}
}
}
});
std::shared_ptr<Node> myAnd = And();
auto op = std::static_pointer_cast<OperatorTensor>(myAnd -> getOperator());
op->associateInput(0, input1);
op->associateInput(1, input2);
op->setBackend("cpu");
op->setDataType(DataType::Int32);
myAnd->forward();
REQUIRE(*(op->getOutput(0)) == *expectedOutput);
}
SECTION("Broadcasting") {
std::shared_ptr<Tensor> input_1 = std::make_shared<Tensor>(Array4D<int,1,3,3,2> {
{ //
{ //
{{10, 20},{22, 23},{20, 20}}, //
{{10, 15},{10, 29},{20, 20}}, //
{{26, 25},{33, 20},{10, 20}} //
} //
} //
}); //
std::shared_ptr<Tensor> input_2 = std::make_shared<Tensor>(Array1D<int,2> {{10, 20}});
std::shared_ptr<Tensor> expectedOutput = std::make_shared<Tensor>(Array4D<int,1,3,3,2> {
{ //
{ //
{{ 1, 1},{ 0, 0},{ 0, 1}}, //
{{ 1, 0},{ 1, 0},{ 0, 1}}, //
{{ 0, 0},{ 0, 1},{ 1, 1}} //
} //
} //
}); //
std::shared_ptr<Node> myAnd = And();
auto op = std::static_pointer_cast<OperatorTensor>(myAnd -> getOperator());
op->associateInput(0, input_1);
op->associateInput(1, input_2);
op->setDataType(DataType::Int32);
op->setBackend("cpu");
myAnd->forward();
op->getOutput(0)->print();
expectedOutput->print();
REQUIRE(*op->getOutput(0) == *expectedOutput);
}
}
\ No newline at end of file
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