/******************************************************************************** * 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 <cstdlib> #include <memory> #include "aidge/data/Tensor.hpp" #include "aidge/data/TensorImpl.hpp" #include "aidge_cpu.hpp" #include "aidge/operator/Conv.hpp" using namespace Aidge; TEST_CASE("[cpu/operator] Conv(forward)") { SECTION("Classic Conv") { std::shared_ptr<Node> myConv = Conv(3,4,{3,3}, "myconv"); myConv->getOperator()->setDatatype(DataType::Int32); myConv->getOperator()->setBackend("cpu"); std::shared_ptr<Tensor> myWeights = std::make_shared<Tensor>(Array4D<int,4,3,3,3> { { { {{ 0, 1, 2}, { 3, 4, 5}, { 6, 7, 8}}, {{ 9, 10, 11}, { 12, 13, 14}, { 15, 16, 17}}, {{ 18, 19, 20}, { 21, 22, 23}, { 24, 25, 26}} }, { {{ 27, 28, 29}, { 30, 31, 32}, { 33, 34, 35}}, {{ 36, 37, 38}, { 39, 40, 41}, { 42, 43, 44}}, {{ 45, 46, 47}, { 48, 49, 50}, { 51, 52, 53}} }, { {{ 54, 55, 56}, { 57, 58, 59}, { 60, 61, 62}}, {{ 63, 64, 65}, { 66, 67, 68}, { 69, 70, 71}}, {{ 72, 73, 74}, { 75, 76, 77}, { 78, 79, 80}} }, { {{ 81, 82, 83}, { 84, 85, 86}, { 87, 88, 89}}, {{ 90, 91, 92}, { 93, 94, 95}, { 96, 97, 98}}, {{ 99, 100, 101}, {102, 103, 104}, {105, 106, 107}} } } }); std::shared_ptr<Tensor> myBias = std::make_shared<Tensor>(Array1D<int,4> {{7,0,9,0}}); std::shared_ptr<Tensor> myInput = std::make_shared<Tensor>(Array4D<int,2,3,5,5> { //NCHW { { {{ 0, 1, 2, 3, 4}, { 5, 6, 7, 8, 9}, { 10, 11, 12, 13, 14}, { 15, 16, 17, 18, 19}, { 20, 21, 22, 23, 24}}, {{ 25, 26, 27, 28, 29}, { 30, 31, 32, 33, 34}, { 35, 36, 37, 38, 39}, { 40, 41, 42, 43, 44}, { 45, 46, 47, 48, 49}}, {{ 50, 51, 52, 53, 54}, { 55, 56, 57, 58, 59}, { 60, 61, 62, 63, 64}, { 65, 66, 67, 68, 69}, { 70, 71, 72, 73, 74}} }, { {{ 75, 76, 77, 78, 79}, { 80, 81, 82, 83, 84}, { 85, 86, 87, 88, 89}, { 90, 91, 92, 93, 94}, { 95, 96, 97, 98, 99}}, {{100, 101, 102, 103, 104}, {105, 106, 107, 108, 109}, {110, 111, 112, 113, 114}, {115, 116, 117, 118, 119}, {120, 121, 122, 123, 124}}, {{125, 126, 127, 128, 129}, {130, 131, 132, 133, 134}, {135, 136, 137, 138, 139}, {140, 141, 142, 143, 144}, {145, 146, 147, 148, 149}} } } }); std::shared_ptr<Tensor> myOutput = std::make_shared<Tensor>(Array4D<int,2,4,3,3> { { { {{ 15226, 15577, 15928}, { 16981, 17332, 17683}, { 18736, 19087, 19438}}, {{ 37818, 38898, 39978}, { 43218, 44298, 45378}, { 48618, 49698, 50778}}, {{ 60426, 62235, 64044}, { 69471, 71280, 73089}, { 78516, 80325, 82134}}, {{ 83016, 85554, 88092}, { 95706, 98244, 100782}, {108396, 110934, 113472}} }, { {{ 41551, 41902, 42253}, { 43306, 43657, 44008}, { 45061, 45412, 45763}}, {{118818, 119898, 120978}, {124218, 125298, 126378}, {129618, 130698, 131778}}, {{196101, 197910, 199719}, {205146, 206955, 208764}, {214191, 216000, 217809}}, {{273366, 275904, 278442}, {286056, 288594, 291132}, {298746, 301284, 303822}} } } }); myConv->getOperator()->associateInput(0,myInput); myConv->getOperator()->associateInput(1,myWeights); myConv->getOperator()->associateInput(2,myBias); myConv->getOperator()->computeOutputDims(); myConv->forward(); // myConv->getOperator()->getOutput(0)->print(); REQUIRE(*(myConv->getOperator()->getOutput(0)) == *myOutput); } SECTION("test Padding") { std::shared_ptr<Node> myConv = Conv(3,4,{3,3}, "myconv", {1,1}, {1,1,1,1}); myConv->getOperator()->setDatatype(DataType::Int32); myConv->getOperator()->setBackend("cpu"); std::shared_ptr<Tensor> myWeights = std::make_shared<Tensor>(Array4D<int,4,3,3,3> { { { {{ 0, 1, 2}, { 3, 4, 5}, { 6, 7, 8}}, {{ 9, 10, 11}, { 12, 13, 14}, { 15, 16, 17}}, {{ 18, 19, 20}, { 21, 22, 23}, { 24, 25, 26}} }, { {{ 27, 28, 29}, { 30, 31, 32}, { 33, 34, 35}}, {{ 36, 37, 38}, { 39, 40, 41}, { 42, 43, 44}}, {{ 45, 46, 47}, { 48, 49, 50}, { 51, 52, 53}} }, { {{ 54, 55, 56}, { 57, 58, 59}, { 60, 61, 62}}, {{ 63, 64, 65}, { 66, 67, 68}, { 69, 70, 71}}, {{ 72, 73, 74}, { 75, 76, 77}, { 78, 79, 80}} }, { {{ 81, 82, 83}, { 84, 85, 86}, { 87, 88, 89}}, {{ 90, 91, 92}, { 93, 94, 95}, { 96, 97, 98}}, {{ 99, 100, 101}, {102, 103, 104}, {105, 106, 107}} } } }); std::shared_ptr<Tensor> myBias = std::make_shared<Tensor>(Array1D<int,4> {{7,0,9,0}}); std::shared_ptr<Tensor> myInput = std::make_shared<Tensor>(Array4D<int,2,3,5,5> { //NCHW { { {{ 0, 1, 2, 3, 4}, { 5, 6, 7, 8, 9}, { 10, 11, 12, 13, 14}, { 15, 16, 17, 18, 19}, { 20, 21, 22, 23, 24}}, {{ 25, 26, 27, 28, 29}, { 30, 31, 32, 33, 34}, { 35, 36, 37, 38, 39}, { 40, 41, 42, 43, 44}, { 45, 46, 47, 48, 49}}, {{ 50, 51, 52, 53, 54}, { 55, 56, 57, 58, 59}, { 60, 61, 62, 63, 64}, { 65, 66, 67, 68, 69}, { 70, 71, 72, 73, 74}} }, { {{ 75, 76, 77, 78, 79}, { 80, 81, 82, 83, 84}, { 85, 86, 87, 88, 89}, { 90, 91, 92, 93, 94}, { 95, 96, 97, 98, 99}}, {{100, 101, 102, 103, 104}, {105, 106, 107, 108, 109}, {110, 111, 112, 113, 114}, {115, 116, 117, 118, 119}, {120, 121, 122, 123, 124}}, {{125, 126, 127, 128, 129}, {130, 131, 132, 133, 134}, {135, 136, 137, 138, 139}, {140, 141, 142, 143, 144}, {145, 146, 147, 148, 149}} } } }); std::shared_ptr<Tensor> myOutput = std::make_shared<Tensor>(Array4D<int,2,4,5,5> { { { {{ 6895, 10225, 10486, 10747, 7063}, { 10303, 15226, 15577, 15928, 10429}, { 11518, 16981, 17332, 17683, 11554}, { 12733, 18736, 19087, 19438, 12679}, { 8047, 11791, 11998, 12205, 7927}}, {{ 15960, 24069, 24816, 25563, 17100}, { 25119, 37818, 38898, 39978, 26703}, { 28764, 43218, 44298, 45378, 30258}, { 32409, 48618, 49698, 50778, 33813}, { 21972, 32925, 33618, 34311, 22824}}, {{ 25041, 37929, 39162, 40395, 27153}, { 39951, 60426, 62235, 64044, 42993}, { 46026, 69471, 71280, 73089, 48978}, { 52101, 78516, 80325, 82134, 54963}, { 35913, 54075, 55254, 56433, 37737}}, {{ 34104, 51771, 53490, 55209, 37188}, { 54765, 83016, 85554, 88092, 59265}, { 63270, 95706, 98244, 100782, 67680}, { 71775, 108396, 110934, 113472, 76095}, { 49836, 75207, 76872, 78537, 52632}} }, { {{ 20395, 29800, 30061, 30322, 19663}, { 28528, 41551, 41902, 42253, 27304}, { 29743, 43306, 43657, 44008, 28429}, { 30958, 45061, 45412, 45763, 29554}, { 18847, 27316, 27523, 27730, 17827}}, {{ 53760, 80094, 80841, 81588, 54000}, { 79794, 118818, 119898, 120978, 80028}, { 83439, 124218, 125298, 126378, 83583}, { 87084, 129618, 130698, 131778, 87138}, { 57072, 84900, 85593, 86286, 57024}}, {{ 87141, 130404, 131637, 132870, 88353}, {131076, 196101, 197910, 199719, 132768}, {137151, 205146, 206955, 208764, 138753}, {143226, 214191, 216000, 217809, 144738}, { 95313, 142500, 143679, 144858, 96237}}, {{120504, 180696, 182415, 184134, 122688}, {182340, 273366, 275904, 278442, 185490}, {190845, 286056, 288594, 291132, 193905}, {199350, 298746, 301284, 303822, 202320}, {133536, 200082, 201747, 203412, 135432}} } } }); myConv->getOperator()->associateInput(0,myInput); myConv->getOperator()->associateInput(1,myWeights); myConv->getOperator()->associateInput(2,myBias); myConv->getOperator()->computeOutputDims(); myConv->forward(); REQUIRE(*(myConv->getOperator()->getOutput(0)) == *myOutput); } SECTION("Point-wise") { std::shared_ptr<Node> myConv = Conv(3,4,{1,1}, "myconv", {1,1}, {0,0,0,0}); myConv->getOperator()->setDatatype(DataType::Float32); myConv->getOperator()->setBackend("cpu"); myConv->getOperator()->input(0) = Array4D<float,2,3,3,3> { { { {{-1.38467371F, -0.87123615F, -0.22336592F}, { 1.71736145F, 0.31888032F, -0.42451897F}, { 0.30572093F, -0.77459252F, -1.55757248F}}, {{ 0.99563611F, -0.87978584F, -0.60114205F}, {-1.27415121F, 2.12278509F, -1.23465312F}, {-0.48791388F, -0.91382301F, -0.65813726F}}, {{ 0.07802387F, 0.52580875F, -0.48799172F}, { 1.19136906F, -0.81400764F, -0.73599279F}, {-1.40324783F, 0.03600367F, -0.06347727F}} }, { {{ 0.67561489F, -0.09780689F, 1.84459400F}, {-1.18453741F, 1.38354933F, 1.44513381F}, { 0.85641253F, 2.21807575F, 0.52316552F}}, {{ 0.34664667F, -0.19733144F, 1.14120162F}, { 0.05164360F, 0.72810954F, -0.71064192F}, {-0.60206831F, 0.96044880F, 0.40481427F}}, {{-1.35434294F, 1.33470297F, 0.48353928F}, {-0.19756168F, 1.26831138F, 1.22426283F}, { 0.09811721F, 1.74225271F, -1.35267365F}} } } }; myConv->getOperator()->input(1) = Array4D<float,4,3,1,1> { { { {{ 0.33669037F}}, {{ 0.12880941F}}, {{ 0.23446237F}} }, { {{ 0.23033303F}}, {{-1.12285638F}}, {{-0.18632829F}} }, { {{ 2.20820141F}}, {{-0.63799703F}}, {{ 0.46165723F}}}, { {{ 0.26735088F}}, {{ 0.53490466F}}, {{ 0.80935723F}} } } }; myConv->getOperator()->input(2) = Array1D<float,4> {{ 1.11029029F, -1.68979895F, -0.98895991F, 0.95797181F}}; Tensor expectedOutput = Array4D<float,2,4,3,3> { { { {{ 0.79062498F, 0.82691115F, 0.84323663F}, { 1.80371785F, 1.30023468F, 0.63576132F}, { 0.82136691F, 0.74022496F, 0.48621333F}}, {{-3.14122939F, -1.00057328F, -0.97532475F}, {-0.08553087F, -3.84826040F, -0.26410526F}, {-0.81005937F, -0.84882969F, -1.29773819F}}, {{-4.64579105F, -2.10878062F, -1.32395494F}, { 4.16622877F, -2.01493120F, -1.47845459F}, {-0.65039843F, -2.09977841F, -4.03780890F}}, {{ 1.18349767F, 0.68001163F, 0.18174142F}, { 1.69980371F, 1.51988935F, -0.41162649F}, {-0.35700959F, 0.29121545F, 0.13813695F}} }, { {{ 1.06487226F, 1.36487913F, 1.99171650F}, { 0.67179936F, 1.96727657F, 1.79235911F}, { 1.34408879F, 2.38930249F, 1.02142799F}}, {{-1.67106462F, -1.73944509F, -2.63643050F}, {-1.98381400F, -2.42500663F, -0.78710288F}, {-0.83478457F, -2.58197999F, -1.77180362F}}, {{-0.34346789F, -0.46286502F, 2.57942152F}, {-3.72881150F, 2.18718910F, 3.22076392F}, { 1.33158576F, 4.10055828F, -0.71644694F}}, {{ 0.22787374F, 1.90652108F, 2.45291567F}, { 0.50901115F, 2.74385118F, 1.95506990F}, { 0.94429719F, 3.47482967F, 0.21958135F}} } } }; myConv->getOperator()->computeOutputDims(); myConv->forward(); float* resPtr = static_cast<float*>(myConv->getOperator()->getOutput(0)->getImpl()->rawPtr()); float* expectedPtr = static_cast<float*>(expectedOutput.getImpl()->rawPtr()); for (std::size_t i = 0; i< expectedOutput.size(); ++i) { REQUIRE(std::abs(resPtr[i]-expectedPtr[i]) < 0.00001); } } }