diff --git a/unit_tests/operator/Test_MulImpl.cpp b/unit_tests/operator/Test_MulImpl.cpp index 2937e94938c671140eeeee87d47d5c48f685203e..f932b150876b4c6113d41165051cee3b7d67cc1b 100644 --- a/unit_tests/operator/Test_MulImpl.cpp +++ b/unit_tests/operator/Test_MulImpl.cpp @@ -9,6 +9,7 @@ * ********************************************************************************/ +<<<<<<< HEAD #include <chrono> #include <cstddef> // std::size_t #include <cstdint> // std::uint16_t @@ -22,6 +23,36 @@ #include "aidge/backend/cpu/data/TensorImpl.hpp" #include "aidge/backend/cpu/operator/MulImpl.hpp" #include "aidge/data/DataType.hpp" +======= +<<<<<<< HEAD +#include <chrono> // std::micro, std::chrono::time_point, + // std::chrono::system_clock, +#include <cstddef> // std::size_t +#include <cstdint> // std::uint16_t +#include <functional> // std::multiplies +#include <memory> +#include <numeric> // std::accumulate +#include <random> // std::random_device, std::mt19937 + // std::uniform_int_distribution, std::uniform_real_distribution +#include <vector> + +#include <catch2/catch_test_macros.hpp> +#include <fmt/core.h> +======= +#include <catch2/catch_test_macros.hpp> +#include <chrono> +#include <cstddef> // std::size_t +#include <cstdint> // std::uint16_t +#include <iostream> +#include <memory> +#include <numeric> // std::accumulate +#include <random> // std::random_device, std::mt19937, std::uniform_real_distribution +>>>>>>> 9d427c111c3c37ad141cd12a30c851f7fdf6a8fe + +#include "aidge/backend/cpu/data/TensorImpl.hpp" +#include "aidge/backend/cpu/operator/MulImpl.hpp" +#include "aidge/data/Data.hpp" +>>>>>>> 30d2af827763a1f1b36c3fe7b152cd4566b3540c #include "aidge/data/Tensor.hpp" #include "aidge/operator/Mul.hpp" #include "aidge/utils/ArrayHelpers.hpp" @@ -30,11 +61,19 @@ namespace Aidge { +<<<<<<< HEAD TEST_CASE("[CPU/Operator] Mul(Backward)", "[Mul][CPU][Backward]") { +======= +<<<<<<< HEAD +TEST_CASE("[CPU/Operator] Mul Backward", "[Mul][CPU][Backward]") +{ + using aif32 = cpptype_t<DataType::Float32>; +>>>>>>> 30d2af827763a1f1b36c3fe7b152cd4566b3540c std::shared_ptr<Mul_Op> op = std::make_shared<Mul_Op>(); op->setDataType(DataType::Float32); op->setBackend("cpu"); +<<<<<<< HEAD // NOTE: The first four tests use fixed values, the last one uses random values but static dimensions. SECTION("Case 1: 1D and 2D Tensors") { @@ -120,6 +159,88 @@ TEST_CASE("[CPU/Operator] Mul(Backward)", "[Mul][CPU][Backward]") { {70.0, 74.0, 78.0}, {82.0, 86.0, 90.0}}}); +======= + SECTION("Case 1: 2D and 1D tensors") { + const auto T0 = std::make_shared<Tensor>(Array2D<aif32,2,3>( + { + { + {1,2,3},{4,5,6} + } + } + )); + + const auto T1 = std::make_shared<Tensor>(Array1D<aif32,3>( + {0.1,0.2,0.3} + )); + + op->getOutput(0)->setGrad(std::make_shared<Tensor>(Array2D<aif32,2,3>({{{1.0,1.0,1.0},{1.0,1.0,1.0}}}))); + + op->associateInput(0,T0); + op->associateInput(1,T1); + op->forwardDims(); + + op->forward(); + op->backward(); + + const Tensor T0Grad = Array2D<aif32, 2, 3>({{{0.1,0.2,0.3},{0.1, 0.2, 0.3}}}); + const Tensor T1Grad = Array1D<aif32, 3>({5,7,9}); + + REQUIRE(approxEq<aif32>(*(op->getInput(0)->grad()), T0Grad)); + REQUIRE(approxEq<aif32>(*(op->getInput(1)->grad()), T1Grad)); + } + + SECTION("Case 2: 3D and 1D tensors") { + const auto T0 = std::make_shared<Tensor>(Array3D<aif32,2,2,3>( + { + { + { + {1.0, 2.0, 3.0}, + {4.0, 5.0, 6.0} + }, + { + {7.0, 8.0, 9.0}, + {10.0, 11.0, 12.0} + } + } + } + )); + + const auto T1 = std::make_shared<Tensor>(Array1D<aif32, 3>({0.3,0.2,0.1})); + + const auto newGrad = std::make_shared<Tensor>(Array3D<aif32,2,2,3>( + { + { + { + {1, 1, 1}, + {1, 1, 1} + }, + { + {1, 1, 1}, + {1, 1, 1} + } + } + } + )); + + const Tensor expectedGrad0 = Array3D<aif32,2,2,3>( + { + { + { + {0.3, 0.2, 0.1}, + {0.3, 0.2, 0.1} + }, + { + {0.3, 0.2, 0.1}, + {0.3, 0.2, 0.1} + } + } + } + ); + + const Tensor expectedGrad1 = Array1D<aif32,3>( + {22.0, 26.0, 30.0} + ); + op->associateInput(0, T0); op->associateInput(1, T1); op->getOutput(0)->setGrad(newGrad); @@ -127,6 +248,133 @@ TEST_CASE("[CPU/Operator] Mul(Backward)", "[Mul][CPU][Backward]") { op->backward(); + REQUIRE(approxEq<aif32>(*(op->getInput(0)->grad()), expectedGrad0)); + REQUIRE(approxEq<aif32>(*(op->getInput(1)->grad()), expectedGrad1)); + } + + SECTION("Case 3: 4D and 2D tensors") { + const auto T0 = std::make_shared<Tensor>(Array4D<aif32,2, 2, 3, 3>( + { + { + { + { + {1.0, 2.0, 3.0}, + {4.0, 5.0, 6.0}, + {7.0, 8.0, 9.0} + }, + { + {10.0, 11.0, 12.0}, + {13.0, 14.0, 15.0}, + {16.0, 17.0, 18.0} + } + }, + { + { + {19.0, 20.0, 21.0}, + {22.0, 23.0, 24.0}, + {25.0, 26.0, 27.0} + }, + { + {28.0, 29.0, 30.0}, + {31.0, 32.0, 33.0}, + {34.0, 35.0, 36.0} + } + } + } + } + )); + + const auto T1 = std::make_shared<Tensor>(Array2D<aif32, 3,3>( + { + { + {0.5,0.3,0.1}, + {0.4,0.2,0.6}, + {0.7,0.8,0.9} + } + } + )); + + const auto newGrad = std::make_shared<Tensor>(Array4D<aif32,2, 2, 3, 3>( + { + { + { + { + {1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0} + }, + { + {1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0} + } + }, + { + { + {1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0} + }, + { + {1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0} + } + } + } + } + )); + + const Tensor expectedGrad0 = Array4D<aif32,2,2,3,3>( + { + { + { + { + {0.5, 0.3, 0.1}, + {0.4, 0.2, 0.6}, + {0.7, 0.8, 0.9} + }, + { + {0.5, 0.3, 0.1}, + {0.4, 0.2, 0.6}, + {0.7, 0.8, 0.9} + } + }, + { + { + {0.5, 0.3, 0.1}, + {0.4, 0.2, 0.6}, + {0.7, 0.8, 0.9} + }, + { + {0.5, 0.3, 0.1}, + {0.4, 0.2, 0.6}, + {0.7, 0.8, 0.9} + } + } + } + } + ); + + const Tensor expectedGrad1 = Array2D<aif32,3, 3>( + { + { + {58.0, 62.0, 66.0}, + {70.0, 74.0, 78.0}, + {82.0, 86.0, 90.0} + } + } + ); + +>>>>>>> 30d2af827763a1f1b36c3fe7b152cd4566b3540c + op->associateInput(0, T0); + op->associateInput(1, T1); + op->getOutput(0)->setGrad(newGrad); + op->forwardDims(); +<<<<<<< HEAD + + op->backward(); + REQUIRE(approxEq<cpptype_t<DataType::Float32>>(*(op->getInput(0)->grad()), expectedGrad0)); REQUIRE(approxEq<cpptype_t<DataType::Float32>>(*(op->getInput(1)->grad()), expectedGrad1)); } @@ -281,6 +529,392 @@ TEST_CASE("[CPU/Operator] Mul(Backward)", "[Mul][CPU][Backward]") { // Perform backward pass op->backward(); +======= + + op->backward(); + + REQUIRE(approxEq<aif32>(*(op->getInput(0)->grad()), expectedGrad0)); + REQUIRE(approxEq<aif32>(*(op->getInput(1)->grad()), expectedGrad1)); + } + + SECTION("Case 4: 3D and 2D tensors") { + const auto T0 = std::make_shared<Tensor>(Array3D<aif32, 2, 3, 4>( + { + { + { + {1.0, 2.0, 3.0, 4.0}, + {5.0, 6.0, 7.0, 8.0}, + {9.0, 10.0, 11.0, 12.0}, + }, + { + {13.0, 14.0, 15.0, 16.0}, + {17.0, 18.0, 19.0, 20.0}, + {21.0, 22.0, 23.0, 24.0}, + } + } + } + )); + + const auto T1 = std::make_shared<Tensor>(Array2D<aif32, 3, 4>( + { + { + {0.1, 0.2, 0.3, 0.4}, + {0.5, 0.6, 0.7, 0.8}, + {0.9, 1.0, 1.1, 1.2} + } + } + )); + + const auto newGrad = std::make_shared<Tensor>(Array3D<aif32, 2,3,4>( + { + { + { + {1.0, 1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0, 1.0}, + }, + { + {1.0, 1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0, 1.0}, + } + } + } + )); + + const Tensor expectedGrad0 = Array3D<aif32,2,3,4>( + { + { + { + {0.1, 0.2, 0.3, 0.4}, + {0.5, 0.6, 0.7, 0.8}, + {0.9, 1.0, 1.1, 1.2} + }, + { + {0.1, 0.2, 0.3, 0.4}, + {0.5, 0.6, 0.7, 0.8}, + {0.9, 1.0, 1.1, 1.2} + } + } + } + ); + + const Tensor expectedGrad1 = Array2D<aif32,3,4>( + { + { + {14.0, 16.0, 18.0, 20.0}, + {22.0, 24.0, 26.0, 28.0}, + {30.0, 32.0, 34.0, 36.0} + } + } + ); + + op->associateInput(0, T0); + op->associateInput(1, T1); + op->getOutput(0)->setGrad(newGrad); + op->forwardDims(); + + op->backward(); + + REQUIRE(approxEq<aif32>(*(op->getInput(0)->grad()), expectedGrad0)); + REQUIRE(approxEq<aif32>(*(op->getInput(1)->grad()), expectedGrad1)); +======= +TEST_CASE("[CPU/Operator] Mul(Backward)", "[Mul][CPU][Backward]") { + std::shared_ptr<Node> myMul = Mul(); + auto op = std::static_pointer_cast<OperatorTensor>(myMul->getOperator()); + op->setDataType(DataType::Float32); + op->setBackend("cpu"); + + // NOTE: The first four tests use fixed values, the last one uses random values but static dimensions. + + SECTION("Case 1: 1D and 2D Tensors") { + const auto T0 = std::make_shared<Tensor>( + Array2D<float, 2, 3>({{{1, 2, 3}, {4, 5, 6}}})); + + const auto T1 = + std::make_shared<Tensor>(Array1D<float, 3>({0.1, 0.2, 0.3})); + + float *input0 = static_cast<float *>(T0->getImpl()->rawPtr()); + float *input1 = static_cast<float *>(T1->getImpl()->rawPtr()); + + // TODO Use + T0->setDataType(DataType::Float32); + T0->setBackend("cpu"); + T1->setDataType(DataType::Float32); + T1->setBackend("cpu"); + + op->associateInput(0, T0); + op->associateInput(1, T1); + op->getOutput(0)->setGrad(std::make_shared<Tensor>( + Array2D<float, 2, 3>({{{1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}}}))); + op->forwardDims(); + + myMul->backward(); + + const auto expectedGrad0 = std::make_shared<Tensor>( + Array2D<float, 2, 3>({{{0.1, 0.2, 0.3}, {0.1, 0.2, 0.3}}})); + + const auto expectedGrad1 = + std::make_shared<Tensor>(Array1D<float, 3>({5, 7, 9})); + + REQUIRE(approxEq<float>(*(op->getInput(0)->grad()), *expectedGrad0)); + REQUIRE(approxEq<float>(*(op->getInput(1)->grad()), *expectedGrad1)); + } + + SECTION("Case 2: 3D and 1D tensors") { + const auto T0 = std::make_shared<Tensor>(Array3D<float, 2, 2, 3>( + {{{{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}}, + {{7.0, 8.0, 9.0}, {10.0, 11.0, 12.0}}}})); + + const auto T1 = + std::make_shared<Tensor>(Array1D<float, 3>({0.3, 0.2, 0.1})); + + const auto newGrad = std::make_shared<Tensor>(Array3D<float, 2, 2, 3>( + {{{{1, 1, 1}, {1, 1, 1}}, {{1, 1, 1}, {1, 1, 1}}}})); + + const auto expectedGrad0 = std::make_shared<Tensor>( + Array3D<float, 2, 2, 3>({{{{0.3, 0.2, 0.1}, {0.3, 0.2, 0.1}}, + {{0.3, 0.2, 0.1}, {0.3, 0.2, 0.1}}}})); + + const auto expectedGrad1 = + std::make_shared<Tensor>(Array1D<float, 3>({22.0, 26.0, 30.0})); + + for (auto T : {T0, T1, newGrad, expectedGrad0, expectedGrad1}) { + T->setBackend("cpu"); + T->setDataType(DataType::Float32); + } + + op->associateInput(0, T0); + op->associateInput(1, T1); + op->getOutput(0)->setGrad(newGrad); + op->forwardDims(); + + myMul->backward(); + + REQUIRE(approxEq<float>(*(op->getInput(0)->grad()), *expectedGrad0)); + REQUIRE(approxEq<float>(*(op->getInput(1)->grad()), *expectedGrad1)); + } + + SECTION("Case 3: 4D and 2D tensors") { + const auto T0 = std::make_shared<Tensor>(Array4D<float, 2, 2, 3, 3>( + {{{{{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}, {7.0, 8.0, 9.0}}, + {{10.0, 11.0, 12.0}, {13.0, 14.0, 15.0}, {16.0, 17.0, 18.0}}}, + {{{19.0, 20.0, 21.0}, {22.0, 23.0, 24.0}, {25.0, 26.0, 27.0}}, + {{28.0, 29.0, 30.0}, + {31.0, 32.0, 33.0}, + {34.0, 35.0, 36.0}}}}})); + + const auto T1 = std::make_shared<Tensor>(Array2D<float, 3, 3>( + {{{0.5, 0.3, 0.1}, {0.4, 0.2, 0.6}, {0.7, 0.8, 0.9}}})); + + const auto newGrad = + std::make_shared<Tensor>(Array4D<float, 2, 2, 3, 3>( + {{{{{1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}}, + {{1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}}}, + {{{1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}}, + {{1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}}}}})); + + const auto expectedGrad0 = + std::make_shared<Tensor>(Array4D<float, 2, 2, 3, 3>( + {{{{{0.5, 0.3, 0.1}, {0.4, 0.2, 0.6}, {0.7, 0.8, 0.9}}, + {{0.5, 0.3, 0.1}, {0.4, 0.2, 0.6}, {0.7, 0.8, 0.9}}}, + {{{0.5, 0.3, 0.1}, {0.4, 0.2, 0.6}, {0.7, 0.8, 0.9}}, + {{0.5, 0.3, 0.1}, {0.4, 0.2, 0.6}, {0.7, 0.8, 0.9}}}}})); + + const auto expectedGrad1 = std::make_shared<Tensor>( + Array2D<float, 3, 3>({{{58.0, 62.0, 66.0}, + {70.0, 74.0, 78.0}, + {82.0, 86.0, 90.0}}})); + + for (const auto T : {T0, T1, newGrad, expectedGrad0, expectedGrad1}) { + T->setBackend("cpu"); + T->setDataType(DataType::Float32); + } + + op->associateInput(0, T0); + op->associateInput(1, T1); + op->getOutput(0)->setGrad(newGrad); + op->forwardDims(); + + myMul->backward(); + + REQUIRE(approxEq<float>(*(op->getInput(0)->grad()), *expectedGrad0)); + REQUIRE(approxEq<float>(*(op->getInput(1)->grad()), *expectedGrad1)); + } + + SECTION("Case 4: 3D and 2D tensors") { + const auto T0 = std::make_shared<Tensor>( + Array3D<float, 2, 3, 4>({{{ + {1.0, 2.0, 3.0, 4.0}, + {5.0, 6.0, 7.0, 8.0}, + {9.0, 10.0, 11.0, 12.0}, + }, + { + {13.0, 14.0, 15.0, 16.0}, + {17.0, 18.0, 19.0, 20.0}, + {21.0, 22.0, 23.0, 24.0}, + }}})); + + const auto T1 = std::make_shared<Tensor>( + Array2D<float, 3, 4>({{{0.1, 0.2, 0.3, 0.4}, + {0.5, 0.6, 0.7, 0.8}, + {0.9, 1.0, 1.1, 1.2}}})); + + const auto newGrad = std::make_shared<Tensor>( + Array3D<float, 2, 3, 4>({{{ + {1.0, 1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0, 1.0}, + }, + { + {1.0, 1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0, 1.0}, + {1.0, 1.0, 1.0, 1.0}, + }}})); + + const auto expectedGrad0 = std::make_shared<Tensor>( + Array3D<float, 2, 3, 4>({{{{0.1, 0.2, 0.3, 0.4}, + {0.5, 0.6, 0.7, 0.8}, + {0.9, 1.0, 1.1, 1.2}}, + {{0.1, 0.2, 0.3, 0.4}, + {0.5, 0.6, 0.7, 0.8}, + {0.9, 1.0, 1.1, 1.2}}}})); + + const auto expectedGrad1 = std::make_shared<Tensor>( + Array2D<float, 3, 4>({{{14.0, 16.0, 18.0, 20.0}, + {22.0, 24.0, 26.0, 28.0}, + {30.0, 32.0, 34.0, 36.0}}})); + + for (const auto T : {T0, T1, newGrad, expectedGrad0, expectedGrad1}) { + T->setBackend("cpu"); + T->setDataType(DataType::Float32); + } + + op->associateInput(0, T0); + op->associateInput(1, T1); + op->getOutput(0)->setGrad(newGrad); + op->forwardDims(); + + myMul->backward(); + + REQUIRE(approxEq<float>(*(op->getInput(0)->grad()), *expectedGrad0)); + REQUIRE(approxEq<float>(*(op->getInput(1)->grad()), *expectedGrad1)); + } + + SECTION("Case 5: Tensors with random values") { + + // Use random values + std::vector<std::size_t> dims0 = {5, 2, 1, 7}; // First tensor + std::vector<std::size_t> dims1 = {2, 6, 7}; // Second tensor + std::vector<std::size_t> outputDims = {5, 2, 6, 7}; + + const auto input0Size = 5 * 2 * 1 * 7; + const auto input1Size = 2 * 6 * 7; + const auto outputSize = 5 * 2 * 6 * 7; + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution<float> dist(0.1f, 1.0f); + + std::vector<float> input0Data(input0Size); + std::vector<float> input1Data(input1Size); + + // Fill with random values + for (auto &val : input0Data) { + val = dist(gen); + } + for (auto &val : input1Data) { + val = dist(gen); + } + + auto T0 = std::make_shared<Tensor>(); + auto T1 = std::make_shared<Tensor>(); + + T0->setDataType(DataType::Float32); + T0->setBackend("cpu"); + T0->resize(dims0); + T0->getImpl()->setRawPtr(input0Data.data(), input0Size); + + T1->setDataType(DataType::Float32); + T1->setBackend("cpu"); + T1->resize(dims1); + T1->getImpl()->setRawPtr(input1Data.data(), input1Size); + + op->associateInput(0, T0); + op->associateInput(1, T1); + + op->forwardDims(); + myMul->forward(); + + std::vector<float> expectedOutput(outputSize); + + for (std::size_t n = 0; n < 5; ++n) { + for (std::size_t c = 0; c < 2; ++c) { + for (std::size_t h = 0; h < 6; ++h) { + for (std::size_t w = 0; w < 7; ++w) { + std::size_t outIdx = w + 7 * (h + 6 * (c + 2 * n)); + std::size_t in0Idx = + w + 7 * (0 + 1 * (c + 2 * n)); // middle dim is 1 + std::size_t in1Idx = + w + 7 * (h + 6 * c); // no n dimension + + expectedOutput[outIdx] = + input0Data[in0Idx] * input1Data[in1Idx]; + } + } + } + } + + auto outputTensor = op->getOutput(0); + + // Verify forward pass + auto expectedOutputTensor = std::make_shared<Tensor>(); + expectedOutputTensor->resize(outputDims); + expectedOutputTensor->setBackend("cpu"); + expectedOutputTensor->setDataType(DataType::Float32); + expectedOutputTensor->getImpl()->setRawPtr(expectedOutput.data(), + expectedOutput.size()); + + REQUIRE(approxEq<float>(*outputTensor, *expectedOutputTensor)); + + // Backward pass + std::vector<float> gradOutputData(outputSize); + for (auto &val : gradOutputData) { + val = dist(gen); + } + + op->getOutput(0)->setGrad(std::make_shared<Tensor>()); + op->getOutput(0)->grad()->resize(outputDims); + op->getOutput(0)->grad()->getImpl()->setRawPtr(gradOutputData.data(), + outputSize); + + // Compute reference gradients + std::vector<float> expectedGrad0(input0Size, 0.0f); + std::vector<float> expectedGrad1(input1Size, 0.0f); + + for (std::size_t n = 0; n < 5; ++n) { + for (std::size_t c = 0; c < 2; ++c) { + for (std::size_t h = 0; h < 6; ++h) { + for (std::size_t w = 0; w < 7; ++w) { + std::size_t outIdx = w + 7 * (h + 6 * (c + 2 * n)); + std::size_t in0Idx = w + 7 * (0 + 1 * (c + 2 * n)); + std::size_t in1Idx = w + 7 * (h + 6 * c); + + // Gradient for input0: grad_output * input1 + expectedGrad0[in0Idx] += + gradOutputData[outIdx] * input1Data[in1Idx]; + + // Gradient for input1: grad_output * input0 + expectedGrad1[in1Idx] += + gradOutputData[outIdx] * input0Data[in0Idx]; + } + } + } + } + + // Perform backward pass + myMul->backward(); +>>>>>>> 30d2af827763a1f1b36c3fe7b152cd4566b3540c auto expectedGrad0Tensor = std::make_shared<Tensor>(); expectedGrad0Tensor->resize(T0->dims()); @@ -289,7 +923,12 @@ TEST_CASE("[CPU/Operator] Mul(Backward)", "[Mul][CPU][Backward]") { expectedGrad0Tensor->getImpl()->setRawPtr(expectedGrad0.data(), expectedGrad0.size()); +<<<<<<< HEAD auto expectedGrad1Tensor = std::make_shared<Tensor>(T1->dims()); +======= + auto expectedGrad1Tensor = std::make_shared<Tensor>(); + expectedGrad1Tensor->resize(T1->dims()); +>>>>>>> 30d2af827763a1f1b36c3fe7b152cd4566b3540c expectedGrad1Tensor->setBackend("cpu"); expectedGrad1Tensor->setDataType(DataType::Float32); expectedGrad1Tensor->getImpl()->setRawPtr(expectedGrad1.data(), @@ -309,6 +948,10 @@ TEST_CASE("[CPU/Operator] Mul(Backward)", "[Mul][CPU][Backward]") { // ")\n"; // std::cout << "Input sizes: " << input0_size << " * " << // input1_size << " -> " << output_size << "\n"; +<<<<<<< HEAD +======= +>>>>>>> 9d427c111c3c37ad141cd12a30c851f7fdf6a8fe +>>>>>>> 30d2af827763a1f1b36c3fe7b152cd4566b3540c } } @@ -326,7 +969,17 @@ TEST_CASE("[cpu/operator] Mul(forward)", "[Mul][CPU]") { std::size_t(3)); std::uniform_int_distribution<int> boolDist(0, 1); +<<<<<<< HEAD std::shared_ptr<Mul_Op> op = std::make_shared<Mul_Op>(); +======= +<<<<<<< HEAD + // Create MatMul Operator + std::shared_ptr<Mul_Op> op = std::make_shared<Mul_Op>(); +======= + std::shared_ptr<Node> myMul = Mul(); + auto op = std::static_pointer_cast<OperatorTensor>(myMul->getOperator()); +>>>>>>> 9d427c111c3c37ad141cd12a30c851f7fdf6a8fe +>>>>>>> 30d2af827763a1f1b36c3fe7b152cd4566b3540c op->setDataType(DataType::Float32); op->setBackend("cpu"); @@ -409,8 +1062,20 @@ TEST_CASE("[cpu/operator] Mul(forward)", "[Mul][CPU]") { delete[] array1; delete[] result; } +<<<<<<< HEAD Log::info("number of elements over time spent: {}\n", (number_of_operation / duration.count())); Log::info("total time: {}μs\n", duration.count()); +======= +<<<<<<< HEAD + Log::info("number of elements over time spent: {}\n", (number_of_operation / duration.count())); + Log::info("total time: {} μs\n", duration.count()); +======= + std::cout << "number of elements over time spent: " + << (number_of_operation / duration.count()) << std::endl; + std::cout << "total time: " << duration.count() << "μs" + << std::endl; +>>>>>>> 9d427c111c3c37ad141cd12a30c851f7fdf6a8fe +>>>>>>> 30d2af827763a1f1b36c3fe7b152cd4566b3540c } SECTION("+1-D Tensor / +1-D Tensor - broadcasting") { @@ -564,8 +1229,20 @@ TEST_CASE("[cpu/operator] Mul(forward)", "[Mul][CPU]") { std::multiplies<std::size_t>()); number_of_operation += nb_elements; } +<<<<<<< HEAD Log::info("number of elements over time spent: {}\n", (number_of_operation / duration.count())); Log::info("total time: {}μs\n", duration.count()); +======= +<<<<<<< HEAD + Log::info("number of elements over time spent: {}\n", (number_of_operation / duration.count())); + Log::info("total time: {} μs\n", duration.count()); +======= + std::cout << "number of elements over time spent: " + << (number_of_operation / duration.count()) << std::endl; + std::cout << "total time: " << duration.count() << "μs" + << std::endl; +>>>>>>> 9d427c111c3c37ad141cd12a30c851f7fdf6a8fe +>>>>>>> 30d2af827763a1f1b36c3fe7b152cd4566b3540c } SECTION("+1-D Tensor / 1-D Tensor") { std::size_t number_of_operation = 0; @@ -702,8 +1379,20 @@ TEST_CASE("[cpu/operator] Mul(forward)", "[Mul][CPU]") { number_of_operation += nb_elements; } +<<<<<<< HEAD Log::info("number of elements over time spent: {}\n", (number_of_operation / duration.count())); Log::info("total time: {}μs\n", duration.count()); +======= +<<<<<<< HEAD + Log::info("number of elements over time spent: {}\n", (number_of_operation / duration.count())); + Log::info("total time: {} μs\n", duration.count()); +======= + std::cout << "number of elements over time spent: " + << (number_of_operation / duration.count()) << std::endl; + std::cout << "total time: " << duration.count() << "μs" + << std::endl; +>>>>>>> 9d427c111c3c37ad141cd12a30c851f7fdf6a8fe +>>>>>>> 30d2af827763a1f1b36c3fe7b152cd4566b3540c } } }