Skip to content
Snippets Groups Projects
Commit 0f05e5fb authored by Houssem ROUIS's avatar Houssem ROUIS Committed by Maxence Naud
Browse files

fix And operator

parent 45bedc95
No related branches found
No related tags found
1 merge request!166Update 0.5.0 -> 0.6.0
......@@ -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
......
......@@ -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
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment