diff --git a/include/aidge/backend/cpu/operator/AndImpl_kernels.hpp b/include/aidge/backend/cpu/operator/AndImpl_kernels.hpp index 73b710e021ac5031923eb1e9a2492502c02a3633..d7c8ebcf19f64cb60aa2b62f312f4b46351e6ec2 100644 --- a/include/aidge/backend/cpu/operator/AndImpl_kernels.hpp +++ b/include/aidge/backend/cpu/operator/AndImpl_kernels.hpp @@ -20,7 +20,7 @@ namespace Aidge { namespace { // suppose values are contiguous in memory template <class I, class O> -void equal_contiguous_arrays(const std::size_t input1size, +void and_contiguous_arrays(const std::size_t input1size, const std::size_t input2size, const std::size_t output1size, const I* input1, @@ -31,14 +31,14 @@ void equal_contiguous_arrays(const std::size_t input1size, { const std::size_t in1_id = (input1size != 1) ? i : 0; const std::size_t in2_id = (input2size != 1) ? i : 0; - output[i] = static_cast<O>(input1[in1_id] == input2[in2_id]); + output[i] = static_cast<O>(input1[in1_id] && input2[in2_id]); } } } template <class I, class O> -void EqualImpl_cpu_forward_kernel(std::vector<std::size_t> dims0, +void AndImpl_cpu_forward_kernel(std::vector<std::size_t> dims0, std::vector<std::size_t> dims1, const std::vector<std::size_t>& outputDims, const void* input0_, @@ -60,9 +60,8 @@ void EqualImpl_cpu_forward_kernel(std::vector<std::size_t> dims0, // special case for equal dimensions, the kernel is called with the entire arrays at once if (dims0 == dims1) { const std::size_t input0_contiguous_size = std::accumulate(dims0.cbegin(), dims0.cend(), std::size_t(1), std::multiplies<std::size_t>()); - for (std::size_t i = 0; i < input0_contiguous_size; ++i) - { - output[i] = static_cast<O>(input_0[i] == input_1[i]); + for (std::size_t i = 0; i < input0_contiguous_size; ++i) { + output[i] = static_cast<O>(input_0[i] && input_1[i]); } return; } @@ -126,7 +125,7 @@ void EqualImpl_cpu_forward_kernel(std::vector<std::size_t> dims0, std::size_t dim = contiguousIdx - 1; const std::size_t nbStacks = std::accumulate(outputDims.cbegin(), outputDims.cbegin() + contiguousIdx, std::size_t(1), std::multiplies<std::size_t>()); for (std::size_t stack = 0; stack < nbStacks;) { - equal_contiguous_arrays<I,O>(input0_contiguous_size, input1_contiguous_size, output_contiguous_size, + and_contiguous_arrays<I,O>(input0_contiguous_size, input1_contiguous_size, output_contiguous_size, input_0 + offsetIn0*input0_contiguous_size, input_1 + offsetIn1*input1_contiguous_size, output + offsetOut*output_contiguous_size); @@ -146,17 +145,17 @@ void EqualImpl_cpu_forward_kernel(std::vector<std::size_t> dims0, // Kernels registration to implementation entry point REGISTRAR(AndImpl_cpu, - {DataType::Float32}, - {ProdConso::inPlaceModel, Aidge::EqualImpl_cpu_forward_kernel<float, float>, nullptr}); + {ImplSpec::IOSpec{DataType::Any}, ImplSpec::IOSpec{DataType::Float32}}, + {ProdConso::inPlaceModel, Aidge::AndImpl_cpu_forward_kernel<float, float>, nullptr}); REGISTRAR(AndImpl_cpu, - {DataType::Float64}, - {ProdConso::inPlaceModel, Aidge::EqualImpl_cpu_forward_kernel<double, double>, nullptr}); + {ImplSpec::IOSpec{DataType::Any}, ImplSpec::IOSpec{DataType::Float64}}, + {ProdConso::inPlaceModel, Aidge::AndImpl_cpu_forward_kernel<double, double>, nullptr}); REGISTRAR(AndImpl_cpu, - {DataType::Int32}, - {ProdConso::inPlaceModel, Aidge::EqualImpl_cpu_forward_kernel<std::int32_t, std::int32_t>, nullptr}); + {ImplSpec::IOSpec{DataType::Any}, ImplSpec::IOSpec{DataType::Int32}}, + {ProdConso::inPlaceModel, Aidge::AndImpl_cpu_forward_kernel<std::int32_t, std::int32_t>, nullptr}); REGISTRAR(AndImpl_cpu, - {DataType::Int64}, - {ProdConso::inPlaceModel, Aidge::EqualImpl_cpu_forward_kernel<std::int64_t, std::int64_t>, nullptr}); + {ImplSpec::IOSpec{DataType::Any}, ImplSpec::IOSpec{DataType::Int64}}, + {ProdConso::inPlaceModel, Aidge::AndImpl_cpu_forward_kernel<std::int64_t, std::int64_t>, nullptr}); } // namespace Aidge diff --git a/unit_tests/operator/Test_AndImpl.cpp b/unit_tests/operator/Test_AndImpl.cpp index c2309dce5f32862ad9aeceaf98430b75ab7be6ef..978a89e5a6fa2cfa7079fc4d6ccd709994eb537c 100644 --- a/unit_tests/operator/Test_AndImpl.cpp +++ b/unit_tests/operator/Test_AndImpl.cpp @@ -26,75 +26,92 @@ using namespace Aidge; TEST_CASE("[cpu/operator] And(forward)", "[And][CPU]") { - SECTION("ForwardDims") - { + SECTION("ForwardDims") { constexpr std::uint16_t NBTRIALS = 10; // Create a random number generator std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution<float> valueDist(0.1f, 1.1f); // Random float distribution between 0 and 1 - std::uniform_int_distribution<std::size_t> dimSizeDist(std::size_t(2), std::size_t(10)); - std::uniform_int_distribution<std::size_t> nbDimsDist(std::size_t(1), std::size_t(5)); - std::uniform_int_distribution<int> boolDist(0,1); + std::uniform_int_distribution<int> boolDist(0, 1); // Use 0 for false, 1 for true + std::uniform_int_distribution<std::size_t> dimSizeDist(2, 10); + std::uniform_int_distribution<std::size_t> nbDimsDist(1, 5); SECTION("Same dimensions") { for (std::uint16_t trial = 0; trial < NBTRIALS; ++trial) { DimSize_t nbDims = nbDimsDist(gen); std::vector<DimSize_t> dims(nbDims); - for (std::size_t i = 0; i < nbDims; i++) { + for (std::size_t i = 0; i < nbDims; ++i) { dims[i] = dimSizeDist(gen); } - + const std::size_t nb_elements = std::accumulate(dims.cbegin(), dims.cend(), std::size_t(1), std::multiplies<std::size_t>()); + float* array0 = new float[nb_elements]; + float* array1 = new float[nb_elements]; + for (std::size_t i = 0; i < nb_elements; ++i) { + array0[i] = boolDist(gen); + array1[i] = boolDist(gen); + } std::shared_ptr<Tensor> myInput1 = std::make_shared<Tensor>(dims); - myInput1->setBackend("cpu"); - myInput1->setDataType(DataType::Float32); - myInput1->zeros(); std::shared_ptr<Tensor> myInput2 = std::make_shared<Tensor>(dims); - myInput2->setBackend("cpu"); + myInput1->setDataType(DataType::Float32); myInput2->setDataType(DataType::Float32); - myInput2->zeros(); + myInput1->setBackend("cpu"); + myInput2->setBackend("cpu"); + + myInput1 -> getImpl() -> setRawPtr(array0, nb_elements); + myInput2 -> getImpl() -> setRawPtr(array1, nb_elements); + std::shared_ptr<Node> myAnd = And(); - auto op = std::static_pointer_cast<OperatorTensor>(myAnd -> getOperator()); - op->associateInput(0,myInput1); - op->associateInput(1,myInput2); + auto op = std::static_pointer_cast<OperatorTensor>(myAnd->getOperator()); + op->associateInput(0, myInput1); + op->associateInput(1, myInput2); op->setDataType(DataType::Float32); op->setBackend("cpu"); op->forwardDims(); const auto outputDims = op->getOutput(0)->dims(); REQUIRE(outputDims == dims); + delete[] array0; + delete[] array1; } } + SECTION("Broadcasting") { for (std::uint16_t trial = 0; trial < NBTRIALS; ++trial) { DimSize_t nbDims = nbDimsDist(gen); std::vector<DimSize_t> dims1(nbDims, 1); std::vector<DimSize_t> dims2(nbDims, 1); std::vector<DimSize_t> expectedOutDims; - for (std::size_t i = 0; i < nbDims; i++) { + for (std::size_t i = 0; i < nbDims; ++i) { DimSize_t dim = dimSizeDist(gen); - if (boolDist(gen)) { - dims1[i] = dim; - } - if (boolDist(gen)) { - dims2[i] = dim; - } - expectedOutDims.push_back(std::max(dims1[i],dims2[i])); + if (boolDist(gen)) dims1[i] = dim; + if (boolDist(gen)) dims2[i] = dim; + expectedOutDims.push_back(std::max(dims1[i], dims2[i])); } + const std::size_t nb_elements0 = std::accumulate(dims1.cbegin(), dims1.cend(), std::size_t(1), std::multiplies<std::size_t>()); + const std::size_t nb_elements1 = std::accumulate(dims2.cbegin(), dims2.cend(), std::size_t(1), std::multiplies<std::size_t>()); + float* array0 = new float[nb_elements0]; + float* array1 = new float[nb_elements1]; + for (std::size_t i = 0; i < nb_elements0; ++i) { + array0[i] = boolDist(gen); + } + for (std::size_t i = 0; i < nb_elements1; ++i) { + array1[i] = boolDist(gen); + } std::shared_ptr<Tensor> myInput1 = std::make_shared<Tensor>(dims1); - myInput1->setBackend("cpu"); - myInput1->setDataType(DataType::Float32); - myInput1->zeros(); std::shared_ptr<Tensor> myInput2 = std::make_shared<Tensor>(dims2); - myInput2->setBackend("cpu"); + myInput1->setDataType(DataType::Float32); myInput2->setDataType(DataType::Float32); - myInput2->zeros(); + myInput1->setBackend("cpu"); + myInput2->setBackend("cpu"); + myInput1 -> getImpl() -> setRawPtr(array0, nb_elements0); + myInput2 -> getImpl() -> setRawPtr(array1, nb_elements1); + + std::shared_ptr<Node> myAnd = And(); - auto op = std::static_pointer_cast<OperatorTensor>(myAnd -> getOperator()); - op->associateInput(0,myInput1); - op->associateInput(1,myInput2); + auto op = std::static_pointer_cast<OperatorTensor>(myAnd->getOperator()); + op->associateInput(0, myInput1); + op->associateInput(1, myInput2); op->setDataType(DataType::Float32); op->setBackend("cpu"); @@ -102,80 +119,48 @@ TEST_CASE("[cpu/operator] And(forward)", "[And][CPU]") { const auto outputDims = op->getOutput(0)->dims(); REQUIRE(outputDims == expectedOutDims); + delete[] array0; + delete[] array1; } } } + SECTION("Same size inputs") { - std::shared_ptr<Tensor> input1 = std::make_shared<Tensor>(Array4D<int,3,3,3,2> { - { // - { // - {{20, 15},{31, 11},{22, 49}}, // - {{41, 10},{24, 51},{27, 52}}, // - {{26, 53},{27, 54},{28, 55}} // - }, // - { // - {{29, 56},{30, 57},{31, 58}}, // - {{32, 59},{33, 60},{34, 61}}, // - {{35, 62},{36, 63},{37, 64}} // - }, // - { // - {{38, 65},{39, 66},{40, 67}}, // - {{41, 68},{42, 69},{43, 70}}, // - {{44, 71},{45, 72},{46, 73}} // - } // - } // - }); // - std::shared_ptr<Tensor> input2 = std::make_shared<Tensor>(Array4D<int,3,3,3,2> { - { // - { // - {{20, 47},{21, 48},{22, 49}}, // - {{23, 50},{24, 51},{25, 52}}, // - {{17, 53},{27, 26},{14, 33}} // - }, // - { // - {{29, 56},{30, 57},{31, 58}}, // - {{72, 44},{33, 20},{27, 55}}, // - {{35, 24},{25, 63},{28, 64}} // - }, // - { // - {{32, 65},{39, 66},{40, 70}}, // - {{41, 53},{42, 60},{34, 70}}, // - {{44, 71},{30, 12},{46, 73}} // - } // - } // - }); // - std::shared_ptr<Tensor> expectedOutput = std::make_shared<Tensor>(Array4D<int,3,3,3,2> { + std::shared_ptr<Tensor> input1 = std::make_shared<Tensor>(Array4D<float, 2, 2, 2, 2>{ { - { - {{1, 0},{0, 0},{1, 1}}, - {{0, 0},{1, 1},{0, 1}}, - {{0, 1},{1, 0},{0, 0}} - }, - { - {{1, 1},{1, 1},{1, 1}}, - {{0, 0},{1, 0},{0, 0}}, - {{1, 0},{0, 1},{0, 1}} - }, - { - {{0, 1},{1, 1},{1, 0}}, - {{1, 0},{1, 0},{0, 1}}, - {{1, 1},{0, 0},{1, 1}} - } - } - }); + {{{1, 0}, {0, 1}}, + {{1, 1}, {0, 0}}}, + {{{0, 1}, {1, 0}}, + {{1, 0}, {0, 1}}}} + }); + std::shared_ptr<Tensor> input2 = std::make_shared<Tensor>(Array4D<float, 2, 2, 2, 2>{ + { + {{{1, 1}, {0, 0}}, + {{0, 1}, {1, 1}}}, + {{{1, 1}, {0, 0}}, + {{0, 1}, {1, 0}}}} + }); + std::shared_ptr<Tensor> expectedOutput = std::make_shared<Tensor>(Array4D<float, 2, 2, 2, 2>{ + { + {{{1, 0}, {0, 0}}, + {{0, 1}, {0, 0}}}, + {{{0, 1}, {0, 0}}, + {{0, 0}, {0, 0}}}} + }); std::shared_ptr<Node> myAnd = And(); - auto op = std::static_pointer_cast<OperatorTensor>(myAnd -> getOperator()); + auto op = std::static_pointer_cast<OperatorTensor>(myAnd->getOperator()); op->associateInput(0, input1); op->associateInput(1, input2); op->setBackend("cpu"); - op->setDataType(DataType::Int32); + op->setDataType(DataType::Float32); myAnd->forward(); - + op->getOutput(0)->print(); REQUIRE(*(op->getOutput(0)) == *expectedOutput); } SECTION("Broadcasting") { +<<<<<<< HEAD std::shared_ptr<Tensor> input_1 = std::make_shared<Tensor>(Array4D<int,1,3,3,2> { { // { // @@ -196,16 +181,28 @@ TEST_CASE("[cpu/operator] And(forward)", "[And][CPU]") { } // } // }); // +======= + std::shared_ptr<Tensor> input_1 = std::make_shared<Tensor>(Array4D<float, 1, 2, 2, 2>{ + { + {{{1, 0}, {1, 0}}, + {{1, 1}, {0, 0}}}} + }); + std::shared_ptr<Tensor> input_2 = std::make_shared<Tensor>(Array1D<float, 2>{{1, 0}}); + std::shared_ptr<Tensor> expectedOutput = std::make_shared<Tensor>(Array4D<float, 1, 2, 2, 2>{ + { + {{{1, 0}, {1, 0}}, + {{1, 0}, {0, 0}}}} + }); +>>>>>>> fix and kernel and unit tests std::shared_ptr<Node> myAnd = And(); - auto op = std::static_pointer_cast<OperatorTensor>(myAnd -> getOperator()); + auto op = std::static_pointer_cast<OperatorTensor>(myAnd->getOperator()); op->associateInput(0, input_1); op->associateInput(1, input_2); - op->setDataType(DataType::Int32); + op->setDataType(DataType::Float32); op->setBackend("cpu"); myAnd->forward(); - op->getOutput(0)->print(); - expectedOutput->print(); - REQUIRE(*op->getOutput(0) == *expectedOutput); + + REQUIRE(*(op->getOutput(0)) == *expectedOutput); } -} \ No newline at end of file +}