You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by "echuraev (via GitHub)" <gi...@apache.org> on 2023/06/01 06:41:51 UTC

[GitHub] [tvm] echuraev commented on a diff in pull request #14922: [OpenCLML] Reactor and introduce on chip memory and memory planner

echuraev commented on code in PR #14922:
URL: https://github.com/apache/tvm/pull/14922#discussion_r1212630411


##########
cmake/modules/OpenCL.cmake:
##########
@@ -59,20 +59,33 @@ if(USE_OPENCL)
     list(APPEND TVM_RUNTIME_LINKER_LIBS ${OpenCL_LIBRARIES})
   endif()
 
-  if(DEFINED USE_OPENCL_GTEST AND EXISTS ${USE_OPENCL_GTEST})
-    include(FetchContent)
-    FetchContent_Declare(googletest SOURCE_DIR "${USE_OPENCL_GTEST}")
-    set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
-    FetchContent_MakeAvailable(googletest)
-    install(TARGETS gtest EXPORT ${PROJECT_NAME}Targets DESTINATION lib${LIB_SUFFIX})
+  if(DEFINED USE_OPENCL_GTEST)
+    if(EXISTS ${USE_OPENCL_GTEST})
+        include(FetchContent)
+        FetchContent_Declare(googletest SOURCE_DIR "${USE_OPENCL_GTEST}")
+        set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+        FetchContent_MakeAvailable(googletest)
+        install(TARGETS gtest EXPORT ${PROJECT_NAME}Targets DESTINATION lib${LIB_SUFFIX})
 
-    message(STATUS "Found OpenCL gtest at ${USE_OPENCL_GTEST}")
+        message(STATUS "Found OpenCL gtest at ${USE_OPENCL_GTEST}")
+        set(Build_OpenCL_GTests ON)
+    elseif (ANDROID_ABI AND DEFINED ENV{ANDROID_NDK_HOME})
+        set(GOOGLETEST_ROOT $ENV{ANDROID_NDK_HOME}/sources/third_party/googletest)
+        add_library(gtest_main STATIC ${GOOGLETEST_ROOT}/src/gtest_main.cc ${GOOGLETEST_ROOT}/src/gtest-all.cc)
+        target_include_directories(gtest_main PRIVATE ${GOOGLETEST_ROOT})
+        target_include_directories(gtest_main PUBLIC ${GOOGLETEST_ROOT}/include)
+        message(STATUS "Using gtest from Android NDK")
+        set(Build_OpenCL_GTests ON)
+    endif()
 
-    tvm_file_glob(GLOB_RECURSE OPENCL_TEST_SRCS
-      "${CMAKE_SOURCE_DIR}/tests/cpp-runtime/opencl/*.cc"
-    )
-    add_executable(opencl-cpptest ${OPENCL_TEST_SRCS})
-    target_link_libraries(opencl-cpptest PRIVATE gtest_main tvm_runtime)
+    if(Build_OpenCL_GTests)
+        message(STATUS "Building OpenCL-Gtests")
+        tvm_file_glob(GLOB_RECURSE OPENCL_TEST_SRCS
+          "${CMAKE_SOURCE_DIR}/tests/cpp-runtime/opencl/*.cc"
+        )
+        add_executable(opencl-cpptest ${OPENCL_TEST_SRCS})
+        target_link_libraries(opencl-cpptest PRIVATE gtest_main tvm_runtime)
+    endif()

Review Comment:
   I suppose it might be useful to write a warning message in case when we cannot build OpenCL GTests.



##########
tests/cpp-runtime/opencl/clml_memory_planner.cc:
##########
@@ -0,0 +1,481 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+#include <tvm/runtime/container/optional.h>
+
+#if defined(TVM_GRAPH_EXECUTOR_CLML)
+#include "../src/runtime/contrib/clml/clml_memory_planner.h"
+#include "../src/runtime/contrib/clml/clml_runtime.h"
+#include "../src/runtime/opencl/opencl_common.h"
+#include "../src/runtime/texture.h"
+
+using namespace tvm::runtime;
+using namespace tvm::runtime::cl;
+
+void InitMemoryPlan(tvm::runtime::contrib::CachedLayer& layer) {
+  tvm::runtime::contrib::CLMLWorkspace* cws = tvm::runtime::contrib::CLMLWorkspace::Global();
+
+  layer.on_chip_pool_size.clear();
+  layer.on_chip_pool_size.insert({0, cws->onchip_mem_size});
+  layer.on_chip_pool_alloc_info.clear();
+  layer.alloc_ping_pong = true;
+  layer.in_chip_total_free = cws->onchip_mem_size;
+  layer.in_chip_total_alloc = 0;
+  layer.on_chip_alert_fail = 0;
+
+  for (auto it = cws->ddr_global_pool.begin(); it != cws->ddr_global_pool.end(); it++) {
+    clReleaseMemObject(it->first);
+  }
+  cws->ddr_global_pool.clear();
+}
+
+void PlanMemory(tvm::runtime::contrib::CachedLayer& layer, int total_nodes,
+                std::map<int, uint32_t>& tensor_sizes,
+                std::map<int, std::vector<int>>& input_tensors) {
+  tvm::runtime::contrib::CLMLWorkspace* cws = tvm::runtime::contrib::CLMLWorkspace::Global();
+
+  for (int nid = 0; nid < total_nodes; ++nid) {
+    uint32_t size = tensor_sizes[nid];
+    size_t offset = -1;
+    if (cws->is_on_chip_memory) {
+      LOG(WARNING) << "Requesting On-chip:" << nid;
+      offset = RequestOnChipMemory(&layer, size);
+    }
+    if (-1 != offset) {
+      LOG(WARNING) << "On Chip not found:" << nid;
+      layer.on_chip_pool_alloc_info.insert({offset, nid});
+      layer.on_chip_alloc_plan.insert({nid, std::make_pair(size, offset)});
+    } else {
+      LOG(WARNING) << "Requesting DDR memory:" << nid;
+      layer.on_chip_reject.insert({nid, size});
+      // DDR Allocation
+      auto ddr_mem = RequestDDRMemory(&layer, size);
+      layer.ddr_alloc_plan.insert({nid, ddr_mem});
+    }
+
+    // Now free up the input tensors on-chip memory for reuse.
+    for (auto& input_node : input_tensors[nid]) {
+      FreeMemory(&layer, input_node);
+    }
+  }
+
+#if 0
+  // Stats dump
+  size_t in_chip_total_alloc = 0;
+  size_t total_reject = 0;
+  for (auto it = layer.on_chip_alloc_plan.begin(); it != layer.on_chip_alloc_plan.end(); it++) {
+    LOG(WARNING) << " On-chip Alloc:" << it->first << " Size:" << it->second.first
+              << " Offset:" << it->second.second;
+    in_chip_total_alloc += it->second.first;
+  }
+
+  for (auto it = layer.on_chip_reject.begin(); it != layer.on_chip_reject.end(); it++) {
+    LOG(WARNING) << "Reject:" << it->first << " Size:" << it->second;
+    total_reject += it->second;
+  }
+  LOG(WARNING) << "Total On-chip Alloc:" << in_chip_total_alloc + total_reject
+            << " On-Chip:" << in_chip_total_alloc << " Reject:" << total_reject;
+
+  for (auto it = cws->ddr_global_pool.begin(); it != cws->ddr_global_pool.end(); it++) {
+    LOG(WARNING) << "DDR Global pool - size:" << it->second.first << " Ref:" << it->second.second;
+  }
+  for (auto it = layer.ddr_storage_ref_map.begin();
+       it != layer.ddr_storage_ref_map.end(); it++) {
+    LOG(WARNING) << "DDR Local pool - size:" << it->second.first << " Ref cnt:" << it->second.second;
+  }
+#endif
+}
+
+void CompareOnChipPlan(tvm::runtime::contrib::CachedLayer& layer,
+                       const std::vector<int>& on_chip_plan) {
+  for (auto& nid : on_chip_plan) {
+    EXPECT_EQ(layer.on_chip_alloc_plan.find(nid) == layer.on_chip_alloc_plan.end(), false);
+  }
+}
+
+void CompareDDRPlan(tvm::runtime::contrib::CachedLayer& layer, const std::vector<int>& ddr_plan) {
+  for (auto& nid : ddr_plan) {
+    EXPECT_EQ(layer.ddr_alloc_plan.find(nid) == layer.ddr_alloc_plan.end(), false);
+  }
+}
+
+TEST(CLMLMemoryPlanner, sequential_all_on_chip) {

Review Comment:
   You can use `TEST_F` instead of `TEST`. In this case, you can move all common parts to the test class. As an example, you can take a look at: https://github.com/apache/tvm/blob/main/tests/cpp-runtime/opencl/opencl_compile_to_bin.cc



##########
tests/cpp-runtime/opencl/clml_memory_planner.cc:
##########
@@ -0,0 +1,481 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+#include <tvm/runtime/container/optional.h>
+
+#if defined(TVM_GRAPH_EXECUTOR_CLML)
+#include "../src/runtime/contrib/clml/clml_memory_planner.h"
+#include "../src/runtime/contrib/clml/clml_runtime.h"
+#include "../src/runtime/opencl/opencl_common.h"
+#include "../src/runtime/texture.h"
+
+using namespace tvm::runtime;
+using namespace tvm::runtime::cl;
+
+void InitMemoryPlan(tvm::runtime::contrib::CachedLayer& layer) {
+  tvm::runtime::contrib::CLMLWorkspace* cws = tvm::runtime::contrib::CLMLWorkspace::Global();
+
+  layer.on_chip_pool_size.clear();
+  layer.on_chip_pool_size.insert({0, cws->onchip_mem_size});
+  layer.on_chip_pool_alloc_info.clear();
+  layer.alloc_ping_pong = true;
+  layer.in_chip_total_free = cws->onchip_mem_size;
+  layer.in_chip_total_alloc = 0;
+  layer.on_chip_alert_fail = 0;
+
+  for (auto it = cws->ddr_global_pool.begin(); it != cws->ddr_global_pool.end(); it++) {
+    clReleaseMemObject(it->first);
+  }
+  cws->ddr_global_pool.clear();
+}
+
+void PlanMemory(tvm::runtime::contrib::CachedLayer& layer, int total_nodes,
+                std::map<int, uint32_t>& tensor_sizes,
+                std::map<int, std::vector<int>>& input_tensors) {
+  tvm::runtime::contrib::CLMLWorkspace* cws = tvm::runtime::contrib::CLMLWorkspace::Global();
+
+  for (int nid = 0; nid < total_nodes; ++nid) {
+    uint32_t size = tensor_sizes[nid];
+    size_t offset = -1;
+    if (cws->is_on_chip_memory) {
+      LOG(WARNING) << "Requesting On-chip:" << nid;
+      offset = RequestOnChipMemory(&layer, size);
+    }
+    if (-1 != offset) {
+      LOG(WARNING) << "On Chip not found:" << nid;
+      layer.on_chip_pool_alloc_info.insert({offset, nid});
+      layer.on_chip_alloc_plan.insert({nid, std::make_pair(size, offset)});
+    } else {
+      LOG(WARNING) << "Requesting DDR memory:" << nid;
+      layer.on_chip_reject.insert({nid, size});
+      // DDR Allocation
+      auto ddr_mem = RequestDDRMemory(&layer, size);
+      layer.ddr_alloc_plan.insert({nid, ddr_mem});
+    }
+
+    // Now free up the input tensors on-chip memory for reuse.
+    for (auto& input_node : input_tensors[nid]) {
+      FreeMemory(&layer, input_node);
+    }
+  }
+
+#if 0
+  // Stats dump
+  size_t in_chip_total_alloc = 0;
+  size_t total_reject = 0;
+  for (auto it = layer.on_chip_alloc_plan.begin(); it != layer.on_chip_alloc_plan.end(); it++) {
+    LOG(WARNING) << " On-chip Alloc:" << it->first << " Size:" << it->second.first
+              << " Offset:" << it->second.second;
+    in_chip_total_alloc += it->second.first;
+  }
+
+  for (auto it = layer.on_chip_reject.begin(); it != layer.on_chip_reject.end(); it++) {
+    LOG(WARNING) << "Reject:" << it->first << " Size:" << it->second;
+    total_reject += it->second;
+  }
+  LOG(WARNING) << "Total On-chip Alloc:" << in_chip_total_alloc + total_reject
+            << " On-Chip:" << in_chip_total_alloc << " Reject:" << total_reject;
+
+  for (auto it = cws->ddr_global_pool.begin(); it != cws->ddr_global_pool.end(); it++) {
+    LOG(WARNING) << "DDR Global pool - size:" << it->second.first << " Ref:" << it->second.second;
+  }
+  for (auto it = layer.ddr_storage_ref_map.begin();
+       it != layer.ddr_storage_ref_map.end(); it++) {
+    LOG(WARNING) << "DDR Local pool - size:" << it->second.first << " Ref cnt:" << it->second.second;
+  }
+#endif

Review Comment:
   Do you really need this debug part?



##########
tests/cpp-runtime/opencl/clml_memory_planner.cc:
##########
@@ -0,0 +1,481 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+#include <tvm/runtime/container/optional.h>
+
+#if defined(TVM_GRAPH_EXECUTOR_CLML)
+#include "../src/runtime/contrib/clml/clml_memory_planner.h"
+#include "../src/runtime/contrib/clml/clml_runtime.h"
+#include "../src/runtime/opencl/opencl_common.h"
+#include "../src/runtime/texture.h"
+
+using namespace tvm::runtime;
+using namespace tvm::runtime::cl;
+
+void InitMemoryPlan(tvm::runtime::contrib::CachedLayer& layer) {

Review Comment:
   I saw that in class `CLMLRuntime` you have almost the same methods. Probably it is better to test them? You can change `private` to `protected` and inherit `CLMLRuntime` class in your test class. It should be like a test wrapper above `CLMLRuntime` class.



-- 
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: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org