Skip to content
Snippets Groups Projects
Commit 4c8346ef authored by Grégoire Kubler's avatar Grégoire Kubler
Browse files

Merge branch 'dev' of...

Merge branch 'dev' of https://gitlab.eclipse.org/eclipse/aidge/aidge_backend_cpu into feat/operator_globalAveragePooling
parents 58cf56e8 07d50e6a
No related branches found
No related tags found
2 merge requests!50version 0.2.0,!42feat/operator_globalAveragePooling
...@@ -9,32 +9,34 @@ ...@@ -9,32 +9,34 @@
* *
********************************************************************************/ ********************************************************************************/
#include <cassert> #include "aidge/backend/cpu/operator/ErfImpl.hpp"
#include <chrono> // std::chrono::milliseconds
#include <numeric> // std::accumulate #include <memory>
#include <thread> // std::this_thread::sleep_for
#include <vector> #include <vector>
#include "aidge/backend/cpu/operator/ErfImpl_forward_kernels.hpp"
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/Erf.hpp" #include "aidge/operator/Erf.hpp"
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/backend/cpu/operator/ErfImpl.hpp"
#include "aidge/backend/cpu/operator/ErfImpl_forward_kernels.hpp"
Aidge::NbElts_t Aidge::ErfImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const { Aidge::NbElts_t Aidge::ErfImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const {
// this implementation can be in-place // this implementation can be in-place
return 0; return 0;
} }
void Aidge::ErfImpl_cpu::forward() { void Aidge::ErfImpl_cpu::forward() {
const Erf_Op& op = static_cast<const Erf_Op&>(mOp);
// Find the correct kernel type // Find the correct kernel type
auto kernelFunc = Registrar<ErfImplForward_cpu>::create({ auto kernelFunc = Registrar<ErfImplForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(), op.getInput(0)->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()}); op.getOutput(0)->dataType()
});
// Call kernel // Call kernel
kernelFunc(std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->size(), kernelFunc(
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(), op.getInput(0)->size(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr()); op.getInput(0)->getImpl()->rawPtr(),
op.getOutput(0)->getImpl()->rawPtr()
);
} }
...@@ -9,31 +9,34 @@ ...@@ -9,31 +9,34 @@
* *
********************************************************************************/ ********************************************************************************/
#include <cassert> #include "aidge/backend/cpu/operator/FCImpl.hpp"
#include <chrono> // std::chrono::milliseconds
#include <numeric> // std::accumulate #include <cstddef> // std::size_t
#include <thread> // std::this_thread::sleep_for #include <functional>
#include <vector> #include <memory>
#include <tuple>
#include "aidge/backend/cpu/data/GetCPUPtr.h"
#include "aidge/backend/cpu/operator/FCImpl_backward_kernels.hpp"
#include "aidge/backend/cpu/operator/FCImpl_forward_kernels.hpp"
#include "aidge/operator/FC.hpp" #include "aidge/operator/FC.hpp"
#include "aidge/utils/ErrorHandling.hpp"
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/backend/cpu/data/GetCPUPtr.h"
#include "aidge/backend/cpu/operator/FCImpl.hpp"
#include "aidge/backend/cpu/operator/FCImpl_forward_kernels.hpp"
void Aidge::FCImpl_cpu::forward() void Aidge::FCImpl_cpu::forward()
{ {
assert(std::static_pointer_cast<Tensor>(mOp.getRawInput(0)) && "missing input #0"); const FC_Op& op_ = dynamic_cast<const FC_Op&>(mOp);
assert(std::static_pointer_cast<Tensor>(mOp.getRawInput(1)) && "missing input #1"); AIDGE_ASSERT(op_.getInput(0), "missing input #0");
assert(std::static_pointer_cast<Tensor>(mOp.getRawInput(2)) && "missing input #2"); AIDGE_ASSERT(op_.getInput(1), "missing input #1");
AIDGE_ASSERT(op_.getInput(2), "missing input #2");
// Find the correct kernel type // Find the correct kernel type
const auto outputDataType = std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType(); const auto outputDataType = op_.getOutput(0)->dataType();
const Registrar<FCImplForward_cpu>::registrar_key registrarKey = { const Registrar<FCImplForward_cpu>::registrar_key registrarKey = {
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(), op_.getInput(0)->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(1))->dataType(), op_.getInput(1)->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(2))->dataType(), op_.getInput(2)->dataType(),
outputDataType}; outputDataType};
Registrar<FCImplForward_cpu>::registrar_type kernelFunc; Registrar<FCImplForward_cpu>::registrar_type kernelFunc;
...@@ -52,9 +55,9 @@ void Aidge::FCImpl_cpu::forward() ...@@ -52,9 +55,9 @@ void Aidge::FCImpl_cpu::forward()
// call to forward(). We might put the following shared_ptr as members of // call to forward(). We might put the following shared_ptr as members of
// this class to avoid that. // this class to avoid that.
std::shared_ptr<Tensor> input0Fallback, input1Fallback, input2Fallback; std::shared_ptr<Tensor> input0Fallback, input1Fallback, input2Fallback;
const auto& input0 = std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->refCastFrom(input0Fallback, *std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))); const auto& input0 = op_.getInput(0)->refCastFrom(input0Fallback, *(op_.getOutput(0)));
const auto& input1 = std::static_pointer_cast<Tensor>(mOp.getRawInput(1))->refCastFrom(input1Fallback, *std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))); const auto& input1 = op_.getInput(1)->refCastFrom(input1Fallback, *(op_.getOutput(0)));
const auto& input2 = std::static_pointer_cast<Tensor>(mOp.getRawInput(2))->refCastFrom(input2Fallback, *std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))); const auto& input2 = op_.getInput(2)->refCastFrom(input2Fallback, *(op_.getOutput(0)));
// Call kernel // Call kernel
const auto batchSize = (input0.dims().size() > 1) ? input0.dims()[0] : 1; const auto batchSize = (input0.dims().size() > 1) ? input0.dims()[0] : 1;
...@@ -64,3 +67,49 @@ void Aidge::FCImpl_cpu::forward() ...@@ -64,3 +67,49 @@ void Aidge::FCImpl_cpu::forward()
input0.getImpl()->rawPtr(), input1.getImpl()->rawPtr(), input2.getImpl()->rawPtr(), input0.getImpl()->rawPtr(), input1.getImpl()->rawPtr(), input2.getImpl()->rawPtr(),
getCPUPtr(mOp.getRawOutput(0))); getCPUPtr(mOp.getRawOutput(0)));
} }
void Aidge::FCImpl_cpu::backward()
{
const FC_Op& op_ = dynamic_cast<const FC_Op&>(mOp);
const auto& fc_grad = op_.getOutput(0)->grad();
assert(fc_grad && "missing ouput #0 gradient");
// Find the correct kernel type
const Registrar<FCImplBackward_cpu>::registrar_key registrarKey = {
fc_grad->dataType(),
op_.getInput(0)->grad()->dataType(),
op_.getInput(1)->grad()->dataType(),
op_.getInput(2)->grad()->dataType()};
Registrar<FCImplBackward_cpu>::registrar_type kernelFunc;
if (Registrar<FCImplBackward_cpu>::exists(registrarKey)) {
// One exists with the right inputs/output types
kernelFunc = Registrar<FCImplBackward_cpu>::create(registrarKey);
}
else {
// Otherwise, fallback to the kernel with all types matching output type
kernelFunc = Registrar<FCImplBackward_cpu>::create({
fc_grad->dataType(), fc_grad->dataType(), fc_grad->dataType(), fc_grad->dataType()});
}
// Convert input data (no overhead if not needed!)
// TODO: right now, if needed, memory will be allocated/deallocated at each
// call to forward(). We might put the following shared_ptr as members of
// this class to avoid that.
std::shared_ptr<Tensor> input0gradFallback, input1gradFallback, input2gradFallback;
const auto& input0grad = op_.getInput(0)->grad()->refCastFrom(input0gradFallback, *(op_.getOutput(0)));
const auto& input1grad = op_.getInput(1)->grad()->refCastFrom(input1gradFallback, *(op_.getOutput(0)));
const auto& input2grad = op_.getInput(2)->grad()->refCastFrom(input2gradFallback, *(op_.getOutput(0)));
// Call kernel
const auto batchSize = (input0grad.dims().size() > 1) ? input0grad.dims()[0] : 1;
kernelFunc(dynamic_cast<const FC_Op&>(mOp).getStaticAttributes(),
batchSize,
input0grad.size() / batchSize,
getCPUPtr(fc_grad),
getCPUPtr(op_.getInput(0)),
getCPUPtr(mOp.getRawInput(1)),
input0grad.getImpl()->rawPtr(),
input1grad.getImpl()->rawPtr(),
input2grad.getImpl()->rawPtr());
}
...@@ -9,32 +9,34 @@ ...@@ -9,32 +9,34 @@
* *
********************************************************************************/ ********************************************************************************/
#include <cassert> #include "aidge/backend/cpu/operator/GatherImpl.hpp"
#include <chrono> // std::chrono::milliseconds
#include <numeric> // std::accumulate #include <memory>
#include <thread> // std::this_thread::sleep_for
#include <vector> #include <vector>
#include "aidge/backend/cpu/operator/GatherImpl_forward_kernels.hpp"
#include "aidge/data/Data.hpp"
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/Gather.hpp" #include "aidge/operator/Gather.hpp"
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/backend/cpu/operator/GatherImpl.hpp"
#include "aidge/backend/cpu/operator/GatherImpl_forward_kernels.hpp"
Aidge::NbElts_t Aidge::GatherImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const { Aidge::NbElts_t Aidge::GatherImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const {
// this implementation can be in-place // this implementation can be in-place
return 0; return 0;
} }
void Aidge::GatherImpl_cpu::forward() { void Aidge::GatherImpl_cpu::forward() {
const Gather_Op& op = static_cast<const Gather_Op&>(mOp);
auto kernelFunc = Registrar<GatherImplForward_cpu>::create({ auto kernelFunc = Registrar<GatherImplForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(), op.getInput(0)->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()}); op.getOutput(0)->dataType()
});
// Call kernel // Call kernel
kernelFunc(dynamic_cast<const Gather_Op&>(mOp).getStaticAttributes(), kernelFunc(dynamic_cast<const Gather_Op&>(mOp).getStaticAttributes(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dims(), op.getInput(0)->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(), op.getInput(0)->getImpl()->rawPtr(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr()); op.getOutput(0)->getImpl()->rawPtr()
);
} }
...@@ -10,17 +10,17 @@ ...@@ -10,17 +10,17 @@
********************************************************************************/ ********************************************************************************/
#include <cassert> #include <cassert>
#include <chrono> // std::chrono::milliseconds
#include <numeric> // std::accumulate
#include <thread> // std::this_thread::sleep_for
#include <vector> #include <vector>
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/LeakyReLU.hpp" #include "aidge/operator/LeakyReLU.hpp"
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/utils/Registrar.hpp"
#include "aidge/backend/cpu/data/GetCPUPtr.h" #include "aidge/backend/cpu/data/GetCPUPtr.h"
#include "aidge/backend/cpu/operator/LeakyReLUImpl.hpp" #include "aidge/backend/cpu/operator/LeakyReLUImpl.hpp"
#include "aidge/backend/cpu/operator/LeakyReLUImpl_forward_kernels.hpp" #include "aidge/backend/cpu/operator/LeakyReLUImpl_forward_kernels.hpp"
#include "aidge/backend/cpu/operator/LeakyReLUImpl_backward_kernels.hpp"
Aidge::NbElts_t Aidge::LeakyReLUImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const { Aidge::NbElts_t Aidge::LeakyReLUImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const {
// this implementation can be in-place // this implementation can be in-place
...@@ -28,16 +28,38 @@ Aidge::NbElts_t Aidge::LeakyReLUImpl_cpu::getNbRequiredProtected(const Aidge::IO ...@@ -28,16 +28,38 @@ Aidge::NbElts_t Aidge::LeakyReLUImpl_cpu::getNbRequiredProtected(const Aidge::IO
} }
void Aidge::LeakyReLUImpl_cpu::forward() { void Aidge::LeakyReLUImpl_cpu::forward() {
assert(std::static_pointer_cast<Tensor>(mOp.getRawInput(0)) && "missing input #0"); const LeakyReLU_Op& op_ = dynamic_cast<const LeakyReLU_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 // Find the correct kernel type
auto kernelFunc = Registrar<LeakyReLUImplForward_cpu>::create({ auto kernelFunc = Registrar<LeakyReLUImplForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(), in0->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()}); out0->dataType()});
// Call kernel // Call kernel
kernelFunc(dynamic_cast<const LeakyReLU_Op&>(mOp).getStaticAttributes(), kernelFunc(dynamic_cast<const LeakyReLU_Op&>(mOp).getStaticAttributes(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->size(), in0->size(),
getCPUPtr(mOp.getRawInput(0)), getCPUPtr(mOp.getRawInput(0)),
getCPUPtr(mOp.getRawOutput(0))); getCPUPtr(mOp.getRawOutput(0)));
} }
void Aidge::LeakyReLUImpl_cpu::backward() {
// reversing in and out Data for backprop
const LeakyReLU_Op& op_ = dynamic_cast<const LeakyReLU_Op&>(mOp);
std::shared_ptr<Tensor> in0 = op_.getOutput(0)->grad();
std::shared_ptr<Tensor> out0 = op_.getInput(0)->grad();
AIDGE_ASSERT(in0, "missing input #0");
// Find the correct kernel type
auto kernelFunc = Registrar<LeakyReLUImplForward_cpu>::create({
in0->dataType(),
out0->dataType()});
// Call kernel
kernelFunc(dynamic_cast<const LeakyReLU_Op&>(mOp).getStaticAttributes(),
in0->size(),
getCPUPtr(in0),
getCPUPtr(out0));
}
\ No newline at end of file
...@@ -48,3 +48,25 @@ void Aidge::PowImpl_cpu::forward() { ...@@ -48,3 +48,25 @@ void Aidge::PowImpl_cpu::forward() {
getCPUPtr(mOp.getRawInput(1)), getCPUPtr(mOp.getRawInput(1)),
getCPUPtr(mOp.getRawOutput(0))); getCPUPtr(mOp.getRawOutput(0)));
} }
void Aidge::PowImpl_cpu::backward() {
// Find the correct kernel type
const Pow_Op& op_ = dynamic_cast<const Pow_Op&>(mOp);
auto kernelFunc = Registrar<PowImplForward_cpu>::create({
op_.getOutput(0)->grad()->dataType(),
op_.getInput(0)->grad()->dataType(),
op_.getInput(1)->grad()->dataType()});
const std::vector<std::size_t> input0gradDims = getBroadcastedDims(op_.getInput(0)->grad()->dims(),
op_.getOutput(0)->grad()->dims());
const std::vector<std::size_t> input1gradDims = getBroadcastedDims(op_.getInput(1)->grad()->dims(),
op_.getOutput(0)->grad()->dims());
// Call kernel
kernelFunc(op_.getOutput(0)->grad()->dims(),
input0gradDims,
input1gradDims,
getCPUPtr(mOp.getRawOutput(0)),
getCPUPtr(mOp.getRawInput(0)),
getCPUPtr(mOp.getRawInput(1)));
}
\ No newline at end of file
...@@ -9,18 +9,18 @@ ...@@ -9,18 +9,18 @@
* *
********************************************************************************/ ********************************************************************************/
#include <cassert> #include <memory>
#include <chrono> // std::chrono::milliseconds
#include <numeric> // std::accumulate
#include <thread> // std::this_thread::sleep_for
#include <vector> #include <vector>
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/ReLU.hpp" #include "aidge/operator/ReLU.hpp"
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/backend/cpu/data/GetCPUPtr.h" #include "aidge/backend/cpu/data/GetCPUPtr.h"
#include "aidge/utils/ErrorHandling.hpp"
#include "aidge/backend/cpu/operator/ReLUImpl.hpp" #include "aidge/backend/cpu/operator/ReLUImpl.hpp"
#include "aidge/backend/cpu/operator/ReLUImpl_forward_kernels.hpp" #include "aidge/backend/cpu/operator/ReLUImpl_forward_kernels.hpp"
#include "aidge/backend/cpu/operator/ReLUImpl_backward_kernels.hpp"
Aidge::NbElts_t Aidge::ReLUImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const { Aidge::NbElts_t Aidge::ReLUImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const {
// this implementation can be in-place // this implementation can be in-place
...@@ -28,15 +28,33 @@ Aidge::NbElts_t Aidge::ReLUImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex ...@@ -28,15 +28,33 @@ Aidge::NbElts_t Aidge::ReLUImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex
} }
void Aidge::ReLUImpl_cpu::forward() { void Aidge::ReLUImpl_cpu::forward() {
assert(std::static_pointer_cast<Tensor>(mOp.getRawInput(0)) && "missing input #0"); std::shared_ptr<Tensor> in0 = std::static_pointer_cast<Tensor>(mOp.getRawInput(0));
AIDGE_ASSERT(in0, "missing input #0");
// Find the correct kernel type // Find the correct kernel type
auto kernelFunc = Registrar<ReLUImplForward_cpu>::create({ auto kernelFunc = Registrar<ReLUImplForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(), in0->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()}); std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()});
// Call kernel // Call kernel
kernelFunc(std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->size(), kernelFunc(in0->size(),
getCPUPtr(mOp.getRawInput(0)), getCPUPtr(mOp.getRawInput(0)),
getCPUPtr(mOp.getRawOutput(0))); getCPUPtr(mOp.getRawOutput(0)));
} }
void Aidge::ReLUImpl_cpu::backward() {
// reversing in and out Tensors
const ReLU_Op& op_ = dynamic_cast<const ReLU_Op&>(mOp);
std::shared_ptr<Tensor> in0 = op_.getOutput(0)->grad();
std::shared_ptr<Tensor> out0 = op_.getInput(0)->grad();
AIDGE_ASSERT(out0, "current {} operator output#0 has not gradient Tensor.", op_.type());
// Find the correct kernel type
auto kernelFunc = Registrar<ReLUImplBackward_cpu>::create({
in0->dataType(),
out0->dataType()
});
// Call kernel
kernelFunc(in0->size(), getCPUPtr(in0), getCPUPtr(out0));
}
...@@ -9,71 +9,87 @@ ...@@ -9,71 +9,87 @@
* *
********************************************************************************/ ********************************************************************************/
#include <cassert> #include "aidge/backend/cpu/operator/ReduceMeanImpl.hpp"
#include <chrono> // std::chrono::milliseconds
#include <numeric> // std::accumulate #include <memory>
#include <thread> // std::this_thread::sleep_for
#include <vector> #include <vector>
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/operator/ReduceMean.hpp" #include "aidge/operator/ReduceMean.hpp"
#include "aidge/backend/cpu/operator/ReduceMeanImpl.hpp"
#include "aidge/backend/cpu/operator/ReduceMeanImpl_forward_kernels.hpp" #include "aidge/backend/cpu/operator/ReduceMeanImpl_forward_kernels.hpp"
Aidge::NbElts_t Aidge::ReduceMeanImpl1D_cpu::getNbRequiredProtected(IOIndex_t /*inputIdx*/) const {
// this implementation can be in-place Aidge::NbElts_t Aidge::ReduceMeanImpl_cpu::getNbRequiredProtected(IOIndex_t /*inputIdx*/) const {
return 0;
}
Aidge::NbElts_t Aidge::ReduceMeanImpl2D_cpu::getNbRequiredProtected(IOIndex_t /*inputIdx*/) const {
// this implementation can be in-place
return 0;
}
Aidge::NbElts_t Aidge::ReduceMeanImpl3D_cpu::getNbRequiredProtected(IOIndex_t /*inputIdx*/) const {
// this implementation can be in-place // this implementation can be in-place
return 0; return 0;
} }
// Aidge::NbElts_t Aidge::ReduceMeanImpl1D_cpu::getNbRequiredProtected(IOIndex_t /*inputIdx*/) const {
// // this implementation can be in-place
// return 0;
// }
// Aidge::NbElts_t Aidge::ReduceMeanImpl2D_cpu::getNbRequiredProtected(IOIndex_t /*inputIdx*/) const {
// // this implementation can be in-place
// return 0;
// }
// Aidge::NbElts_t Aidge::ReduceMeanImpl3D_cpu::getNbRequiredProtected(IOIndex_t /*inputIdx*/) const {
// // this implementation can be in-place
// return 0;
// }
void Aidge::ReduceMeanImpl1D_cpu::forward() { void Aidge::ReduceMeanImpl_cpu::forward() {
const ReduceMean_Op& op_ = dynamic_cast<const ReduceMean_Op&>(mOp);
// Find the correct kernel type // Find the correct kernel type
auto kernelFunc = auto kernelFunc = Registrar<ReduceMeanImplForward_cpu>::create({
Registrar<ReduceMeanImpl1DForward_cpu>::create({ op_.getInput(0)->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(), op_.getOutput(0)->dataType()});
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()});
// Call kernel // Call kernel
kernelFunc(dynamic_cast<const ReduceMean_Op<1>&>(mOp).getStaticAttributes(), kernelFunc(op_.getStaticAttributes(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dims(), op_.getInput(0)->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(), op_.getInput(0)->getImpl()->rawPtr(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr()); op_.getOutput(0)->getImpl()->rawPtr());
} }
void Aidge::ReduceMeanImpl2D_cpu::forward() { // void Aidge::ReduceMeanImpl1D_cpu::forward() {
// Find the correct kernel type // // Find the correct kernel type
auto kernelFunc = // auto kernelFunc =
Registrar<ReduceMeanImpl2DForward_cpu>::create({ // Registrar<ReduceMeanImpl1DForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(), // std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()}); // std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()});
// Call kernel // // Call kernel
kernelFunc(dynamic_cast<const ReduceMean_Op<2>&>(mOp).getStaticAttributes(), // kernelFunc(dynamic_cast<const ReduceMean_Op<1>&>(mOp).getStaticAttributes(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dims(), // std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(), // std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr()); // std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr());
} // }
void Aidge::ReduceMeanImpl3D_cpu::forward() { // void Aidge::ReduceMeanImpl2D_cpu::forward() {
// Find the correct kernel type // // Find the correct kernel type
auto kernelFunc = // auto kernelFunc =
Registrar<ReduceMeanImpl3DForward_cpu>::create({ // Registrar<ReduceMeanImpl2DForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(), // std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()}); // std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()});
// Call kernel // // Call kernel
kernelFunc(dynamic_cast<const ReduceMean_Op<3>&>(mOp).getStaticAttributes(), // kernelFunc(dynamic_cast<const ReduceMean_Op<2>&>(mOp).getStaticAttributes(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dims(), // std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dims(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(), // std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr()); // std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr());
} // }
\ No newline at end of file
// void Aidge::ReduceMeanImpl3D_cpu::forward() {
// // Find the correct kernel type
// auto kernelFunc =
// Registrar<ReduceMeanImpl3DForward_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 ReduceMean_Op<3>&>(mOp).getStaticAttributes(),
// std::static_pointer_cast<Tensor>(mOp.getRawInput(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
...@@ -9,13 +9,13 @@ ...@@ -9,13 +9,13 @@
* *
********************************************************************************/ ********************************************************************************/
#include <cassert> #include "aidge/backend/cpu/operator/ReshapeImpl.hpp"
#include "aidge/backend/cpu/operator/ReshapeImpl_forward_kernels.hpp"
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/Reshape.hpp" #include "aidge/operator/Reshape.hpp"
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/utils/ErrorHandling.hpp"
#include "aidge/backend/cpu/operator/ReshapeImpl.hpp"
#include "aidge/backend/cpu/operator/ReshapeImpl_forward_kernels.hpp"
Aidge::NbElts_t Aidge::ReshapeImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const { Aidge::NbElts_t Aidge::ReshapeImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const {
// this implementation can be in-place // this implementation can be in-place
...@@ -23,17 +23,17 @@ Aidge::NbElts_t Aidge::ReshapeImpl_cpu::getNbRequiredProtected(const Aidge::IOIn ...@@ -23,17 +23,17 @@ Aidge::NbElts_t Aidge::ReshapeImpl_cpu::getNbRequiredProtected(const Aidge::IOIn
} }
void Aidge::ReshapeImpl_cpu::forward() { void Aidge::ReshapeImpl_cpu::forward() {
assert(std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->size() == const Reshape_Op& op_ = static_cast<const Reshape_Op&>(mOp);
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->size() AIDGE_ASSERT(op_.getInput(0)->size() == op_.getOutput(0)->size(),
&& "input must have the same overall size as shape"); "input must have the same overall size as shape");
// Find the correct kernel type // Find the correct kernel type
auto kernelFunc = Registrar<ReshapeImplForward_cpu>::create({ auto kernelFunc = Registrar<ReshapeImplForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(), op_.getInput(0)->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()}); op_.getOutput(0)->dataType()});
// Call kernel // Call kernel
kernelFunc(std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->size(), kernelFunc(op_.getInput(0)->size(),
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->getImpl()->rawPtr(), op_.getInput(0)->getImpl()->rawPtr(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->getImpl()->rawPtr()); op_.getOutput(0)->getImpl()->rawPtr());
} }
...@@ -9,18 +9,18 @@ ...@@ -9,18 +9,18 @@
* *
********************************************************************************/ ********************************************************************************/
#include <cassert> #include <memory>
#include <chrono> // std::chrono::milliseconds
#include <numeric> // std::accumulate
#include <thread> // std::this_thread::sleep_for
#include <vector> #include <vector>
#include "aidge/backend/cpu/data/GetCPUPtr.h"
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/Sqrt.hpp" #include "aidge/operator/Sqrt.hpp"
#include "aidge/utils/ErrorHandling.hpp"
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/backend/cpu/data/GetCPUPtr.h"
#include "aidge/backend/cpu/operator/SqrtImpl.hpp" #include "aidge/backend/cpu/operator/SqrtImpl.hpp"
#include "aidge/backend/cpu/operator/SqrtImpl_forward_kernels.hpp" #include "aidge/backend/cpu/operator/SqrtImpl_forward_kernels.hpp"
#include "aidge/backend/cpu/operator/SqrtImpl_backward_kernels.hpp"
Aidge::NbElts_t Aidge::SqrtImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const { Aidge::NbElts_t Aidge::SqrtImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const {
// this implementation can be in-place // this implementation can be in-place
...@@ -28,15 +28,35 @@ Aidge::NbElts_t Aidge::SqrtImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex ...@@ -28,15 +28,35 @@ Aidge::NbElts_t Aidge::SqrtImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex
} }
void Aidge::SqrtImpl_cpu::forward() { void Aidge::SqrtImpl_cpu::forward() {
assert(std::static_pointer_cast<Tensor>(mOp.getRawInput(0)) && "missing input #0"); std::shared_ptr<Tensor> in0 = std::static_pointer_cast<Tensor>(mOp.getRawInput(0));
std::shared_ptr<Tensor> out0 = std::static_pointer_cast<Tensor>(mOp.getRawOutput(0));
AIDGE_ASSERT(in0, "missing input #0");
// Find the correct kernel type // Find the correct kernel type
auto kernelFunc = Registrar<SqrtImplForward_cpu>::create({ auto kernelFunc = Registrar<SqrtImplForward_cpu>::create({
std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->dataType(), in0->dataType(),
std::static_pointer_cast<Tensor>(mOp.getRawOutput(0))->dataType()}); out0->dataType()});
// Call kernel // Call kernel
kernelFunc(std::static_pointer_cast<Tensor>(mOp.getRawInput(0))->size(), kernelFunc(in0->size(),
getCPUPtr(mOp.getRawInput(0)), getCPUPtr(mOp.getRawInput(0)),
getCPUPtr(mOp.getRawOutput(0))); getCPUPtr(mOp.getRawOutput(0)));
}
void Aidge::SqrtImpl_cpu::backward() {
// reversing in and out Data for backprop
const Sqrt_Op& op_ = dynamic_cast<const Sqrt_Op&>(mOp);
std::shared_ptr<Tensor> out0grad = op_.getOutput(0)->grad();
std::shared_ptr<Tensor> in0grad = op_.getInput(0)->grad();
AIDGE_ASSERT(out0grad, "missing output #0");
// Find the correct kernel type
auto kernelFunc = Registrar<SqrtImplForward_cpu>::create({
out0grad->dataType(),
in0grad->dataType()});
// Call kernel
kernelFunc(out0grad->size(),
getCPUPtr(out0grad),
getCPUPtr(in0grad));
} }
\ 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 <cstddef> // std::size_t
#include <cstdint> // std::uint16_t
#include <chrono>
#include <iostream>
#include <memory>
#include <numeric> // std::accumulate
#include <random> // std::random_device, std::mt19937, std::uniform_real_distribution
#include "aidge/data/Tensor.hpp"
#include "aidge/backend/cpu/data/TensorImpl.hpp"
#include "aidge/operator/Add.hpp"
#include "aidge/backend/cpu/operator/AddImpl.hpp"
namespace Aidge {
TEST_CASE("Test addition of Tensors","[TensorImpl][Add]") {
constexpr std::uint16_t NBTRIALS = 10;
// Create a random number generator
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<float> valueDist(0.1f, 1.1f); // Random float distribution between 0 and 1
std::uniform_int_distribution<std::size_t> dimSizeDist(std::size_t(2), std::size_t(10));
std::uniform_int_distribution<int> boolDist(0,1);
// Create MatMul Operator
std::shared_ptr<Node> mySub = Add(2);
auto op = std::static_pointer_cast<OperatorTensor>(mySub-> getOperator());
op->setDataType(DataType::Float32);
op->setBackend("cpu");
// Create 2 input Tensors
std::shared_ptr<Tensor> T0 = std::make_shared<Tensor>();
op->associateInput(0,T0);
T0->setDataType(DataType::Float32);
T0->setBackend("cpu");
std::shared_ptr<Tensor> T1 = std::make_shared<Tensor>();
op -> associateInput(1,T1);
T1->setDataType(DataType::Float32);
T1->setBackend("cpu");
// Create results Tensor
Tensor Tres{};
Tres.setDataType(DataType::Float32);
Tres.setBackend("cpu");
// To measure execution time of 'MatMul_Op::forward()' member function call
std::chrono::time_point<std::chrono::system_clock> start;
std::chrono::time_point<std::chrono::system_clock> end;
std::chrono::duration<double, std::micro> duration{};
std::size_t number_of_operation = 0;
for (std::uint16_t trial = 0; trial < NBTRIALS; ++trial) {
// generate 2 random Tensors
// handle dimensions, replace some dimensions with '1' to get broadcasting
constexpr std::size_t nbDims = 4;
std::vector<std::size_t> dims;
for (std::size_t i = 0; i < nbDims; ++i) {
dims.push_back(dimSizeDist(gen));
}
std::vector<std::size_t> dims0 = dims;
std::vector<std::size_t> dims1 = dims;
std::vector<std::size_t> dimsOut = dims;
for (std::size_t i = 0; i < nbDims; ++i) {
if (boolDist(gen)) {
dims0[i] = 1;
}
if (boolDist(gen)) {
dims1[i] = 1;
}
dimsOut[i] = (dims0[i] == 1) ? dims1[i] : dims0[i];
}
// create arrays and fill them with random values
float* array0 = new float[dims0[0]*dims0[1]*dims0[2]*dims0[3]];
float* array1 = new float[dims1[0]*dims1[1]*dims1[2]*dims1[3]];
float* result = new float[dimsOut[0]*dimsOut[1]*dimsOut[2]*dimsOut[3]];
for (std::size_t i = 0; i < dims0[0]*dims0[1]*dims0[2]*dims0[3]; ++i) {
array0[i] = valueDist(gen);
}
for (std::size_t i = 0; i < dims1[0]*dims1[1]*dims1[2]*dims1[3]; ++i) {
array1[i] = valueDist(gen);
}
// compute true result
const std::size_t strides0[nbDims] = {dims0[1]*dims0[2]*dims0[3], dims0[2]*dims0[3], dims0[3], 1};
const std::size_t strides1[nbDims] = {dims1[1]*dims1[2]*dims1[3], dims1[2]*dims1[3], dims1[3], 1};
for (std::size_t a = 0; a < dimsOut[0]; ++a) {
for (std::size_t b = 0; b < dimsOut[1]; ++b) {
const std::size_t idx0_0 = strides0[0] * ((dims0[0] > 1) ? a : 0)
+ strides0[1] * ((dims0[1] > 1) ? b : 0);
const std::size_t idx1_0 = strides1[0] * ((dims1[0] > 1) ? a : 0)
+ strides1[1] * ((dims1[1] > 1) ? b : 0);
for (std::size_t c = 0; c < dimsOut[2]; ++c) {
const std::size_t idx_out = dimsOut[3] * (c + dimsOut[2] * (b + dimsOut[1] * a));
for (std::size_t d = 0; d < dimsOut[3]; ++d) {
std::size_t idx0 = idx0_0
+ strides0[2] * ((dims0[2] > 1) ? c : 0)
+ ((dims0[3] > 1) ? d : 0);
std::size_t idx1 = idx1_0
+ strides1[2] * ((dims1[2] > 1) ? c : 0)
+ ((dims1[3] > 1) ? d : 0);
result[idx_out + d] = array0[idx0] + array1[idx1];
// std::cout << "(" << idx0 << ", " << idx1 << ") -> " << array0[idx0] << " - " << array1[idx1] << " -> " << idx_out + d << std::endl;
}
}
}
}
// conversion to Aidge::Tensors
// input0
T0->resize(dims0);
T0->getImpl() -> setRawPtr(array0, dims0[0]*dims0[1]*dims0[2]*dims0[3]);
// input1
T1->resize(dims1);
T1->getImpl() -> setRawPtr(array1, dims1[0]*dims1[1]*dims1[2]*dims1[3]);
// results
Tres.resize(dimsOut);
Tres.getImpl() -> setRawPtr(result, dimsOut[0]*dimsOut[1]*dimsOut[2]*dimsOut[3]);
Tensor T2 = *T0 + *T1;
REQUIRE(T2 == Tres);
// no implementation
Tensor T3(T1->dims());
REQUIRE_THROWS(*T0 + T3);
// // wrong backend
// static Registrar<Add_Op> registrarAddImpl_custom("custom", [](const Add_Op& op) { return std::make_unique<AddImpl_cpu>(op); } );
// static Registrar<Tensor> registrarTensorImpl_custom_Int32({"custom", DataType::Int32},
// [] (DeviceIdx_t device, std::vector<DimSize_t> dims) {
// return std::make_shared<TensorImpl_cpu<int>>(device, dims);
// }
// );
// T1.setBackend("custom");
// REQUIRE_THROWS(T0 + T1);
// wrong datatype
Tensor T4(T1->dims());
T4.setDataType(DataType::Float64);
REQUIRE_THROWS(*T0 + T4);
}
}
TEST_CASE("Test substraction of Tensors","[TensorImpl][Sub]") {
Tensor T0 = Array3D<int, 2, 2, 2>{{{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}};
Tensor T1 = Array3D<int, 2, 2, 2>{{{{7, 1}, {3, 7}}, {{54, 0}, {7, 12}}}};
Tensor T2 = T0 - T1;
T2.print();
REQUIRE(T2 == Tensor(Array3D<int, 2, 2, 2>{{{{-6,1},{0,-3}},{{-49,6},{0,-4}}}}));
Tensor T3(T1.dims());
REQUIRE_THROWS(T0 - T3);
}
TEST_CASE("Test multiplication of Tensors","[TensorImpl][Mul]") {
Tensor T0 = Array3D<int, 2, 2, 2>{{{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}};
Tensor T1 = Array3D<int, 2, 2, 2>{{{{7, 2}, {3, 7}}, {{5, 6}, {7, 8}}}};
Tensor T2 = T0 * T1;
T2.print();
REQUIRE(T2 == Tensor(Array3D<int, 2, 2, 2>{{{{7,4},{9,28}},{{25,36},{49,64}}}}));
Tensor T3(T1.dims());
REQUIRE_THROWS(T0 * T3);
}
TEST_CASE("Test division of Tensors","[TensorImpl][Div]") {
Tensor T0 = Array3D<int, 2, 2, 2>{{{{7,4},{9,28}},{{25,36},{49,64}}}};
Tensor T1 = Array3D<int, 2, 2, 2>{{{{7, 2}, {3, 7}}, {{5, 6}, {7, 8}}}};
Tensor T2 = T0 / T1;
T2.print();
REQUIRE(T2 == Tensor(Array3D<int, 2, 2, 2>{{{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}}));
Tensor T3(T1.dims());
REQUIRE_THROWS(T0 / T3);
}
} // namespace Aidge
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "aidge/operator/Conv.hpp" #include "aidge/operator/Conv.hpp"
#include "aidge/backend/cpu.hpp" #include "aidge/backend/cpu.hpp"
#include "aidge/utils/TensorUtils.hpp"
using namespace Aidge; using namespace Aidge;
...@@ -138,35 +139,60 @@ TEST_CASE("[cpu/operator] ReduceMean(forward)", "[ReduceMean][CPU]") { ...@@ -138,35 +139,60 @@ TEST_CASE("[cpu/operator] ReduceMean(forward)", "[ReduceMean][CPU]") {
} }
SECTION("all_axes") { SECTION("all_axes") {
std::shared_ptr<Tensor> myInput = std::make_shared<Tensor>(Array3D<float,3,2,2> { SECTION("1") {
{ std::shared_ptr<Tensor> myInput = std::make_shared<Tensor>(Array3D<float,3,2,2> {
{
{ 5.0, 1.0 },
{ 20.0, 2.0 }
},
{
{ 30.0, 1.0 },
{ 40.0, 2.0 }
},
{ {
{ 55.0, 1.0 }, {
{ 60.0, 2.0 } { 5.0, 1.0 },
{ 20.0, 2.0 }
},
{
{ 30.0, 1.0 },
{ 40.0, 2.0 }
},
{
{ 55.0, 1.0 },
{ 60.0, 2.0 }
}
} }
} });
}); std::shared_ptr<Tensor> myOutput = std::make_shared<Tensor>(Array1D<float,1> {
std::shared_ptr<Tensor> myOutput = std::make_shared<Tensor>(Array1D<float,1> { {18.25}
{18.25} });
});
std::shared_ptr<Node> myReduceMean = ReduceMean({0, 1, 2}, 0); std::shared_ptr<Node> myReduceMean = ReduceMean({0, 1, 2}, 0);
auto op = std::static_pointer_cast<OperatorTensor>(myReduceMean -> getOperator()); auto op = std::static_pointer_cast<OperatorTensor>(myReduceMean -> getOperator());
op->associateInput(0,myInput); op->associateInput(0,myInput);
op->setDataType(DataType::Float32); op->setDataType(DataType::Float32);
op->setBackend("cpu"); op->setBackend("cpu");
op->computeOutputDims(); op->computeOutputDims();
myReduceMean->forward(); myReduceMean->forward();
op->getOutput(0)->print(); op->getOutput(0)->print();
REQUIRE(*(op->getOutput(0)) == *myOutput); REQUIRE(*(op->getOutput(0)) == *myOutput);
}
SECTION("2") {
std::shared_ptr<Tensor> myInput = std::make_shared<Tensor>(Array2D<float,5,4> {
{{ 0.004232f, 0.105120f, 0.045124f, 0.009205f},
{ 0.000766f, 0.272162f, 0.503560f, 0.044163f},
{ 0.049755f, 0.000305f, 0.143634f, 0.013253f},
{ 0.096258f, 0.311231f, 0.358143f, 0.000452f},
{ 0.468617f, 0.015693f, 0.145316f, 0.000105f}}
});
std::shared_ptr<Tensor> myOutput = std::make_shared<Tensor>(Array1D<float,1> {
{0.1293547f}
});
std::shared_ptr<Node> myReduceMean = ReduceMean({0, 1}, 0);
auto op = std::static_pointer_cast<OperatorTensor>(myReduceMean -> getOperator());
op->associateInput(0,myInput);
op->setDataType(DataType::Float32);
op->setBackend("cpu");
op->computeOutputDims();
myReduceMean->forward();
op->getOutput(0)->print();
// approxEq<float>(*(op->getOutput(0)), *myOutput);
REQUIRE(approxEq<float>(*(op->getOutput(0)), *myOutput));
}
} }
} }
\ No newline at end of file
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "aidge/scheduler/Scheduler.hpp" #include "aidge/scheduler/Scheduler.hpp"
#include "aidge/backend/cpu.hpp" #include "aidge/backend/cpu.hpp"
#include "aidge/recipes/GraphViewHelper.hpp"
using namespace Aidge; using namespace Aidge;
...@@ -300,7 +301,7 @@ TEST_CASE("[cpu/scheduler] SequentialScheduler(forward)") { ...@@ -300,7 +301,7 @@ TEST_CASE("[cpu/scheduler] SequentialScheduler(forward)") {
std::vector<std::shared_ptr<Aidge::Tensor>> dataIn = {inputTensor}; std::vector<std::shared_ptr<Aidge::Tensor>> dataIn = {inputTensor};
REQUIRE_NOTHROW(scheduler.forward(true, false, dataIn)); REQUIRE_NOTHROW(scheduler.forward(true, false, dataIn));
scheduler.saveSchedulingDiagram("schedulingSequential"); scheduler.saveSchedulingDiagram("schedulingSequential");
std::shared_ptr<Tensor> expectedOutput1 = std::make_shared<Tensor>(Array4D<int, 2, 3, 3, 3>{ std::shared_ptr<Tensor> expectedOutput1 = std::make_shared<Tensor>(Array4D<int, 2, 3, 3, 3>{
...@@ -345,4 +346,45 @@ TEST_CASE("[cpu/scheduler] SequentialScheduler(forward)") { ...@@ -345,4 +346,45 @@ TEST_CASE("[cpu/scheduler] SequentialScheduler(forward)") {
bool equal4 = (*other4 == expectedOutput4); bool equal4 = (*other4 == expectedOutput4);
REQUIRE(equal4); REQUIRE(equal4);
} }
}
TEST_CASE("[cpu/scheduler] SequentialScheduler(backward)", "[scheduler][backward]") {
// create GraphView
std::shared_ptr<GraphView> gv = Sequential({ReLU("relu0"), Sqrt("srqt0"), ReLU("relu1")});
std::shared_ptr<Tensor> inputTensor =
std::make_shared<Tensor>(Array4D<float, 2, 1, 5, 5>{{{{{0.0f, 1.0f, 2.0f, 3.0f, 4.0f},
{5.0f, 6.0f, 7.0f, 8.0f, 9.0f},
{10.0f, 11.0f, 12.0f, 13.0f, 14.0f},
{15.0f, 16.0f, 17.0f, 18.0f, 19.0f},
{20.0f, 21.0f, 22.0f, 23.0f, 24.0f}}},
{{{25.0f, 26.0f, 27.0f, 28.0f, 29.0f},
{30.0f, 31.0f, 32.0f, 33.0f, 34.0f},
{35.0f, 36.0f, 37.0f, 38.0f, 39.0f},
{40.0f, 41.0f, 42.0f, 43.0f, 44.0f},
{45.0f, 46.0f, 47.0f, 48.0f, 49.0f}}}}});
auto label = inputTensor;
// implem already set to default
auto myProd = Producer(inputTensor, "prod");
myProd -> addChild(gv);
gv -> compile("cpu", DataType::Float32);
compile_gradient(gv);
SequentialScheduler scheduler(gv);
scheduler.forward();
auto predictedOutput = gv->getOrderedOutputs()[0].first;
std::shared_ptr<Tensor> targetOutput =
std::make_shared<Tensor>(Array4D<float, 2, 1, 5, 5>{{{{{0.0f, 1.0f, 1.0f, 2.0f, 2.0f},
{2.0f, 2.0f, 3.0f, 3.0f, 3.0f},
{3.0f, 3.0f, 3.0f, 4.0f, 4.0f},
{4.0f, 4.0f, 4.0f, 4.0f, 4.0f},
{4.0f, 5.0f, 5.0f, 5.0f, 5.0f}}},
{{{5.0f, 5.0f, 5.0f, 5.0f, 5.0f},
{5.0f, 6.0f, 6.0f, 6.0f, 6.0f},
{6.0f, 6.0f, 6.0f, 6.0f, 6.0f},
{6.0f, 6.0f, 6.0f, 7.0f, 7.0f},
{7.0f, 7.0f, 7.0f, 7.0f, 7.0f}}}}});
REQUIRE_NOTHROW(scheduler.backward({targetOutput}));
} }
\ No newline at end of file
0.0.1 0.2.0
\ No newline at end of file \ 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