From 701a63b693bc877fc44abd802a9b2a431d81cfbe Mon Sep 17 00:00:00 2001 From: Jens Elofsson Date: Sun, 23 May 2021 17:37:07 +0200 Subject: Add Event Recorder Profiling * Add event recorded profiling to ethosu_profiler. * Rename ethosu_profiler to layer_by_layer_profiler. Change-Id: Ie39c29845b2d1eb6d9d72e3fce68bf373e9dc888 --- applications/inference_process/CMakeLists.txt | 4 +- .../inference_process/src/inference_process.cpp | 4 +- event_recorder.cmake | 13 ++- lib/CMakeLists.txt | 5 +- lib/ethosu_monitor/include/RTE_Components.h | 23 ---- lib/ethosu_profiler/CMakeLists.txt | 26 ----- lib/ethosu_profiler/include/ethosu_profiler.hpp | 49 --------- lib/ethosu_profiler/src/ethosu_profiler.cpp | 112 ------------------- lib/layer_by_layer_profiler/CMakeLists.txt | 26 +++++ .../include/layer_by_layer_profiler.hpp | 56 ++++++++++ .../src/layer_by_layer_profiler.cpp | 121 +++++++++++++++++++++ lib/rte_component/include/RTE_Components.h | 24 ++++ 12 files changed, 240 insertions(+), 223 deletions(-) delete mode 100644 lib/ethosu_monitor/include/RTE_Components.h delete mode 100644 lib/ethosu_profiler/CMakeLists.txt delete mode 100644 lib/ethosu_profiler/include/ethosu_profiler.hpp delete mode 100644 lib/ethosu_profiler/src/ethosu_profiler.cpp create mode 100644 lib/layer_by_layer_profiler/CMakeLists.txt create mode 100644 lib/layer_by_layer_profiler/include/layer_by_layer_profiler.hpp create mode 100644 lib/layer_by_layer_profiler/src/layer_by_layer_profiler.cpp create mode 100644 lib/rte_component/include/RTE_Components.h diff --git a/applications/inference_process/CMakeLists.txt b/applications/inference_process/CMakeLists.txt index 4bd75c4..1378181 100644 --- a/applications/inference_process/CMakeLists.txt +++ b/applications/inference_process/CMakeLists.txt @@ -24,8 +24,8 @@ target_include_directories(inference_process PUBLIC include PRIVATE ${TENSORFLOW_PATH} ${TENSORFLOW_PATH}/tensorflow/lite/micro/tools/make/downloads/flatbuffers/include) target_link_libraries(inference_process PRIVATE tflu cmsis_core cmsis_device) -if (TARGET ethosu_profiler) - target_link_libraries(inference_process PRIVATE ethosu_profiler) +if (TARGET layer_by_layer_profiler) + target_link_libraries(inference_process PRIVATE layer_by_layer_profiler) endif() if (TARGET arm_profiler) target_link_libraries(inference_process PRIVATE arm_profiler) diff --git a/applications/inference_process/src/inference_process.cpp b/applications/inference_process/src/inference_process.cpp index 009706e..511a139 100644 --- a/applications/inference_process/src/inference_process.cpp +++ b/applications/inference_process/src/inference_process.cpp @@ -26,7 +26,7 @@ #include "arm_profiler.hpp" #ifdef ETHOSU -#include "ethosu_profiler.hpp" +#include "layer_by_layer_profiler.hpp" #endif #include "inference_process.hpp" @@ -202,7 +202,7 @@ bool InferenceProcess::runJob(InferenceJob &job) { // Create the TFL micro interpreter tflite::AllOpsResolver resolver; #ifdef ETHOSU - tflite::EthosUProfiler profiler; + tflite::LayerByLayerProfiler profiler; #else tflite::ArmProfiler profiler; #endif diff --git a/event_recorder.cmake b/event_recorder.cmake index 3823896..bb9efd9 100644 --- a/event_recorder.cmake +++ b/event_recorder.cmake @@ -16,17 +16,18 @@ # limitations under the License. # +add_library(rte_component INTERFACE) +target_include_directories(rte_component INTERFACE lib/rte_component/include) +target_link_libraries(rte_component INTERFACE cmsis_device) +target_compile_definitions(rte_component INTERFACE RTE_Components_CMSIS_device_header=\"${ARM_CPU}${ARM_FEATURES}.h\") + add_library(event_recorder INTERFACE) target_include_directories(event_recorder INTERFACE ${CMSIS_VIEW_PATH}/EventRecorder/Include ${CMSIS_VIEW_PATH}/EventRecorder/Config) -target_include_directories(event_recorder INTERFACE - ${CMSIS_VIEW_PATH}/EventRecorder/Config) +target_link_libraries(event_recorder INTERFACE rte_component) +target_sources(event_recorder INTERFACE ${CMSIS_VIEW_PATH}/EventRecorder/Source/EventRecorder.c) -target_link_libraries(event_recorder INTERFACE cmsis_device) -target_sources(event_recorder INTERFACE - ${CMSIS_VIEW_PATH}/EventRecorder/Source/EventRecorder.c) -target_compile_definitions(event_recorder INTERFACE RTE_Components_CMSIS_device_header=\"${ARM_CPU}${ARM_FEATURES}.h\") diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ae18806..5536949 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -16,12 +16,11 @@ # limitations under the License. # -# Build ethosu_profiler -add_subdirectory(ethosu_profiler) +# Build layer_by_layer_profiler +add_subdirectory(layer_by_layer_profiler) # Build arm_profiler add_subdirectory(arm_profiler) # Build ethosu_monitor add_subdirectory(ethosu_monitor) - diff --git a/lib/ethosu_monitor/include/RTE_Components.h b/lib/ethosu_monitor/include/RTE_Components.h deleted file mode 100644 index 97b6624..0000000 --- a/lib/ethosu_monitor/include/RTE_Components.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2021 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * 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 - * - * 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 RTE_COMPONENTS_H -#define RTE_COMPONENTS_H - -#define CMSIS_device_header RTE_Components_CMSIS_device_header - -#endif diff --git a/lib/ethosu_profiler/CMakeLists.txt b/lib/ethosu_profiler/CMakeLists.txt deleted file mode 100644 index 336a696..0000000 --- a/lib/ethosu_profiler/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# -# Copyright (c) 2021 Arm Limited. All rights reserved. -# -# SPDX-License-Identifier: Apache-2.0 -# -# 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 -# -# 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. -# - -if (NOT TARGET ethosu_core_driver) - return() -endif() -add_library(ethosu_profiler INTERFACE) - -target_link_libraries(ethosu_profiler INTERFACE ethosu_core_driver tflu) -target_include_directories(ethosu_profiler INTERFACE include) -target_sources(ethosu_profiler INTERFACE src/ethosu_profiler.cpp) diff --git a/lib/ethosu_profiler/include/ethosu_profiler.hpp b/lib/ethosu_profiler/include/ethosu_profiler.hpp deleted file mode 100644 index 12c337c..0000000 --- a/lib/ethosu_profiler/include/ethosu_profiler.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2021 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * 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 - * - * 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 ETHOSU_PROFILER_H -#define ETHOSU_PROFILER_H - -#include "tensorflow/lite/kernels/internal/compatibility.h" -#include -#include - -// NOTE: This profiler only works on systems with 1 NPU due to the use of -// ethosu_reserve_driver(). -namespace tflite { -class EthosUProfiler : public MicroProfiler { -public: - EthosUProfiler(size_t max_events = 200); - uint32_t BeginEvent(const char *tag); - void EndEvent(uint32_t event_handle); - uint64_t GetTotalTicks() const; - void Log() const; - -private: - size_t max_events_; - std::unique_ptr tags_; - std::unique_ptr start_ticks_; - std::unique_ptr end_ticks_; - size_t num_events_; - - TF_LITE_REMOVE_VIRTUAL_DELETE; -}; - -} // namespace tflite - -#endif diff --git a/lib/ethosu_profiler/src/ethosu_profiler.cpp b/lib/ethosu_profiler/src/ethosu_profiler.cpp deleted file mode 100644 index 50b65f0..0000000 --- a/lib/ethosu_profiler/src/ethosu_profiler.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2021 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * 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 - * - * 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 "tensorflow/lite/kernels/internal/compatibility.h" -#include "tensorflow/lite/micro/micro_error_reporter.h" -#include "tensorflow/lite/micro/micro_profiler.h" -#include "tensorflow/lite/micro/micro_time.h" - -#include - -#include "ethosu_profiler.hpp" -#include -#include -#include - -namespace { - -uint64_t GetCurrentEthosuTicks(struct ethosu_driver *drv) { - return ETHOSU_PMU_Get_CCNTR(drv); -} - -} // namespace - -namespace tflite { - -EthosUProfiler::EthosUProfiler(size_t max_events) : max_events_(max_events), num_events_(0) { - tags_ = std::make_unique(max_events_); - start_ticks_ = std::make_unique(max_events_); - end_ticks_ = std::make_unique(max_events_); - - struct ethosu_driver *drv = ethosu_reserve_driver(); - ETHOSU_PMU_CNTR_Enable(drv, ETHOSU_PMU_CCNT_Msk); - ETHOSU_PMU_CYCCNT_Reset(drv); - ethosu_release_driver(drv); -} - -// NOTE: THIS PROFILER ONLY WORKS ON SYSTEMS WITH 1 NPU -uint32_t EthosUProfiler::BeginEvent(const char *tag) { - if (num_events_ == max_events_) { - tflite::GetMicroErrorReporter()->Report("Profiling event overflow, max: %u events", max_events_); - num_events_ = 0; - } - - tags_[num_events_] = tag; - - if (strcmp("ethos-u", tag) == 0) { - struct ethosu_driver *ethosu_drv = ethosu_reserve_driver(); - ETHOSU_PMU_CYCCNT_Reset(ethosu_drv); - ETHOSU_PMU_PMCCNTR_CFG_Set_Start_Event(ethosu_drv, ETHOSU_PMU_NPU_ACTIVE); - ETHOSU_PMU_PMCCNTR_CFG_Set_Stop_Event(ethosu_drv, ETHOSU_PMU_NPU_IDLE); - start_ticks_[num_events_] = GetCurrentEthosuTicks(ethosu_drv); - ethosu_release_driver(ethosu_drv); - } else { - start_ticks_[num_events_] = GetCurrentTimeTicks(); - } - - end_ticks_[num_events_] = start_ticks_[num_events_] - 1; - return num_events_++; -} - -// NOTE: THIS PROFILER ONLY WORKS ON SYSTEMS WITH 1 NPU -void EthosUProfiler::EndEvent(uint32_t event_handle) { - TFLITE_DCHECK(event_handle < max_events_); - - if (strcmp("ethos-u", tags_[event_handle]) == 0) { - struct ethosu_driver *ethosu_drv = ethosu_reserve_driver(); - end_ticks_[event_handle] = GetCurrentEthosuTicks(ethosu_drv); - ethosu_release_driver(ethosu_drv); - } else { - end_ticks_[event_handle] = GetCurrentTimeTicks(); - } - - printf("%s : cycle_cnt : %" PRIu64 " cycles\n", - tags_[event_handle], - end_ticks_[event_handle] - start_ticks_[event_handle]); -} - -uint64_t EthosUProfiler::GetTotalTicks() const { - uint64_t ticks = 0; - - for (size_t i = 0; i < num_events_; ++i) { - ticks += end_ticks_[i] - start_ticks_[i]; - } - - return ticks; -} - -void EthosUProfiler::Log() const { -#if !defined(TF_LITE_STRIP_ERROR_STRINGS) - for (int i = 0; i < num_events_; ++i) { - uint64_t ticks = end_ticks_[i] - start_ticks_[i]; - printf("%s took %" PRIu64 " cycles\n", tags_[i], ticks); - } -#endif -} - -} // namespace tflite diff --git a/lib/layer_by_layer_profiler/CMakeLists.txt b/lib/layer_by_layer_profiler/CMakeLists.txt new file mode 100644 index 0000000..9774685 --- /dev/null +++ b/lib/layer_by_layer_profiler/CMakeLists.txt @@ -0,0 +1,26 @@ +# +# Copyright (c) 2021 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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 +# +# 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. +# + +if (NOT TARGET ethosu_core_driver) + return() +endif() + +add_library(layer_by_layer_profiler INTERFACE) +target_link_libraries(layer_by_layer_profiler INTERFACE ethosu_core_driver tflu event_recorder) +target_include_directories(layer_by_layer_profiler INTERFACE include) +target_sources(layer_by_layer_profiler INTERFACE src/layer_by_layer_profiler.cpp) diff --git a/lib/layer_by_layer_profiler/include/layer_by_layer_profiler.hpp b/lib/layer_by_layer_profiler/include/layer_by_layer_profiler.hpp new file mode 100644 index 0000000..8e8dc0f --- /dev/null +++ b/lib/layer_by_layer_profiler/include/layer_by_layer_profiler.hpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 + * + * 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 LAYER_BY_LAYER_PROFILER_H +#define LAYER_BY_LAYER_PROFILER_H + +#include "EventRecorder.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include +#include + +// NOTE: This profiler only works on systems with 1 NPU due to the use of +// ethosu_reserve_driver(). +namespace tflite { +class LayerByLayerProfiler : public MicroProfiler { +public: + enum Backend { PRINTF, EVENT_RECORDER }; + LayerByLayerProfiler(size_t max_events = 200, + Backend backend = PRINTF, + int32_t event_id = EventID(EventLevelError, EvtStatistics_No, EventRecordNone)); + uint32_t BeginEvent(const char *tag); + void EndEvent(uint32_t event_handle); + uint64_t GetTotalTicks() const; + void Log() const; + +private: + size_t max_events_; + std::unique_ptr tags_; + std::unique_ptr start_ticks_; + std::unique_ptr end_ticks_; + + Backend backend_; + int32_t event_id_; + size_t num_events_; + + TF_LITE_REMOVE_VIRTUAL_DELETE; +}; + +} // namespace tflite + +#endif diff --git a/lib/layer_by_layer_profiler/src/layer_by_layer_profiler.cpp b/lib/layer_by_layer_profiler/src/layer_by_layer_profiler.cpp new file mode 100644 index 0000000..f7922cb --- /dev/null +++ b/lib/layer_by_layer_profiler/src/layer_by_layer_profiler.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 + * + * 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 "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" +#include "tensorflow/lite/micro/micro_profiler.h" +#include "tensorflow/lite/micro/micro_time.h" + +#include + +#include "layer_by_layer_profiler.hpp" +#include +#include +#include + +namespace { + +uint64_t GetCurrentEthosuTicks(struct ethosu_driver *drv) { + return ETHOSU_PMU_Get_CCNTR(drv); +} + +} // namespace + +namespace tflite { + +LayerByLayerProfiler::LayerByLayerProfiler(size_t max_events, Backend backend, int32_t event_id) : + max_events_(max_events), backend_(backend), event_id_(event_id), num_events_(0) { + + tags_ = std::make_unique(max_events_); + start_ticks_ = std::make_unique(max_events_); + end_ticks_ = std::make_unique(max_events_); + + struct ethosu_driver *drv = ethosu_reserve_driver(); + ETHOSU_PMU_CNTR_Enable(drv, ETHOSU_PMU_CCNT_Msk); + ETHOSU_PMU_CYCCNT_Reset(drv); + ethosu_release_driver(drv); +} + +// NOTE: THIS PROFILER ONLY WORKS ON SYSTEMS WITH 1 NPU +uint32_t LayerByLayerProfiler::BeginEvent(const char *tag) { + if (num_events_ == max_events_) { + tflite::GetMicroErrorReporter()->Report("Profiling event overflow, max: %u events", max_events_); + num_events_ = 0; + } + + tags_[num_events_] = tag; + + if (strcmp("ethos-u", tag) == 0) { + struct ethosu_driver *ethosu_drv = ethosu_reserve_driver(); + ETHOSU_PMU_CYCCNT_Reset(ethosu_drv); + ETHOSU_PMU_PMCCNTR_CFG_Set_Start_Event(ethosu_drv, ETHOSU_PMU_NPU_ACTIVE); + ETHOSU_PMU_PMCCNTR_CFG_Set_Stop_Event(ethosu_drv, ETHOSU_PMU_NPU_IDLE); + start_ticks_[num_events_] = GetCurrentEthosuTicks(ethosu_drv); + ethosu_release_driver(ethosu_drv); + } else { + start_ticks_[num_events_] = GetCurrentTimeTicks(); + } + + end_ticks_[num_events_] = start_ticks_[num_events_] - 1; + return num_events_++; +} + +// NOTE: THIS PROFILER ONLY WORKS ON SYSTEMS WITH 1 NPU +void LayerByLayerProfiler::EndEvent(uint32_t event_handle) { + TFLITE_DCHECK(event_handle < max_events_); + + if (strcmp("ethos-u", tags_[event_handle]) == 0) { + struct ethosu_driver *ethosu_drv = ethosu_reserve_driver(); + end_ticks_[event_handle] = GetCurrentEthosuTicks(ethosu_drv); + ethosu_release_driver(ethosu_drv); + } else { + end_ticks_[event_handle] = GetCurrentTimeTicks(); + } + + if (backend_ == PRINTF) { + printf("%s : cycle_cnt : %" PRIu64 " cycles\n", + tags_[event_handle], + end_ticks_[event_handle] - start_ticks_[event_handle]); + } else { + EventRecord2(event_id_, (int32_t)event_handle, end_ticks_[event_handle] - start_ticks_[event_handle]); + } +} + +uint64_t LayerByLayerProfiler::GetTotalTicks() const { + uint64_t ticks = 0; + + for (size_t i = 0; i < num_events_; ++i) { + ticks += end_ticks_[i] - start_ticks_[i]; + } + + return ticks; +} + +void LayerByLayerProfiler::Log() const { + +#if !defined(TF_LITE_STRIP_ERROR_STRINGS) + if (backend_ == PRINTF) { + for (size_t i = 0; i < num_events_; ++i) { + uint64_t ticks = end_ticks_[i] - start_ticks_[i]; + printf("%s took %" PRIu64 " cycles\n", tags_[i], ticks); + } + } +#endif +} + +} // namespace tflite diff --git a/lib/rte_component/include/RTE_Components.h b/lib/rte_component/include/RTE_Components.h new file mode 100644 index 0000000..024f52b --- /dev/null +++ b/lib/rte_component/include/RTE_Components.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 + * + * 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 RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + +#define CMSIS_device_header RTE_Components_CMSIS_device_header + +#endif -- cgit v1.2.1