From 2dbb53e36b1d46fe2fedc785a427cabcf6c63aff Mon Sep 17 00:00:00 2001 From: Wissam Boussella <wissam.boussella@cea.fr> Date: Wed, 12 Mar 2025 15:00:57 +0100 Subject: [PATCH 1/9] [New] Unit test for expected results at the end of the MR --- unit_tests/operator/Test_TransposeImpl.cpp | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/unit_tests/operator/Test_TransposeImpl.cpp b/unit_tests/operator/Test_TransposeImpl.cpp index 02b338dd2..be54b8c42 100644 --- a/unit_tests/operator/Test_TransposeImpl.cpp +++ b/unit_tests/operator/Test_TransposeImpl.cpp @@ -200,3 +200,33 @@ TEST_CASE("[cpu/operator] Transpose(forward)") { REQUIRE(*(op->getOutput(0)) == *output); } } + +TEST_CASE("[cpu/operator] Transpose DataFormat") { + SECTION("NCHW to NHWC"){ + std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450})); + input->setDataFormat(Aidge::DataFormat::NCHW); + + auto transposeNode = Transpose({0,2,3,1}); + + auto op = std::static_pointer_cast<OperatorTensor>(transposeNode -> getOperator()); + op->associateInput(0,input); + op->setBackend("cpu"); + transposeNode->forward(); + + REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NHWC); + } + SECTION("NHWC to NCHW"){ + std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450})); + input->setDataFormat(Aidge::DataFormat::NHWC); + + auto transposeNode = Transpose({0,3,1,2}); + + auto op = std::static_pointer_cast<OperatorTensor>(transposeNode -> getOperator()); + op->associateInput(0,input); + op->setBackend("cpu"); + transposeNode->forward(); + + REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NHWC); + } +} + -- GitLab From 05f7109d11190c048b48da55b45cc68579159315 Mon Sep 17 00:00:00 2001 From: Wissam Boussella <wissam.boussella@cea.fr> Date: Wed, 19 Mar 2025 10:19:34 +0100 Subject: [PATCH 2/9] Add transpose output data format computation and related tests --- include/aidge/data/DataFormat.hpp | 19 +++++ src/data/DataFormat.cpp | 46 +++++++++++ src/operator/Transpose.cpp | 7 ++ unit_tests/operator/Test_TransposeImpl.cpp | 90 +++++++++++++++++++++- 4 files changed, 159 insertions(+), 3 deletions(-) diff --git a/include/aidge/data/DataFormat.hpp b/include/aidge/data/DataFormat.hpp index 4df854a1e..9b929b14a 100644 --- a/include/aidge/data/DataFormat.hpp +++ b/include/aidge/data/DataFormat.hpp @@ -83,6 +83,25 @@ using DataFormatTranspose = std::array<std::size_t, 5>; */ DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataFormat& dst); +/** + * @brief Determine the output data format after applying a transpose operation. + * + * This function computes the new data format after transposing a tensor. + * It follows these steps: + * 1. Retrieves the permutation mapping from the default format (NCHW) to the input format. + * 2. Applies the given output dimensions order to compute the new permutation. + * 3. Determines the number of dimensions associated with the input data format. + * 4. Identifies the corresponding data format for the new permutation. + * + * @param inputDataFormat The data format of the input tensor. + * @param outputDimsOrder The permutation applied to the input tensor's dimensions. + * @return DataFormat The computed output data format after applying the permutation. + * + * @throws std::runtime_error if the provided permutation is invalid for the given format. + * @pre `outputDimsOrder` must be a valid permutation of the format's dimensions. + */ +DataFormat getTransposeOutputDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder); + } // namespace Aidge namespace { diff --git a/src/data/DataFormat.cpp b/src/data/DataFormat.cpp index 8b7460b3d..25621e1af 100644 --- a/src/data/DataFormat.cpp +++ b/src/data/DataFormat.cpp @@ -51,6 +51,25 @@ static std::size_t getNbDimensions(DataFormat dformat) { return nbDimensions[static_cast<std::size_t>(dformat)]; } +/** + * @brief Get the DataFormat corresponding to a given permutation vector. + * + * @param perm The permutation vector. + * @return DataFormat The matching DataFormat, or DataFormat::Default if not found. + */ +static DataFormat getDataFormatFromPermutation(const DataFormatTranspose& perm, const unsigned int nbDims) { + for (size_t i = 0; i < NB_DFORMAT; ++i) { + DataFormat candidateFormat = static_cast<DataFormat>(i); + const DataFormatTranspose& candidatePerm = getPermutationFromNCHW(candidateFormat); + + if (std::equal(candidatePerm.begin(), candidatePerm.begin() + nbDims, perm.begin())) { + return candidateFormat; + } + } + Log::warn("No matching DataFormat found for the given permutation : {}", perm); + return DataFormat::Default; +} + DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataFormat& dst) { AIDGE_ASSERT((src != DataFormat::Any && dst != DataFormat::Any), "Permutation is not defined for DataFormat::Any"); if (src == DataFormat::Default || dst == DataFormat::Default || src == dst) { @@ -78,4 +97,31 @@ DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataForma return src_to_dst; } + +/** + * @brief Applies one permutation to another. + * + * Given an initial permutation `perm1` and another permutation `perm2`, + * this function returns a new permutation that results from applying `perm2` to `perm1`. + * + * @param perm1 The base permutation (original ordering → intermediate ordering). + * @param perm2 The permutation to apply (intermediate ordering → final ordering). + * @return DataFormatTranspose The resultng permutation (original ordering → final ordering). + */ +static DataFormatTranspose applyPermutation(const DataFormatTranspose& perm1, const DataFormatTranspose& perm2) { + DataFormatTranspose permuted{}; + for (std::size_t i = 0; i < perm1.size(); ++i) { + permuted[i] = perm2[perm1[i]]; + } + return permuted; +} + +DataFormat getTransposeOutputDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder){ + const DataFormatTranspose permFromInput = getPermutationFromNCHW(inputDataFormat); + const DataFormatTranspose newPerm = applyPermutation(permFromInput, outputDimsOrder); + + const unsigned int nbDims = getNbDimensions(inputDataFormat); + + return getDataFormatFromPermutation(newPerm, nbDims); +} } // namespace Aidge \ No newline at end of file diff --git a/src/operator/Transpose.cpp b/src/operator/Transpose.cpp index f9d612353..51c2d5960 100644 --- a/src/operator/Transpose.cpp +++ b/src/operator/Transpose.cpp @@ -77,7 +77,14 @@ bool Aidge::Transpose_Op::forwardDims(bool /*allowDataDependency*/) { AIDGE_ASSERT(i == outputDimsOrder()[i], "Permutation vector ({}) must be the identity above the input tensor rank ({}).", outputDimsOrder(), getInput(0)->dims()); } + mOutputs[0]->resize(outputDims); + + // Set the data format of the output tensor + std::array<std::size_t, 5> outputDimsArray; + std::copy_n(outputDimsOrder().begin(), 5, outputDimsArray.begin()); + + mOutputs[0]->setDataFormat(getTransposeOutputDataFormat(getInput(0)->dataFormat(), outputDimsArray)); return true; } return false; diff --git a/unit_tests/operator/Test_TransposeImpl.cpp b/unit_tests/operator/Test_TransposeImpl.cpp index be54b8c42..0e3037773 100644 --- a/unit_tests/operator/Test_TransposeImpl.cpp +++ b/unit_tests/operator/Test_TransposeImpl.cpp @@ -205,7 +205,7 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") { SECTION("NCHW to NHWC"){ std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450})); input->setDataFormat(Aidge::DataFormat::NCHW); - + input->setBackend("cpu"); auto transposeNode = Transpose({0,2,3,1}); auto op = std::static_pointer_cast<OperatorTensor>(transposeNode -> getOperator()); @@ -218,15 +218,99 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") { SECTION("NHWC to NCHW"){ std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450})); input->setDataFormat(Aidge::DataFormat::NHWC); - + input->setBackend("cpu"); auto transposeNode = Transpose({0,3,1,2}); auto op = std::static_pointer_cast<OperatorTensor>(transposeNode -> getOperator()); op->associateInput(0,input); op->setBackend("cpu"); transposeNode->forward(); + REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW); + } + SECTION("CHWN to NCHW") { + std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({3,224,450,16})); + input->setDataFormat(Aidge::DataFormat::CHWN); + input->setBackend("cpu"); + auto transposeNode = Transpose({3,0,1,2}); - REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NHWC); + auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); + op->associateInput(0, input); + op->setBackend("cpu"); + transposeNode->forward(); + + REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW); + } + + SECTION("NCDHW to NDHWC") { + std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,8,224,450})); + input->setDataFormat(Aidge::DataFormat::NCDHW); + input->setBackend("cpu"); + auto transposeNode = Transpose({0,2,3,4,1}); + + auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); + op->associateInput(0, input); + op->setBackend("cpu"); + transposeNode->forward(); + + REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NDHWC); + } + + SECTION("NDHWC to NCDHW") { + std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,8,224,450,3})); + input->setDataFormat(Aidge::DataFormat::NDHWC); + input->setBackend("cpu"); + auto transposeNode = Transpose({0,4,1,2,3}); + + auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); + op->associateInput(0, input); + op->setBackend("cpu"); + transposeNode->forward(); + + REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCDHW); + } + + SECTION("CDHWN to NCDHW") { + std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({3,8,224,450,16})); + input->setDataFormat(Aidge::DataFormat::CDHWN); + input->setBackend("cpu"); + auto transposeNode = Transpose({4,0,1,2,3}); + + auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); + op->associateInput(0, input); + op->setBackend("cpu"); + transposeNode->forward(); + + REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCDHW); } + + SECTION("(Identity) NCHW to NCHW)") { + std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450})); + input->setDataFormat(Aidge::DataFormat::NCHW); + input->setBackend("cpu"); + auto transposeNode = Transpose({0,1,2,3}); // Identity permutation + + auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); + op->associateInput(0, input); + op->setBackend("cpu"); + transposeNode->forward(); + + REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW); + } + + SECTION("Invalid Format Handling") { + std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450})); + input->setDataFormat(Aidge::DataFormat::Default); + input->setBackend("cpu"); + auto transposeNode = Transpose({0,2,3,1}); + + auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); + op->associateInput(0, input); + op->setBackend("cpu"); + + transposeNode->forward(); + REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::Default); + //Should throw a Warning + } + } -- GitLab From 0cd6c63c097e8091591c0c1f0e888269f151e06d Mon Sep 17 00:00:00 2001 From: Wissam Boussella <wissam.boussella@cea.fr> Date: Wed, 19 Mar 2025 10:20:55 +0100 Subject: [PATCH 3/9] Change doxygen --- include/aidge/data/DataFormat.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/aidge/data/DataFormat.hpp b/include/aidge/data/DataFormat.hpp index 9b929b14a..238d48e82 100644 --- a/include/aidge/data/DataFormat.hpp +++ b/include/aidge/data/DataFormat.hpp @@ -97,7 +97,6 @@ DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataForma * @param outputDimsOrder The permutation applied to the input tensor's dimensions. * @return DataFormat The computed output data format after applying the permutation. * - * @throws std::runtime_error if the provided permutation is invalid for the given format. * @pre `outputDimsOrder` must be a valid permutation of the format's dimensions. */ DataFormat getTransposeOutputDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder); -- GitLab From b45e341b13cb1b8f982ec7ae5c0d5f007525adc0 Mon Sep 17 00:00:00 2001 From: Wissam Boussella <wissam.boussella@cea.fr> Date: Wed, 19 Mar 2025 10:47:28 +0100 Subject: [PATCH 4/9] add pybind --- python_binding/data/pybind_DataFormat.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/python_binding/data/pybind_DataFormat.cpp b/python_binding/data/pybind_DataFormat.cpp index 5308fb302..d41251153 100644 --- a/python_binding/data/pybind_DataFormat.cpp +++ b/python_binding/data/pybind_DataFormat.cpp @@ -67,6 +67,7 @@ void init_DataFormat(py::module& m) { bindEnum<DataFormat>(m, "dformat"); m.def("format_as", (const char* (*)(DataFormat)) &format_as, py::arg("df")); m.def("get_permutation_mapping", &getPermutationMapping, py::arg("src"), py::arg("dst")); + m.def("get_transpose_output_data_format", &getTransposeOutputDataFormat, py::arg("inputDataFormat"), py::arg("outputDimsOrder")); } } // namespace Aidge -- GitLab From f69f024087e7544d9e56ede4529b22c66419ba63 Mon Sep 17 00:00:00 2001 From: Wissam Boussella <wissam.boussella@cea.fr> Date: Wed, 19 Mar 2025 16:09:37 +0100 Subject: [PATCH 5/9] Rename getTransposeOutputDataFormat to getTransposedDataFormat and update related bindings and usages --- include/aidge/data/DataFormat.hpp | 7 +---- python_binding/data/pybind_DataFormat.cpp | 2 +- src/data/DataFormat.cpp | 2 +- src/operator/Transpose.cpp | 4 +-- unit_tests/operator/Test_TransposeImpl.cpp | 34 ++++++---------------- 5 files changed, 14 insertions(+), 35 deletions(-) diff --git a/include/aidge/data/DataFormat.hpp b/include/aidge/data/DataFormat.hpp index 238d48e82..64a996501 100644 --- a/include/aidge/data/DataFormat.hpp +++ b/include/aidge/data/DataFormat.hpp @@ -87,11 +87,6 @@ DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataForma * @brief Determine the output data format after applying a transpose operation. * * This function computes the new data format after transposing a tensor. - * It follows these steps: - * 1. Retrieves the permutation mapping from the default format (NCHW) to the input format. - * 2. Applies the given output dimensions order to compute the new permutation. - * 3. Determines the number of dimensions associated with the input data format. - * 4. Identifies the corresponding data format for the new permutation. * * @param inputDataFormat The data format of the input tensor. * @param outputDimsOrder The permutation applied to the input tensor's dimensions. @@ -99,7 +94,7 @@ DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataForma * * @pre `outputDimsOrder` must be a valid permutation of the format's dimensions. */ -DataFormat getTransposeOutputDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder); +DataFormat getTransposedDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder); } // namespace Aidge diff --git a/python_binding/data/pybind_DataFormat.cpp b/python_binding/data/pybind_DataFormat.cpp index d41251153..ae8b3636e 100644 --- a/python_binding/data/pybind_DataFormat.cpp +++ b/python_binding/data/pybind_DataFormat.cpp @@ -67,7 +67,7 @@ void init_DataFormat(py::module& m) { bindEnum<DataFormat>(m, "dformat"); m.def("format_as", (const char* (*)(DataFormat)) &format_as, py::arg("df")); m.def("get_permutation_mapping", &getPermutationMapping, py::arg("src"), py::arg("dst")); - m.def("get_transpose_output_data_format", &getTransposeOutputDataFormat, py::arg("inputDataFormat"), py::arg("outputDimsOrder")); + m.def("get_transpose_output_data_format", &getTransposeOutputDataFormat, py::arg("input_data_format"), py::arg("output_dims_order")); } } // namespace Aidge diff --git a/src/data/DataFormat.cpp b/src/data/DataFormat.cpp index 25621e1af..e8dd605bb 100644 --- a/src/data/DataFormat.cpp +++ b/src/data/DataFormat.cpp @@ -116,7 +116,7 @@ static DataFormatTranspose applyPermutation(const DataFormatTranspose& perm1, co return permuted; } -DataFormat getTransposeOutputDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder){ +DataFormat getTransposedDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder){ const DataFormatTranspose permFromInput = getPermutationFromNCHW(inputDataFormat); const DataFormatTranspose newPerm = applyPermutation(permFromInput, outputDimsOrder); diff --git a/src/operator/Transpose.cpp b/src/operator/Transpose.cpp index 51c2d5960..876d4e3fe 100644 --- a/src/operator/Transpose.cpp +++ b/src/operator/Transpose.cpp @@ -81,10 +81,10 @@ bool Aidge::Transpose_Op::forwardDims(bool /*allowDataDependency*/) { mOutputs[0]->resize(outputDims); // Set the data format of the output tensor - std::array<std::size_t, 5> outputDimsArray; + DataFormatTranspose outputDimsArray; std::copy_n(outputDimsOrder().begin(), 5, outputDimsArray.begin()); - mOutputs[0]->setDataFormat(getTransposeOutputDataFormat(getInput(0)->dataFormat(), outputDimsArray)); + mOutputs[0]->setDataFormat(getTransposedDataFormat(getInput(0)->dataFormat(), outputDimsArray)); return true; } return false; diff --git a/unit_tests/operator/Test_TransposeImpl.cpp b/unit_tests/operator/Test_TransposeImpl.cpp index 0e3037773..75adc9fd5 100644 --- a/unit_tests/operator/Test_TransposeImpl.cpp +++ b/unit_tests/operator/Test_TransposeImpl.cpp @@ -205,38 +205,32 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") { SECTION("NCHW to NHWC"){ std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450})); input->setDataFormat(Aidge::DataFormat::NCHW); - input->setBackend("cpu"); auto transposeNode = Transpose({0,2,3,1}); auto op = std::static_pointer_cast<OperatorTensor>(transposeNode -> getOperator()); op->associateInput(0,input); - op->setBackend("cpu"); - transposeNode->forward(); + op->forwardDims(); REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NHWC); } SECTION("NHWC to NCHW"){ std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450})); input->setDataFormat(Aidge::DataFormat::NHWC); - input->setBackend("cpu"); auto transposeNode = Transpose({0,3,1,2}); auto op = std::static_pointer_cast<OperatorTensor>(transposeNode -> getOperator()); op->associateInput(0,input); - op->setBackend("cpu"); - transposeNode->forward(); + op->forwardDims(); REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW); } SECTION("CHWN to NCHW") { std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({3,224,450,16})); input->setDataFormat(Aidge::DataFormat::CHWN); - input->setBackend("cpu"); auto transposeNode = Transpose({3,0,1,2}); auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); op->associateInput(0, input); - op->setBackend("cpu"); - transposeNode->forward(); + op->forwardDims(); REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW); } @@ -244,13 +238,11 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") { SECTION("NCDHW to NDHWC") { std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,8,224,450})); input->setDataFormat(Aidge::DataFormat::NCDHW); - input->setBackend("cpu"); auto transposeNode = Transpose({0,2,3,4,1}); auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); op->associateInput(0, input); - op->setBackend("cpu"); - transposeNode->forward(); + op->forwardDims(); REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NDHWC); } @@ -258,13 +250,11 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") { SECTION("NDHWC to NCDHW") { std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,8,224,450,3})); input->setDataFormat(Aidge::DataFormat::NDHWC); - input->setBackend("cpu"); auto transposeNode = Transpose({0,4,1,2,3}); auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); op->associateInput(0, input); - op->setBackend("cpu"); - transposeNode->forward(); + op->forwardDims(); REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCDHW); } @@ -272,13 +262,12 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") { SECTION("CDHWN to NCDHW") { std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({3,8,224,450,16})); input->setDataFormat(Aidge::DataFormat::CDHWN); - input->setBackend("cpu"); auto transposeNode = Transpose({4,0,1,2,3}); auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); op->associateInput(0, input); - op->setBackend("cpu"); - transposeNode->forward(); + op->forwardDims(); + REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCDHW); } @@ -286,13 +275,11 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") { SECTION("(Identity) NCHW to NCHW)") { std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450})); input->setDataFormat(Aidge::DataFormat::NCHW); - input->setBackend("cpu"); auto transposeNode = Transpose({0,1,2,3}); // Identity permutation auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); op->associateInput(0, input); - op->setBackend("cpu"); - transposeNode->forward(); + op->forwardDims(); REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW); } @@ -300,14 +287,11 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") { SECTION("Invalid Format Handling") { std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450})); input->setDataFormat(Aidge::DataFormat::Default); - input->setBackend("cpu"); auto transposeNode = Transpose({0,2,3,1}); - auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); op->associateInput(0, input); - op->setBackend("cpu"); - transposeNode->forward(); + op->forwardDims(); REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::Default); //Should throw a Warning } -- GitLab From 665b736bb01b95788a80d5cf3b40b44b4fcd3b2b Mon Sep 17 00:00:00 2001 From: Wissam Boussella <wissam.boussella@cea.fr> Date: Thu, 20 Mar 2025 11:32:37 +0100 Subject: [PATCH 6/9] docstring : Back to the future --- include/aidge/data/DataFormat.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/aidge/data/DataFormat.hpp b/include/aidge/data/DataFormat.hpp index 64a996501..d89eb24cd 100644 --- a/include/aidge/data/DataFormat.hpp +++ b/include/aidge/data/DataFormat.hpp @@ -88,6 +88,11 @@ DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataForma * * This function computes the new data format after transposing a tensor. * + * It follows these steps: + * 1. Retrieves the permutation mapping from the input format. + * 2. Applies the given output dimensions order to compute the new permutation. + * 3. Identifies the corresponding data format after applying the new permutation. + * * @param inputDataFormat The data format of the input tensor. * @param outputDimsOrder The permutation applied to the input tensor's dimensions. * @return DataFormat The computed output data format after applying the permutation. -- GitLab From 4849218e34905c35b8b03aa92e62a765c04d7a4f Mon Sep 17 00:00:00 2001 From: Wissam Boussella <wissam.boussella@cea.fr> Date: Thu, 20 Mar 2025 15:24:37 +0100 Subject: [PATCH 7/9] Update docstring for DataFormatTranspose and improve test case descriptions --- src/data/DataFormat.cpp | 2 +- unit_tests/operator/Test_TransposeImpl.cpp | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/data/DataFormat.cpp b/src/data/DataFormat.cpp index e8dd605bb..095ef9368 100644 --- a/src/data/DataFormat.cpp +++ b/src/data/DataFormat.cpp @@ -52,7 +52,7 @@ static std::size_t getNbDimensions(DataFormat dformat) { } /** - * @brief Get the DataFormat corresponding to a given permutation vector. + * @brief Get the DataFormat corresponding to a given ``DataFormatTranspose``. * * @param perm The permutation vector. * @return DataFormat The matching DataFormat, or DataFormat::Default if not found. diff --git a/unit_tests/operator/Test_TransposeImpl.cpp b/unit_tests/operator/Test_TransposeImpl.cpp index 75adc9fd5..f852c3fe0 100644 --- a/unit_tests/operator/Test_TransposeImpl.cpp +++ b/unit_tests/operator/Test_TransposeImpl.cpp @@ -284,7 +284,7 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") { REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW); } - SECTION("Invalid Format Handling") { + SECTION("Default to Default") { std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450})); input->setDataFormat(Aidge::DataFormat::Default); auto transposeNode = Transpose({0,2,3,1}); @@ -293,7 +293,19 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") { op->forwardDims(); REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::Default); - //Should throw a Warning + //Should print a Log::Warning + } + + SECTION("Invalid Format Handling") { + std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450})); + input->setDataFormat(Aidge::DataFormat::NCHW); + auto transposeNode = Transpose({0,2,1,3}); + auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator()); + op->associateInput(0, input); + + op->forwardDims(); + REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::Default); + //Should print a Log::Warning } } -- GitLab From 353048840e68a3c61b08e823901c2770b6bec2d9 Mon Sep 17 00:00:00 2001 From: Wissam Boussella <wissam.boussella@cea.fr> Date: Thu, 20 Mar 2025 15:29:00 +0100 Subject: [PATCH 8/9] remove magic number --- src/operator/Transpose.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operator/Transpose.cpp b/src/operator/Transpose.cpp index 876d4e3fe..f9e469476 100644 --- a/src/operator/Transpose.cpp +++ b/src/operator/Transpose.cpp @@ -82,7 +82,7 @@ bool Aidge::Transpose_Op::forwardDims(bool /*allowDataDependency*/) { // Set the data format of the output tensor DataFormatTranspose outputDimsArray; - std::copy_n(outputDimsOrder().begin(), 5, outputDimsArray.begin()); + std::copy_n(outputDimsOrder().begin(), outputDimsOrder().size(), outputDimsArray.begin()); mOutputs[0]->setDataFormat(getTransposedDataFormat(getInput(0)->dataFormat(), outputDimsArray)); return true; -- GitLab From 1c2e90e334d83444d1c1a94e46d3b0516649a7dc Mon Sep 17 00:00:00 2001 From: Cyril Moineau <cyril.moineau@cea.fr> Date: Thu, 20 Mar 2025 15:43:53 +0000 Subject: [PATCH 9/9] Apply 1 suggestion(s) to 1 file(s) --- python_binding/data/pybind_DataFormat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python_binding/data/pybind_DataFormat.cpp b/python_binding/data/pybind_DataFormat.cpp index ae8b3636e..354911c33 100644 --- a/python_binding/data/pybind_DataFormat.cpp +++ b/python_binding/data/pybind_DataFormat.cpp @@ -67,7 +67,7 @@ void init_DataFormat(py::module& m) { bindEnum<DataFormat>(m, "dformat"); m.def("format_as", (const char* (*)(DataFormat)) &format_as, py::arg("df")); m.def("get_permutation_mapping", &getPermutationMapping, py::arg("src"), py::arg("dst")); - m.def("get_transpose_output_data_format", &getTransposeOutputDataFormat, py::arg("input_data_format"), py::arg("output_dims_order")); + m.def("get_transposed_data_format", &getTransposedDataFormat, py::arg("input_data_format"), py::arg("output_dims_order")); } } // namespace Aidge -- GitLab