Skip to content
Snippets Groups Projects
Commit 04c4a3fa authored by Maxence Naud's avatar Maxence Naud
Browse files

Merge branch 'tmp_branch' into 'main'

Solve memory leaks and add CI

See merge request !1
parents f6f1c60c 02668cdc
No related branches found
No related tags found
No related merge requests found
Showing
with 1037 additions and 78 deletions
###############################################################################
# Aidge Continious Integration and Continious Deployment #
# #
###############################################################################
stages:
# Analyse code
- static_analysis
# Build Aidge
- build
# Unit test stage
- test
include:
- local: '/.gitlab/ci/_global.gitlab-ci.yml'
- local: '/.gitlab/ci/static_analysis.gitlab-ci.yml'
- local: '/.gitlab/ci/build.gitlab-ci.yml'
- local: '/.gitlab/ci/test.gitlab-ci.yml'
################################################################################
# Centralized definitions of common job parameter values. #
# Parameters with many optional configurations may be in separate files. #
# #
################################################################################
variables:
GIT_SUBMODULE_STRATEGY: recursive
OMP_NUM_THREADS: 4
GIT_SSL_NO_VERIFY: 1
DEBIAN_FRONTEND: noninteractive
image: n2d2-ci/ubuntu20.04/cpu:latest
\ No newline at end of file
build:ubuntu_cpp:
stage: build
tags:
- docker
image: n2d2-ci/ubuntu20.04/cpu:latest
script:
- mkdir -p build_cpp
- mkdir -p install_cpp
- cd build_cpp
- cmake -DCMAKE_INSTALL_PREFIX:PATH=../install_cpp -DCMAKE_BUILD_TYPE=Debug -DWERROR=ON ..
- make -j4 all install
artifacts:
paths:
- build_cpp/
- install_cpp/
build:ubuntu_python:
stage: build
tags:
- docker
image: n2d2-ci/ubuntu20.04/cpu:latest
script:
- python3 -m pip install virtualenv
- virtualenv venv
- source venv/bin/activate
- export AIDGE_INSTALL=`pwd`/install
- python3 -m pip install .
artifacts:
paths:
- venv/
\ No newline at end of file
static_analysis:cpp:
stage: static_analysis
tags:
- static_analysis
allow_failure: true
script:
- mkdir -p $CI_COMMIT_REF_NAME
- cppcheck -j 4 --enable=all --inconclusive --force --xml --xml-version=2 . 2> cppcheck-result.xml
- python -m pip install Pygments
- cppcheck-htmlreport --file=cppcheck-result.xml --report-dir=$CI_COMMIT_REF_NAME --source-dir=.
- python3 -m pip install -U cppcheck_codequality
- cppcheck-codequality --input-file=cppcheck-result.xml --output-file=cppcheck.json
- mkdir -p public/cpp
- mv $CI_COMMIT_REF_NAME public/cpp/
artifacts:
paths:
- public
reports:
codequality: cppcheck.json
static_analysis:python:
stage: static_analysis
tags:
- static_analysis
allow_failure: true
script:
- pip install pylint
- pip install pylint-gitlab
- pylint --rcfile=.pylintrc --exit-zero --output-format=pylint_gitlab.GitlabCodeClimateReporter aidge_core/ > codeclimate.json
- pylint --rcfile=.pylintrc --exit-zero --output-format=pylint_gitlab.GitlabPagesHtmlReporter aidge_core/ > pylint.html
- mkdir -p public/python/$CI_COMMIT_REF_NAME
- mv pylint.html public/python/$CI_COMMIT_REF_NAME/
artifacts:
paths:
- public
reports:
codequality: codeclimate.json
\ No newline at end of file
test:ubuntu_cpp:
stage: test
needs: ["build:ubuntu_cpp"]
tags:
- docker
image: n2d2-ci/ubuntu20.04/cpu:latest
script:
- cd build_cpp
- ctest --output-on-failure
test:ubuntu_python:
stage: test
needs: ["build:ubuntu_python"]
tags:
- docker
image: n2d2-ci/ubuntu20.04/cpu:latest
script:
- source venv/bin/activate
- cd aidge_core
- python3 -m pip list
# Run on discovery all tests located in core/unit_tests/python and discard the stdout
# only to show the errors/warnings and the results of the tests
- python3 -m unittest discover -s unit_tests/ -v -b 1> /dev/null
.pylintrc 0 → 100644
This diff is collapsed.
from aidge_core.aidge_core import * # import so generated by PyBind """
\ No newline at end of file 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
"""
from aidge_core.aidge_core import * # import so generated by PyBind
"""
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
"""
import unittest
import aidge_core
class test_operator_binding(unittest.TestCase):
"""Very basic test to make sure the python APi is not broken.
Can be remove in later stage of the developpement.
"""
def setUp(self):
self.generic_operator = aidge_core.GenericOperator("FakeConv", 1, 1, 1).get_operator()
def tearDown(self):
pass
def test_default_name(self):
op_type = "Conv"
gop = aidge_core.GenericOperator(op_type, 1, 1, 1, "FictiveName")
# check node name is not operator type
self.assertNotEqual(gop.name(), "Conv")
# check node name is not default
self.assertNotEqual(gop.name(), "")
def test_param_bool(self):
self.generic_operator.add_parameter("bool", True)
self.assertEqual(self.generic_operator.get_parameter("bool"), True)
def test_param_int(self):
self.generic_operator.add_parameter("int", 1)
self.assertEqual(self.generic_operator.get_parameter("int"), 1)
def test_param_float(self):
self.generic_operator.add_parameter("float", 2.0)
self.assertEqual(self.generic_operator.get_parameter("float"), 2.0)
def test_param_str(self):
self.generic_operator.add_parameter("str", "value")
self.assertEqual(self.generic_operator.get_parameter("str"), "value")
def test_param_l_int(self):
self.generic_operator.add_parameter("l_int", [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15])
self.assertEqual(self.generic_operator.get_parameter("l_int"), [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15])
def test_param_l_bool(self):
self.generic_operator.add_parameter("l_bool", [True, False, False, True])
self.assertEqual(self.generic_operator.get_parameter("l_bool"), [True, False, False, True])
def test_param_l_float(self):
self.generic_operator.add_parameter("l_float", [2.0, 1.0])
self.assertEqual(self.generic_operator.get_parameter("l_float"), [2.0, 1.0])
def test_param_l_str(self):
self.generic_operator.add_parameter("l_str", ["ok"])
self.assertEqual(self.generic_operator.get_parameter("l_str"), ["ok"])
if __name__ == '__main__':
unittest.main()
\ No newline at end of file
"""
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
"""
import unittest
import aidge_core
class test_parameters(unittest.TestCase):
"""Very basic test to make sure the python APi is not broken.
Can be remove in later stage of the developpement.
"""
def setUp(self):
pass
def tearDown(self):
pass
def test_conv(self):
# TODO : test StrideDims & DilationDims when supported in ctor
in_channels = 4
out_channels = 8
k_dims = [2, 2]
conv_op = aidge_core.Conv2D(in_channels , out_channels, k_dims).get_operator()
self.assertEqual(conv_op.get("InChannels"), in_channels)
self.assertEqual(conv_op.get("OutChannels"), out_channels)
self.assertEqual(conv_op.get("KernelDims"), k_dims)
def test_fc(self):
out_channels = 8
nb_bias = True
fc_op = aidge_core.FC(out_channels, nb_bias).get_operator()
self.assertEqual(fc_op.get("OutChannels"), out_channels)
self.assertEqual(fc_op.get("NoBias"), nb_bias)
def test_matmul(self):
out_channels = 8
matmul_op = aidge_core.Matmul(out_channels).get_operator()
self.assertEqual(matmul_op.get("OutChannels"), out_channels)
def test_producer_1D(self):
dims = [5]
producer_op = aidge_core.Producer(dims).get_operator()
self.assertEqual(producer_op.dims(), dims)
def test_producer_2D(self):
dims = [10,5]
producer_op = aidge_core.Producer(dims).get_operator()
self.assertEqual(producer_op.dims(), dims)
def test_producer_3D(self):
dims = [1,10,5]
producer_op = aidge_core.Producer(dims).get_operator()
self.assertEqual(producer_op.dims(), dims)
def test_producer_4D(self):
dims = [12,1,10,5]
producer_op = aidge_core.Producer(dims).get_operator()
self.assertEqual(producer_op.dims(), dims)
def test_producer_5D(self):
dims = [2,12,1,10,5]
producer_op = aidge_core.Producer(dims).get_operator()
self.assertEqual(producer_op.dims(), dims)
def test_leaky_relu(self):
negative_slope = 0.25
leakyrelu_op = aidge_core.LeakyReLU(negative_slope).get_operator()
self.assertEqual(leakyrelu_op.get("NegativeSlope"), negative_slope)
if __name__ == '__main__':
unittest.main()
...@@ -34,13 +34,23 @@ class GraphView; ...@@ -34,13 +34,23 @@ class GraphView;
*/ */
class Node : public std::enable_shared_from_this<Node> { class Node : public std::enable_shared_from_this<Node> {
private: private:
struct weakCompare {
bool operator()(const std::weak_ptr<Aidge::GraphView>& a, const std::weak_ptr<Aidge::GraphView>& b) const {
// Compare the content of the weak_ptrs
auto sharedA = a.lock();
auto sharedB = b.lock();
if (!sharedB) return false; // nothing after expired pointer
if (!sharedA) return true;
return sharedA < sharedB; // shared_ptr has a valid comparison operator
}
};
std::string mName; /** Name of the Node. Should be unique. */ std::string mName; /** Name of the Node. Should be unique. */
std::set<std::shared_ptr<GraphView>> mViews = std::set<std::shared_ptr<GraphView>>(); /** Set of pointers to GraphView instances including this Node instance. */ std::set<std::weak_ptr<GraphView>, weakCompare> mViews; /** Set of pointers to GraphView instances including this Node instance. */
const std::shared_ptr<Operator> mOperator; // Pointer to the associated Operator const std::shared_ptr<Operator> mOperator; // Pointer to the associated Operator
std::vector<NodePtr> mParents; /** List of parent node for each input (Parent --> Node --> Child) */ std::vector<NodePtr> mParents; /** List of parent node for each input (Parent --> Node --> Child) */
std::vector<std::vector<NodePtr>> mChildren; /** List of children nodes for each output (Parent --> Node --> Child) */ std::vector<std::vector<std::weak_ptr<Node>>> mChildren; /** List of children nodes for each output (Parent --> Node --> Child) */
std::vector<std::vector<IOIndex_t>> mIdInChildren; /** List of input index for each Node linked to each output of the Node. */ std::vector<std::vector<IOIndex_t>> mIdInChildren; /** List of input index for each Node linked to each output of the Node. */
std::vector<IOIndex_t> mIdOutParents; /** index of the output linked to each input of the Node. Default: gk_IODefaultIndex. */ std::vector<IOIndex_t> mIdOutParents; /** index of the output linked to each input of the Node. Default: gk_IODefaultIndex. */
...@@ -70,7 +80,7 @@ public: ...@@ -70,7 +80,7 @@ public:
* @param ctors Ordered Connectors linking their associated Node to the input of the current Node with the same index. * @param ctors Ordered Connectors linking their associated Node to the input of the current Node with the same index.
* @return Connector * @return Connector
*/ */
Connector operator()(const std::vector<Connector> ctors); Connector operator()(const std::vector<Connector> &ctors);
public: public:
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
...@@ -131,14 +141,14 @@ public: ...@@ -131,14 +141,14 @@ public:
/** /**
* @brief List of pair <Parent, ID of the data intput>. When an input is not * @brief List of pair <Parent, ID of the data intput>. When an input is not
* linked to any Parent, the pair is <nullptr, gk_IODefaultIndex>. * linked to any Parent, the pair is <nullptr, gk_IODefaultIndex>.
* @return std::vector<std::pair<NodePtr, IOIndex_t>> * @return std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>>
*/ */
std::vector<std::pair<NodePtr, IOIndex_t>> dataInputs() const; std::vector<std::pair<NodePtr, IOIndex_t>> dataInputs() const;
/** /**
* @brief List of pair <Parent, ID of the parent output>. When an input is not linked * @brief List of pair <Parent, ID of the parent output>. When an input is not linked
* to any Parent, the pair is <nullptr, gk_IODefaultIndex>. * to any Parent, the pair is <nullptr, gk_IODefaultIndex>.
* @return std::vector<std::pair<NodePtr, IOIndex_t>> * @return std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>>
*/ */
std::vector<std::pair<NodePtr, IOIndex_t>> inputs() const; std::vector<std::pair<NodePtr, IOIndex_t>> inputs() const;
...@@ -146,7 +156,7 @@ public: ...@@ -146,7 +156,7 @@ public:
* @brief Parent and its output Tensor ID linked to the inID-th input Tensor. * @brief Parent and its output Tensor ID linked to the inID-th input Tensor.
* If the input is not linked to any Parent, the pair is <nullptr, gk_IODefaultIndex>. * If the input is not linked to any Parent, the pair is <nullptr, gk_IODefaultIndex>.
* @param inID * @param inID
* @return std::pair<NodePtr, IOIndex_t> * @return std::pair<std::shared_ptr<Node>, IOIndex_t>
*/ */
inline std::pair<NodePtr, IOIndex_t> input(const IOIndex_t inID) const { inline std::pair<NodePtr, IOIndex_t> input(const IOIndex_t inID) const {
assert((inID != gk_IODefaultIndex) && (inID < nbInputs()) && "Input index out of bound."); assert((inID != gk_IODefaultIndex) && (inID < nbInputs()) && "Input index out of bound.");
...@@ -178,19 +188,19 @@ public: ...@@ -178,19 +188,19 @@ public:
/** /**
* @brief List input ids of children liked to outputs of the node * @brief List input ids of children liked to outputs of the node
* @return std::vector<std::vector<std::pair<NodePtr, * @return std::vector<std::vector<std::pair<std::shared_ptr<Node>,
* IOIndex_t>>> * IOIndex_t>>>
*/ */
std::vector<std::vector<std::pair<NodePtr, IOIndex_t>>> outputs() const; std::vector<std::vector<std::pair<NodePtr, IOIndex_t>>> outputs() const;
/** /**
* @brief Children and their input Tensor ID linked to the outID-th output * @brief Children and their input Tensor ID linked to the outId-th output
* Tensor. * Tensor.
* @param outID * @param outId
* @return std::vector<std::pair<NodePtr, IOIndex_t>> * @return std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>>
*/ */
std::vector<std::pair<NodePtr, IOIndex_t>> std::vector<std::pair<NodePtr, IOIndex_t>>
output(IOIndex_t outID) const; output(IOIndex_t outId) const;
/** /**
* @brief Number of inputs, including both data and learnable parameters. * @brief Number of inputs, including both data and learnable parameters.
...@@ -231,7 +241,11 @@ public: ...@@ -231,7 +241,11 @@ public:
* @return std::vector<GraphView> * @return std::vector<GraphView>
*/ */
inline std::set<std::shared_ptr<GraphView>> views() const noexcept { inline std::set<std::shared_ptr<GraphView>> views() const noexcept {
return mViews; std::set<std::shared_ptr<GraphView>> res;
for (const auto &v : mViews) {
res.insert(v.lock());
}
return res;
} }
/** /**
...@@ -239,14 +253,14 @@ public: ...@@ -239,14 +253,14 @@ public:
* the current Node. This feature allows transparent GraphViews. * the current Node. This feature allows transparent GraphViews.
* @param graphPtr Pointer to GraphView to add to the list. * @param graphPtr Pointer to GraphView to add to the list.
*/ */
inline void addView(const std::shared_ptr<GraphView> graphPtr) { inline void addView(const std::shared_ptr<GraphView> &graphPtr) {
mViews.insert(graphPtr); mViews.insert(std::weak_ptr<GraphView>(graphPtr));
} }
inline void removeView(const std::shared_ptr<GraphView> graphPtr) { inline void removeView(const std::shared_ptr<GraphView> &graphPtr) {
if (mViews.find(graphPtr) != mViews.end()) { std::set<std::weak_ptr<GraphView>, weakCompare>::const_iterator viewIt = mViews.cbegin();
mViews.erase(graphPtr); for (; (viewIt != mViews.cend()) && ((*viewIt).lock() != graphPtr) ; ++viewIt) {}
} mViews.erase(*viewIt);
} }
/** /**
...@@ -280,14 +294,14 @@ public: ...@@ -280,14 +294,14 @@ public:
/** /**
* @brief Get the list of parent Nodes. As an input is linked to a unique Node, * @brief Get the list of parent Nodes. As an input is linked to a unique Node,
* if none is linked then the parent is a nullptr. * if none is linked then the parent is a nullptr.
* @return std::vector<NodePtr> * @return std::vector<std::shared_ptr<Node>>
*/ */
std::vector<NodePtr> getParents() const; std::vector<NodePtr> getParents() const;
/** /**
* @brief Get the pointer to parent of the specified input index. This pointer is nullptr if no parent is linked. * @brief Get the pointer to parent of the specified input index. This pointer is nullptr if no parent is linked.
* @param inId Input index. * @param inId Input index.
* @return NodePtr& * @return std::shared_ptr<Node>&
*/ */
inline NodePtr &getParents(const IOIndex_t inId) { inline NodePtr &getParents(const IOIndex_t inId) {
assert(inId != gk_IODefaultIndex); assert(inId != gk_IODefaultIndex);
...@@ -298,7 +312,7 @@ public: ...@@ -298,7 +312,7 @@ public:
* @brief Unlink the parent Node at the specified input index and return its pointer. * @brief Unlink the parent Node at the specified input index and return its pointer.
* Return a nullptr is no parent was linked. * Return a nullptr is no parent was linked.
* @param inId Input index. * @param inId Input index.
* @return NodePtr * @return std::shared_ptr<Node>
*/ */
NodePtr popParent(const IOIndex_t inId); NodePtr popParent(const IOIndex_t inId);
...@@ -308,7 +322,7 @@ public: ...@@ -308,7 +322,7 @@ public:
* @brief Get the set of pointers to children Nodes linked to the current Node.object. * @brief Get the set of pointers to children Nodes linked to the current Node.object.
* @details The returned set does not include any nullptr as an output maybe linked to * @details The returned set does not include any nullptr as an output maybe linked to
* an undifined number of Nodes. It does not change the computation of its associated Operator. * an undifined number of Nodes. It does not change the computation of its associated Operator.
* @return std::set<NodePtr>> * @return std::set<std::shared_ptr<Node>>>
*/ */
std::set<NodePtr> getChildren() const; std::set<NodePtr> getChildren() const;
...@@ -317,14 +331,14 @@ public: ...@@ -317,14 +331,14 @@ public:
/** /**
* @brief Get the list of children Nodes linked to the output at specified index. * @brief Get the list of children Nodes linked to the output at specified index.
* @param outId Output index. * @param outId Output index.
* @return std::vector<NodePtr> * @return std::vector<std::shared_ptr<Node>>
*/ */
std::vector<NodePtr> getChildren(const IOIndex_t outID) const; std::vector<NodePtr> getChildren(const IOIndex_t outId) const;
/** /**
* @brief Remove registered child from children list of specified output if possible. * @brief Remove registered child from children list of specified output if possible.
* If so, also remove current Node from child Node from parent. * If so, also remove current Node from child Node from parent.
* @param nodePtr Node to remove. * @param std::shared_ptr<Node> Node to remove.
* @param outId Output index. Default 0. * @param outId Output index. Default 0.
* @return true Child found and removed for given output index. * @return true Child found and removed for given output index.
* @return false Child not found at given index. Nothing removed. * @return false Child not found at given index. Nothing removed.
...@@ -388,4 +402,4 @@ private: ...@@ -388,4 +402,4 @@ private:
}; };
} // namespace Aidge } // namespace Aidge
#endif /* __AIDGE_CORE_GRAPH_NODE_H__ */ #endif /* __AIDGE_CORE_GRAPH_NODE_H__ */
\ No newline at end of file
...@@ -79,6 +79,7 @@ class GenericOperator_Op ...@@ -79,6 +79,7 @@ class GenericOperator_Op
mParams.Add<T>(key, value); mParams.Add<T>(key, value);
} }
std::string getParameterType(std::string const &key) { return mParams.getParamType(key); } std::string getParameterType(std::string const &key) { return mParams.getParamType(key); }
std::vector<std::string> getParametersName() { return mParams.getParametersName(); } std::vector<std::string> getParametersName() { return mParams.getParametersName(); }
...@@ -88,7 +89,7 @@ class GenericOperator_Op ...@@ -88,7 +89,7 @@ class GenericOperator_Op
printf("Info: using associateInput() on a GenericOperator.\n"); printf("Info: using associateInput() on a GenericOperator.\n");
} }
void computeOutputDims() override final { void computeOutputDims() override final {
assert(false && "Cannot compute output dim of a GenericOperator"); assert(false && "Cannot compute output dim of a GenericOperator");
} }
...@@ -115,7 +116,7 @@ class GenericOperator_Op ...@@ -115,7 +116,7 @@ class GenericOperator_Op
printf("Info: using getInput() on a GenericOperator.\n"); printf("Info: using getInput() on a GenericOperator.\n");
return mInputs[inputIdx]; return mInputs[inputIdx];
} }
inline std::shared_ptr<Tensor> getOutput(const IOIndex_t outputIdx) const override final { inline std::shared_ptr<Tensor> getOutput(const IOIndex_t outputIdx) const override final {
assert((outputIdx < mNbOut) && "output index out of range for this instance of GenericOperator"); assert((outputIdx < mNbOut) && "output index out of range for this instance of GenericOperator");
printf("Info: using getOutput() on a GenericOperator.\n"); printf("Info: using getOutput() on a GenericOperator.\n");
return mOutputs[outputIdx]; return mOutputs[outputIdx];
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <assert.h> #include <assert.h>
#include <map> #include <map>
#include <vector> #include <vector>
#include <numeric>
namespace Aidge { namespace Aidge {
...@@ -23,6 +22,13 @@ namespace Aidge { ...@@ -23,6 +22,13 @@ namespace Aidge {
///\todo managing complex types or excluding non-trivial, non-aggregate types ///\todo managing complex types or excluding non-trivial, non-aggregate types
class CParameter class CParameter
{ {
private:
template <typename T>
struct is_vector : std::false_type {};
template <typename T, typename Alloc>
struct is_vector<std::vector<T, Alloc>> : std::true_type {};
public: public:
// not copyable, not movable // not copyable, not movable
CParameter(CParameter const &) = delete; CParameter(CParameter const &) = delete;
...@@ -30,6 +36,7 @@ public: ...@@ -30,6 +36,7 @@ public:
CParameter &operator=(CParameter const &) = delete; CParameter &operator=(CParameter const &) = delete;
CParameter &operator=(CParameter &&) = delete; CParameter &operator=(CParameter &&) = delete;
CParameter() : m_Params({}){}; CParameter() : m_Params({}){};
~CParameter() = default;
/** /**
* \brief Returning a parameter identified by its name * \brief Returning a parameter identified by its name
...@@ -41,7 +48,7 @@ public: ...@@ -41,7 +48,7 @@ public:
* param buffer that will get invalid after the CParam death. * param buffer that will get invalid after the CParam death.
* \note at() throws if the parameter does not exist, using find to test for parameter existance * \note at() throws if the parameter does not exist, using find to test for parameter existance
*/ */
template<class T> T Get(std::string const &i_ParamName) const template<class T> T Get(std::string const i_ParamName) const
{ {
assert(m_Params.find(i_ParamName) != m_Params.end()); assert(m_Params.find(i_ParamName) != m_Params.end());
assert(m_Types.find(i_ParamName) != m_Types.end()); assert(m_Types.find(i_ParamName) != m_Types.end());
...@@ -65,9 +72,11 @@ public: ...@@ -65,9 +72,11 @@ public:
= i_Value; // Black-magic used to add anytype into the vector = i_Value; // Black-magic used to add anytype into the vector
m_Params[i_ParamName] = m_OffSet; // Copy pointer offset m_Params[i_ParamName] = m_OffSet; // Copy pointer offset
m_OffSet += sizeof(T); // Increment offset m_OffSet += sizeof(T); // Increment offset
m_Types[i_ParamName] = typeid(i_Value).name(); m_Types[i_ParamName] = typeid(i_Value).name();
} }
std::string getParamType(std::string const &i_ParamName){ std::string getParamType(std::string const &i_ParamName){
return m_Types[i_ParamName]; return m_Types[i_ParamName];
} }
...@@ -79,18 +88,14 @@ public: ...@@ -79,18 +88,14 @@ public:
return parametersName; return parametersName;
} }
~CParameter() = default;
private: private:
// Note for Cyril: of course storing offset and not address! Good idea
std::map<std::string, std::size_t> m_Params; // { Param name : offset } std::map<std::string, std::size_t> m_Params; // { Param name : offset }
///\brief Map to check type error ///\brief Map to check type error
/* Note : i tried this : `std::map<std::string, std::type_info const *> m_Types;` /* Note : i tried this : `std::map<std::string, std::type_info const *> mTypes;`
but looks like the type_ingo object was destroyed. but looks like the type_ingo object was destroyed.
I am not a hugde fan of storing a string and making string comparison. I am not a hugde fan of storing a string and making string comparison.
Maybe we can use a custom enum type (or is there a standard solution ?) Maybe we can use a custom enum type (or is there a standard solution ?)
*/ */
std::map<std::string, std::string> m_Types; std::map<std::string, std::string> m_Types;
...@@ -102,9 +107,9 @@ private: ...@@ -102,9 +107,9 @@ private:
///\brief Offset, in number of uint8_t, of the next parameter to write ///\brief Offset, in number of uint8_t, of the next parameter to write
std::size_t m_OffSet = 0; std::size_t m_OffSet = 0;
}; };
} }
#endif /* __AIDGE_CPARAMETER_H__ */ #endif /* __AIDGE_CPARAMETER_H__ */
...@@ -21,7 +21,7 @@ namespace py = pybind11; ...@@ -21,7 +21,7 @@ namespace py = pybind11;
namespace Aidge { namespace Aidge {
void declare_FC(py::module &m) { void declare_FC(py::module &m) {
py::class_<FC_Op, std::shared_ptr<FC_Op>, Operator>(m, "FC_Op", py::multiple_inheritance()); py::class_<FC_Op, std::shared_ptr<FC_Op>, Operator, PyAbstractParametrizable>(m, "FC_Op", py::multiple_inheritance());
m.def("FC", &FC, py::arg("out_channels"), py::arg("nobias") = false, py::arg("name") = nullptr); m.def("FC", &FC, py::arg("out_channels"), py::arg("nobias") = false, py::arg("name") = nullptr);
} }
......
...@@ -21,7 +21,7 @@ namespace py = pybind11; ...@@ -21,7 +21,7 @@ namespace py = pybind11;
namespace Aidge { namespace Aidge {
void declare_Matmul(py::module &m) { void declare_Matmul(py::module &m) {
py::class_<Matmul_Op, std::shared_ptr<Matmul_Op>, Operator>(m, "Matmul_Op", py::multiple_inheritance()); py::class_<Matmul_Op, std::shared_ptr<Matmul_Op>, Operator, PyAbstractParametrizable>(m, "Matmul_Op", py::multiple_inheritance());
m.def("Matmul", &Matmul, py::arg("out_channels"), py::arg("name") = nullptr); m.def("Matmul", &Matmul, py::arg("out_channels"), py::arg("name") = nullptr);
} }
......
...@@ -21,8 +21,8 @@ Aidge::Node::Node(std::shared_ptr<Operator> op, const char *name) ...@@ -21,8 +21,8 @@ Aidge::Node::Node(std::shared_ptr<Operator> op, const char *name)
: mName((name == nullptr) ? std::string() : std::string(name)), : mName((name == nullptr) ? std::string() : std::string(name)),
mOperator(op), mOperator(op),
mParents(std::vector<std::shared_ptr<Node>>(static_cast<std::size_t>(op->nbInputs()), nullptr)), mParents(std::vector<std::shared_ptr<Node>>(static_cast<std::size_t>(op->nbInputs()), nullptr)),
mChildren(std::vector<std::vector<std::shared_ptr<Node>>>(static_cast<std::size_t>(op->nbOutputs()), mChildren(std::vector<std::vector<std::weak_ptr<Node>>>(static_cast<std::size_t>(op->nbOutputs()),
std::vector<std::shared_ptr<Node>>())), std::vector<std::weak_ptr<Node>>())),
mIdInChildren( mIdInChildren(
std::vector<std::vector<IOIndex_t>>(static_cast<std::size_t>(op->nbOutputs()), std::vector<IOIndex_t>())), std::vector<std::vector<IOIndex_t>>(static_cast<std::size_t>(op->nbOutputs()), std::vector<IOIndex_t>())),
mIdOutParents(std::vector<IOIndex_t>(static_cast<std::size_t>(op->nbInputs()), gk_IODefaultIndex)) { mIdOutParents(std::vector<IOIndex_t>(static_cast<std::size_t>(op->nbInputs()), gk_IODefaultIndex)) {
...@@ -33,7 +33,7 @@ Aidge::Node::Node(std::shared_ptr<Operator> op, const char *name) ...@@ -33,7 +33,7 @@ Aidge::Node::Node(std::shared_ptr<Operator> op, const char *name)
// FUNCTIONAL DESCRIPTION // FUNCTIONAL DESCRIPTION
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
Aidge::Connector Aidge::Node::operator()(const std::vector<Connector> ctors) { Aidge::Connector Aidge::Node::operator()(const std::vector<Connector> &ctors) {
assert((ctors.size() == nbDataInputs()) && "Wrong number of arguments.\n"); assert((ctors.size() == nbDataInputs()) && "Wrong number of arguments.\n");
for (__attribute__((unused)) std::pair<std::shared_ptr<Node>, IOIndex_t> &input : inputs()) { for (__attribute__((unused)) std::pair<std::shared_ptr<Node>, IOIndex_t> &input : inputs()) {
assert((gk_IODefaultIndex == input.second) && "At least one input connection is not free.\n"); assert((gk_IODefaultIndex == input.second) && "At least one input connection is not free.\n");
...@@ -134,12 +134,12 @@ Aidge::Node::outputs() const { ...@@ -134,12 +134,12 @@ Aidge::Node::outputs() const {
} }
std::vector<std::pair<std::shared_ptr<Aidge::Node>, Aidge::IOIndex_t>> std::vector<std::pair<std::shared_ptr<Aidge::Node>, Aidge::IOIndex_t>>
Aidge::Node::output(Aidge::IOIndex_t outID) const { Aidge::Node::output(Aidge::IOIndex_t outId) const {
std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>> listOutputs = std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>> listOutputs =
std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>>(mIdInChildren[outID].size()); std::vector<std::pair<std::shared_ptr<Node>, IOIndex_t>>(mIdInChildren[outId].size());
for (std::size_t i = 0; i < mIdInChildren[outID].size(); ++i) { for (std::size_t i = 0; i < mIdInChildren[outId].size(); ++i) {
listOutputs[i] = listOutputs[i] =
std::pair<std::shared_ptr<Node>, IOIndex_t>(mChildren[outID][i], mIdInChildren[outID][i]); std::pair<std::shared_ptr<Node>, IOIndex_t>(mChildren[outId][i].lock(), mIdInChildren[outId][i]);
} }
return listOutputs; return listOutputs;
} }
...@@ -161,7 +161,7 @@ Aidge::IOIndex_t Aidge::Node::nbValidOutputs() const { ...@@ -161,7 +161,7 @@ Aidge::IOIndex_t Aidge::Node::nbValidOutputs() const {
return counter; return counter;
} }
void Aidge::Node::setInputId(const IOIndex_t inId, const IOIndex_t newNodeOutID) { void Aidge::Node::setInputId(const IOIndex_t inId, const IOIndex_t newNodeoutId) {
assert(inId != gk_IODefaultIndex && (inId < nbInputs()) && "Must be a valid index"); assert(inId != gk_IODefaultIndex && (inId < nbInputs()) && "Must be a valid index");
if (mIdOutParents[inId] != gk_IODefaultIndex) { if (mIdOutParents[inId] != gk_IODefaultIndex) {
std::printf("Warning: filling a Tensor already attributed\n"); std::printf("Warning: filling a Tensor already attributed\n");
...@@ -171,7 +171,7 @@ void Aidge::Node::setInputId(const IOIndex_t inId, const IOIndex_t newNodeOutID) ...@@ -171,7 +171,7 @@ void Aidge::Node::setInputId(const IOIndex_t inId, const IOIndex_t newNodeOutID)
// find first occurence of child in the output's children // find first occurence of child in the output's children
originalParent.first->removeChild(shared_from_this(), originalParent.second); originalParent.first->removeChild(shared_from_this(), originalParent.second);
} }
mIdOutParents[inId] = newNodeOutID; mIdOutParents[inId] = newNodeoutId;
} }
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
...@@ -179,9 +179,8 @@ void Aidge::Node::setInputId(const IOIndex_t inId, const IOIndex_t newNodeOutID) ...@@ -179,9 +179,8 @@ void Aidge::Node::setInputId(const IOIndex_t inId, const IOIndex_t newNodeOutID)
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
void Aidge::Node::addChildOp(std::shared_ptr<Node> otherNode, const IOIndex_t outId, const IOIndex_t otherInId) { void Aidge::Node::addChildOp(std::shared_ptr<Node> otherNode, const IOIndex_t outId, const IOIndex_t otherInId) {
assert((otherInId != gk_IODefaultIndex) && (otherInId < otherNode->nbInputs()) && assert((otherInId < otherNode->nbInputs()) && "Input index out of bound.");
"Input index out of bound."); assert((outId < nbOutputs()) && "Output index out of bound.");
assert((outId != gk_IODefaultIndex) && (outId < nbOutputs()) && "Output index out of bound.");
if (otherNode->input(otherInId).second != gk_IODefaultIndex) { if (otherNode->input(otherInId).second != gk_IODefaultIndex) {
std::printf("Warning, the %d-th Parent of the child node already existed.\n", otherInId); std::printf("Warning, the %d-th Parent of the child node already existed.\n", otherInId);
} }
...@@ -189,24 +188,22 @@ void Aidge::Node::addChildOp(std::shared_ptr<Node> otherNode, const IOIndex_t ou ...@@ -189,24 +188,22 @@ void Aidge::Node::addChildOp(std::shared_ptr<Node> otherNode, const IOIndex_t ou
otherNode->setInputId(otherInId, outId); otherNode->setInputId(otherInId, outId);
otherNode->getOperator()->associateInput(otherInId, getOperator()->getRawOutput(outId)); otherNode->getOperator()->associateInput(otherInId, getOperator()->getRawOutput(outId));
// manage nodes // manage nodes
mChildren[outId].push_back(otherNode); mChildren[outId].push_back(std::weak_ptr<Node>(otherNode));
mIdInChildren[outId].push_back(otherInId); mIdInChildren[outId].push_back(otherInId);
otherNode->addParent(shared_from_this(), otherInId); otherNode->addParent(shared_from_this(), otherInId);
} }
void Aidge::Node::addChildView(std::shared_ptr<GraphView> other_graph, const IOIndex_t outID, void Aidge::Node::addChildView(std::shared_ptr<GraphView> otherGraph, const IOIndex_t outId,
std::pair<std::shared_ptr<Node>, IOIndex_t> otherInId) { std::pair<std::shared_ptr<Node>, IOIndex_t> otherInId) {
assert((otherInId.second != gk_IODefaultIndex) && assert((otherInId.second < otherInId.first->nbInputs()) && "Other graph input index out of bound.");
(otherInId.second < otherInId.first->nbInputs()) && assert((outId < nbOutputs()) && "Output index out of bound.");
"Other graph input index out of bound."); std::set<std::shared_ptr<Node>> inNodes = otherGraph->inputNodes();
assert((outID != gk_IODefaultIndex) && (outID < nbOutputs()) && "Output index out of bound.");
std::set<std::shared_ptr<Node>> inNodes = other_graph->inputNodes();
if (inNodes.size() == std::size_t(0)) { // no input Node if (inNodes.size() == std::size_t(0)) { // no input Node
printf("Cannot add GraphView to the Node. No input node detected.\n"); printf("Cannot add GraphView to the Node. No input node detected.\n");
} else // inNodes.size() >= 1 } else // inNodes.size() >= 1
{ {
assert((inNodes.find(otherInId.first) != inNodes.end())); // assert it really is an input node assert((inNodes.find(otherInId.first) != inNodes.end())); // assert it really is an input node
addChildOp(otherInId.first, outID, otherInId.second); addChildOp(otherInId.first, outId, otherInId.second);
} }
} }
...@@ -256,24 +253,36 @@ bool Aidge::Node::removeParent(const IOIndex_t inId) { ...@@ -256,24 +253,36 @@ bool Aidge::Node::removeParent(const IOIndex_t inId) {
std::set<std::shared_ptr<Aidge::Node>> Aidge::Node::getChildren() const { std::set<std::shared_ptr<Aidge::Node>> Aidge::Node::getChildren() const {
std::set<std::shared_ptr<Node>> children; std::set<std::shared_ptr<Node>> children;
for (const std::vector<std::shared_ptr<Node>> &childrenOfOneOutput : mChildren) { for (const auto &childrenOfOneOutput : mChildren) {
children.insert(childrenOfOneOutput.begin(), childrenOfOneOutput.end()); for (const auto &oneChild : childrenOfOneOutput) {
children.insert(oneChild.lock());
}
} }
return children; return children;
} }
std::vector<std::vector<std::shared_ptr<Aidge::Node>>> Aidge::Node::getOrderedChildren() const { return mChildren; } std::vector<std::vector<std::shared_ptr<Aidge::Node>>> Aidge::Node::getOrderedChildren() const {
std::vector<std::vector<std::shared_ptr<Node>>> children = std::vector<std::vector<std::shared_ptr<Node>>>(mChildren.size());
for (std::size_t outId = 0; outId < mChildren.size(); ++outId) {
children[outId] = getChildren(outId);
}
return children;
}
std::vector<std::shared_ptr<Aidge::Node>> Aidge::Node::getChildren(const IOIndex_t outID) const { std::vector<std::shared_ptr<Aidge::Node>> Aidge::Node::getChildren(const IOIndex_t outId) const {
assert((outID != gk_IODefaultIndex) && (outID < nbOutputs()) && "Output index out of bound."); assert((outId < nbOutputs()) && "Output index out of bound.");
return mChildren[outID]; std::vector<std::shared_ptr<Node>> children = std::vector<std::shared_ptr<Node>>(mChildren[outId].size());
for (std::size_t i = 0; i < mChildren[outId].size(); ++i) {
children.push_back(mChildren[outId][i].lock());
}
return children;
} }
bool Aidge::Node::removeChild(const std::shared_ptr<Aidge::Node> nodePtr, const Aidge::IOIndex_t outId) { bool Aidge::Node::removeChild(const std::shared_ptr<Aidge::Node> nodePtr, const Aidge::IOIndex_t outId) {
assert((outId != gk_IODefaultIndex) && (outId < nbOutputs()) && "Child index out of bound."); assert((outId < nbOutputs()) && "Child index out of bound.");
bool removed = false; bool removed = false;
for (std::size_t j = 0; j < mChildren[outId].size(); ++j) { for (std::size_t j = 0; j < mChildren[outId].size(); ++j) {
if (mChildren[outId][j] == nodePtr) { if (mChildren[outId][j].lock() == nodePtr) {
mChildren[outId].erase(mChildren[outId].begin() + j); mChildren[outId].erase(mChildren[outId].begin() + j);
mIdInChildren[outId].erase(mIdInChildren[outId].begin() + j); mIdInChildren[outId].erase(mIdInChildren[outId].begin() + j);
removed = true; removed = true;
...@@ -301,7 +310,7 @@ void Aidge::Node::resetConnections(bool includeLearnableParam) { ...@@ -301,7 +310,7 @@ void Aidge::Node::resetConnections(bool includeLearnableParam) {
for (std::pair<std::shared_ptr<Node>, IOIndex_t> child : output(i)) { for (std::pair<std::shared_ptr<Node>, IOIndex_t> child : output(i)) {
child.first->removeParent(child.second); child.first->removeParent(child.second);
} }
mChildren[i] = std::vector<std::shared_ptr<Node>>(); mChildren[i] = std::vector<std::weak_ptr<Node>>();
mIdInChildren[i] = std::vector<IOIndex_t>(); mIdInChildren[i] = std::vector<IOIndex_t>();
} }
// removing this Node from every GraphView it belongs to // removing this Node from every GraphView it belongs to
......
...@@ -22,10 +22,10 @@ std::shared_ptr<Aidge::GraphView> Aidge::Sequential(std::initializer_list<OpArgs ...@@ -22,10 +22,10 @@ std::shared_ptr<Aidge::GraphView> Aidge::Sequential(std::initializer_list<OpArgs
assert(static_cast<std::size_t>(elt.node()->getNbFreeDataInputs()) >= gv->outputNodes().size()); assert(static_cast<std::size_t>(elt.node()->getNbFreeDataInputs()) >= gv->outputNodes().size());
/* /*
* /!\ mn.view()->outputNodes() is a set, order of Nodes cannot be guaranted. * /!\ mn.view()->outputNodes() is a set, order of Nodes cannot be guaranted.
* Prefer a functional descrition for detailed inputs * Prefer a functional description for detailed inputs
*/ */
for (const std::shared_ptr<Node>& node_ptr : gv->outputNodes()) { for (const std::shared_ptr<Node>& node_ptr : gv->outputNodes()) {
node_ptr -> addChild(elt.node()); // already check that node_ptr->nbOutput == 1 node_ptr -> addChild(elt.node()); // already checks that node_ptr->nbOutput() == 1
} }
gv->add(elt.node()); gv->add(elt.node());
} }
......
...@@ -22,33 +22,44 @@ TEST_CASE("[core/operators] GenericOp(add & get parameters)", "[Operator]") { ...@@ -22,33 +22,44 @@ TEST_CASE("[core/operators] GenericOp(add & get parameters)", "[Operator]") {
GenericOperator_Op Testop("TestOp", 1, 1, 1); GenericOperator_Op Testop("TestOp", 1, 1, 1);
int value = 5; int value = 5;
const char* key = "intParam"; const char* key = "intParam";
Testop.addParameter<int>(key, value); Testop.addParameter(key, value);
REQUIRE(Testop.getParameter<int>(key) == value); REQUIRE(Testop.getParameter<int>(key) == value);
} }
SECTION("LONG") { SECTION("LONG") {
GenericOperator_Op Testop("TestOp", 1, 1, 1); GenericOperator_Op Testop("TestOp", 1, 1, 1);
long value = 3; long value = 3;
const char* key = "longParam"; const char* key = "longParam";
Testop.addParameter<long>(key, value); Testop.addParameter(key, value);
REQUIRE(Testop.getParameter<long>(key) == value); REQUIRE(Testop.getParameter<long>(key) == value);
} }
SECTION("FLOAT") { SECTION("FLOAT") {
GenericOperator_Op Testop("TestOp", 1, 1, 1); GenericOperator_Op Testop("TestOp", 1, 1, 1);
float value = 2.0; float value = 2.0;
const char* key = "floatParam"; const char* key = "floatParam";
Testop.addParameter<float>(key, value); Testop.addParameter(key, value);
REQUIRE(Testop.getParameter<float>(key) == value); REQUIRE(Testop.getParameter<float>(key) == value);
}
SECTION("VECTOR<BOOL>") {
GenericOperator_Op Testop("TestOp", 1, 1, 1);
std::vector<bool> value = {true, false, false, true, true};
const char* key = "vect";
Testop.addParameter(key, value);
REQUIRE(Testop.getParameter<std::vector<bool>>(key).size() == value.size());
for (std::size_t i=0; i < value.size(); ++i){
REQUIRE(Testop.getParameter<std::vector<bool>>(key)[i] == value[i]);
}
} }
SECTION("VECTOR<INT>") { SECTION("VECTOR<INT>") {
GenericOperator_Op Testop("TestOp", 1, 1, 1); GenericOperator_Op Testop("TestOp", 1, 1, 1);
std::vector<int> value = {1, 2}; std::vector<int> value = {1, 2, 3, 4, 5, 6, 7, 8, 9};
const char* key = "vect"; const char* key = "vect";
Testop.addParameter<std::vector<int>>(key, value); Testop.addParameter(key, value);
REQUIRE(Testop.getParameter<std::vector<int>>(key).size() == value.size()); REQUIRE(Testop.getParameter<std::vector<int>>(key).size() == value.size());
for (std::size_t i=0; i < value.size(); ++i){ for (std::size_t i=0; i < value.size(); ++i){
REQUIRE(Testop.getParameter<std::vector<int>>(key)[i] == value[i]); REQUIRE(Testop.getParameter<std::vector<int>>(key)[i] == value[i]);
} }
} }
SECTION("MULTIPLE PARAMS") { SECTION("MULTIPLE PARAMS") {
/* /*
......
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