summaryrefslogtreecommitdiff
path: root/runtime/neurun/backend/cpu_common
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/neurun/backend/cpu_common')
-rw-r--r--runtime/neurun/backend/cpu_common/CMakeLists.txt28
-rw-r--r--runtime/neurun/backend/cpu_common/MemoryPlanner.cc220
-rw-r--r--runtime/neurun/backend/cpu_common/MemoryPlanner.h217
-rw-r--r--runtime/neurun/backend/cpu_common/MemoryPlanner.test.cc193
-rw-r--r--runtime/neurun/backend/cpu_common/MemoryPlannerFactory.cc51
-rw-r--r--runtime/neurun/backend/cpu_common/MemoryPlannerFactory.h45
6 files changed, 754 insertions, 0 deletions
diff --git a/runtime/neurun/backend/cpu_common/CMakeLists.txt b/runtime/neurun/backend/cpu_common/CMakeLists.txt
new file mode 100644
index 000000000..5b6161ba7
--- /dev/null
+++ b/runtime/neurun/backend/cpu_common/CMakeLists.txt
@@ -0,0 +1,28 @@
+file(GLOB SOURCES "*.cc")
+file(GLOB_RECURSE TESTS "*.test.cc")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(${LIB_NEURUN_BACKEND_CPU_COMMON} STATIC ${SOURCES})
+
+target_include_directories(${LIB_NEURUN_BACKEND_CPU_COMMON} PUBLIC ${NEURUN_INCLUDE_DIR})
+target_include_directories(${LIB_NEURUN_BACKEND_CPU_COMMON} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+target_link_libraries(${LIB_NEURUN_BACKEND_CPU_COMMON} PUBLIC nnfw_lib_cpp14)
+target_link_libraries(${LIB_NEURUN_BACKEND_CPU_COMMON} PRIVATE nnfw_lib_misc)
+target_link_libraries(${LIB_NEURUN_BACKEND_CPU_COMMON} PRIVATE neurun_core)
+target_link_libraries(${LIB_NEURUN_BACKEND_CPU_COMMON} PRIVATE nnfw_common)
+target_link_libraries(${LIB_NEURUN_BACKEND_CPU_COMMON} PRIVATE nnfw_coverage)
+
+set_target_properties(${LIB_NEURUN_BACKEND_CPU_COMMON} PROPERTIES POSITION_INDEPENDENT_CODE ON)
+set_target_properties(${LIB_NEURUN_BACKEND_CPU_COMMON} PROPERTIES OUTPUT_NAME backend_cpu_common)
+
+# Unit Tests
+set(TEST_NEURUN_BACKEND_CPU_COMMON test_neurun_backend_cpu_common)
+
+add_executable(${TEST_NEURUN_BACKEND_CPU_COMMON} ${TESTS})
+
+target_link_libraries(${TEST_NEURUN_BACKEND_CPU_COMMON} ${LIB_NEURUN_BACKEND_CPU_COMMON})
+target_link_libraries(${TEST_NEURUN_BACKEND_CPU_COMMON} gtest gtest_main dl ${LIB_PTHREAD})
+target_include_directories(${TEST_NEURUN_BACKEND_CPU_COMMON} PRIVATE ${NEURUN_INCLUDE_DIR})
+
+add_test(${TEST_NEURUN_BACKEND_CPU_COMMON} ${TEST_NEURUN_BACKEND_CPU_COMMON})
+install(TARGETS ${TEST_NEURUN_BACKEND_CPU_COMMON} DESTINATION unittest)
diff --git a/runtime/neurun/backend/cpu_common/MemoryPlanner.cc b/runtime/neurun/backend/cpu_common/MemoryPlanner.cc
new file mode 100644
index 000000000..19961362e
--- /dev/null
+++ b/runtime/neurun/backend/cpu_common/MemoryPlanner.cc
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MemoryPlanner.h"
+#include "util/logging.h"
+#include <cassert>
+
+namespace neurun
+{
+namespace backend
+{
+namespace cpu_common
+{
+
+Allocator::Allocator(uint32_t capacity)
+{
+ _base = nnfw::cpp14::make_unique<uint8_t[]>(capacity);
+
+ VERBOSE(ALLOC) << "allocation capacity: " << capacity << std::endl;
+ VERBOSE(ALLOC) << "base pointer: " << static_cast<void *>(_base.get()) << std::endl;
+}
+
+void BumpPlanner::claim(const ir::OperandIndex &ind, size_t size)
+{
+ assert(size != 0);
+
+ Block blk{_capacity, size};
+ _mem_plans[ind] = blk;
+ _capacity += size;
+
+ VERBOSE(BP_PLANNER) << "CLAIM(#" << ind.value() << "): " << blk.offset << ", " << blk.size
+ << std::endl;
+}
+
+void BumpPlanner::release(const ir::OperandIndex &ind)
+{
+ VERBOSE(BP_PLANNER) << "RELEASE(#" << ind.value() << "): "
+ << "NOTHING does" << std::endl;
+}
+
+// There are some assumptions for claiming memory(== making a reservation for memory).
+// 1. About _claim_table(std::map).
+// - The table's data structure is std::map so that it always sorts
+// value(OperandIndex) by key(base_offset).
+// - This claim() inserts key/value into _claim_table and the release() removes the key/value from
+// _claim_table.
+// - _claim_table shows the memory status at a certain point in time. Therefore,
+// - If _claim_table has an offset and a certain size at a certain point in time,
+// it means the place at the offset has been already claimed(== can't claim now. need to find
+// someplace new).
+// - If _claim_table doesn't have any element for an offset and a certain size at a certain
+// point in time, it means the place at the offset can be claimed.
+// 2. In the loop for _claim_table, we can assume the current claim_base_offset value is bigger than
+// the previous claim_base_offset.
+void FirstFitPlanner::claim(const ir::OperandIndex &ind, size_t size)
+{
+ assert(size != 0);
+
+ // Find the right position for claiming
+ uint32_t next_offset = 0;
+ for (auto &mem_claim : _claim_table)
+ {
+ auto claimed_base_offset = mem_claim.first;
+ auto claimed_size = _mem_plans[mem_claim.second].size;
+ if (next_offset + size <= claimed_base_offset)
+ {
+ break;
+ }
+ else
+ {
+ next_offset = claimed_base_offset + claimed_size;
+ }
+ }
+
+ // Now next_offset is set to the proper offset
+ _claim_table[next_offset] = ind;
+ _mem_plans[ind] = {next_offset, size};
+
+ VERBOSE(FF_PLANNER) << "claim(#" << ind.value() << "): [+" << next_offset << ", " << size << "sz]"
+ << std::endl;
+
+ if (_capacity < next_offset + size)
+ {
+ _capacity = next_offset + size;
+ }
+}
+
+void FirstFitPlanner::release(const ir::OperandIndex &ind)
+{
+ for (auto it = _claim_table.cbegin(); it != _claim_table.cend(); ++it)
+ {
+ if (it->second == ind)
+ {
+ uint32_t offset = it->first;
+ uint32_t index = ind.value();
+ uint32_t size = _mem_plans[ind].size;
+
+ _claim_table.erase(it);
+
+ VERBOSE(FF_PLANNER) << "release(#" << index << "): [+" << offset << ", " << size << "sz]"
+ << std::endl;
+ return;
+ }
+ }
+ assert(!"Cannot release for given index. It has been not claimed or released already.");
+}
+
+WICPlanner::WICPlanner()
+ : _initialized(false), _capacity(0), _mem_plans(), _live_operands(), _interference_graph(),
+ _map_size_to_operands(), _claim_table()
+{
+ // DO NOTHING
+}
+
+void WICPlanner::claim(const ir::OperandIndex &ind, size_t size)
+{
+ assert(size != 0);
+
+ _map_size_to_operands.insert({size, ind});
+ for (auto &live_operand : _live_operands)
+ {
+ _interference_graph[live_operand].insert(ind);
+ _interference_graph[ind].insert(live_operand);
+ }
+ _live_operands.insert(ind);
+
+ VERBOSE(WIC_PLANNER) << "claim(#" << ind.value() << "): [" << size << "sz]" << std::endl;
+}
+
+void WICPlanner::release(const ir::OperandIndex &ind)
+{
+ _live_operands.erase(ind);
+ VERBOSE(WIC_PLANNER) << "release(#" << ind.value() << ")" << std::endl;
+}
+
+/*
+ * Build memory plans using liveness and size of operands
+ * 1. Build inference graph at claim
+ * - Two operands interfere if they have overlapped live range
+ * 2. Sort operands descending order of size
+ * - Use std::multimap to sort operands
+ * 3. Allocate memory block for sorted operands
+ * - Find free memory block which does not overlap with interfered operands
+ */
+void WICPlanner::buildMemoryPlans()
+{
+ for (auto &size_to_operand : _map_size_to_operands)
+ {
+ uint32_t size = size_to_operand.first;
+ ir::OperandIndex ind = size_to_operand.second;
+ VERBOSE(WIC_PLANNER) << "build_plan(#" << ind.value() << "): [" << size << "sz]" << std::endl;
+
+ // Find firstfit which does not interfere with live operands
+ uint32_t next_offset = 0;
+ if (_interference_graph.find(ind) != _interference_graph.end())
+ {
+ std::unordered_set<ir::OperandIndex> &interferences = _interference_graph.find(ind)->second;
+ for (auto &mem_claim : _claim_table)
+ {
+ if (interferences.find(mem_claim.second) != interferences.end())
+ {
+ auto claimed_base_offset = mem_claim.first;
+ auto claimed_size = _mem_plans[mem_claim.second].size;
+ VERBOSE(WIC_PLANNER) << "interfere (#" << mem_claim.second.value() << "): [+"
+ << claimed_base_offset << ", " << claimed_size << "sz]" << std::endl;
+ if (next_offset + size <= claimed_base_offset)
+ {
+ break;
+ }
+ else if (next_offset < claimed_base_offset + claimed_size)
+ {
+ next_offset = claimed_base_offset + claimed_size;
+ }
+ }
+ }
+ }
+ else
+ {
+ VERBOSE(WIC_PLANNER) << "No interference" << std::endl;
+ }
+
+ _claim_table.insert({next_offset, ind});
+ _mem_plans[ind] = {next_offset, size};
+ VERBOSE(WIC_PLANNER) << "alloc(#" << ind.value() << "): [+" << next_offset << ", " << size
+ << "sz]" << std::endl;
+
+ if (_capacity < next_offset + size)
+ {
+ _capacity = next_offset + size;
+ }
+ }
+ _initialized = true;
+ _interference_graph.clear();
+ _map_size_to_operands.clear();
+ _claim_table.clear();
+}
+
+WICPlanner::MemoryPlans &WICPlanner::memory_plans()
+{
+ if (!_initialized)
+ buildMemoryPlans();
+ return _mem_plans;
+}
+
+} // namespace cpu_common
+} // namespace backend
+} // namespace neurun
diff --git a/runtime/neurun/backend/cpu_common/MemoryPlanner.h b/runtime/neurun/backend/cpu_common/MemoryPlanner.h
new file mode 100644
index 000000000..c4f5e6a9e
--- /dev/null
+++ b/runtime/neurun/backend/cpu_common/MemoryPlanner.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file        MemoryPlanner.h
+ * @brief       This file contains Memory Planning related classes
+ */
+
+#ifndef __NEURUN_BACKEND_CPU_COMMON_MEMORY_PLANNER_H__
+#define __NEURUN_BACKEND_CPU_COMMON_MEMORY_PLANNER_H__
+
+#include <map>
+#include <unordered_set>
+#include <cpp14/memory.h>
+
+#include "ir/OperandIndexMap.h"
+
+namespace neurun
+{
+namespace backend
+{
+namespace cpu_common
+{
+
+/**
+ * @brief Structure to have memory offset and size
+ */
+struct Block
+{
+ uint32_t offset;
+ size_t size;
+};
+
+/**
+ * @brief Class to allocate memory
+ */
+class Allocator
+{
+public:
+ Allocator(uint32_t capacity);
+ /**
+ * @brief Get memory base pointer
+ * @return base pointer
+ */
+ uint8_t *base() const { return _base.get(); }
+ void release() { _base.reset(); }
+
+private:
+ std::unique_ptr<uint8_t[]> _base;
+};
+
+/**
+ * @brief Interface to plan memory
+ */
+struct IMemoryPlanner
+{
+ using MemoryPlans = ir::OperandIndexMap<Block>;
+
+ /**
+ * @brief Claim memory for operand
+ * @param[in] index The operand index
+ * @param[in] size The size of the memory
+ */
+ virtual void claim(const ir::OperandIndex &, size_t) = 0;
+ /**
+ * @brief Release memory for operand
+ * @param[in] index The operand index
+ */
+ virtual void release(const ir::OperandIndex &) = 0;
+ /**
+ * @brief Get capacity for memory planning
+ * @return The value of capacity
+ */
+ virtual uint32_t capacity() = 0;
+ /**
+ * @brief Get MemoryPlans
+ * @return MemoryPlans
+ */
+ virtual MemoryPlans &memory_plans() = 0;
+
+ virtual ~IMemoryPlanner() = default;
+};
+
+/**
+ * @brief Class to plan memory by bump way
+ */
+class BumpPlanner : public IMemoryPlanner
+{
+public:
+ /**
+ * @brief Claim memory for operand by bump way
+ * @param[in] index The operand index
+ * @param[in] size The size of the memory
+ */
+ void claim(const ir::OperandIndex &, size_t) override;
+ /**
+ * @brief Release memory for operand by bump way
+ * @param[in] index The operand index
+ */
+ void release(const ir::OperandIndex &) override;
+ /**
+ * @brief Get capacity for memory planning
+ * @return The value of capacity
+ */
+ uint32_t capacity() override { return _capacity; }
+ /**
+ * @brief Get MemoryPlans
+ * @return MemoryPlans
+ */
+ MemoryPlans &memory_plans() override { return _mem_plans; }
+
+private:
+ uint32_t _capacity = 0;
+ MemoryPlans _mem_plans;
+};
+
+/**
+ * @brief Class to plan memory by firstfit way
+ */
+class FirstFitPlanner : public IMemoryPlanner
+{
+public:
+ /**
+ * @brief Claim memory for operand by firstfit way
+ * @param[in] index The operand index
+ * @param[in] size The size of the memory
+ */
+ void claim(const ir::OperandIndex &, size_t) override;
+ /**
+ * @brief Release memory for operand by firstfit way
+ * @param[in] index The operand index
+ */
+ void release(const ir::OperandIndex &) override;
+ /**
+ * @brief Get capacity for memory planning
+ * @return The value of capacity
+ */
+ uint32_t capacity() override { return _capacity; }
+ /**
+ * @brief Get MemoryPlans
+ * @return MemoryPlans
+ */
+ MemoryPlans &memory_plans() override { return _mem_plans; }
+
+private:
+ uint32_t _capacity = 0;
+ MemoryPlans _mem_plans;
+ // Use std::map because claim() assumes that _claim_table is sorted by uint32_t(base_offset)
+ std::map<uint32_t, ir::OperandIndex> _claim_table;
+};
+
+/**
+ * @brief Class to plan memory by Weighted Interval Color algorithm
+ */
+class WICPlanner : public IMemoryPlanner
+{
+public:
+ WICPlanner();
+
+ /**
+ * @brief Claim memory for operand by WIC algorithm
+ * @param[in] index The operand index
+ * @param[in] size The size of the memory
+ */
+ void claim(const ir::OperandIndex &, size_t) override;
+ /**
+ * @brief Release memory for operand by WIC algorithm
+ * @param[in] index The operand index
+ */
+ void release(const ir::OperandIndex &) override;
+ /**
+ * @brief Get capacity for memory planning
+ * @return The value of capacity
+ */
+ uint32_t capacity() override
+ {
+ if (!_initialized)
+ buildMemoryPlans();
+ return _capacity;
+ }
+ /**
+ * @brief Get MemoryPlans
+ * @return MemoryPlans
+ */
+ MemoryPlans &memory_plans() override;
+
+private:
+ void buildMemoryPlans();
+
+ bool _initialized;
+ uint32_t _capacity;
+ MemoryPlans _mem_plans;
+ std::unordered_set<ir::OperandIndex> _live_operands;
+ ir::OperandIndexMap<std::unordered_set<ir::OperandIndex>> _interference_graph;
+ // Sort operands by descending order of size
+ std::multimap<uint32_t, ir::OperandIndex, std::greater<uint32_t>> _map_size_to_operands;
+ std::multimap<uint32_t, ir::OperandIndex> _claim_table;
+};
+
+} // namespace cpu_common
+} // namespace backend
+} // namespace neurun
+
+#endif // __NEURUN_BACKEND_CPU_COMMON_MEMORY_PLANNER_H__
diff --git a/runtime/neurun/backend/cpu_common/MemoryPlanner.test.cc b/runtime/neurun/backend/cpu_common/MemoryPlanner.test.cc
new file mode 100644
index 000000000..b2be7db24
--- /dev/null
+++ b/runtime/neurun/backend/cpu_common/MemoryPlanner.test.cc
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "MemoryPlanner.h"
+#include "ir/Index.h"
+
+TEST(Allocator, allocate_test)
+{
+ ::neurun::backend::cpu_common::Allocator allocator(1024);
+ ASSERT_NE(allocator.base(), nullptr);
+}
+
+TEST(BumpPlanner, claim_test)
+{
+ ::neurun::backend::cpu_common::BumpPlanner planner;
+
+ auto claim = [&planner](uint32_t index, size_t size, uint32_t expected_offset) {
+ neurun::ir::OperandIndex mem_idx(index);
+ planner.claim(mem_idx, size);
+ auto mem_blk = planner.memory_plans()[mem_idx];
+ ASSERT_EQ(mem_blk.offset, expected_offset);
+ ASSERT_EQ(mem_blk.size, size);
+ };
+
+ claim(0, 10, 0);
+ claim(1, 20, 10);
+ claim(2, 30, 30);
+}
+
+TEST(FirstFitPlanner, claim_release_test)
+{
+ ::neurun::backend::cpu_common::FirstFitPlanner planner;
+
+ auto claim = [&planner](uint32_t index, size_t size, uint32_t expected_offset) {
+ neurun::ir::OperandIndex mem_idx(index);
+ planner.claim(mem_idx, size);
+ auto mem_blk = planner.memory_plans()[mem_idx];
+ ASSERT_EQ(mem_blk.offset, expected_offset);
+ ASSERT_EQ(mem_blk.size, size);
+ };
+
+ auto release = [&planner](uint32_t index) {
+ neurun::ir::OperandIndex mem_idx(index);
+ planner.release(mem_idx);
+ };
+
+ // 0 CLAIM - 10
+ claim(0, 10, 0);
+
+ // 1 CLAIM - 20
+ claim(1, 20, 10);
+
+ // 2 CLAIM - 30
+ claim(2, 30, 30);
+
+ // 0 RELEASE - 10
+ release(0);
+
+ // 3 CLAIM - 20
+ claim(3, 20, 60);
+
+ // 4 CLAIM - 5
+ claim(4, 5, 0);
+
+ // 5 CLAIM - 10
+ claim(5, 10, 80);
+
+ // 6 CLAIM - 5
+ claim(6, 5, 5);
+
+ // 2 RELEASE - 30
+ release(2);
+
+ // 7 CLAIM - 35
+ claim(7, 35, 90);
+
+ // 8 CLAIM - 10
+ claim(8, 10, 30);
+
+ // 4 RELEASE - 5
+ release(4);
+
+ // 9 CLAIM - 10
+ claim(9, 10, 40);
+
+ // 10 CLAIM - 10
+ claim(10, 10, 50);
+
+ // 6 RELEASE
+ release(6);
+
+ // 1 RELEASE
+ release(1);
+
+ // 8 RELEASE
+ release(8);
+
+ // 9 RELEASE
+ release(9);
+
+ // 10 RELEASE
+ release(10);
+
+ // 3 RELEASE
+ release(3);
+
+ // 5 RELEASE
+ release(5);
+
+ // 7 RELEASE
+ release(7);
+}
+
+TEST(WICPlanner, claim_release_test)
+{
+ ::neurun::backend::cpu_common::WICPlanner planner;
+
+ auto claim = [&planner](uint32_t index, size_t size) {
+ neurun::ir::OperandIndex mem_idx(index);
+ planner.claim(mem_idx, size);
+ };
+
+ auto release = [&planner](uint32_t index) {
+ neurun::ir::OperandIndex mem_idx(index);
+ planner.release(mem_idx);
+ };
+
+ auto verify = [&planner](uint32_t index, uint32_t size, uint32_t expected_offset) {
+ neurun::ir::OperandIndex mem_idx(index);
+ auto mem_blk = planner.memory_plans()[mem_idx];
+ ASSERT_EQ(mem_blk.offset, expected_offset);
+ ASSERT_EQ(mem_blk.size, size);
+ };
+
+ auto capacity = [&planner](uint32_t expected_capacity) {
+ auto actual_capacity = planner.capacity();
+ ASSERT_EQ(actual_capacity, expected_capacity);
+ };
+
+ claim(0, 20);
+ claim(1, 5);
+ release(0);
+ claim(2, 10);
+ release(1);
+ claim(3, 10);
+ release(2);
+ claim(4, 10);
+ release(3);
+ claim(5, 20);
+ release(4);
+ claim(6, 20);
+ release(5);
+ release(7);
+
+ // VERIFY 0 - 0
+ verify(0, 20, 0);
+
+ // VERIFY 1 - 20
+ verify(1, 5, 20);
+
+ // VERIFY 2 - 0
+ verify(2, 10, 0);
+
+ // VERIFY 3 - 10
+ verify(3, 10, 10);
+
+ // VERIFY 4 - 20
+ verify(4, 10, 20);
+
+ // VERIFY 5 - 0
+ verify(5, 20, 0);
+
+ // VERIFY 6 - 20
+ verify(6, 20, 20);
+
+ // CAPACITY - 40
+ capacity(40);
+}
diff --git a/runtime/neurun/backend/cpu_common/MemoryPlannerFactory.cc b/runtime/neurun/backend/cpu_common/MemoryPlannerFactory.cc
new file mode 100644
index 000000000..9da987aa4
--- /dev/null
+++ b/runtime/neurun/backend/cpu_common/MemoryPlannerFactory.cc
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MemoryPlannerFactory.h"
+
+namespace neurun
+{
+namespace backend
+{
+namespace cpu_common
+{
+
+MemoryPlannerFactory &MemoryPlannerFactory::get()
+{
+ static MemoryPlannerFactory instance;
+ return instance;
+}
+
+IMemoryPlanner *MemoryPlannerFactory::create(const std::string &key)
+{
+ if (key == "FirstFit")
+ {
+ return new FirstFitPlanner;
+ }
+ else if (key == "Bump")
+ {
+ return new BumpPlanner;
+ }
+ else if (key == "WIC")
+ {
+ return new WICPlanner;
+ }
+ return new FirstFitPlanner; // Default Planner
+}
+
+} // namespace cpu_common
+} // namespace backend
+} // namespace neurun
diff --git a/runtime/neurun/backend/cpu_common/MemoryPlannerFactory.h b/runtime/neurun/backend/cpu_common/MemoryPlannerFactory.h
new file mode 100644
index 000000000..829600e27
--- /dev/null
+++ b/runtime/neurun/backend/cpu_common/MemoryPlannerFactory.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NEURUN_BACKEND_CPU_COMMON_MEMORY_PLANNER_FACTORY_H__
+#define __NEURUN_BACKEND_CPU_COMMON_MEMORY_PLANNER_FACTORY_H__
+
+#include "MemoryPlanner.h"
+
+namespace neurun
+{
+namespace backend
+{
+namespace cpu_common
+{
+
+class MemoryPlannerFactory
+{
+public:
+ static MemoryPlannerFactory &get();
+
+private:
+ MemoryPlannerFactory() = default;
+
+public:
+ IMemoryPlanner *create(const std::string &key);
+};
+
+} // namespace cpu_common
+} // namespace backend
+} // namespace neurun
+
+#endif // __NEURUN_BACKEND_CPU_COMMON_MEMORY_PLANNER_FACTORY_H__