diff --git a/.gitlab/ci/build.gitlab-ci.yml b/.gitlab/ci/build.gitlab-ci.yml index 68fcb6b4bc0dac08c4f0029ec1f2d3404226c1c2..365b6ddf4d009476122188adf1770243022ee663 100644 --- a/.gitlab/ci/build.gitlab-ci.yml +++ b/.gitlab/ci/build.gitlab-ci.yml @@ -23,6 +23,98 @@ build:ubuntu_cpp: - build_cpp/ - install_cpp/ +build:ubuntu_cpp_g++10: + stage: build + needs: [] + tags: + - docker + + script: + # Download dependencies + # aidge_core + - 'curl --location --output build_artifacts.zip "https://gitlab.eclipse.org/api/v4/projects/5139/jobs/artifacts/main/download?job=build:ubuntu_cpp"' + - unzip -o build_artifacts.zip -d . + - rm -rf build_cpp + + # Build current module + - export CMAKE_PREFIX_PATH=../install_cpp + - apt install -y g++-10 + - mkdir -p build_cpp + - mkdir -p install_cpp + - cd build_cpp + - export CXX=/usr/bin/g++-10 + - cmake -DCMAKE_INSTALL_PREFIX:PATH=../install_cpp -DCMAKE_BUILD_TYPE=Debug -DWERROR=ON -DCOVERAGE=ON .. + - make -j4 all install + +build:ubuntu_cpp_g++12: + stage: build + needs: [] + tags: + - docker + + script: + # Download dependencies + # aidge_core + - 'curl --location --output build_artifacts.zip "https://gitlab.eclipse.org/api/v4/projects/5139/jobs/artifacts/main/download?job=build:ubuntu_cpp"' + - unzip -o build_artifacts.zip -d . + - rm -rf build_cpp + + # Build current module + - export CMAKE_PREFIX_PATH=../install_cpp + - apt install -y g++-12 + - mkdir -p build_cpp + - mkdir -p install_cpp + - cd build_cpp + - export CXX=/usr/bin/g++-12 + - cmake -DCMAKE_INSTALL_PREFIX:PATH=../install_cpp -DCMAKE_BUILD_TYPE=Debug -DWERROR=ON -DCOVERAGE=ON .. + - make -j4 all install + +build:ubuntu_cpp_clang12: + stage: build + needs: [] + tags: + - docker + + script: + # Download dependencies + # aidge_core + - 'curl --location --output build_artifacts.zip "https://gitlab.eclipse.org/api/v4/projects/5139/jobs/artifacts/main/download?job=build:ubuntu_cpp"' + - unzip -o build_artifacts.zip -d . + - rm -rf build_cpp + + # Build current module + - export CMAKE_PREFIX_PATH=../install_cpp + - apt install -y clang-12 + - mkdir -p build_cpp + - mkdir -p install_cpp + - cd build_cpp + - export CXX=/usr/bin/clang++-12 + - cmake -DCMAKE_INSTALL_PREFIX:PATH=../install_cpp -DCMAKE_BUILD_TYPE=Debug -DWERROR=ON -DCOVERAGE=ON .. + - make -j4 all install + +build:ubuntu_cpp_clang15: + stage: build + needs: [] + tags: + - docker + + script: + # Download dependencies + # aidge_core + - 'curl --location --output build_artifacts.zip "https://gitlab.eclipse.org/api/v4/projects/5139/jobs/artifacts/main/download?job=build:ubuntu_cpp"' + - unzip -o build_artifacts.zip -d . + - rm -rf build_cpp + + # Build current module + - export CMAKE_PREFIX_PATH=../install_cpp + - apt install -y clang-15 + - mkdir -p build_cpp + - mkdir -p install_cpp + - cd build_cpp + - export CXX=/usr/bin/clang++-15 + - cmake -DCMAKE_INSTALL_PREFIX:PATH=../install_cpp -DCMAKE_BUILD_TYPE=Debug -DWERROR=ON -DCOVERAGE=ON .. + - make -j4 all install + build:ubuntu_python: stage: build needs: [] @@ -84,3 +176,42 @@ build:windows_cpp: paths: - build_cpp/ - install_cpp/ + +build:windows_python: + stage: build + needs: [] + tags: + - windows + + image: buildtools + before_script: + # Install Chocolatey + - Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + # Install dependencies + - choco install cmake.install --installargs '"ADD_CMAKE_TO_PATH=System"' -Y + - choco install git -Y + - choco install python -Y + # Update PATH + - $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") + script: + # Download dependencies + # aidge_core (CPP) + - 'curl "https://gitlab.eclipse.org/api/v4/projects/5139/jobs/artifacts/main/download?job=build:windows_cpp" -o build_artifacts.zip' + - Expand-Archive -Path .\build_artifacts.zip -DestinationPath . -Force + - Remove-Item .\build_cpp\ -Recurse + # aidge_core (Python) + - 'curl "https://gitlab.eclipse.org/api/v4/projects/5139/jobs/artifacts/main/download?job=build:windows_python" -o build_artifacts.zip' + - Expand-Archive -Path .\build_artifacts.zip -DestinationPath . -Force + + - python -m pip install virtualenv + - virtualenv venv + - venv\Scripts\Activate.ps1 + # Numpy dependancy for unit test + - python -m pip install numpy + - $env:AIDGE_INSTALL = "$pwd" + "install" + - $env:CMAKE_PREFIX_PATH = "../install_cpp" + - python -m pip install . + artifacts: + expire_in: 1 week + paths: + - venv/ diff --git a/include/aidge/backend/cpu.hpp b/include/aidge/backend/cpu.hpp index e3fa457c5cf557328a7fbf2049b9e577c44391f9..4d334e2a492962ab40efaf9bf1fe64682f225db2 100644 --- a/include/aidge/backend/cpu.hpp +++ b/include/aidge/backend/cpu.hpp @@ -13,7 +13,6 @@ #define AIDGE_CPU_IMPORTS_H_ #include "aidge/backend/cpu/data/TensorImpl.hpp" - #include "aidge/backend/cpu/operator/AddImpl.hpp" #include "aidge/backend/cpu/operator/AvgPoolingImpl.hpp" #include "aidge/backend/cpu/operator/MaxPoolingImpl.hpp" @@ -23,10 +22,10 @@ #include "aidge/backend/cpu/operator/FCImpl.hpp" #include "aidge/backend/cpu/operator/LeakyReLUImpl.hpp" #include "aidge/backend/cpu/operator/MatMulImpl.hpp" +#include "aidge/backend/cpu/operator/PadImpl.hpp" #include "aidge/backend/cpu/operator/ProducerImpl.hpp" #include "aidge/backend/cpu/operator/ReLUImpl.hpp" -#include "aidge/backend/cpu/operator/ScalingImpl.hpp" -#include "aidge/backend/cpu/operator/SliceImpl.hpp" #include "aidge/backend/cpu/operator/SoftmaxImpl.hpp" +#include "aidge/backend/cpu/operator/ScalingImpl.hpp" #endif /* AIDGE_CPU_IMPORTS_H_ */ \ No newline at end of file diff --git a/include/aidge/backend/cpu/operator/AddImpl.hpp b/include/aidge/backend/cpu/operator/AddImpl.hpp index 6e1cd03a3af81ee85f4f9e0e212af7c02089734e..99c83e2c6f91d50475ff7896dbe286286f7c8e2d 100644 --- a/include/aidge/backend/cpu/operator/AddImpl.hpp +++ b/include/aidge/backend/cpu/operator/AddImpl.hpp @@ -74,12 +74,12 @@ class AddImpl_cpu : public OperatorImpl { return std::accumulate(inputDims.begin(), inputDims.end(), NbElts_t(1), std::multiplies<NbElts_t>()); } - NbElts_t getNbRequiredProtected(const IOIndex_t inputIdx) const override final { + NbElts_t getNbRequiredProtected(const IOIndex_t /*inputIdx*/) const override final { // for the direct convolution algorithm, convolutions can be in-place, if there is no padding! return 0; } - NbElts_t getRequiredMemory(const IOIndex_t outputIdx, const std::vector<DimSize_t>& inputsSize) const override final { + NbElts_t getRequiredMemory(const IOIndex_t outputIdx, const std::vector<DimSize_t>& /*inputsSize*/) const override final { // Requires the whole tensors, regardless of available data on inputs assert(outputIdx == 0 && "operator has only one output"); (void) outputIdx; @@ -99,11 +99,11 @@ class AddImpl_cpu : public OperatorImpl { } void updateConsummerProducer() override final; - void forward() { + void forward() override { // nothing } - void backward() { printf("Not implemented yet.\n"); } + void backward() override { printf("Not implemented yet.\n"); } }; template <> @@ -133,9 +133,9 @@ class AddImpl_cpu<1> : public OperatorImpl { NbElts_t getNbProducedData(const IOIndex_t /*outputIdx*/) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; template <> @@ -165,9 +165,9 @@ class AddImpl_cpu<2> : public OperatorImpl { NbElts_t getNbProducedData(const IOIndex_t /*outputIdx*/) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; template <> @@ -196,9 +196,9 @@ class AddImpl_cpu<3> : public OperatorImpl { NbElts_t getNbProducedData(const IOIndex_t outputIdx) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; namespace { diff --git a/include/aidge/backend/cpu/operator/AvgPoolingImpl.hpp b/include/aidge/backend/cpu/operator/AvgPoolingImpl.hpp index cfbcadfe6b719369618955a14c4cde5733ef6773..635c246c95d5625f9cb703e34d4d1fbbda833998 100644 --- a/include/aidge/backend/cpu/operator/AvgPoolingImpl.hpp +++ b/include/aidge/backend/cpu/operator/AvgPoolingImpl.hpp @@ -56,9 +56,9 @@ class AvgPoolingImpl2D_cpu : public OperatorImpl { NbElts_t getNbProducedData(const IOIndex_t outputIdx) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; namespace { diff --git a/include/aidge/backend/cpu/operator/AvgPoolingImpl_forward_kernels.hpp b/include/aidge/backend/cpu/operator/AvgPoolingImpl_forward_kernels.hpp index 60b4923bdc18674da52be9bd07d9947fb9790f0d..ea46a540ad04b6227d6ec01c965e2eb99806d5e1 100644 --- a/include/aidge/backend/cpu/operator/AvgPoolingImpl_forward_kernels.hpp +++ b/include/aidge/backend/cpu/operator/AvgPoolingImpl_forward_kernels.hpp @@ -43,11 +43,11 @@ void AvgPoolingImpl2D_cpu_forward_kernel(const AvgPooling_Op<2>::Attrs &attrs, // output H size const std::size_t oxSize = - static_cast<std::size_t>(std::floor(static_cast<float>(dims[2] + std::get<2>(attrs)[0] + std::get<2>(attrs)[2] - std::get<1>(attrs)[0] + std::get<0>(attrs)[0]) / + static_cast<std::size_t>(std::floor(static_cast<float>(dims[2] - std::get<1>(attrs)[0] + std::get<0>(attrs)[0]) / static_cast<float>(std::get<0>(attrs)[0]))); // output W size const std::size_t oySize = - static_cast<std::size_t>(std::floor(static_cast<float>(dims[3] + std::get<2>(attrs)[1] + std::get<2>(attrs)[3] - std::get<1>(attrs)[1] + std::get<0>(attrs)[1])/ + static_cast<std::size_t>(std::floor(static_cast<float>(dims[3] - std::get<1>(attrs)[1] + std::get<0>(attrs)[1]) / static_cast<float>(std::get<0>(attrs)[1]))); // TODO: kernel computation @@ -61,11 +61,11 @@ void AvgPoolingImpl2D_cpu_forward_kernel(const AvgPooling_Op<2>::Attrs &attrs, const std::size_t oIndex = (ch + batch*dims[1]) * oxSize * oySize; const std::size_t iIndex = (ch + batch*dims[1]) * dims[2] * dims[3]; for (std::size_t ox = 0; ox < oxSize; ++ox) { - const signedsize difx = static_cast<signedsize>(std::get<2>(attrs)[0] - ox * std::get<0>(attrs)[0]); + const signedsize difx = static_cast<signedsize>(- ox * std::get<0>(attrs)[0]); const std::size_t sxMin = static_cast<std::size_t>(std::max(difx, signedsize(0))); const std::size_t sxMax = (static_cast<signedsize>(dims[2]) + difx) < 0 ? 0 : ((dims[2] + difx) > std::get<1>(attrs)[0] ? std::get<1>(attrs)[0] : dims[2] + difx); for (std::size_t oy = 0; oy < oySize; ++oy) { - const signedsize dify = static_cast<signedsize>(std::get<2>(attrs)[1] - oy * std::get<0>(attrs)[1]); + const signedsize dify = static_cast<signedsize>(- oy * std::get<0>(attrs)[1]); const std::size_t syMin = static_cast<std::size_t>(std::max(dify, signedsize(0))); const std::size_t syMax = (static_cast<signedsize>(dims[3]) + dify) < 0 ? 0 : ((dims[3] + dify) > std::get<1>(attrs)[1] ? std::get<1>(attrs)[1] : dims[3] + dify); const std::size_t oIndexFull = oIndex + ox*oySize + oy; diff --git a/include/aidge/backend/cpu/operator/BatchNormImpl.hpp b/include/aidge/backend/cpu/operator/BatchNormImpl.hpp index 30557f6cbba05829b3cc9e17364ae4d933a568cf..f46113543d7c4a9d55dc7710fec74cca7fb3814d 100644 --- a/include/aidge/backend/cpu/operator/BatchNormImpl.hpp +++ b/include/aidge/backend/cpu/operator/BatchNormImpl.hpp @@ -71,9 +71,9 @@ class BatchNormImpl2D_cpu : public OperatorImpl { NbElts_t getNbProducedData(const IOIndex_t outputIdx) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; namespace { diff --git a/include/aidge/backend/cpu/operator/ConvDepthWiseImpl.hpp b/include/aidge/backend/cpu/operator/ConvDepthWiseImpl.hpp index 2826b635590c5d19f34c8e4beee20fc8dba2183b..a5a144f50d6fbe1eb6c63827cad6a654777b60ae 100644 --- a/include/aidge/backend/cpu/operator/ConvDepthWiseImpl.hpp +++ b/include/aidge/backend/cpu/operator/ConvDepthWiseImpl.hpp @@ -58,9 +58,9 @@ class ConvDepthWiseImpl2D_cpu : public OperatorImpl { NbElts_t getNbProducedData(const IOIndex_t outputIdx) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; namespace { diff --git a/include/aidge/backend/cpu/operator/ConvDepthWiseImpl_forward_kernels.hpp b/include/aidge/backend/cpu/operator/ConvDepthWiseImpl_forward_kernels.hpp index 669bdbc898528b0f96a59dd3c6f8e438ae1291e4..5aa29ac55740d46bba873bb9d85a04cd004cc3bd 100644 --- a/include/aidge/backend/cpu/operator/ConvDepthWiseImpl_forward_kernels.hpp +++ b/include/aidge/backend/cpu/operator/ConvDepthWiseImpl_forward_kernels.hpp @@ -9,7 +9,7 @@ * ********************************************************************************/ -#ifndef AIDGE_CPU_OPERATOR_CONVDEPTHWISEIMP_FORWARD_KERNEL_H_ +#ifndef AIDGE_CPU_OPERATOR_CONVDEPTHWISEIMPL_FORWARD_KERNEL_H_ #define AIDGE_CPU_OPERATOR_CONVDEPTHWISEIMPL_FORWARD_KERNEL_H_ #include "aidge/utils/Registrar.hpp" @@ -46,11 +46,11 @@ void ConvDepthWiseImpl2D_cpu_forward_kernel(const ConvDepthWise_Op<2>::Attrs &at // output H size const std::size_t oxSize = - static_cast<std::size_t>(std::floor(static_cast<float>(dims[2] + std::get<4>(attrs)[0] + std::get<4>(attrs)[2] - std::get<3>(attrs)[0] + std::get<0>(attrs)[0]) / + static_cast<std::size_t>(std::floor(static_cast<float>(dims[2] - std::get<3>(attrs)[0] + std::get<0>(attrs)[0]) / static_cast<float>(std::get<0>(attrs)[0]))); // output W size const std::size_t oySize = - static_cast<std::size_t>(std::floor(static_cast<float>(dims[3] + std::get<4>(attrs)[1] + std::get<4>(attrs)[3] - std::get<3>(attrs)[1] + std::get<0>(attrs)[1]) / + static_cast<std::size_t>(std::floor(static_cast<float>(dims[3] - std::get<3>(attrs)[1] + std::get<0>(attrs)[1]) / static_cast<float>(std::get<0>(attrs)[1]))); // TODO: kernel computation @@ -67,16 +67,16 @@ void ConvDepthWiseImpl2D_cpu_forward_kernel(const ConvDepthWise_Op<2>::Attrs &at const std::size_t iIndex = (ch + batch*dims[1]) * dims[2] * dims[3]; const std::size_t wIndex = ch * std::get<3>(attrs)[0] * std::get<3>(attrs)[1]; for (std::size_t ox = 0; ox < oxSize; ++ox) { - const signedsize difx = static_cast<signedsize>(std::get<4>(attrs)[0] - ox * std::get<0>(attrs)[0]); + const signedsize difx = static_cast<signedsize>(- ox * std::get<0>(attrs)[0]); const std::size_t sxMin = static_cast<std::size_t>(std::max(difx, signedsize(0))); const std::size_t sxMax = (static_cast<signedsize>(dims[2]) + difx) < 0 ? 0 : ((dims[2] + difx) > std::get<3>(attrs)[0] ? std::get<3>(attrs)[0] : dims[2] + difx); for (std::size_t oy = 0; oy < oySize; ++oy) { - const signedsize dify = static_cast<signedsize>(std::get<4>(attrs)[1] - oy * std::get<0>(attrs)[1]); + const signedsize dify = static_cast<signedsize>(- oy * std::get<0>(attrs)[1]); const std::size_t syMin = static_cast<std::size_t>(std::max(dify, signedsize(0))); const std::size_t syMax = (static_cast<signedsize>(dims[3]) + dify) < 0 ? 0 : ((dims[3] + dify) > std::get<3>(attrs)[1] ? std::get<3>(attrs)[1] : dims[3] + dify); const std::size_t oIndexFull = oIndex + ox*oySize + oy; - const signedsize ix = static_cast<signedsize>(ox * std::get<0>(attrs)[0]) - std::get<4>(attrs)[0]; - const signedsize iy = static_cast<signedsize>(oy * std::get<0>(attrs)[1]) - std::get<4>(attrs)[1]; + const signedsize ix = static_cast<signedsize>(ox * std::get<0>(attrs)[0]); + const signedsize iy = static_cast<signedsize>(oy * std::get<0>(attrs)[1]); if (sxMin == 0 && syMin == 0 && sxMax == 3 && syMax == 3) { output[oIndexFull] += (weights[wIndex + 0*std::get<3>(attrs)[1] + 0] * input[iIndex + static_cast<std::size_t>(ix+0)*dims[3] + static_cast<std::size_t>(iy+0)] + diff --git a/include/aidge/backend/cpu/operator/ConvImpl.hpp b/include/aidge/backend/cpu/operator/ConvImpl.hpp index b9411fe0f1ac079d9857cc8f2178fc98fadc3a77..fba1fd6aad72189ea9e18b5da0d1fc2613d0cc69 100644 --- a/include/aidge/backend/cpu/operator/ConvImpl.hpp +++ b/include/aidge/backend/cpu/operator/ConvImpl.hpp @@ -58,9 +58,9 @@ class ConvImpl2D_cpu : public OperatorImpl { NbElts_t getNbProducedData(const IOIndex_t outputIdx) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; namespace { diff --git a/include/aidge/backend/cpu/operator/ConvImpl_forward_kernels.hpp b/include/aidge/backend/cpu/operator/ConvImpl_forward_kernels.hpp index 9d4d6dfdfcc114e47e478089c4d5a42c2bee0f28..03e2c35170432181c7a9b3934d61f0bd18471876 100644 --- a/include/aidge/backend/cpu/operator/ConvImpl_forward_kernels.hpp +++ b/include/aidge/backend/cpu/operator/ConvImpl_forward_kernels.hpp @@ -88,11 +88,11 @@ void ConvImpl2D_cpu_forward_kernel(const Conv_Op<2>::Attrs &attrs, const std::ar // output H size const std::size_t oxSize = - static_cast<std::size_t>(std::floor(static_cast<float>(dims[2] + std::get<5>(attrs)[0] + std::get<5>(attrs)[2] - std::get<4>(attrs)[0] + std::get<0>(attrs)[0]) / + static_cast<std::size_t>(std::floor(static_cast<float>(dims[2] - std::get<4>(attrs)[0] + std::get<0>(attrs)[0]) / static_cast<float>(std::get<0>(attrs)[0]))); // output W size const std::size_t oySize = - static_cast<std::size_t>(std::floor(static_cast<float>(dims[3] + std::get<5>(attrs)[1] + std::get<5>(attrs)[3] - std::get<4>(attrs)[1] + std::get<0>(attrs)[1]) / + static_cast<std::size_t>(std::floor(static_cast<float>(dims[3] - std::get<4>(attrs)[1] + std::get<0>(attrs)[1]) / static_cast<float>(std::get<0>(attrs)[1]))); // TODO: kernel computation @@ -110,16 +110,16 @@ void ConvImpl2D_cpu_forward_kernel(const Conv_Op<2>::Attrs &attrs, const std::ar const std::size_t iIndex = (inCh + batch*dims[1]) * dims[2] * dims[3]; const std::size_t wIndex = (inCh + outCh*dims[1]) * std::get<4>(attrs)[0] * std::get<4>(attrs)[1]; for (std::size_t ox = 0; ox < oxSize; ++ox) { - const signedsize difx = static_cast<signedsize>(std::get<5>(attrs)[0] - ox * std::get<0>(attrs)[0]); + const signedsize difx = static_cast<signedsize>(- ox * std::get<0>(attrs)[0]); const std::size_t sxMin = static_cast<std::size_t>(std::max(difx, signedsize(0))); const std::size_t sxMax = (static_cast<signedsize>(dims[2]) + difx) < 0 ? 0 : ((dims[2] + difx) > std::get<4>(attrs)[0] ? std::get<4>(attrs)[0] : dims[2] + difx); for (std::size_t oy = 0; oy < oySize; ++oy) { - const signedsize dify = static_cast<signedsize>(std::get<5>(attrs)[1] - oy * std::get<0>(attrs)[1]); + const signedsize dify = static_cast<signedsize>(- oy * std::get<0>(attrs)[1]); const std::size_t syMin = static_cast<std::size_t>(std::max(dify, signedsize(0))); const std::size_t syMax = (static_cast<signedsize>(dims[3]) + dify) < 0 ? 0 : ((dims[3] + dify) > std::get<4>(attrs)[1] ? std::get<4>(attrs)[1] : dims[3] + dify); const std::size_t oIndexFull = oIndex + ox*oySize + oy; - const signedsize ix = static_cast<signedsize>(ox * std::get<0>(attrs)[0]) - std::get<5>(attrs)[0]; - const signedsize iy = static_cast<signedsize>(oy * std::get<0>(attrs)[1]) - std::get<5>(attrs)[1]; + const signedsize ix = static_cast<signedsize>(ox * std::get<0>(attrs)[0]); + const signedsize iy = static_cast<signedsize>(oy * std::get<0>(attrs)[1]); if (sxMin == 0 && syMin == 0 && sxMax == 3 && syMax == 3) { output[oIndexFull] += (weights[wIndex + 0*std::get<4>(attrs)[1] + 0] * input[iIndex + static_cast<std::size_t>(ix+0)*dims[3] + static_cast<std::size_t>(iy+0)] + diff --git a/include/aidge/backend/cpu/operator/FCImpl.hpp b/include/aidge/backend/cpu/operator/FCImpl.hpp index 1dfa40439dbba9cdd4fe3436fea30f771678c1ff..875456d185bf28ec06c2491bd5c57ce7e6236e49 100644 --- a/include/aidge/backend/cpu/operator/FCImpl.hpp +++ b/include/aidge/backend/cpu/operator/FCImpl.hpp @@ -51,9 +51,9 @@ class FCImpl_cpu : public OperatorImpl { NbElts_t getNbConsumedData(const IOIndex_t inputIdx) const override final; NbElts_t getNbProducedData(const IOIndex_t outputIdx) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; namespace { diff --git a/include/aidge/backend/cpu/operator/LeakyReLUImpl.hpp b/include/aidge/backend/cpu/operator/LeakyReLUImpl.hpp index 386ef999fddbda184edee88723d213f53ff62ded..dc895c2758bda2aa766227eb628e990316a5bd52 100644 --- a/include/aidge/backend/cpu/operator/LeakyReLUImpl.hpp +++ b/include/aidge/backend/cpu/operator/LeakyReLUImpl.hpp @@ -50,9 +50,9 @@ class LeakyReLUImpl_cpu : public OperatorImpl { NbElts_t getNbConsumedData(const IOIndex_t inputIdx) const override final; NbElts_t getNbProducedData(const IOIndex_t outputIdx) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; namespace { diff --git a/include/aidge/backend/cpu/operator/MatMulImpl.hpp b/include/aidge/backend/cpu/operator/MatMulImpl.hpp index bf8e31efd253ee8855f3473ef0b4a60c59a04b5f..504406c7a7f2741abfa68d934c20e15bfcce59dd 100644 --- a/include/aidge/backend/cpu/operator/MatMulImpl.hpp +++ b/include/aidge/backend/cpu/operator/MatMulImpl.hpp @@ -64,8 +64,8 @@ public: void updateConsummerProducer() override final; - void forward(); - void backward(); + void forward() override; + void backward() override; }; namespace { diff --git a/include/aidge/backend/cpu/operator/MaxPoolingImpl.hpp b/include/aidge/backend/cpu/operator/MaxPoolingImpl.hpp index ef7835c742235f96e36423b9f5388efc4649199f..ca4480653b8315ab3d986eac1c460e2d7c17b844 100644 --- a/include/aidge/backend/cpu/operator/MaxPoolingImpl.hpp +++ b/include/aidge/backend/cpu/operator/MaxPoolingImpl.hpp @@ -56,9 +56,9 @@ class MaxPoolingImpl2D_cpu : public OperatorImpl { NbElts_t getNbProducedData(const IOIndex_t outputIdx) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; namespace { diff --git a/include/aidge/backend/cpu/operator/MaxPoolingImpl_forward_kernels.hpp b/include/aidge/backend/cpu/operator/MaxPoolingImpl_forward_kernels.hpp index eae73f8d8fb7546bb234e7ad7dce38b59378b4ee..caa99e8678a72c7fd3c77fe8b7579ea739ac64c7 100644 --- a/include/aidge/backend/cpu/operator/MaxPoolingImpl_forward_kernels.hpp +++ b/include/aidge/backend/cpu/operator/MaxPoolingImpl_forward_kernels.hpp @@ -42,15 +42,14 @@ void MaxPoolingImpl2D_cpu_forward_kernel(const MaxPooling_Op<2>::Attrs &attrs, std::array<DimSize_t, 2> strideDims = std::get<0>(attrs); std::array<DimSize_t, 2> kernelDims = std::get<1>(attrs); - std::array<DimSize_t, 4> paddingDims = std::get<2>(attrs); // output H size const std::size_t oxSize = - static_cast<std::size_t>(std::floor(static_cast<float>(dims[2] + paddingDims[0] + paddingDims[2] - kernelDims[0] + strideDims[0]) / + static_cast<std::size_t>(std::floor(static_cast<float>(dims[2] - kernelDims[0] + strideDims[0]) / static_cast<float>(strideDims[0]))); // output W size const std::size_t oySize = - static_cast<std::size_t>(std::floor(static_cast<float>(dims[3] + paddingDims[1] + paddingDims[3] - kernelDims[1] + strideDims[1]) / + static_cast<std::size_t>(std::floor(static_cast<float>(dims[3] - kernelDims[1] + strideDims[1]) / static_cast<float>(strideDims[1]))); // TODO: kernel computation @@ -64,11 +63,11 @@ void MaxPoolingImpl2D_cpu_forward_kernel(const MaxPooling_Op<2>::Attrs &attrs, const std::size_t oIndex = (ch + batch*dims[1]) * oxSize * oySize; const std::size_t iIndex = (ch + batch*dims[1]) * dims[2] * dims[3]; for (std::size_t ox = 0; ox < oxSize; ++ox) { - const signedsize difx = static_cast<signedsize>(paddingDims[0] - ox * strideDims[0]); + const signedsize difx = static_cast<signedsize>(- ox * strideDims[0]); const std::size_t sxMin = static_cast<std::size_t>(std::max(difx, signedsize(0))); const std::size_t sxMax = (static_cast<signedsize>(dims[2]) + difx) < 0 ? 0 : ((dims[2] + difx) > kernelDims[0] ? kernelDims[0] : dims[2] + difx); for (std::size_t oy = 0; oy < oySize; ++oy) { - const signedsize dify = static_cast<signedsize>(paddingDims[1] - oy * strideDims[1]); + const signedsize dify = static_cast<signedsize>(- oy * strideDims[1]); const std::size_t syMin = static_cast<std::size_t>(std::max(dify, signedsize(0))); const std::size_t syMax = (static_cast<signedsize>(dims[3]) + dify) < 0 ? 0 : ((dims[3] + dify) > kernelDims[1] ? kernelDims[1] : dims[3] + dify); const std::size_t oIndexFull = oIndex + ox*oySize + oy; diff --git a/include/aidge/backend/cpu/operator/PadImpl.hpp b/include/aidge/backend/cpu/operator/PadImpl.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1a3202a7c71a6669e191fefa7e7b29849fc017f8 --- /dev/null +++ b/include/aidge/backend/cpu/operator/PadImpl.hpp @@ -0,0 +1,72 @@ +/******************************************************************************** + * 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_PADIMPL_H_ +#define AIDGE_CPU_OPERATOR_PADIMPL_H_ + +#include <array> +#include <memory> +#include <tuple> +#include <vector> + +#include "aidge/backend/OperatorImpl.hpp" +#include "aidge/operator/Pad.hpp" +#include "aidge/utils/Registrar.hpp" +#include "aidge/utils/Types.h" + +namespace Aidge { +// class Pad_Op; + +// compute kernel registry for forward and backward +class PadImpl2DForward_cpu + : public Registrable<PadImpl2DForward_cpu, + std::tuple<DataType, DataType>, + void(const Pad_Op<2>::Attrs &, const std::array<DimSize_t, 4> &, const void *, + void *)> {}; +class PadImpl2DBackward_cpu + : public Registrable<PadImpl2DBackward_cpu, + std::tuple<DataType, DataType>, + void(const Pad_Op<2>::Attrs &, const std::array<DimSize_t, 4> &, const void *, + void *)> {}; + +class PadImpl2D_cpu : public OperatorImpl { + private: + const Pad_Op<2> &mOp; + std::array<NbElts_t, 1> mNbConsumedData = {0}; + std::array<NbElts_t, 1> mNbProducedData = {0}; + + public: + PadImpl2D_cpu(const Pad_Op<2> &op) : mOp(op) {} + + static std::unique_ptr<PadImpl2D_cpu> create(const Pad_Op<2> &op) { + return std::make_unique<PadImpl2D_cpu>(op); + } + + public: + NbElts_t getNbRequiredData(const IOIndex_t inputIdx) const override final; + NbElts_t getNbRequiredProtected(const IOIndex_t inputIdx) const override final; + NbElts_t getRequiredMemory(const IOIndex_t /*outputIdx*/, const std::vector<DimSize_t> &/*inputsSize*/) const override final; + NbElts_t getNbConsumedData(const IOIndex_t inputIdx) const override final; + NbElts_t getNbProducedData(const IOIndex_t outputIdx) const override final; + void updateConsummerProducer() override final; + + void forward() override; + + void backward() override; +}; + +namespace { +// add cpu backend to Pad_Op<2> implementation registry +static Registrar<Pad_Op<2>> registrarPadImpl2D_cpu("cpu", Aidge::PadImpl2D_cpu::create); +} // namespace +} // namespace Aidge + +#endif /* AIDGE_CPU_OPERATOR_PADIMPL_H_ */ diff --git a/include/aidge/backend/cpu/operator/PadImpl_forward_kernels.hpp b/include/aidge/backend/cpu/operator/PadImpl_forward_kernels.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1babc3ecf2ff2fa8db2fd5ffbd34d89b8d7d88b6 --- /dev/null +++ b/include/aidge/backend/cpu/operator/PadImpl_forward_kernels.hpp @@ -0,0 +1,110 @@ +/******************************************************************************** + * 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_PADIMPL_FORWARD_KERNEL_H_ +#define AIDGE_CPU_OPERATOR_PADIMPL_FORWARD_KERNEL_H_ + +#include "aidge/utils/Registrar.hpp" + +#include "aidge/backend/cpu/operator/PadImpl.hpp" +#include "aidge/utils/Types.h" +#include <cmath> +#include <array> +#include <algorithm> + +namespace Aidge { +/** + * @brief Forward kernel for 2D Padding on CPU backend. + * @tparam I Input data type. + * @tparam O Output data type. + * @param attrs tuple of Parameters from the Operator + * @param dims Array of input dimensions. + * @param input_ const input Tensor. + * @param output_ Output Tensor. + */ +template <class I, class O> +void PadImpl2D_cpu_forward_kernel(const Pad_Op<2>::Attrs &attrs, const std::array<DimSize_t, 4> &dims, + const void *input_, void *output_) +{ + const I *input = static_cast<const I *>(input_); + O *output = static_cast<O *>(output_); + + const std::size_t oySize = dims[2] + std::get<0>(attrs)[0][0] + std::get<0>(attrs)[0][1]; + const std::size_t oxSize = dims[3] + std::get<0>(attrs)[1][0] + std::get<0>(attrs)[1][1]; + + for (std::size_t batch = 0; batch < dims[0]; ++batch) { + for (std::size_t ch = 0; ch < dims[1]; ++ch) { + const std::size_t iIndex = (ch + batch*dims[1]) * dims[2] * dims[3]; + const std::size_t oIndex = (ch + batch*dims[1]) * oxSize * oySize; + + for (unsigned int oy = 0; oy < oySize; ++oy) { + for (unsigned int ox = 0; ox < oxSize; ++ox) { + const std::size_t oIndexFull = oIndex + ox*oySize + oy; + + O outputValue = std::get<2>(attrs); + + if (std::get<1>(attrs) == PadBorderType::Constant) { + int ix = static_cast<int>(ox) - static_cast<int>(std::get<0>(attrs)[1][1]); + int iy = static_cast<int>(oy) - static_cast<int>(std::get<0>(attrs)[0][1]); + + if (ix >= 0 && ix < static_cast<int>(dims[3]) && iy >= 0 && iy < static_cast<int>(dims[2])) { + outputValue = input[iIndex + static_cast<std::size_t>(ix)*dims[2] + static_cast<std::size_t>(iy)]; + } + } + else if (std::get<1>(attrs) == PadBorderType::Replicate) { + int ix = std::max(0, std::min(static_cast<int>(dims[3]) - 1, static_cast<int>(ox) - static_cast<int>(std::get<0>(attrs)[1][1]))); + int iy = std::max(0, std::min(static_cast<int>(dims[2]) - 1, static_cast<int>(oy) - static_cast<int>(std::get<0>(attrs)[0][1]))); + + outputValue = input[iIndex + static_cast<std::size_t>(ix)*dims[2] + static_cast<std::size_t>(iy)]; + } + else if (std::get<1>(attrs) == PadBorderType::Reflect) { + int ix = static_cast<int>(ox) - static_cast<int>(std::get<0>(attrs)[1][1]); + int iy = static_cast<int>(oy) - static_cast<int>(std::get<0>(attrs)[0][1]); + + if (ix < 0) + ix = 0 - ix; + if (iy < 0) + iy = 0 - iy; + if (ix >= static_cast<int>(dims[3])) + ix = static_cast<int>(dims[3]) - ix; + if (iy >= static_cast<int>(dims[2])) + iy = static_cast<int>(dims[2]) - iy; + + outputValue = input[iIndex + static_cast<std::size_t>(ix)*dims[2] + static_cast<std::size_t>(iy)]; + } + else if (std::get<1>(attrs) == PadBorderType::Wrap) { + int ix = (static_cast<int>(dims[3]) + static_cast<int>(ox) - static_cast<int>(std::get<0>(attrs)[1][1])) % static_cast<int>(dims[3]); + int iy = (static_cast<int>(dims[2]) + static_cast<int>(oy) - static_cast<int>(std::get<0>(attrs)[0][1])) % static_cast<int>(dims[2]); + + outputValue = input[iIndex + static_cast<std::size_t>(ix)*dims[2] + static_cast<std::size_t>(iy)]; + } + + output[oIndexFull] = outputValue; + } + } + } + } +} + +namespace { +static Registrar<PadImpl2DForward_cpu> registrarPadImpl2DForward_cpu_Float32( + {DataType::Float32, DataType::Float32}, + Aidge::PadImpl2D_cpu_forward_kernel<float, float>); +static Registrar<PadImpl2DForward_cpu> registrarPadImpl2DForward_cpu_Int32( + {DataType::Int32, DataType::Int32}, + Aidge::PadImpl2D_cpu_forward_kernel<int, int>); +static Registrar<PadImpl2DForward_cpu> registrarPadImpl2DForward_cpu_Float64( + {DataType::Float64, DataType::Float64}, + Aidge::PadImpl2D_cpu_forward_kernel<double, double>); +} // namespace +} // namespace Aidge + +#endif /* AIDGE_CPU_OPERATOR_PADIMPL_FORWARD_KERNEL_H_ */ diff --git a/include/aidge/backend/cpu/operator/ProducerImpl.hpp b/include/aidge/backend/cpu/operator/ProducerImpl.hpp index 032172dbf0995fc62ce631aa5eba1cabf2374ad3..f23dfc2656ae5c91c8879f24474efc2eb0b04231 100644 --- a/include/aidge/backend/cpu/operator/ProducerImpl.hpp +++ b/include/aidge/backend/cpu/operator/ProducerImpl.hpp @@ -39,9 +39,9 @@ class ProducerImpl_cpu : public OperatorImpl { NbElts_t getNbProducedData(const IOIndex_t outputIdx) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; namespace { diff --git a/include/aidge/backend/cpu/operator/ReLUImpl.hpp b/include/aidge/backend/cpu/operator/ReLUImpl.hpp index 537bdeeaf89b388a82e819330649c2ae3445c590..dd785d1d4231eff562fce8a814934aefd715c23f 100644 --- a/include/aidge/backend/cpu/operator/ReLUImpl.hpp +++ b/include/aidge/backend/cpu/operator/ReLUImpl.hpp @@ -50,9 +50,9 @@ class ReLUImpl_cpu : public OperatorImpl { NbElts_t getNbConsumedData(const IOIndex_t inputIdx) const override final; NbElts_t getNbProducedData(const IOIndex_t outputIdx) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; namespace { diff --git a/include/aidge/backend/cpu/operator/ScalingImpl.hpp b/include/aidge/backend/cpu/operator/ScalingImpl.hpp index 37549349b9f5ffbf443d976135db05b4cec209b7..58ca58510e7e89faac95ef5df637aaf3ac8ed98d 100644 --- a/include/aidge/backend/cpu/operator/ScalingImpl.hpp +++ b/include/aidge/backend/cpu/operator/ScalingImpl.hpp @@ -54,9 +54,9 @@ class ScalingImpl_cpu : public OperatorImpl { void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; namespace { diff --git a/include/aidge/backend/cpu/operator/SoftmaxImpl.hpp b/include/aidge/backend/cpu/operator/SoftmaxImpl.hpp index 08567ab98e55233f1f578e82cb39ac5681f0a839..e2b30a59d9a15627e8d71e7c0b7f031dcf79964d 100644 --- a/include/aidge/backend/cpu/operator/SoftmaxImpl.hpp +++ b/include/aidge/backend/cpu/operator/SoftmaxImpl.hpp @@ -50,9 +50,9 @@ class SoftmaxImpl_cpu : public OperatorImpl { NbElts_t getNbConsumedData(const IOIndex_t inputIdx) const override final; NbElts_t getNbProducedData(const IOIndex_t outputIdx) const override final; void updateConsummerProducer() override final; - void forward(); + void forward() override; - void backward(); + void backward() override; }; namespace { diff --git a/setup.py b/setup.py index 16305afdfdfa5de2e328460d9e96c77eb96a9d98..b88329e54feab78e39bd79be0a129030098e216a 100644 --- a/setup.py +++ b/setup.py @@ -70,7 +70,8 @@ class CMakeBuild(build_ext): self.spawn(['cmake', str(cwd), param_py, '-DTEST=OFF', f'-DCMAKE_INSTALL_PREFIX:PATH={install_path}']) if not self.dry_run: - self.spawn(['make', 'all', 'install', '-j', max_jobs]) + self.spawn(['cmake', '--build', '.', '--config', 'Debug', '-j', max_jobs]) + self.spawn(['cmake', '--install', '.', '--config', 'Debug']) os.chdir(str(cwd)) aidge_package = build_lib / (get_project_name()) @@ -81,7 +82,7 @@ class CMakeBuild(build_ext): # Copy all shared object files from build_temp/lib to aidge_package for root, _, files in os.walk(build_temp.absolute()): for file in files: - if file.endswith('.so') and (root != str(aidge_package.absolute())): + if (file.endswith('.so') or file.endswith('.pyd')) and (root != str(aidge_package.absolute())): currentFile=os.path.join(root, file) shutil.copy(currentFile, str(aidge_package.absolute())) @@ -100,7 +101,6 @@ if __name__ == '__main__': long_description_content_type="text/markdown", long_description="\n".join(DOCLINES[2:]), classifiers=[c for c in CLASSIFIERS.split('\n') if c], - platforms=["Linux"], packages=find_packages(where="."), include_package_data=True, ext_modules=[CMakeExtension(get_project_name())], diff --git a/src/operator/PadImpl.cpp b/src/operator/PadImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a7d2fb4e3fd7d10a59bc019c992cfad263954c17 --- /dev/null +++ b/src/operator/PadImpl.cpp @@ -0,0 +1,92 @@ +/******************************************************************************** + * 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/Conv.hpp" + +#include "aidge/backend/cpu/operator/PadImpl.hpp" +#include "aidge/backend/cpu/operator/PadImpl_forward_kernels.hpp" + +Aidge::NbElts_t Aidge::PadImpl2D_cpu::getNbRequiredData(const Aidge::IOIndex_t inputIdx) const { + assert(inputIdx == 0 && "operator has only one input"); + (void) inputIdx; + + // Requires the whole tensors + const auto &inputDims = std::static_pointer_cast<Tensor>(mOp.getInput(0))->dims(); + + return std::accumulate(inputDims.begin(), inputDims.end(), Aidge::NbElts_t(1), std::multiplies<NbElts_t>()); +} + +Aidge::NbElts_t Aidge::PadImpl2D_cpu::getNbRequiredProtected(IOIndex_t inputIdx) const { + assert(inputIdx == 0 && "operator has only one input"); + (void) inputIdx; + + // Padding cannot be in-place! + // We must ensure that we do not override data that has not been consummed yet. + const auto &inputDims = std::static_pointer_cast<Tensor>(mOp.getInput(0))->dims(); + const size_t inputSize = std::accumulate(inputDims.begin(), inputDims.end(), Aidge::NbElts_t(1), std::multiplies<NbElts_t>()); + const auto &outputDims = std::static_pointer_cast<Tensor>(mOp.getOutput(0))->dims(); + const size_t outputSize = std::accumulate(outputDims.begin(), inputDims.end(), Aidge::NbElts_t(1), std::multiplies<NbElts_t>()); + + return (outputSize - inputSize); +} + +Aidge::NbElts_t Aidge::PadImpl2D_cpu::getRequiredMemory(const Aidge::IOIndex_t outputIdx, + const std::vector<Aidge::DimSize_t> &/*inputsSize*/) const { + // Requires the whole tensors, regardless of available data on inputs + assert(outputIdx == 0 && "operator has only one output"); + (void) outputIdx; + + const auto &outputDims = std::static_pointer_cast<Tensor>(mOp.getOutput(0))->dims(); + return std::accumulate(outputDims.begin(), outputDims.end(), NbElts_t(1), std::multiplies<NbElts_t>()); +} + +Aidge::NbElts_t Aidge::PadImpl2D_cpu::getNbConsumedData(Aidge::IOIndex_t inputIdx) const { + assert(static_cast<std::size_t>(inputIdx) < mNbConsumedData.size()); + return mNbConsumedData[static_cast<std::size_t>(inputIdx)]; +} + +Aidge::NbElts_t Aidge::PadImpl2D_cpu::getNbProducedData(Aidge::IOIndex_t outputIdx) const { + assert((outputIdx == 0) && (static_cast<std::size_t>(outputIdx) < mNbProducedData.size())); + return mNbProducedData[static_cast<std::size_t>(outputIdx)]; +} + +void Aidge::PadImpl2D_cpu::updateConsummerProducer(){ + // Update producer-consumer data + for (std::size_t inputIdx = 0; inputIdx < mNbConsumedData.size(); ++inputIdx) + mNbConsumedData[inputIdx] += getNbRequiredData(static_cast<IOIndex_t>(inputIdx)); // each input is consumed by the minimum + // amount for a forward pass + + mNbProducedData[0] += getRequiredMemory(0, {}); +} + +void Aidge::PadImpl2D_cpu::forward() { + // FIXME: uncomment the following code once memory handling will work + assert(mOp.getInput(0) && "missing input #0"); + + // Find the correct kernel type + auto kernelFunc = + Registrar<PadImpl2DForward_cpu>::create({mOp.getInput(0)->dataType(), mOp.getOutput(0)->dataType()}); + + // Call kernel + kernelFunc(mOp.getStaticAttributes(), std::static_pointer_cast<Tensor>(mOp.getInput(0))->dims<4>(), + mOp.getInput(0)->getImpl()->rawPtr(), mOp.getOutput(0)->getImpl()->rawPtr()); + + +} + +void Aidge::PadImpl2D_cpu::backward() { printf("Not implemented yet.\n"); } diff --git a/unit_tests/operator/Test_ConvImpl.cpp b/unit_tests/operator/Test_ConvImpl.cpp index 23ff1aaebcfb79a4d4b1abc4f1a77f1c6de63b21..891f0e94b02d07d41751728e83fa9b42e4b89be8 100644 --- a/unit_tests/operator/Test_ConvImpl.cpp +++ b/unit_tests/operator/Test_ConvImpl.cpp @@ -156,165 +156,8 @@ TEST_CASE("[cpu/operator] Conv(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}); + std::shared_ptr<Node> myConv = Conv(3,4,{1,1}, "myconv", {1,1}); myConv->getOperator()->setDatatype(DataType::Float32); myConv->getOperator()->setBackend("cpu"); myConv->getOperator()->input(0) = Array4D<float,2,3,3,3> { diff --git a/unit_tests/operator/Test_PadImpl.cpp b/unit_tests/operator/Test_PadImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f40b62faa8207d770b895258c786580f82ae7f21 --- /dev/null +++ b/unit_tests/operator/Test_PadImpl.cpp @@ -0,0 +1,569 @@ +/******************************************************************************** + * 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/operator/Pad.hpp" + +#include "aidge/backend/cpu.hpp" + +using namespace Aidge; + +TEST_CASE("[cpu/operator] Pad(forward)") { + SECTION("Symmetric Pad") { + const int pv = 0; // pad value + + std::shared_ptr<Node> myPad = Pad({{1, 1}, {1, 1}}, "mypad", PadBorderType::Constant, static_cast<double>(pv)); + myPad->getOperator()->setDatatype(DataType::Int32); + myPad->getOperator()->setBackend("cpu"); + 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,3,7,7> { //NCHW + { + { + {{ pv, pv, pv, pv, pv, pv, pv}, + { pv, 0, 1, 2, 3, 4, pv}, + { pv, 5, 6, 7, 8, 9, pv}, + { pv, 10, 11, 12, 13, 14, pv}, + { pv, 15, 16, 17, 18, 19, pv}, + { pv, 20, 21, 22, 23, 24, pv}, + { pv, pv, pv, pv, pv, pv, pv}}, + + {{ pv, pv, pv, pv, pv, pv, pv}, + { pv, 25, 26, 27, 28, 29, pv}, + { pv, 30, 31, 32, 33, 34, pv}, + { pv, 35, 36, 37, 38, 39, pv}, + { pv, 40, 41, 42, 43, 44, pv}, + { pv, 45, 46, 47, 48, 49, pv}, + { pv, pv, pv, pv, pv, pv, pv}}, + + {{ pv, pv, pv, pv, pv, pv, pv}, + { pv, 50, 51, 52, 53, 54, pv}, + { pv, 55, 56, 57, 58, 59, pv}, + { pv, 60, 61, 62, 63, 64, pv}, + { pv, 65, 66, 67, 68, 69, pv}, + { pv, 70, 71, 72, 73, 74, pv}, + { pv, pv, pv, pv, pv, pv, pv}} + }, + { + {{ pv, pv, pv, pv, pv, pv, pv}, + { pv, 75, 76, 77, 78, 79, pv}, + { pv, 80, 81, 82, 83, 84, pv}, + { pv, 85, 86, 87, 88, 89, pv}, + { pv, 90, 91, 92, 93, 94, pv}, + { pv, 95, 96, 97, 98, 99, pv}, + { pv, pv, pv, pv, pv, pv, pv}}, + + {{ pv, pv, pv, pv, pv, pv, pv}, + {pv, 100, 101, 102, 103, 104, pv}, + {pv, 105, 106, 107, 108, 109, pv}, + {pv, 110, 111, 112, 113, 114, pv}, + {pv, 115, 116, 117, 118, 119, pv}, + {pv, 120, 121, 122, 123, 124, pv}, + { pv, pv, pv, pv, pv, pv, pv}}, + + {{ pv, pv, pv, pv, pv, pv, pv}, + {pv, 125, 126, 127, 128, 129, pv}, + {pv, 130, 131, 132, 133, 134, pv}, + {pv, 135, 136, 137, 138, 139, pv}, + {pv, 140, 141, 142, 143, 144, pv}, + {pv, 145, 146, 147, 148, 149, pv}, + { pv, pv, pv, pv, pv, pv, pv}} + } + } + }); + + myPad->getOperator()->associateInput(0,myInput); + myPad->getOperator()->computeOutputDims(); + myPad->forward(); + // myPad->getOperator()->getOutput(0)->print(); + REQUIRE(*(myPad->getOperator()->getOutput(0)) == *myOutput); + } + + SECTION("Asymmetric Pad") { + const int pv = 0; // pad value + + std::shared_ptr<Node> myPad = Pad({{1, 0}, {0, 1}}, "mypad", PadBorderType::Constant, static_cast<double>(pv)); + myPad->getOperator()->setDatatype(DataType::Int32); + myPad->getOperator()->setBackend("cpu"); + 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,3,6,6> { //NCHW + { + { + {{ pv, pv, pv, pv, pv, pv}, + { 0, 1, 2, 3, 4, pv}, + { 5, 6, 7, 8, 9, pv}, + { 10, 11, 12, 13, 14, pv}, + { 15, 16, 17, 18, 19, pv}, + { 20, 21, 22, 23, 24, pv}}, + + {{ pv, pv, pv, pv, pv, pv}, + { 25, 26, 27, 28, 29, pv}, + { 30, 31, 32, 33, 34, pv}, + { 35, 36, 37, 38, 39, pv}, + { 40, 41, 42, 43, 44, pv}, + { 45, 46, 47, 48, 49, pv}}, + + {{ pv, pv, pv, pv, pv, pv}, + { 50, 51, 52, 53, 54, pv}, + { 55, 56, 57, 58, 59, pv}, + { 60, 61, 62, 63, 64, pv}, + { 65, 66, 67, 68, 69, pv}, + { 70, 71, 72, 73, 74, pv}} + }, + { + {{ pv, pv, pv, pv, pv, pv}, + { 75, 76, 77, 78, 79, pv}, + { 80, 81, 82, 83, 84, pv}, + { 85, 86, 87, 88, 89, pv}, + { 90, 91, 92, 93, 94, pv}, + { 95, 96, 97, 98, 99, pv}}, + + {{ pv, pv, pv, pv, pv, pv}, + { 100, 101, 102, 103, 104, pv}, + { 105, 106, 107, 108, 109, pv}, + { 110, 111, 112, 113, 114, pv}, + { 115, 116, 117, 118, 119, pv}, + { 120, 121, 122, 123, 124, pv}}, + + {{ pv, pv, pv, pv, pv, pv}, + { 125, 126, 127, 128, 129, pv}, + { 130, 131, 132, 133, 134, pv}, + { 135, 136, 137, 138, 139, pv}, + { 140, 141, 142, 143, 144, pv}, + { 145, 146, 147, 148, 149, pv}} + } + } + }); + + myPad->getOperator()->associateInput(0,myInput); + myPad->getOperator()->computeOutputDims(); + myPad->forward(); + // myPad->getOperator()->getOutput(0)->print(); + REQUIRE(*(myPad->getOperator()->getOutput(0)) == *myOutput); + } + + SECTION("Pad Replicate") { + std::shared_ptr<Node> myPad = Pad({{1, 1}, {1, 1}}, "mypad", PadBorderType::Replicate); + myPad->getOperator()->setDatatype(DataType::Int32); + myPad->getOperator()->setBackend("cpu"); + 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,3,7,7> { //NCHW + { + { + {{ 0, 0, 1, 2, 3, 4, 4}, + { 0, 0, 1, 2, 3, 4, 4}, + { 5, 5, 6, 7, 8, 9, 9}, + { 10, 10, 11, 12, 13, 14, 14}, + { 15, 15, 16, 17, 18, 19, 19}, + { 20, 20, 21, 22, 23, 24, 24}, + { 20, 20, 21, 22, 23, 24, 24}}, + + {{ 25, 25, 26, 27, 28, 29, 29}, + { 25, 25, 26, 27, 28, 29, 29}, + { 30, 30, 31, 32, 33, 34, 34}, + { 35, 35, 36, 37, 38, 39, 39}, + { 40, 40, 41, 42, 43, 44, 44}, + { 45, 45, 46, 47, 48, 49, 49}, + { 45, 45, 46, 47, 48, 49, 49}}, + + {{ 50, 50, 51, 52, 53, 54, 54}, + { 50, 50, 51, 52, 53, 54, 54}, + { 55, 55, 56, 57, 58, 59, 59}, + { 60, 60, 61, 62, 63, 64, 64}, + { 65, 65, 66, 67, 68, 69, 69}, + { 70, 70, 71, 72, 73, 74, 74}, + { 70, 70, 71, 72, 73, 74, 74}} + }, + { + {{ 75, 75, 76, 77, 78, 79, 79}, + { 75, 75, 76, 77, 78, 79, 79}, + { 80, 80, 81, 82, 83, 84, 84}, + { 85, 85, 86, 87, 88, 89, 89}, + { 90, 90, 91, 92, 93, 94, 94}, + { 95, 95, 96, 97, 98, 99, 99}, + { 95, 95, 96, 97, 98, 99, 99}}, + + {{100, 100, 101, 102, 103, 104, 104}, + {100, 100, 101, 102, 103, 104, 104}, + {105, 105, 106, 107, 108, 109, 109}, + {110, 110, 111, 112, 113, 114, 114}, + {115, 115, 116, 117, 118, 119, 119}, + {120, 120, 121, 122, 123, 124, 124}, + {120, 120, 121, 122, 123, 124, 124}}, + + {{125, 125, 126, 127, 128, 129, 129}, + {125, 125, 126, 127, 128, 129, 129}, + {130, 130, 131, 132, 133, 134, 134}, + {135, 135, 136, 137, 138, 139, 139}, + {140, 140, 141, 142, 143, 144, 144}, + {145, 145, 146, 147, 148, 149, 149}, + {145, 145, 146, 147, 148, 149, 149}} + } + } + }); + + myPad->getOperator()->associateInput(0,myInput); + myPad->getOperator()->computeOutputDims(); + myPad->forward(); + // myPad->getOperator()->getOutput(0)->print(); + REQUIRE(*(myPad->getOperator()->getOutput(0)) == *myOutput); + } + + SECTION("Pad Reflect") { + std::shared_ptr<Node> myPad = Pad({{1, 1}, {1, 1}}, "mypad", PadBorderType::Reflect); + myPad->getOperator()->setDatatype(DataType::Int32); + myPad->getOperator()->setBackend("cpu"); + 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,3,7,7> { //NCHW + { + { + { + { 6, 5, 6, 7, 8, 9, 5}, + { 1, 0, 1, 2, 3, 4, 0}, + { 6, 5, 6, 7, 8, 9, 5}, + { 11, 10, 11, 12, 13, 14, 10}, + { 16, 15, 16, 17, 18, 19, 15}, + { 21, 20, 21, 22, 23, 24, 20}, + { 1, 0, 1, 2, 3, 4, 0} + }, + { + { 31, 30, 31, 32, 33, 34, 30}, + { 26, 25, 26, 27, 28, 29, 25}, + { 31, 30, 31, 32, 33, 34, 30}, + { 36, 35, 36, 37, 38, 39, 35}, + { 41, 40, 41, 42, 43, 44, 40}, + { 46, 45, 46, 47, 48, 49, 45}, + { 26, 25, 26, 27, 28, 29, 25} + }, + { + { 56, 55, 56, 57, 58, 59, 55}, + { 51, 50, 51, 52, 53, 54, 50}, + { 56, 55, 56, 57, 58, 59, 55}, + { 61, 60, 61, 62, 63, 64, 60}, + { 66, 65, 66, 67, 68, 69, 65}, + { 71, 70, 71, 72, 73, 74, 70}, + { 51, 50, 51, 52, 53, 54, 50} + } + }, + { + { + { 81, 80, 81, 82, 83, 84, 80}, + { 76, 75, 76, 77, 78, 79, 75}, + { 81, 80, 81, 82, 83, 84, 80}, + { 86, 85, 86, 87, 88, 89, 85}, + { 91, 90, 91, 92, 93, 94, 90}, + { 96, 95, 96, 97, 98, 99, 95}, + { 76, 75, 76, 77, 78, 79, 75} + }, + { + { 106, 105, 106, 107, 108, 109, 105}, + { 101, 100, 101, 102, 103, 104, 100}, + { 106, 105, 106, 107, 108, 109, 105}, + { 111, 110, 111, 112, 113, 114, 110}, + { 116, 115, 116, 117, 118, 119, 115}, + { 121, 120, 121, 122, 123, 124, 120}, + { 101, 100, 101, 102, 103, 104, 100} + }, + { + { 131, 130, 131, 132, 133, 134, 130}, + { 126, 125, 126, 127, 128, 129, 125}, + { 131, 130, 131, 132, 133, 134, 130}, + { 136, 135, 136, 137, 138, 139, 135}, + { 141, 140, 141, 142, 143, 144, 140}, + { 146, 145, 146, 147, 148, 149, 145}, + { 126, 125, 126, 127, 128, 129, 125} + } + } + } + }); + + myPad->getOperator()->associateInput(0,myInput); + myPad->getOperator()->computeOutputDims(); + myPad->forward(); + myPad->getOperator()->getOutput(0)->print(); + REQUIRE(*(myPad->getOperator()->getOutput(0)) == *myOutput); + } + + SECTION("Pad Wrap") { + std::shared_ptr<Node> myPad = Pad({{1, 1}, {1, 1}}, "mypad", PadBorderType::Wrap); + myPad->getOperator()->setDatatype(DataType::Int32); + myPad->getOperator()->setBackend("cpu"); + 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,3,7,7> { //NCHW + { + { + {{ 24, 20, 21, 22, 23, 24, 20}, + { 4, 0, 1, 2, 3, 4, 0}, + { 9, 5, 6, 7, 8, 9, 5}, + { 14, 10, 11, 12, 13, 14, 10}, + { 19, 15, 16, 17, 18, 19, 15}, + { 24, 20, 21, 22, 23, 24, 20}, + { 4, 0, 1, 2, 3, 4, 0}}, + + {{ 49, 45, 46, 47, 48, 49, 45}, + { 29, 25, 26, 27, 28, 29, 25}, + { 34, 30, 31, 32, 33, 34, 30}, + { 39, 35, 36, 37, 38, 39, 35}, + { 44, 40, 41, 42, 43, 44, 40}, + { 49, 45, 46, 47, 48, 49, 45}, + { 29, 25, 26, 27, 28, 29, 25}}, + + {{ 74, 70, 71, 72, 73, 74, 70}, + { 54, 50, 51, 52, 53, 54, 50}, + { 59, 55, 56, 57, 58, 59, 55}, + { 64, 60, 61, 62, 63, 64, 60}, + { 69, 65, 66, 67, 68, 69, 65}, + { 74, 70, 71, 72, 73, 74, 70}, + { 54, 50, 51, 52, 53, 54, 50}} + }, + { + {{ 99, 95, 96, 97, 98, 99, 95}, + { 79, 75, 76, 77, 78, 79, 75}, + { 84, 80, 81, 82, 83, 84, 80}, + { 89, 85, 86, 87, 88, 89, 85}, + { 94, 90, 91, 92, 93, 94, 90}, + { 99, 95, 96, 97, 98, 99, 95}, + { 79, 75, 76, 77, 78, 79, 75}}, + + {{124, 120, 121, 122, 123, 124, 120}, + {104, 100, 101, 102, 103, 104, 100}, + {109, 105, 106, 107, 108, 109, 105}, + {114, 110, 111, 112, 113, 114, 110}, + {119, 115, 116, 117, 118, 119, 115}, + {124, 120, 121, 122, 123, 124, 120}, + {104, 100, 101, 102, 103, 104, 100}}, + + {{149, 145, 146, 147, 148, 149, 145}, + {129, 125, 126, 127, 128, 129, 125}, + {134, 130, 131, 132, 133, 134, 130}, + {139, 135, 136, 137, 138, 139, 135}, + {144, 140, 141, 142, 143, 144, 140}, + {149, 145, 146, 147, 148, 149, 145}, + {129, 125, 126, 127, 128, 129, 125}} + } + } + }); + + myPad->getOperator()->associateInput(0,myInput); + myPad->getOperator()->computeOutputDims(); + myPad->forward(); + // myPad->getOperator()->getOutput(0)->print(); + REQUIRE(*(myPad->getOperator()->getOutput(0)) == *myOutput); + } +} \ No newline at end of file diff --git a/unit_tests/operator/Test_PaddedConv.cpp b/unit_tests/operator/Test_PaddedConv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e41be85ab00faae1af7239c43b74a34f558a663c --- /dev/null +++ b/unit_tests/operator/Test_PaddedConv.cpp @@ -0,0 +1,319 @@ +/******************************************************************************** + * 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/operator/MetaOperator.hpp" +#include "aidge/operator/MetaOperatorDefs.hpp" + +#include "aidge/backend/cpu.hpp" + +using namespace Aidge; + +TEST_CASE("[cpu/operator] PaddedConv(forward)") { + SECTION("Classic Conv") { + std::shared_ptr<Node> myConv = PaddedConv(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(); + + REQUIRE(*(myConv->getOperator()->getOutput(0)) == *myOutput); + } + SECTION("test Padding") { + std::shared_ptr<Node> myConv = PaddedConv(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); + } +}