Skip to content
Snippets Groups Projects
Commit 919dda1e authored by Olivier BICHLER's avatar Olivier BICHLER
Browse files

Move transpose default impl to core

parent e3dd40c9
No related branches found
No related tags found
2 merge requests!610.2.2,!54Make forwardDims() optional and handle data dependency & moved several operators impl to core
Pipeline #43936 failed
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include "aidge/backend/cpu/operator/SoftmaxImpl.hpp" #include "aidge/backend/cpu/operator/SoftmaxImpl.hpp"
#include "aidge/backend/cpu/operator/SubImpl.hpp" #include "aidge/backend/cpu/operator/SubImpl.hpp"
#include "aidge/backend/cpu/operator/TanhImpl.hpp" #include "aidge/backend/cpu/operator/TanhImpl.hpp"
#include "aidge/backend/cpu/operator/TransposeImpl.hpp"
#include "aidge/backend/cpu/data/TensorImpl.hpp" #include "aidge/backend/cpu/data/TensorImpl.hpp"
......
/********************************************************************************
* 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_TransposeIMPL_H_
#define AIDGE_CPU_OPERATOR_TransposeIMPL_H_
#include "aidge/backend/OperatorImpl.hpp"
#include "aidge/operator/Transpose.hpp"
#include "aidge/utils/Registrar.hpp"
#include "aidge/utils/Types.h"
#include <memory>
#include <vector>
namespace Aidge {
// class Transpose_Op;
// compute kernel registry for forward and backward
class TransposeImpl2DForward_cpu
: public Registrable<TransposeImpl2DForward_cpu, std::tuple<DataType, DataType>, void( const typename Transpose_Op<2>::Attrs& attrs, const std::vector<DimSize_t>&, const std::vector<DimSize_t>&, const void*, void*)> {
};
class TransposeImpl3DForward_cpu
: public Registrable<TransposeImpl3DForward_cpu, std::tuple<DataType, DataType>, void( const typename Transpose_Op<3>::Attrs& attrs, const std::vector<DimSize_t>&, const std::vector<DimSize_t>&, const void*, void*)> {
};
class TransposeImpl4DForward_cpu
: public Registrable<TransposeImpl4DForward_cpu, std::tuple<DataType, DataType>, void( const typename Transpose_Op<4>::Attrs& attrs, const std::vector<DimSize_t>&, const std::vector<DimSize_t>&, const void*, void*)> {
};
class TransposeImpl5DForward_cpu
: public Registrable<TransposeImpl5DForward_cpu, std::tuple<DataType, DataType>, void( const typename Transpose_Op<5>::Attrs& attrs, const std::vector<DimSize_t>&, const std::vector<DimSize_t>&, const void*, void*)> {
};
class TransposeImpl6DForward_cpu
: public Registrable<TransposeImpl6DForward_cpu, std::tuple<DataType, DataType>, void( const typename Transpose_Op<6>::Attrs& attrs, const std::vector<DimSize_t>&, const std::vector<DimSize_t>&, const void*, void*)> {
};
class TransposeImpl2DBackward_cpu
: public Registrable<TransposeImpl2DBackward_cpu, std::tuple<DataType, DataType>, void( const typename Transpose_Op<2>::Attrs& attrs, const std::vector<DimSize_t>&, const std::vector<DimSize_t>&, const void*, void*)> {
};
class TransposeImpl3DBackward_cpu
: public Registrable<TransposeImpl3DBackward_cpu, std::tuple<DataType, DataType>, void( const typename Transpose_Op<3>::Attrs& attrs, const std::vector<DimSize_t>&, const std::vector<DimSize_t>&, const void*, void*)> {
};
class TransposeImpl4DBackward_cpu
: public Registrable<TransposeImpl4DBackward_cpu, std::tuple<DataType, DataType>, void( const typename Transpose_Op<4>::Attrs& attrs, const std::vector<DimSize_t>&, const std::vector<DimSize_t>&, const void*, void*)> {
};
class TransposeImpl5DBackward_cpu
: public Registrable<TransposeImpl5DBackward_cpu, std::tuple<DataType, DataType>, void( const typename Transpose_Op<5>::Attrs& attrs, const std::vector<DimSize_t>&, const std::vector<DimSize_t>&, const void*, void*)> {
};
class TransposeImpl6DBackward_cpu
: public Registrable<TransposeImpl6DBackward_cpu, std::tuple<DataType, DataType>, void( const typename Transpose_Op<6>::Attrs& attrs, const std::vector<DimSize_t>&, const std::vector<DimSize_t>&, const void*, void*)> {
};
class TransposeImpl2D_cpu : public OperatorImpl {
public:
TransposeImpl2D_cpu(const Transpose_Op<2>& op) : OperatorImpl(op, "cpu") {}
static std::unique_ptr<TransposeImpl2D_cpu> create(const Transpose_Op<2>& op) {
return std::make_unique<TransposeImpl2D_cpu>(op);
}
void forward() override;
};
class TransposeImpl3D_cpu : public OperatorImpl {
public:
TransposeImpl3D_cpu(const Transpose_Op<3>& op) : OperatorImpl(op, "cpu") {}
static std::unique_ptr<TransposeImpl3D_cpu> create(const Transpose_Op<3>& op) {
return std::make_unique<TransposeImpl3D_cpu>(op);
}
void forward() override;
};
class TransposeImpl4D_cpu : public OperatorImpl {
public:
TransposeImpl4D_cpu(const Transpose_Op<4>& op) : OperatorImpl(op, "cpu") {}
static std::unique_ptr<TransposeImpl4D_cpu> create(const Transpose_Op<4>& op) {
return std::make_unique<TransposeImpl4D_cpu>(op);
}
void forward() override;
};
class TransposeImpl5D_cpu : public OperatorImpl {
public:
TransposeImpl5D_cpu(const Transpose_Op<5>& op) : OperatorImpl(op, "cpu") {}
static std::unique_ptr<TransposeImpl5D_cpu> create(const Transpose_Op<5>& op) {
return std::make_unique<TransposeImpl5D_cpu>(op);
}
void forward() override;
};
class TransposeImpl6D_cpu : public OperatorImpl {
public:
TransposeImpl6D_cpu(const Transpose_Op<6>& op) : OperatorImpl(op, "cpu") {}
static std::unique_ptr<TransposeImpl6D_cpu> create(const Transpose_Op<6>& op) {
return std::make_unique<TransposeImpl6D_cpu>(op);
}
void forward() override;
};
namespace {
static Registrar<Transpose_Op<2>> registrarTransposeImpl2D_cpu("cpu", Aidge::TransposeImpl2D_cpu::create);
static Registrar<Transpose_Op<3>> registrarTransposeImpl3D_cpu("cpu", Aidge::TransposeImpl3D_cpu::create);
static Registrar<Transpose_Op<4>> registrarTransposeImpl4D_cpu("cpu", Aidge::TransposeImpl4D_cpu::create);
static Registrar<Transpose_Op<5>> registrarTransposeImpl5D_cpu("cpu", Aidge::TransposeImpl5D_cpu::create);
static Registrar<Transpose_Op<6>> registrarTransposeImpl6D_cpu("cpu", Aidge::TransposeImpl6D_cpu::create);
}
} // namespace Aidge
#endif /* AIDGE_CPU_OPERATOR_TransposeIMPL_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_TRANSPOSEIMPL_FORWARD_KERNEL_H_
#define AIDGE_CPU_OPERATOR_TRANSPOSEIMPL_FORWARD_KERNEL_H_
#include "aidge/utils/Registrar.hpp"
#include <cstddef>
#include <cmath>
#include "aidge/data/Data.hpp"
#include "aidge/utils/Types.h"
#include "aidge/backend/cpu/operator/TransposeImpl.hpp"
namespace Aidge {
template <class I, class O, DimSize_t DIM>
void TransposeImpl_cpu_forward_kernel( const typename Transpose_Op<DIM>::Attrs& attrs, const std::vector<DimSize_t>& inputDims, const std::vector<DimSize_t>& outputDims, const void* input_, void* output_)
{
O* output = static_cast<O*>(output_);
const I* input = static_cast<const I*>(input_);
// Compute total number of elements in the input array
size_t totalElements = 1;
for (size_t dimSize : inputDims) {
totalElements *= dimSize;
}
std::vector<std::size_t> outStrides(DIM, 1);
for (size_t i = 0; i < DIM; ++i) {
for (size_t j = i+1; j < DIM; ++j)
{
outStrides[i] *= outputDims[j];
}
}
std::vector<size_t> indices(outputDims.size(), 0);
for (size_t i = 0; i < totalElements; ++i) {
size_t idx = 0;
// Permute indices based on OutputDimsOrder attr
std::vector<size_t> permutedIndices(DIM);
for (size_t j = 0; j < DIM; ++j) {
permutedIndices[j] = indices[std::get<0>(attrs)[j]];
}
for (int j = DIM -1; j >=0; --j) {
idx += permutedIndices[j] * outStrides[j];
}
// Copy the value in output
output[idx] = input[i];
// Update indices for the next iteration
for (int j = DIM - 1; j >= 0; --j) {
if (indices[j] < inputDims[j] - 1) {
indices[j]++;
break;
} else {
indices[j] = 0;
}
}
}
}
namespace {
// DIM = 2
static Registrar<TransposeImpl2DForward_cpu> registrarTransposeImpl2DForward_cpu_Float32(
{DataType::Float32, DataType::Float32}, Aidge::TransposeImpl_cpu_forward_kernel<float, float, 2>);
static Registrar<TransposeImpl2DForward_cpu> registrarTransposeImpl2DForward_cpu_Int32(
{DataType::Int32, DataType::Int32}, Aidge::TransposeImpl_cpu_forward_kernel<int, int, 2>);
static Registrar<TransposeImpl2DForward_cpu> registrarTransposeImpl2DForward_cpu_Float64(
{DataType::Float64, DataType::Float64}, Aidge::TransposeImpl_cpu_forward_kernel<double, double, 2>);
// DIM = 3
static Registrar<TransposeImpl3DForward_cpu> registrarTransposeImpl3DForward_cpu_Float32(
{DataType::Float32, DataType::Float32}, Aidge::TransposeImpl_cpu_forward_kernel<float, float, 3>);
static Registrar<TransposeImpl3DForward_cpu> registrarTransposeImpl3DForward_cpu_Int32(
{DataType::Int32, DataType::Int32}, Aidge::TransposeImpl_cpu_forward_kernel<int, int, 3>);
static Registrar<TransposeImpl3DForward_cpu> registrarTransposeImpl3DForward_cpu_Float64(
{DataType::Float64, DataType::Float64}, Aidge::TransposeImpl_cpu_forward_kernel<double, double, 3>);
// DIM = 4
static Registrar<TransposeImpl4DForward_cpu> registrarTransposeImpl4DForward_cpu_Float32(
{DataType::Float32, DataType::Float32}, Aidge::TransposeImpl_cpu_forward_kernel<float, float, 4>);
static Registrar<TransposeImpl4DForward_cpu> registrarTransposeImpl4DForward_cpu_Int32(
{DataType::Int32, DataType::Int32}, Aidge::TransposeImpl_cpu_forward_kernel<int, int, 4>);
static Registrar<TransposeImpl4DForward_cpu> registrarTransposeImpl4DForward_cpu_Float64(
{DataType::Float64, DataType::Float64}, Aidge::TransposeImpl_cpu_forward_kernel<double, double, 4>);
// DIM = 5
static Registrar<TransposeImpl5DForward_cpu> registrarTransposeImpl5DForward_cpu_Float32(
{DataType::Float32, DataType::Float32}, Aidge::TransposeImpl_cpu_forward_kernel<float, float, 5>);
static Registrar<TransposeImpl5DForward_cpu> registrarTransposeImpl5DForward_cpu_Int32(
{DataType::Int32, DataType::Int32}, Aidge::TransposeImpl_cpu_forward_kernel<int, int, 5>);
static Registrar<TransposeImpl5DForward_cpu> registrarTransposeImpl5DForward_cpu_Float64(
{DataType::Float64, DataType::Float64}, Aidge::TransposeImpl_cpu_forward_kernel<double, double, 5>);
// DIM = 6
static Registrar<TransposeImpl6DForward_cpu> registrarTransposeImpl6DForward_cpu_Float32(
{DataType::Float32, DataType::Float32}, Aidge::TransposeImpl_cpu_forward_kernel<float, float, 6>);
static Registrar<TransposeImpl6DForward_cpu> registrarTransposeImpl6DForward_cpu_Int32(
{DataType::Int32, DataType::Int32}, Aidge::TransposeImpl_cpu_forward_kernel<int, int, 6>);
static Registrar<TransposeImpl6DForward_cpu> registrarTransposeImpl6DForward_cpu_Float64(
{DataType::Float64, DataType::Float64}, Aidge::TransposeImpl_cpu_forward_kernel<double, double, 6>);
} // namespace
} // namespace Aidge
#endif /* AIDGE_CPU_OPERATOR_TRANSPOSEIMPL_FORWARD_KERNEL_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
*
********************************************************************************/
#include <cassert>
#include <chrono> // std::chrono::milliseconds
#include <numeric> // std::accumulate
#include <thread> // std::this_thread::sleep_for
#include <vector>
#include "aidge/utils/Types.h"
#include "aidge/operator/Transpose.hpp"
#include "aidge/backend/cpu/operator/TransposeImpl.hpp"
#include "aidge/backend/cpu/operator/TransposeImpl_forward_kernels.hpp"
void Aidge::TransposeImpl2D_cpu::forward() {
// Find the correct kernel type
auto kernelFunc =
Registrar<TransposeImpl2DForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()});
// auto attr = dynamic_cast<const Transpose_Op<2>&>(mOp).getStaticAttributes();
// std::vector<DimIdx_t> outDimsOrder;
// outDimsOrder.reserve(std::get<0>(attr).size()); // Reserve space for the new vector
// std::transform(std::get<0>(attr).begin(), std::get<0>(attr).end(), std::back_inserter(outDimsOrder),
// [](int intValue) { return static_cast<DimIdx_t>(intValue); });
// Call kernel
kernelFunc(dynamic_cast<const Transpose_Op<2>&>(mOp).getStaticAttributes(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr());
}
void Aidge::TransposeImpl3D_cpu::forward() {
// Find the correct kernel type
auto kernelFunc =
Registrar<TransposeImpl3DForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()});
// Call kernel
kernelFunc(dynamic_cast<const Transpose_Op<3>&>(mOp).getStaticAttributes(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr());
}
void Aidge::TransposeImpl4D_cpu::forward() {
// Find the correct kernel type
auto kernelFunc =
Registrar<TransposeImpl4DForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()});
// Call kernel
kernelFunc(dynamic_cast<const Transpose_Op<4>&>(mOp).getStaticAttributes(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr());
}
void Aidge::TransposeImpl5D_cpu::forward() {
// Find the correct kernel type
auto kernelFunc =
Registrar<TransposeImpl5DForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()});
// Call kernel
kernelFunc(dynamic_cast<const Transpose_Op<5>&>(mOp).getStaticAttributes(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr());
}
void Aidge::TransposeImpl6D_cpu::forward() {
// Find the correct kernel type
auto kernelFunc =
Registrar<TransposeImpl6DForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()});
// Call kernel
kernelFunc(dynamic_cast<const Transpose_Op<6>&>(mOp).getStaticAttributes(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr());
}
\ No newline at end of file
/********************************************************************************
* 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 <catch2/catch_test_macros.hpp>
#include <memory>
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/Transpose.hpp"
#include "aidge/backend/cpu.hpp"
using namespace Aidge;
TEST_CASE("[cpu/operator] Transpose(forward)") {
SECTION("3D Tensor") {
std::shared_ptr<Tensor> input = std::make_shared<Tensor>(Array3D<float,2,3,4> {
{
{{0.42507452, 0.11244237, 0.43243718, 0.62354952},
{0.90250170, 0.48719984, 0.45781207, 0.92536664},
{0.06348717, 0.91678733, 0.64452291, 0.00484818}},
{{0.66873497, 0.99508536, 0.55714869, 0.84887981},
{0.41666120, 0.92365038, 0.80034822, 0.38721532},
{0.52037925, 0.53937608, 0.66380072, 0.36330253}}
}
});
std::shared_ptr<Tensor> output = std::make_shared<Tensor>(Array3D<float,2,4,3> {
{
{{0.42507452, 0.90250170, 0.06348717},
{0.11244237, 0.48719984, 0.91678733},
{0.43243718, 0.45781207, 0.64452291},
{0.62354952, 0.92536664, 0.00484818}},
{{0.66873497, 0.41666120, 0.52037925},
{0.99508536, 0.92365038, 0.53937608},
{0.55714869, 0.80034822, 0.66380072},
{0.84887981, 0.38721532, 0.36330253}}
}
});
std::shared_ptr<Node> myTranspose = Transpose<3>(std::array<DimSize_t,3>{{0,2,1}});
auto op = std::static_pointer_cast<OperatorTensor>(myTranspose -> getOperator());
op->associateInput(0,input);
op->setDataType(DataType::Float32);
op->setBackend("cpu");
myTranspose->forward();
REQUIRE(*(op->getOutput(0)) == *output);
}
SECTION("4D Tensor") {
std::shared_ptr<Tensor> input = std::make_shared<Tensor>(Array4D<int,2,3,1,4> {
{
{
{
{1, 2, 3, 4}
},
{
{5, 6, 7, 8}
},
{
{9, 10, 11, 12}
}
},
{
{
{13, 14, 15, 16}
},
{
{17, 18, 19, 20}
},
{
{21, 22, 23, 24}
}
}
}
});
std::shared_ptr<Tensor> output = std::make_shared<Tensor>(Array4D<int,2,4,1,3> {
{
{
{
{1, 5, 9}
},
{
{2, 6, 10}
},
{
{3, 7, 11}
},
{
{4, 8, 12}
}
},
{
{
{13, 17, 21}
},
{
{14, 18, 22}
},
{
{15, 19, 23}
},
{
{16, 20, 24}
}
}
}
});
std::shared_ptr<Node> myTranspose = Transpose<4>(std::array<DimSize_t,4>{{0,3,2,1}});
auto op = std::static_pointer_cast<OperatorTensor>(myTranspose -> getOperator());
op->associateInput(0,input);
op->setDataType(DataType::Int32);
op->setBackend("cpu");
myTranspose->forward();
REQUIRE(*(op->getOutput(0)) == *output);
}
}
\ 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