echuraev commented on code in PR #14922:
URL: https://github.com/apache/tvm/pull/14922#discussion_r1205019553
##########
python/tvm/relay/op/contrib/clml.py:
##########
@@ -394,7 +447,7 @@ def check_default_op(extract):
("clml.minimum", is_op("minimum")(wildcard(), wildcard()),
check_binary_op),
("clml.maximum", is_op("maximum")(wildcard(), wildcard()),
check_binary_op),
("clml.softmax", is_op("nn.softmax")(wildcard()), check_softmax_op),
- ("clml.reshape", is_op("reshape")(wildcard()), check_default_op),
+ # ("clml.reshape", is_op("reshape")(wildcard()), check_default_op),
Review Comment:
Why did you comment this line? Probably it can be just removed?
##########
python/tvm/relay/op/contrib/clml.py:
##########
@@ -344,9 +373,19 @@ def check_conv_transpose(extract):
def check_binary_op(extract):
call = extract
- if len(call.args[1].checked_type.shape) > 0:
- return True
- return False
+ # Scalers are not supported
Review Comment:
```suggestion
# Scalars are not supported
```
##########
src/runtime/contrib/clml/clml_utils.cc:
##########
@@ -0,0 +1,258 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 src/runtime/contrib/clml/clml_utils.cc
+ * \brief Utilities.
+ */
+#ifdef TVM_GRAPH_EXECUTOR_CLML
+#include "clml_utils.h"
+
+namespace tvm {
+namespace runtime {
+namespace contrib {
+
+using namespace tvm::runtime::json;
+using JSONGraphNode = tvm::runtime::json::JSONGraphNode;
+
+/*!
+ * \brief Copy utility to CLML Tensor.
+ *
+ * \param tensor CLML tensor descriptor
+ * \param data pointer to host data
+ * \param layout host data layout
+ */
+void CopyDataToCLMLTensor(std::shared_ptr<cl_ml_tensor_memory_desc_qcom>
tensor, void* data,
+ cl_ml_tensor_layout_qcom layout) {
+ cl_int result = 0;
+ cl_event evt = nullptr;
+ result = CLML_INTF->clEnqueueWriteMLTensorDataQCOM(CLML_QUEUE, data, layout,
tensor->tensor,
+ tensor->memory,
+ 0, // n waitlist
+ nullptr, // waitlist
+ &evt); // event
+ ICHECK((evt != nullptr) && result == CL_SUCCESS) <<
"clEnqueueWriteMLTensorDataQCOM:" << result;
+}
+
+/*!
+ * \brief Copy utility from CLML tensor.
+ *
+ * \param tensor CLML tensor descriptor
+ * \param data pointer to host data
+ * \param layout expectred host data layout
+ */
+void CopyDataFromCLMLTensor(std::shared_ptr<cl_ml_tensor_memory_desc_qcom>
tensor, void* data,
+ cl_ml_tensor_layout_qcom layout) {
+ cl_int result = 0;
+ cl_event readEvent = nullptr;
+ // Read the output tensor
+ result = CLML_INTF->clEnqueueReadMLTensorDataQCOM(CLML_QUEUE,
tensor->tensor, tensor->memory,
+ data, layout,
+ 0, // n waitlist
+ nullptr, // waitlist
+ &readEvent); // event
+ ICHECK(result == CL_SUCCESS) << "clEnqueueReadMLTensorDataQCOM:" << result;
+
+ result = clWaitForEvents(1, &readEvent);
+ ICHECK(result == CL_SUCCESS) << "clWaitForEvents:" << result;
+}
+
+/*!
+ * \brief Make a CLML tensor given it's attributes
+ *
+ * \param context OpenCL context
+ * \param dims Tensor dimensions
+ * \param layout CLML tensor layout of tensor
+ * \param dtype Tensor data type
+ * \return CLML tensor
+ */
+cl_ml_tensor_qcom DeviceMakeCLMLTensor(cl_context context, tensor_dims_t dims,
+ cl_ml_tensor_layout_qcom layout,
cl_channel_type dtype) {
+ cl_ml_tensor_qcom tensor;
+ cl_int result = CL_OUT_OF_RESOURCES;
+
+ cl_ml_tensor_desc_qcom desc = {
+ dtype, layout, dims.n, dims.c, dims.h, dims.w, 0,
CL_TENSOR_DIMENSIONS_4D_QCOM, {0}};
+ result = CLML_INTF->clCreateMLTensorQCOM(CLML_CTX, nullptr, &desc, &tensor);
+ ICHECK(tensor && result == CL_SUCCESS) << "clCreateMLTensorQCOM:" << result;
+ (void)result;
Review Comment:
Why do you need this line?
##########
src/runtime/contrib/clml/clml_memory_planner.cc:
##########
@@ -0,0 +1,269 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 src/runtime/contrib/clml/clml_memory_planner.cc
+ * \brief Various memory planning methods.
+ */
+#ifdef TVM_GRAPH_EXECUTOR_CLML
+#include "clml_memory_planner.h"
+
+#include <map>
+#include <utility>
+
+#include "clml_utils.h"
+
+namespace tvm {
+namespace runtime {
+namespace contrib {
+
+using namespace tvm::runtime::json;
+using JSONGraphNode = tvm::runtime::json::JSONGraphNode;
+
+/*!
+ * Release memory after use.
+ *
+ */
+void FreeMemory(CachedLayer* layer, int nid) {
+ LOG_MEM << "FreeMemory:" << nid;
+ if (layer->storage_ref_map.find(nid) != layer->storage_ref_map.end()) {
+ LOG_MEM << "Ref Cnt:" << layer->storage_ref_map[nid];
+ layer->storage_ref_map[nid]--;
+ if (0 == layer->storage_ref_map[nid]) {
+ LOG_MEM << "Ref Cnt Nill";
+ // Look into on-chip allocation
+ for (auto it = layer->on_chip_pool_alloc_info.begin();
+ it != layer->on_chip_pool_alloc_info.end(); it++) {
+ if (it->second == nid) {
+ LOG_MEM << "Free Segment:" << it->first << " Nid:" << nid;
+ layer->in_chip_total_free += layer->on_chip_pool_size[it->first];
+ layer->in_chip_total_alloc -= layer->on_chip_pool_size[it->first];
+ layer->on_chip_pool_alloc_info.erase(it->first);
+ return;
+ }
+ }
+ // Look into DDR allocation
+ if (layer->ddr_alloc_plan.find(nid) != layer->ddr_alloc_plan.end()) {
+ LOG_MEM << "Free DDR segment from local pool";
+ layer->ddr_storage_ref_map[layer->ddr_alloc_plan[nid]].second = false;
+ return;
+ }
+ LOG_MEM << "*** Not a managed memory buffer";
+ }
+ } else {
+ LOG_MEM << "Not in storage ref map :" << nid;
+ }
+}
+
+/*!
+ * \brief Partition and allocate
+ *
+ */
+size_t PartitionAndAllocate(CachedLayer* layer, size_t segment_start, size_t
size, bool is_left) {
+ LOG_MEM << "PartitionAndAllocate:" << segment_start << " Size:" << size
+ << " Is Begin:" << is_left;
+ size_t segment_size = layer->on_chip_pool_size[segment_start];
+ size_t left_space = segment_size - size;
+
+ layer->in_chip_total_free -= size;
+ layer->in_chip_total_alloc += size;
+
+ if (is_left) {
+ // Start allocation
+ layer->on_chip_pool_size[segment_start] = size;
+ if (left_space) {
+ layer->on_chip_pool_size.insert({segment_start + size, left_space});
+ }
+ return segment_start;
+ } else {
+ // End allocation
+ if (left_space) {
+ layer->on_chip_pool_size[segment_start] = left_space;
+ }
+ layer->on_chip_pool_size.insert({segment_start + left_space, size});
+ return segment_start + left_space;
+ }
+}
+
+/*!
+ * \brief Ping-Pong allocation with in best fit
+ *
+ */
+size_t PingPongAllocate(CachedLayer* layer, const std::map<size_t, size_t>&
segments, size_t size) {
+ /*
+ * segments contains all free segments details (start, size) that can fit
the requirement
+ * PingPong Allocation Strategy:
+ * Here we find the smallest segment among all.
+ * We allocate at begining or end of this segment based on the ping-pong
flag.
+ * Ping-pong allocation helps to have largest possible free segment at center
+ * for most of the graphs.
+ *
+ */
+ ssize_t free_start;
+ ssize_t free_size;
+ ssize_t last_found_size = CLMLWorkspace::Global()->onchip_mem_size + 1;
+
+ for (auto it = segments.begin(); it != segments.end(); it++) {
+ if (it->second < last_found_size) {
+ free_start = it->first;
+ free_size = it->second;
+ last_found_size = it->second;
+ LOG_MEM << "Mem Found:" << free_start << " Size:" << free_size;
+ }
+ }
+
+ LOG_MEM << "Alloc On-chip Mem:" << free_start << " Size:" << free_size
+ << " PingPong:" << layer->alloc_ping_pong;
+
+ // Allocate on-chip memory
+ layer->alloc_ping_pong ^= 1;
+ return PartitionAndAllocate(layer, free_start, size, layer->alloc_ping_pong);
+}
+
+/*!
+ * \brief Allocate on-chip memory.
+ *
+ */
+size_t RequestOnChipMemory(CachedLayer* layer, size_t size) {
+ LOG_MEM << "Request On-Chip Mem:" << size;
+ // Optimize for any fragmented parts
+ bool any_merge = true;
+ while (any_merge) {
+ any_merge = false;
+ for (auto it = layer->on_chip_pool_size.begin(); it !=
layer->on_chip_pool_size.end(); it++) {
+ if ((layer->on_chip_pool_alloc_info.find(it->first) ==
+ layer->on_chip_pool_alloc_info.end()) &&
+ (layer->on_chip_pool_alloc_info.find(it->first + it->second) ==
+ layer->on_chip_pool_alloc_info.end()) &&
+ (it->first + it->second < CLMLWorkspace::Global()->onchip_mem_size))
{
+ size_t left_begin = it->first;
+ size_t left_size = it->second;
+ size_t right_size = layer->on_chip_pool_size[it->first + it->second];
+ LOG_MEM << "Merge:" << left_begin << " Size:" << left_size << " with
:" << right_size;
+ layer->on_chip_pool_size[left_begin] = left_size + right_size;
+ layer->on_chip_pool_size.erase(left_begin + left_size);
+ any_merge = true;
+ break;
+ }
+ }
+ }
+
+ // Look for any best fit free fragment
+ std::map<size_t, size_t> feasible_segments;
+ for (auto it = layer->on_chip_pool_size.begin(); it !=
layer->on_chip_pool_size.end(); it++) {
+ if (layer->on_chip_pool_alloc_info.find(it->first) ==
layer->on_chip_pool_alloc_info.end()) {
+ if (it->second >= size) {
+ LOG_MEM << "Mem Pool:" << it->first << " - " << it->first + it->second
<< ":" << it->second
+ << " - Free";
+ feasible_segments.insert({it->first, it->second});
+ } else {
+ LOG_MEM << "Mem Pool:" << it->first << " - " << it->first + it->second
<< ":" << it->second
+ << " - Doesn't fit";
+ }
+ } else {
+ LOG_MEM << "Mem Pool:" << it->first << " - " << it->first + it->second
<< ":" << it->second
+ << " - Busy";
+ }
+ }
+ if (0 == feasible_segments.size()) {
+ LOG_MEM << "No Suitable Mem Found:" << size << " Free Size:" <<
layer->in_chip_total_free;
+ if (size <= layer->in_chip_total_free) {
+ LOG_STATS << "*** ALERT ***: Couldn't allocate due to fragmentation:" <<
size
+ << " Total Free:" << layer->in_chip_total_free;
+ layer->on_chip_alert_fail += size;
+ }
+ return -1;
+ }
+
+ return PingPongAllocate(layer, feasible_segments, size);
+}
+
+/*!
+ * \brief Allocate DDR memory for requested size.
+ *
+ */
+cl_mem RequestDDRMemory(CachedLayer* layer, size_t size) {
+ // Look for local storage map for a best fit
+ auto cws = CLMLWorkspace::Global();
+ cl_mem memptr = nullptr;
+ size_t best_fit = INT_MAX;
+ for (auto it = layer->ddr_storage_ref_map.begin(); it !=
layer->ddr_storage_ref_map.end(); it++) {
+ if ((it->second.first >= size) && (false == it->second.second)) {
+ if (best_fit > it->second.first) {
+ memptr = it->first;
+ best_fit = it->second.first;
+ }
+ }
+ }
+
+ if (memptr) {
+ LOG_MEM << "Reuse from local pool";
+ layer->ddr_storage_ref_map[memptr].second = true;
+ return memptr;
+ } else {
+ // No available buffer in local pool, look for global pool
+ for (auto it = cws->ddr_global_pool.begin(); it !=
cws->ddr_global_pool.end(); it++) {
+ if ((it->second.first >= size) &&
+ (layer->ddr_storage_ref_map.find(it->first) ==
layer->ddr_storage_ref_map.end())) {
+ // Found a buffer in global pool. Insert in local pool and then use.
+ if (best_fit > it->second.first) {
+ memptr = it->first;
+ best_fit = it->second.first;
+ }
+ }
+ }
+ }
Review Comment:
```suggestion
}
// No available buffer in local pool, look for global pool
for (auto it = cws->ddr_global_pool.begin(); it !=
cws->ddr_global_pool.end(); it++) {
if ((it->second.first >= size) &&
(layer->ddr_storage_ref_map.find(it->first) ==
layer->ddr_storage_ref_map.end())) {
// Found a buffer in global pool. Insert in local pool and then use.
if (best_fit > it->second.first) {
memptr = it->first;
best_fit = it->second.first;
}
}
}
```
##########
src/runtime/contrib/clml/clml_runtime.cc:
##########
@@ -198,7 +229,7 @@ class CLMLRuntime : public JSONRuntimeBase {
if (header != kTVMCLMLTuningCacheMagic) break;
if (!strm->Read(&reserve)) break;
if (!strm->Read(&tune_symbol)) break;
- LOG(INFO) << "Tuning Cache Symbol:" << tune_symbol;
+ // LOG(INFO) << "Tuning Cache Symbol:" << tune_symbol;
Review Comment:
Probably can be removed?
##########
src/runtime/contrib/clml/clml_memory_planner.cc:
##########
@@ -0,0 +1,269 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 src/runtime/contrib/clml/clml_memory_planner.cc
+ * \brief Various memory planning methods.
+ */
+#ifdef TVM_GRAPH_EXECUTOR_CLML
+#include "clml_memory_planner.h"
+
+#include <map>
+#include <utility>
+
+#include "clml_utils.h"
+
+namespace tvm {
+namespace runtime {
+namespace contrib {
+
+using namespace tvm::runtime::json;
+using JSONGraphNode = tvm::runtime::json::JSONGraphNode;
+
+/*!
+ * Release memory after use.
+ *
+ */
+void FreeMemory(CachedLayer* layer, int nid) {
+ LOG_MEM << "FreeMemory:" << nid;
+ if (layer->storage_ref_map.find(nid) != layer->storage_ref_map.end()) {
+ LOG_MEM << "Ref Cnt:" << layer->storage_ref_map[nid];
+ layer->storage_ref_map[nid]--;
+ if (0 == layer->storage_ref_map[nid]) {
+ LOG_MEM << "Ref Cnt Nill";
+ // Look into on-chip allocation
+ for (auto it = layer->on_chip_pool_alloc_info.begin();
+ it != layer->on_chip_pool_alloc_info.end(); it++) {
+ if (it->second == nid) {
+ LOG_MEM << "Free Segment:" << it->first << " Nid:" << nid;
+ layer->in_chip_total_free += layer->on_chip_pool_size[it->first];
+ layer->in_chip_total_alloc -= layer->on_chip_pool_size[it->first];
+ layer->on_chip_pool_alloc_info.erase(it->first);
+ return;
+ }
+ }
+ // Look into DDR allocation
+ if (layer->ddr_alloc_plan.find(nid) != layer->ddr_alloc_plan.end()) {
+ LOG_MEM << "Free DDR segment from local pool";
+ layer->ddr_storage_ref_map[layer->ddr_alloc_plan[nid]].second = false;
+ return;
+ }
+ LOG_MEM << "*** Not a managed memory buffer";
+ }
+ } else {
+ LOG_MEM << "Not in storage ref map :" << nid;
+ }
+}
+
+/*!
+ * \brief Partition and allocate
+ *
+ */
+size_t PartitionAndAllocate(CachedLayer* layer, size_t segment_start, size_t
size, bool is_left) {
+ LOG_MEM << "PartitionAndAllocate:" << segment_start << " Size:" << size
+ << " Is Begin:" << is_left;
+ size_t segment_size = layer->on_chip_pool_size[segment_start];
+ size_t left_space = segment_size - size;
+
+ layer->in_chip_total_free -= size;
+ layer->in_chip_total_alloc += size;
+
+ if (is_left) {
+ // Start allocation
+ layer->on_chip_pool_size[segment_start] = size;
+ if (left_space) {
+ layer->on_chip_pool_size.insert({segment_start + size, left_space});
+ }
+ return segment_start;
+ } else {
+ // End allocation
+ if (left_space) {
+ layer->on_chip_pool_size[segment_start] = left_space;
+ }
+ layer->on_chip_pool_size.insert({segment_start + left_space, size});
+ return segment_start + left_space;
+ }
+}
+
+/*!
+ * \brief Ping-Pong allocation with in best fit
+ *
+ */
+size_t PingPongAllocate(CachedLayer* layer, const std::map<size_t, size_t>&
segments, size_t size) {
+ /*
+ * segments contains all free segments details (start, size) that can fit
the requirement
+ * PingPong Allocation Strategy:
+ * Here we find the smallest segment among all.
+ * We allocate at begining or end of this segment based on the ping-pong
flag.
+ * Ping-pong allocation helps to have largest possible free segment at center
+ * for most of the graphs.
+ *
+ */
+ ssize_t free_start;
+ ssize_t free_size;
+ ssize_t last_found_size = CLMLWorkspace::Global()->onchip_mem_size + 1;
+
+ for (auto it = segments.begin(); it != segments.end(); it++) {
+ if (it->second < last_found_size) {
+ free_start = it->first;
+ free_size = it->second;
+ last_found_size = it->second;
+ LOG_MEM << "Mem Found:" << free_start << " Size:" << free_size;
+ }
+ }
+
+ LOG_MEM << "Alloc On-chip Mem:" << free_start << " Size:" << free_size
+ << " PingPong:" << layer->alloc_ping_pong;
+
+ // Allocate on-chip memory
+ layer->alloc_ping_pong ^= 1;
+ return PartitionAndAllocate(layer, free_start, size, layer->alloc_ping_pong);
+}
+
+/*!
+ * \brief Allocate on-chip memory.
+ *
+ */
+size_t RequestOnChipMemory(CachedLayer* layer, size_t size) {
+ LOG_MEM << "Request On-Chip Mem:" << size;
+ // Optimize for any fragmented parts
+ bool any_merge = true;
+ while (any_merge) {
+ any_merge = false;
+ for (auto it = layer->on_chip_pool_size.begin(); it !=
layer->on_chip_pool_size.end(); it++) {
+ if ((layer->on_chip_pool_alloc_info.find(it->first) ==
+ layer->on_chip_pool_alloc_info.end()) &&
+ (layer->on_chip_pool_alloc_info.find(it->first + it->second) ==
+ layer->on_chip_pool_alloc_info.end()) &&
+ (it->first + it->second < CLMLWorkspace::Global()->onchip_mem_size))
{
+ size_t left_begin = it->first;
+ size_t left_size = it->second;
+ size_t right_size = layer->on_chip_pool_size[it->first + it->second];
+ LOG_MEM << "Merge:" << left_begin << " Size:" << left_size << " with
:" << right_size;
+ layer->on_chip_pool_size[left_begin] = left_size + right_size;
+ layer->on_chip_pool_size.erase(left_begin + left_size);
+ any_merge = true;
+ break;
+ }
+ }
+ }
+
+ // Look for any best fit free fragment
+ std::map<size_t, size_t> feasible_segments;
+ for (auto it = layer->on_chip_pool_size.begin(); it !=
layer->on_chip_pool_size.end(); it++) {
+ if (layer->on_chip_pool_alloc_info.find(it->first) ==
layer->on_chip_pool_alloc_info.end()) {
+ if (it->second >= size) {
+ LOG_MEM << "Mem Pool:" << it->first << " - " << it->first + it->second
<< ":" << it->second
+ << " - Free";
+ feasible_segments.insert({it->first, it->second});
+ } else {
+ LOG_MEM << "Mem Pool:" << it->first << " - " << it->first + it->second
<< ":" << it->second
+ << " - Doesn't fit";
+ }
+ } else {
+ LOG_MEM << "Mem Pool:" << it->first << " - " << it->first + it->second
<< ":" << it->second
+ << " - Busy";
+ }
+ }
+ if (0 == feasible_segments.size()) {
+ LOG_MEM << "No Suitable Mem Found:" << size << " Free Size:" <<
layer->in_chip_total_free;
+ if (size <= layer->in_chip_total_free) {
+ LOG_STATS << "*** ALERT ***: Couldn't allocate due to fragmentation:" <<
size
+ << " Total Free:" << layer->in_chip_total_free;
+ layer->on_chip_alert_fail += size;
+ }
+ return -1;
+ }
+
+ return PingPongAllocate(layer, feasible_segments, size);
+}
+
+/*!
+ * \brief Allocate DDR memory for requested size.
+ *
+ */
+cl_mem RequestDDRMemory(CachedLayer* layer, size_t size) {
+ // Look for local storage map for a best fit
+ auto cws = CLMLWorkspace::Global();
+ cl_mem memptr = nullptr;
+ size_t best_fit = INT_MAX;
+ for (auto it = layer->ddr_storage_ref_map.begin(); it !=
layer->ddr_storage_ref_map.end(); it++) {
+ if ((it->second.first >= size) && (false == it->second.second)) {
+ if (best_fit > it->second.first) {
+ memptr = it->first;
+ best_fit = it->second.first;
+ }
+ }
+ }
+
+ if (memptr) {
+ LOG_MEM << "Reuse from local pool";
+ layer->ddr_storage_ref_map[memptr].second = true;
+ return memptr;
+ } else {
+ // No available buffer in local pool, look for global pool
+ for (auto it = cws->ddr_global_pool.begin(); it !=
cws->ddr_global_pool.end(); it++) {
+ if ((it->second.first >= size) &&
+ (layer->ddr_storage_ref_map.find(it->first) ==
layer->ddr_storage_ref_map.end())) {
+ // Found a buffer in global pool. Insert in local pool and then use.
+ if (best_fit > it->second.first) {
+ memptr = it->first;
+ best_fit = it->second.first;
+ }
+ }
+ }
+ }
+
+ if (memptr) {
+ LOG_MEM << "Reuse from global pool";
+ cws->ddr_global_pool[memptr].second += 1;
+ layer->ddr_storage_ref_map.insert(
+ {memptr, std::make_pair(cws->ddr_global_pool[memptr].first, true)});
+ return memptr;
+ } else {
+ // Allocate a fresh buffer in global then use in local pool.
+ LOG_MEM << "Allocating fresh buffer in global pool";
+ memptr = AllocateDDRTensorMemory(size);
+ cws->ddr_global_pool.insert({memptr, std::make_pair(size, 1)});
+ layer->ddr_storage_ref_map.insert({memptr, std::make_pair(size, true)});
+ }
Review Comment:
```suggestion
}
// Allocate a fresh buffer in global then use in local pool.
LOG_MEM << "Allocating fresh buffer in global pool";
memptr = AllocateDDRTensorMemory(size);
cws->ddr_global_pool.insert({memptr, std::make_pair(size, 1)});
layer->ddr_storage_ref_map.insert({memptr, std::make_pair(size, true)});
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]