From 8866557c1f651445f6a51de43687010149c06ac1 Mon Sep 17 00:00:00 2001 From: Ben Clark Date: Tue, 15 Oct 2024 16:50:55 +0100 Subject: [PATCH 01/17] temp for moving laptops --- .../profiling-ml-on-arm/Streamline.png | Bin 0 -> 128971 bytes .../profiling-ml-on-arm/_index.md | 39 ++++ .../profiling-ml-on-arm/_next-steps.md | 27 +++ .../profiling-ml-on-arm/_review.md | 45 ++++ .../app-profiling-android-studio.md | 13 ++ .../app-profiling-streamline.md | 200 ++++++++++++++++++ .../profiling-ml-on-arm/example-picture.png | Bin 0 -> 63167 bytes .../nn-profiling-executenetwork.md | 13 ++ .../nn-profiling-general.md | 13 ++ .../profiling-ml-on-arm/plan.txt | 20 ++ .../profiling-ml-on-arm/why-profile.md | 23 ++ 11 files changed, 393 insertions(+) create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/Streamline.png create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_next-steps.md create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/example-picture.png create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/plan.txt create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/Streamline.png b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/Streamline.png new file mode 100644 index 0000000000000000000000000000000000000000..e02ea645ce7d20f24944ba14174c2fb1ad0d6d17 GIT binary patch literal 128971 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�B(BOE^@J&KdUc|8N8v1AuWo-d)IIb3%DNU=&#> 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 + PLACEHOLDER QUESTION 1? + answers: + - PLACEHOLDER ANSWER A + - PLACEHOLDER ANSWER B + correct_answer: 1 + explanation: > + PLACEHOLDER EXPLANATION 1 + + - questions: + question: > + PLACEHOLDER QUESTION 2? + answers: + - PLACEHOLDER ANSWER A + - PLACEHOLDER ANSWER B + - PLACEHOLDER ANSWER C + - PLACEHOLDER ANSWER D + correct_answer: 4 + explanation: > + PLACEHOLDER EXPLANATION 2 + + - questions: + question: > + PLACEHOLDER QUESTION 3? + answers: + - PLACEHOLDER ANSWER A + - PLACEHOLDER ANSWER B + - PLACEHOLDER ANSWER C + - PLACEHOLDER ANSWER D + correct_answer: 2 + explanation: > + PLACEHOLDER EXPLANATION 3 + + + +# ================================================================================ +# FIXED, DO NOT MODIFY +# ================================================================================ +title: "Review" # Always the same title +weight: 20 # Set to always be larger than the content in this path +layout: "learningpathall" # All files under learning paths have this same wrapper +--- diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md new file mode 100644 index 000000000..1d63e0df0 --- /dev/null +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md @@ -0,0 +1,13 @@ +--- +title: App Profiling with Android Studio +weight: 4 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## PLACEHOLDER HEADER OF SECOND STEP +YOUR CONTENT GOES HERE + +IMAGE HERE: +![example image alt-text#center](example-picture.png "Figure 1. Example image caption") diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md new file mode 100644 index 000000000..65ccd6eb7 --- /dev/null +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md @@ -0,0 +1,200 @@ +--- +title: App Profiling with Streamline +weight: 3 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Application Profiling +Application profiling can be split into 2 main types - *Instrumentation* and *Sampling*. Streamline, for example, is a sampling profiler, that takes regular samples of various counters and registers in the system to provide a detailed view of the system's performance. Sampling will only provide a statistical view, but it is less intrusive and has less processing overhead than instrumentation. + +The profiler can look at memory, CPU activity and cycles, cache misses, and may parts of the GPU as well as other performance metrics. It can also provide a timeline view of these counters to show the application's performance over time. This will show bottlenecks, and help you understand where to focus your optimization efforts. + +![Streamline image alt-text#center](Streamline.png "Figure 1. Streamline timeline view") + +## Streamline +Streamline (and Performance Studio) will be installed on a host machine, and will connect to your target Arm device to capture the data. In our example, this will be an Android phone. The data is captured over a USB connection, and the data is then analyzed on the host machine. + +There are many tutorials and training videos on Streamline, which you can refer to for more depth. Our example will be Android-based, but you can use these instructions for Linux setup and capture. + +For now, as per these setup instructions, make sure you have `adb` (Android Debug Bridge) installed. We will be looking at Android Studio profiling shortly, and if you have installed Android Studio, it will have installed adb. Otherwise, you can get it as part of the Android SDK platform tools here. + +Make sure adb is in your path. You can check this by running `adb` in a terminal. If it is not in your path, you can add it by adding the platform-tools directory to your path. The instructions for this will depend on your host machine's operating system. + +Next, install Arm Performance Studio, which includes Streamline. + +Connect your device to your computer through USB. Ensure that your device is set to Developer mode. + +On your device, go to `Settings > Developer Options` and enable USB Debugging. If your device asks you to authorize connection to your computer, confirm this. Test the connection by running `adb devices` in a terminal. You should see your device ID listed. + +Next, you need a debuggable build of the application you want to profile. +- In Android Studio, ensure your *Build Variant* is set to `debug`. You can then build the application and install it on your device. +- For a Unity app, select Development Build under File > Build Settings when building your application. +- In Unreal Engine, open Project Settings > Project > Packaging > Project, and ensure that the For Distribution checkbox is not set. +- In the general case, you can set `android:debuggable=true` in the application manifest file. + +You can now run Streamline, and do a capture of your application. This can be used to do a general performance analysis of your application, but we intend to add additional useful information first. + +## Custom Annotations + +In Streamline it is possible to add custom annotations to the timeline view. This can be useful to mark the start and end of specific parts of your application, or to mark when a specific event occurs. This can help you understand the performance of your application in relation to these events. In the picture above there are annotations to show when inference, pre-processing, and post-processing are happening. + +To add annotations, we need to add some files into our project from the Gator daemon that Streamline uses. These files are `streamline_annotate.c`, `streamline_annotate.h` and `streamline_annotate_logging.h` from here. Then we will be able to show log strings, markers, counters and Custom Activity Maps. + +These files are obviously C code, so if your Android Studio project is in Java or Kotlin, you will need to add a C library to your project. This is skightly trickier than just adding a Java or Kotlin file, but it is not difficult. You can find instructions on how to do this here. + +For us, we create a file the we will call `annotate_jni_wrapper.c`. This will be a wrapper around the Gator daemon's functions, and will be called from our Kotlin code. It starts as below and continues with very similar wrapper functions for the other Gator daemon functions you want. + +```c +#include +#include "streamline_annotate.h" + +JNIEXPORT void JNICALL Java_AnnotateStreamline_AnnotateSetup(JNIEnv* env, jobject obj) { + gator_annotate_setup(); +} + +JNIEXPORT jlong JNICALL Java_AnnotateStreamline_GetTime(JNIEnv* env, jobject obj) { + return gator_get_time(); +} +``` + +Some functions have `unsigned int`, but that needs to be a `jint` in the wrapper, with some casting required in your Kotlin code to enforce type correctness at that end. Some functions have strings as arguments, and you will need to do a small conversion: + +```c +JNIEXPORT void JNICALL Java_AnnotateStreamline_AnnotateMarkerColorStr(JNIEnv* env, jobject obj, jint color, jstring str) { + const char* nativeStr = (*env)->GetStringUTFChars(env, str, 0); + gator_annotate_marker_color(color, nativeStr); + (*env)->ReleaseStringUTFChars(env, str, nativeStr); +} +``` + +In Android Studio `cmake` is used to create your C library, so we need a CMakelists.txt file in the same directory as the C file. This will look like: + +```cmake +# Sets the minimum CMake version required for this project. +cmake_minimum_required(VERSION 3.22.1) + +# Declare the project name. +project("StreamlineAnnotationJNI") + +# Create and name the library +add_library(${CMAKE_PROJECT_NAME} SHARED + annotate_jni_wrapper.c + streamline_annotate.c) + +# Specifies libraries CMake should link to your target library. +# Adding in the Android system log library pulls in the NDK path. +find_library( # Sets the path to the NDK library. + log-lib + log ) + +target_link_libraries( # Specifies the target library. + ${CMAKE_PROJECT_NAME} + ${log-lib} ) +``` + +If you add the following to your `build.gradle` file, you will be able to call the functions from your Kotlin code: + +```gradle + externalNativeBuild { + cmake { + path file('src/main/cpp/CMakeLists.txt') + version '3.22.1' + } + } +``` + +This will create a `libStreamlineAnnotationJNI.so` library that you can load in your Kotlin code, and then you can call the functions. Here we create a singleton `AnnotateStreamline.kt` that then enables Kotlin calls from the rest of our code: + +```kotlin +// Kotlin wrapper class for integration into Android project +class AnnotateStreamline { + init { + // Load the native library + System.loadLibrary("StreamlineAnnotationJNI") + } + + companion object { + // #defines for colors from the Streamline Annotation c code + const val ANNOTATE_RED: UInt = 0x0000ff1bu + const val ANNOTATE_BLUE: UInt = 0xff00001bu + const val ANNOTATE_GREEN: UInt = 0x00ff001bu + const val ANNOTATE_PURPLE: UInt = 0xff00ff1bu + const val ANNOTATE_YELLOW: UInt = 0x00ffff1bu + // any other constants you want from the included gator files + + // Create an instance of the AnnotateStreamline class + private val annotations = AnnotateStreamline() + + // Function to setup the Streamline Annotation - call this first + @JvmStatic + fun setup() { + annotations.AnnotateSetup() + } + + // Function to get the current time from gator + @JvmStatic + fun getTime(): Long { + return annotations.GetTime() + } + + // more functions that you want, e.g. (note UInt conversion) + @JvmStatic + fun annotateMarkerColorStr(color: UInt, str: String) { + annotations.AnnotateMarkerColorStr(color.toInt(), str) + } + // ... + } + + // externals match the last part of function names in annotate_jni_wrapper.c + external fun AnnotateSetup() + external fun GetTime(): Long + external fun AnnotateMarkerColorStr(color: Int, str: String) + // ... +} +``` + +The `AnnotateStreamline` class can now be used in your Kotlin code to add annotations to the Streamline timeline view. Make sure that `AnnotateStreamline.setup()` is called first, and then you can add annotations like this: + +```kotlin + AnnotateStreamline.annotateMarkerColorStr(AnnotateStreamline.ANNOTATE_BLUE, "Important event") +``` + +## Custom Activity Maps (CAMs) + +In addition to adding strings to the log and colored markers to the timeline, a particularly useful set of annotations is the Custom Activity Maps. These are the named colored bands you can see at the bottom of the Streamline timeline view shown above. They can be used to show when specific parts of your application are running, such as the pre-processing or inference, and layered for functions within functions etc. + +To add these you'll need to import the functions that start `gator_cam_` from `streamline_annotate.h` through your wrapper files in the same way as the functions above. Then you can use CAMs, but first you'll need to set up the tracks the annotations will appear on and an id system for each annotation. The `baseId` code below is to ensure that in the case of multiple places in your code adding annotations, the ids are unique. + +Here is an example setup in a class's companion object. + +```kotlin + companion object { + const val camViewId = 1u + const val trackRoot = 1u + const val trackChild = 2u + baseId = (0u..UInt.MAX_VALUE/2u-5000u).random() + currentId = baseId + + init { + AnnotateStreamline.camViewName(camViewId, "Inference") + AnnotateStreamline.camTrack(camViewId, trackRoot,0xffffffffu, "Root") // root wants -1 for parent id + AnnotateStreamline.camTrack(camViewId, trackChild, trackRoot, "Children") + } +``` + +Then they can be used like this: + +```kotlin + val preprocess = currentId++ + AnnotateStreamline.camJobStart(camViewId, preprocess, "Preprocess", trackRoot, AnnotateStreamline.getTime(), AnnotateStreamline.ANNOTATE_YELLOW) + val childjob = currentId++ + AnnotateStreamline.camJobStart(camViewId, childjob, "child job", trackChild, AnnotateStreamline.getTime(), AnnotateStreamline.ANNOTATE_CYAN) + //child job code... + AnnotateStreamline.camJobEnd(camViewId, childjob, AnnotateStreamline.getTime()) + //rest of preprocessing code... + AnnotateStreamline.camJobEnd(camViewId, preprocess, AnnotateStreamline.getTime()) +``` + +Now when you build and deploy a debug version of your application, you can run Streamline and see the annotations and CAMs in the timeline view. This will make it obvious whether the time spent in your application is on the inference, ML pre-processing, ML post-processing, or other parts of your application. diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/example-picture.png b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/example-picture.png new file mode 100644 index 0000000000000000000000000000000000000000..c69844bed44b65c7f5bc6cf511f93987fdcd7b95 GIT binary patch literal 63167 zcmeFa2UL^U+6EeXMMVUZIs+pJ3K&D^keLz00^~3ugw9BmUWCvCWE@9n0!I-cw2Yt$ zBoKrEAw)o=Nl9XeA@m-4?}T>aIsboV=3oC^_ny1%x@+CD+#$)E@7wuy`QH7O=Y4nB z>)aazoVk7D)(ybEeE`5d;RCQYy#Laz>(`zC_7n8REi;pUoY;RJAS?&30sua~fdN06 z{`ifJt=%_Yj{SGJi$p#6Z~A|E7hZR*QAlB>1>rL=K-jpj zv-gDbIk$h(py+Yc+ z$2;gtTVKkT9-qAL3x^5cZG=x501EIEz!dPKkp6$Q{4t+?IRJppDgbcc?|&R~!2$r( z#{j_j?mv!w_d5V^`ZoZeob}*tz}7u}=WNar^)7=pWzx z<6iuqjP)DgcVvX)^b>R&We2t{K4`k|Kf9+cLN^2s%0NhxCR2342er9!hT)&(Iw|YyX1G*pD$YNbpuWc z2fAPMfG7Y0SXxBI8koEvu3o9F9q37tmzIAprB%>XMjXhA4}>KLsNmCG$d;nQBKz!U zYNUm-z_d@U;^SIB>%#Vf`Jxs_=rrOCKi7ppD}!qz$W({{}+t$RX6@e=*G_Y zXfZ#EbdqXKPu5b}BChF_VEfJI-7^1EW}&Q+=*Xy_rZ9FD(U2>VTtoKYPU9wnWf$@N zh4lCTLJI%?PaI476P`EP^mJDzgvVDWtde3-B1x5mN&{(~0bSZOH0A*43$*>8QuYBy zAc?Z8n|JbeJcniea_{dJuUoB~K5~;D*EaN61h{(rr;Pc_IFt*Cl6*a65!jEw&DQYuWqt=E0h z)CcR66Up?;>|G_)@52`S2MrtW7smdJP`lc>MMUS;QWBOkvP(C90fB${4;r`FpBcOP z&k}A-T0RIG7^>x8jY4(c&K!1q`yVvy{eNNXzeu<`I(m3~1~44;nV$ zFO2;c376*m57piERdxU8-0!cd`>X2ys=B|b?ysu*KR~8`Ro#d)|DM+^#ymKiB^J6E z;x(Jq^mxq`o9D*yQfdk$Cr%pIuLb3$5h0p&-|qpQ?Ey?RZgf=L$8L>Zme1&FosLtl zZ)@{vCNR$$WViyu_{5^SQ+Nes3)}3%a0T06zy~(J2@F{AaqFkRpRZ)Mj)_Hr;}a_#>h3zDPZnzd@`U-16{#~a9!#;Nm!Y~;hBms3><*e zsuAn-W1I-??jpj2VgmLu43Fpzd(tpcG6N1Jm9aHBQp{w%T^rbfZ2kBD&dS*r5Dr{% z95NNxfyUC;UDXLF%c|65*UAD{Mx|aUq9xm^J}k?A^TY$OJ-{y=JNFUWa!!x3ztNn3 zfr@%Iz+JnW=2AFJwlryuiOo(Kcz!R;XS=eY^`%NWKHb&TMc2&)z58SD!9BnrxW*Q~ z2RL+ZGO|`JsWt)WGdz=FTR!Vq(Iu(DNq*KBxhifc3Ixe!r9h|L1xe_ffsi%ma9E8I z$L(U1iyzV>hmQibHiIT!KIyo(aZ(8uFdMJQv3d~ZqM$tcWA-nZDqj*K|0rQ^XDu=6 z4e^-*syfVgX<-RF%0@>X4n5{rc{vMWzy7&?r=7HWa+(u0F}w#zGG#t#MeYH9@LNz^ zQ2ImoUcpSCj2^D;Jft zSK#OV$Jpj}z@hpcY-zU%j%KkQpO=QN0@o6!^a$@ck(jiau5jQwjI9~GdHyilpn$&~fzUf3_ zloT}~CAMz8(>l$(z%=b^RS8$$0~h)>&c zY;0m6*K7}9m!9L|5>b4$GevscICxG@eW+WS$gT8f{tOIwPy`nh?Z7jv;AX6BOegQe-y&S5+ zT5OmbU#0ijKW`d@)L;#$3FfndQ$req(>V<r`EP+m`3EotXa&HJRz#w_i*M2(G= zhzaj<$cn@sU_Zn~u?(_NLmH&)Cen%_?A`IdAH3yy4gFd>No{p$&bj?gcBSM^KRNqp zes9g|R71N^=Zf4)13CY;h^6^L#M582q`v=4tAF`$;)l7&(4LO!@98URc86Ik)O2Hi z+0vl_Ldhr11MU$5^sAs5?V)o5?x{QN^!f09Ol-HHfod1vlrn(sSl+hab*RxQH1w#` zrcb}SP&2f?bGznBN#~)Q<=_9(4B&vZK!3gu6qET)Pdf9^lxJ0Zv=@{?WewOhQ;aPg z%))e+;&KOxvfn<-)EVyB0}L4voCwA1hh{ERwbDmesx!_p2C$*Aj5DowRZ&H2e2nO{n~b3 zcm<`v4rPmM3nwT3s#^_IPGPdAC{`-!Q~R~TQQPhfZcj5gE{BLzpS9G!6q}@`$@W!d zAnXjTZfuR?*DtI`iOg!4RS{;}(2JT}r!3E+5?$yMh1no8<$?a=gZY=GZ+&53VGU zX+lYrKMn#7VNKILH7|FQy+1S~rZEnaH z=GtHfHQ1I=YV=-{22xPs3Av9gDq%9k43SC`ALg#&9v9>@&kczx#WDJFMyxL6}(Nggf#h>ZFB+C|r`* zp~=f7Unp-?e1E?}Rei{3!81KacRb_PG}iz9*#^&l4gLQX@&7zrwC}SXa6{0AQDJXg zBzhP8NeaHwhmM~Mueo54Gp$C3@HW2RuZb(BqcEA_MI*f3=LANi8e`XgswT-UhGM3QFG1?LLhPJv~f6OGAOssN^_AncelX2$7-Q;Jn4FV z^5DYe6ZK3jh4KBWqp=((rwB=8Z+#mfe+&>V|pajy;{)?m1~2p6OxNN6L}b?WMCJ zcUsv&-gm-mY&*P~K2id7IRSl^EqOS`mAsLnV`b_hi>DzTe3)Y>9NMMlYht-$qy{s* zwK4L7gQzpxK2?s$gr&i?rU;L$Pyx#yz@_NRPNu#Y9n(W>gJeCA*DFEGw1rdM3P$9t z(sk>igbS4xU0js^m}^>9(>W7;q@D3htt4)K^O)_&5b!2HcF( zqM%rJZ6lt|NlF5{r~8HV6=GZUEz2aqqz=+-SpveyW+(eNX@R>NeQCiuXHw2NmL5-$ zB*SWX8T7(~tZUmww(*&2@yX6dvI9A{rpB{MdSgT4S{sdCZ-jSjvydygzGruBkD~jMc6u zvGS1X6Jno%kUT({4OpIqAtvzm*G7JKmQ_-4o$E>ZHR$*rAeepkm32E(DNG@4EsD&Q zK9s_df`eJ*MrPfgD^L3`L#d8Eb~jS8&V>QXq?9~2aw^_1sfYui^pZj@CSYO9wt)iG zC9Z1emsKKJ;GSui=)$rWY{^A67M~XzJClaHJlD^0@xT?CnW67K*#oe5_gCzSwB+L~ zlI28)8`ychhza_K?8~l+J~B8;V7+ zH*M57&uAvftdiFC2eSQx>l1T}I))gLNmOD#7 zZ@S>zLG4aV+?ZHcp?x}4qG`~X78d@*{N0t4_FcM?#5lDsiZRbIC@d#!7Q2xx`L~HW zkW6Hk0bvg?Wx1^CQiX~ugERB6y`3Lyo?0lxgY+KY6(c61|KQT(KNf%a8RI=b_~l&( zza0tZ9X-k(U;?*;9BVY_mFd$~9Xpj9jgeGpTlKZA@^vT2E}MgTPVZ+2?sNsY_nNh@ zr^H)Y7!AIU4^dLw1GpCh&0!E(ar>RKYkJpK3~4n$Aa!1>(7EB0pJ`w%C&#sKW-21} zGEPK-(A-*HboyQZcK(KkYvx5Adh%#Vr94E^$<4{$MF(cKynG`|%+MiO{*Ygf z^yLsg2iD-uoAOmzr#*lX%tFZ!p;z-5D3iZ2c9$1u@mMCRL(OEm2YtkBe8-_zphARz zW&MO|hn+<)*IHw@&$`o*CUu;v-t{IDKp&Gzwk+xLZ$5(3>3Jc+TC( zt(%#7iiY^04->B;mrZEtH89u{DXmmVvmJMQWb(3if9J{a%0MbSkQD)~eR|>i=J`}o zV@q)WqX)$$_qDjD=i@Z%*XkO%{Z}5Gj+XhEL+7DBPmJp73XU1o$TpcuL@gt-`8eS!IgsTUNsZcY^fB+ehi zmjzn!F+1p6@mN8z85&~M-~XQf0`?{d0U8ipaMh~$H2wPUBjes(C0HI?6l^wlzncz} zf5cS9#VKYy_p&=oqk=p+)Wb;`c)sNjCDnxl-;N;0WILa@FS;}SHaO%=X-2yGVozr{ zUaiGdLBl?lJWywX@iE>8UhS%z1%J%aV2jBmLg#zgjXQEfQ+T%{!7ky%c4UOH8M<>r zfBsf>e0TJr5|v(h_|B}Ur>oOkpaV^2{w@OIU{6TF}n$>Wq{}&$w}0FU`{n5nSBCRnM4gb1V!KsBzDH z7UJW7TB1p}iH5qte`blUygw(TDP(La0ulIf(70cPW?^r)c1*r$|3PU_q)q6a70 zTo=rroEZPfwEdG7bGXlTWirF-I+J^Cir>P#7)R#HY*WtFFC{%e%aU?UO&ExT3(k#> z4FPKzrT)GQ@&4SBwV;m+Jrt(CO42l9FzFyFJJRt;7y5|X!tzb(tC_w7Vt49u6qK&8 zTj1sSQ_G`wNL-UWcr@b9CV7+^XEa&qOI}6+0;@l+2f#p=ZbgzGDP+4+KB)x=cRQGwtg>67k;)+JKnPz)ZL89{V z-|Z`f!^|x;xuQT|i%Y~?@^-`onzE6akX)f6Z2FZ`T~2Ztlm-}wOL_>jyH3(+8Za<)ONnQV`_cKxmvqn9H+=^gDnP;mb+ zXKrvxFS3jB%w;r~Z55RtyHMYBufD!+>Gyic&{q5K2uj8sUA zZq3d4xqY8d^@p>T68+ls1to3ULI==D<42(fK4gRW3AfL*itR_=QeHF|z_RHY2Xcr$03Ca5xbJS>pq%#=gDO*X=HbKO-ptI57u^(Bt{6Pz zGBM0Vvp%@3jinA{y3H83O`bk6Ibo0VpL<$S+mkL4MR*2kr41vw!5E0O^7Eku(C=jJ z&JB9TQ{H7Vzr}?wB_1azHhrnE)8dxN(h$*H;`2!#srqPd9|nQIe&dsM`pBJns;H>j z*#@o2nM8;27s0GL!@M&`+!6wbb?1!0w#563ed=k54@d}}{Bhjs{!}U?R z=Js4A$!+RIPp1qyt({21&L{l_x??*5YuZujLtL4Cr*`K>oAKT89-#McNRC5f1{m4Jxu4P5Swxc?r&FPP}YdEN9Oa^|j-Y-9FsJ(B2=0q#baZ(|ov z7w%w}qja^za~W=oG2O5-RqyYmb`U1hdlz((w6RzSVpyS|Esl0(^TdD?j|aq z7F=^kvuP5`7iGGB8xi`$C(@Ix5oI2M^pc%8ls>%X=(nu5nn;}B*bo*Q9 zId)&jE7nbsQ+kUOmCqhA zwN{}UFK?*E@)wDzQi5Y1QVE#}m`Bu+1J`tU)=9|$t_=gHb;<(J?l>?QmGmUl`ABK7 zpP6Np4v5E+&jF^-C|y2b)?3SMG!8_;XC`ogf^+WZ%8q!FPaop)bzb1~hSU@BX3DdK zsMs8OP}6f4%c6qKmMjV<7jLuIxiGLr`bUsQiA!+t7D#AnF1_QjE<)P;(5ICtUH5KW)7}Om8U~ zHnEEolNm19CRt+;cAiPBV`|k8-vyClh{STCTiRo8_t;@%#XilwViYb^8`(GUhRMsf zW@k$~AxsF--H`=C}jI6;@VXOx6hD(P>h5OB`2(ATLe$i44 z3HOEGV$W+TG0V$k;D9G@Pt(zN;_y*bK>d;7Cd|YhK!Xf<>?pJ`%|at=YQh_4yvl4o zQXEMypsIOfES~7b02&=x;2F+;P?z?XmMZWWqO8mah_Nv>S~>A6W}6-~sA>*IUo-ss znZm3(rmE)_XJv++JxSG}rg61~v2i)z z>4b?Jm=a!zs=`WdTpqSvPuXeyh0uZda0Now^1J7VXT-yMX%0*HI29~0U$`V5qja=C zUBCHxr9gyTU&va!pE-T*Uf26}-vFxCG+q_&Sp)H5Dk=BZM~JIwwGJtZRG?ilq_4Y9 zrbk-UqpHkfh^sI;TN*+SkI{p~cV7X=ru)=$^>Z;38TaWTNsTZ`4X(r_&U-HDDMitD z;q=oUa<9{;4Zp&EssYV`p46*?W1&dL<}yA-Cv`t2s`q_bX}d&9t!n=4(_p#SVCeed zlpzCO&s|fA8GxL_v)H@N#uy1c99m)|Hq6A0iZ?-a*1A_8W9Sh+&aa$rim38}%F3^< zo?dyddIAm?sHWRF0XhF#riSQ4DR3!co?PeVwbQ{5>S8ja+&20s;7Ikj2yMR+xI|4) z5?a81!Ww95YN1#g!Q(>;5i-OaJ`fHztrHtUFo7#qhgfI)m%xTNmku5epH9qq=c()B zT$Fmxp-kRO7UyHC?l2Yx9}K#hamSZ7IIJ=#K)%#QZRFBkzIURS^}g>N+5@}{Q|>b0 z%(5S%^F@vLJtW=DmqvyD!?fDZ~a0CYDpX3E?=kY@%rn?74awkI=C zzM~$%W}v|WKoFsJgtj{3XScb3p3~(n4KZXDNr&@3N=9Y3e*a12)$-)rW8T|=-(b^L zx*E6VtER(tmA$4V`aGJ$5s~xutVMlioAR;2cT)p}a##QEx(A3JSXJFFY5iFup83lc zow8Oss{!k{mV4qBr-Txq8cVz~VoT(sM0-G7yi(Zpsr7$BE~%~)mq9Y&O|uJ=wz!g) zNs61#`nG*2Y#G26YQAHkicX z4A>5)4cAB1S#Hu%S9mwl1-78Rgr~Vjbm$?jGFqgPr_Q~fvm#2su|X~kF8Lv z*CkAg)1ESWU4UT!;PH$yAa5ecY|hOo;Zt%_Wm&qP^QY2TE!ADJ?<-@tyo_ZB8e4Tp zXED~r&#v)P$rN4*ot0oZ0No1Y$QS13#_HdC%5xMNyl)oY+B(2qGs0J=<&|#wS)5pe zMwgn;4wQfmPKX**f6Q=fXYF1T)7&jpE0y%ItMVlw3ONCBBPmu~86k2ERHe3`c;!3L zSJ9}hGa)!FBUQ88^-@C{?&K=6*0UzQpY>Al!_?2^iScD7=hK7?oYC_+act{I zh=|b7g@fxcPoj7w$mi(NB+rLQ$iH!x0}EynKtDCm6H;S?N!l}gcn_gZ?IvtdY%nb? zEqqeb;@#UKS0&|JfT$XIH0A0%~WtBO~7>~=8V3NPDt`ZVQ>MU76AMg^7rbhX-J;;yU0&=8Q z|5vZd?jK&&xrWGAC5AO=iuG%FnK4wwyVWrA)6tj_^$Y{L+xNvQyo@m45No47fS9I7 zGl)4hzV)r&#agCn1_g2DM!E-U*81nO=guFgdF5``IL=)Rl&!%Jus(x)O$s8==YmKy zt4#&S@`5o$$wkpN5@yB&nga`3KSi1!@SOAECa=kL3oU|tbfz&oHo>tgDTyT3x=f}X z);l_3=NK1bbF0gyQ(1iUk+=q!BrwI_-%w^19j-WF^u*KM@pSn2)9;A8 z-&x>{n{-GJb#4*2BRzLG?bfA<3r%(taYT}@B}lfEn+In?OlVKy6HV-IJ;jd3A-f=& z*+TC=urUShu!S5t*~gjyH@#E6OlD@}j+uzEUK-^>b!V1L{BQ50g&X-3JZwqI4nvI; zUxtzNOYfa$!u6$vC;zQObluOx--^Y zsVpFt4;SZXa?LjJ%I|lj_|-a)ItxW4Jc+&*oRtN)1e)*iCFa?zR`ZrHxcnPzFS?6< zJ$l=!qdcma)!ND_?Rn8nEJ)8G&h}5$^ZW`$W!>>^sYVW)^-a&dX+_0{CBTefK&u;7 z{#8d=Yj$fU#!kcvVr-UTPSD)u9o#YX4?~SB!@*Rk!_A)pz*oqY@a7y{dx|kjy{cur zpACgvX<1r;y;5ouM)#4^z1PVdqa71`2c$VaA&$FzU4ZCpGq-77bt1h9;fFhUHiz0O4-s6nQ{p4-As?-c3dl-L%6up-44$NB4isAJBccM2=>hZBm1Px%9-A{ zpbkw>w=Ol^Ik`+j_(EV-5XUJtDPFE7MtWX|u7?ZJb<7#B>$8o$9%G49k3&2Yy~0KCyCva?p$P1W*p{m_bu8T z4lDVmh5NO66tRpC=(diiHaUENA&#qXQZup@qBN$sq*St{FfWGeK(m6GoNLl0y48xx z*+zB^t?k6}^%b3CH?`JF1Tu0l*;l+f)5hiNI_06)9i=XieXQ*rH5>G%CxgrVT-{lP zy)<|;;So@#dwI)d{m*dCP2r`md}&2ztT50bQZ-Y4CIItK6!xsMAjnM!J3|CbjQBD( zyb>QbneK@XGcyyyMxe#j^@z4PhOa9c^IJgFOTx!HlUXho5eVr1d_vy7l})t3dVp8f zKfQe{$5Sf$0lzP*p^-cf!x=gH7C_Y_2&oXw>gYe@o4p?@+ifOtRc1?1fSIYLee8f3 zkq*TW>n+LYfdcRpbjdNEn(?!HBRt$Ay=;`@$sIZsLA-9%zo8!CpV;Hq2S1bJ986*(8}bGt-SmQ>}9T;4jZw3hV@ zwIltaA$Vkkjan&vApL{RI}T=VdtpyjMs!j)P?JT=%eJ#ds`VIG*Bofsq=Rc{VE z#}NY=J`?3fGLlO|G|sH6%W=BHeZndeeIo5H5lYfkcFTgegZQ+>F6@HlorhUs<;ur^ z-c#X?Mn;3Z13pecTMn}}xS38WLWhvLHa-B2rqs%s)oD^vIjftV+3vfWujD?ig@|V( z3=rHL-KlKfiD}$ipyg}|o0NbSFy2+2M!MS9(`6=_8EK7FtFU2TGqYXy7lLe|k3x(g zd-l9&YceXB5=SLHDjCq|VEdn^l~xc5Q^v-A8wL8(`(CmwQay?J(;bR^ghtyR8l3ho zNlnN^H!{izPAB3OT=n&lB@u7Oy{L2XuI%j#C4n2Hf%S+Uu4%en zd5-d0z5?u}i!btOX+Mpnw;VD-){54kq>O=wyv-PzlPp%Ns8Qlux!uRVPwV3l4WEK{ zGcb_9F=!G6$j;nC#}-1f=pF#~>$f$abB!elv21O&Yg1 zW@Ak8MO0AdAmIle+V5RWyb4-C0`ezfx>tfK7j?d3d5oNw9pY+q%4!W`r*EBln_Zf4 z;&^{njz?&E)Wtl$5DeGs&cVf{yL>C%=p&l}dtcXdJbW{E6&g_WsD9WZKCQc=B0Dj> zs!DWz&b2Z2Q`75H6yx3^4;xPI9$*<&XbIZP$ENlrK8!$RJIwp!ZLIz?cGXPs045te z`vO|0C;ZwnnV_0J-Xnk1)wS%)C6fFq?YphP=a(8Kf{0@fFwBhRG~P*Xy+3N9KGQA8 zP7Y9=YU&E*_Tck3RMYr~v6ppK=FnU1s|EV$!Nmlmn@d05gXX5d)xJbjZr0?Ao$Lrs zUj=R3DInR+%bqUPNe@z*cFMZHM6=|NA$6)V{U*RvZIO7v9^mL!b^;M5j<8M*plyjM zL>S~@$F+z{#*u_avk|Ib@`N6)Ia|v1-gyO4+x@h`NN;73k$p``(TG!?OQk-T$lnf0csNIQysI`CniC)PadrA zR6CXe2Z>u&V}=>8Ue|mK5#H&YSfYSAzYQJLXYT=a>$#C`A-fs_{burTVK(T-PAvm% z<%ip#xO-?U$qMbrJ%Ed6HH9urg^(Pn{>0Xjl+;%L)brA}n-kbZ^g*(NM|+9su6^QA zJwiF!^X1$Lt>PrIPj_sGqLcG3&9<6>yk@W2U(e7pn`{OdRGO`t{&a9@`2M{?zAdA! z#_{P>^ozc-;5ZuGB#@;epQZGp+j0Iu_LeP5 z#7%S$TXe^6Sa(}Y-1NC@*bA8>!*g$H6TiLdTVO++6Jc$t6B6WCI?K$0XqY$9OTx^# zv?Y}1%lLvxbo|XaUa476Sg6$FxNH7JJvg*5=Fh|?F^rDQK90<~-+vwR*f{bwtxE3k zP)XSMY=rXu86kF=cx$D}#Hk+#Mfdp|rMx?v`&34sj=oiouWJ3h!8ZK9CA6jrs<9;G ztJ6*jN{T`sWH2_>Tc*uWu)y=6`(>X!>3gaJa@t91#mn51Fg+l%(9oSvjQf+KOdW1n z=@^V&JQ8ktMr&8xYQjE!7CsPnX+4d`>2Wm7dM3WcgVyn4W`6U_aXUzefA?dqHlk_T zr>_eBuIhTB+}cjWW>1qabI-*U!^RgGT=7Jm0N*tzawg$x2vP6i8ry=K=aZ=nW&n?{0I@P=jneKdML8r~a0vKS<{NjTMP1u5YWD2YHbJEG%EfC=^5~{>q z!V57$zNl!6f;@3vJhn(OoWxybt>>(?K9DGBQ#)^O@VRkQ2wWs$n$*=i9HfSJgQuCq zxMkJYCJvA|yQQd_m;DALx?{r!!;Rc=S3ZO!Cnr2k2myf<`r;)n5odd-s&VdA6Cl%* z=vJbjpyYZ#O;%~6FS#-C8>f~J^x%Z5*9@CVIF=X&H-=W%07r?V_0VjUIONB^mTQ|$ z1MNk{GL)q?nm#o9#+^sl984_YBILqa=mcM|ODE1n`sw?7VT10CPa&q8o9T!r^c1LW zw$sgJ<6vV$fK9Qena6QeB3_unl;vttIB}r?Hz?AD{V;29biq&Dbi?hX-Uwb>%K=f4oe?3&3ARqIK!J+*Q-UY5l0_cpB?RmK^8tKEaV|pD zgKuSKsyhyB2@6O)I1p)6kzB|Nk-q2N9o64}P0N{WiE3`1+6E!s#ct$pPslz^y$}@` zrJ# zF-b?BizW^2gezxyg>CNvE)?ym7wT&SAg3K-vS*{NCOQa=DdLz@^=;vvF&ohM`-hz# z5Z)+@S0ITDsamTMOD{dK z90KL~=QS5wt-(dDf;m=UsWFx`b#BSJNE(rOpO&GWW4H_6h@A^@-|)b3WQNg7KNT}`Dhs*dY&|pm zR3FQz-fo%{2l%?_RibpRuO}ViKV@%kU)+mYDac5pPA&yakWzJ)>ooc(~6)|PmLhK&=&t?)qr(jZo|m>y={X0wcHD1JVV=ssQXcoZahMx6n=kUIPmyz z$kAXwNnmM&AwMB%HB0($xt0_Y;&2*Wv%bEY##GL#%!ynvRmrw&xeLmPQ?oRu2MR5E zW0<*S)1{cCgT|28$e3P}?q0R-E_-_L_zfdDNL5Z8+Si#TjMVl)I*4IWUD=jmSBkYY z9{Aj#aAkMQJ@e~^T;G}7!3rWht3-K5zh$~5?oReKMAqWMv#@@reI~0)dvY=~2R;hp z@VtPEwAk(Qzky6AgW3<6wqz1RW@nhC%fxr1UI*_Al@2qmzehIoda5$+K`09O~a%CX+*Yxw%$f z--aSkQ;qyVa;MftT&}KPr7Ced+wWd^KT_aottk40WaqZk9;tA;fq8mnSJQ{6#hlMo ziVybVJWEQ6g`c};LpCtHO~mKL5cQRmlrtlMVqy;y`&wq)lVVb9?UM zEG^7(K5=(8LEnA0K&O#Y+Ip^&V(MlW7V1TeD1#eJ5hExdjgr;n<%QCBG6{DqTc`=~ z@xCNpkpqcjUa6881P6`A#Qc=45xCZI`Lo}|_BWj3nY&#?_XK+_ULY+TDd?DmR^f5l zc1msxxx@XEhho~ivem)U*o{^!)^$TBj$sfnDf5{l+S<&OwVZj}f5AWGP4vwZLX75v zSiN_*=X4M~MXS)HXiXv8AxpTUW8S<9_Q3a~c}4>%^qKXmfQ<9$<%ShyqQUumbM3q& zv?!=W@ADEL)FVSjVnit$bcwN159=(4-BVgee3p8BCMZC-n1L|e+hY#P4gfqzmTc{l z_Pg0HjkfF-tf}crMG=ymz*|AaP(9B?hY{Sb$P$-`WYH_nhEFkBLu+dt<}?H4JxE05ygT5rbrL!JnZNND-GHut8C+J9&x_cha!;F^6@ zxOju5Cc_da*40`&h`n7O95+R^LKsh8&Fm{P*$T4zrvz}g^XXHdnzFZhg+2Pm57bz~ zy zv~gKaLM_t(1Qffa9c^I&o|9?iy6dLtqYqd6n>=;!^hF4BdV6VN2D|6^i+VN&B=I!U z3&sIKto4?`v5Z@(_mU;lnPsLM9>QPkor>Arl+wGl2e>{d4BuY=IJa1%;bz=sZoOPQ z>x4%#dZ0SnoU`RwGL?=V4vtJJh3YGkrHFzXGa&)Qs3zuAlU`0DikZG?%(4z!PCB@$ zsIH;daQ9M1@*7K8^9YLfwHfA&O@eTvMulB~K*7Z=wZ`P>zQ)@rN%*4u1@k@x=d){T z=P;*zwm{YnmZD-QkD)#e+pCs6RuQu9von00$nSK|zAboXl?k|qX2x~|o9Ymibj|K4 zg$}*-9KwlfOEB@-HXB$J>TFm*Y!gj1fTsab^^9{HiZxsFlh(eJ2}Z4jA?Yg{#DuCA zkK*8`A3l4CFTn@cMx8vT(Q^l1IhH2>J{}{Y&zBi^9kLGiQ}(&7YgAZB2Tt;p7G|LU zk`MhQw||1#x0Ae)?Z+y8r)oGCA34wki5=VCGB1c`O{{I)!ItBG?VBeo3pd-m{rupQ zMf8r;!kT()d_9Bz(7dlT-!8sF%a_C2(3i`bnZX_E&IxPV@Q95=zF4JoIK>*MP#fgb z?luyVBm*P&r+r?|$Cc5zMEw-n@+yhXG$`f3EG*4)+EjDRF4D%wHzPVMK8yxB@vhZK zP3l?7Wv5qVvL|^&Ktv&zw&Ivd1Cl_rQ;(&Am;r`bu)}0 z_J=B`WUeT&vT^5|Zfb!02fHDdEJ)9*PYPOtaw}c}F3oVB#Ygo`!<+QHs8(=u%LTLG zJ0Cw*J!~L<`=H4x*Q%>019ZwIk2q$~o4z<-kFn;{*2_$%m(4Vja_41M5_P>dxihwe z(}?%P45{pMa2CxWZCsqqPgmuG#1_oLWVTzC=&77WXf+Kn5P2UtU0IzMDzV{##R#{N=N=!5ZCUUAQkF1cZZx7DjCJ zLpMR_0<*t!SVCfl`{jX@mwoS>#t&JGKgLp?E(|ij1^IM$l7N zo{y8DC)Uq}m_B0aCJA?25Eq}Vm#eq%LSyNgeOcv;Tjf!2!qqHUB^iMmp5*)`;qD(0 zXe_$c`P4(1OJ%vU4*i!s)7WdiG`LN8AXm10QH|SDnakkO%$gc}4Q4L9ymnP5jLu=m z?g0iaqrPn+GJ&6mYU)^4tH!ALu_QBk)8UOD%5{LHSA4SeGbFF6#`$_);Fw;qMKuGKNpf6$g3zvR6)y5u}i-MSIfKc1*cgQuwmbW_94sp6fk<|VAZRo zy{az04r#)mDVA@3jw4$J2X%=aht!|KIb7#b=In;%k{|y*xzg4^$7lzh zLTx!0jJ9QmjwNT_I`?nIZ~XmCo2sIN^KuGdP^zW_g(cv2&&K7lxO^kI<^}B{@3m`O zgG=q?N&b4h?s-RAOR=OvpMxrRlBfs`Y?({4H~(C^gM>D60}EPpL&Jjet6X-{hl%Qz zR;alAw1xV*t_Nen(2SXaOJ0YJ{2R#|I~q^z!{>%R`TLB_i(G4Cs!h45Y-#lw)*ySA zH^Wn)zoHGquJCGH*1*$gU0S5FU@pw0HAslqn^+p)m6U6NMmIiz)(OtXd}hrT6Y6~w zCG!b$QKk1Afb;H5yy42WYZ}DAUe>dL1ffJmf=}a}ZWU9OJm};RB zhBxD;H&pRS`o^LnLa8_uc9AwJU@khEgG8EYzyI|>O-V}%2VPf9&)Qz5RT`>ta(OX^KxP399$D!y*fR8Z) zC9{1#Henf9M6t%69Q-6eEe_nN@vSobTYC^%b7|VH`F&1eX_Pp*fFAW>{rg~Rl2)HrL2+RHp}60Q)evJM3&@NNMp$)uxXL_ZMh-%qJit z3KDnvD)djgdg<3$64Q!b5A`;uVfj3wVn1h*i?GHqKW3q9n7w+;;Hvz-44N=Ow2idd zw&6w2Ct@7P5VN_z>t7Fiuzb5~+o$PsHf211Ah5+m7yso#8v{N1Fa4< zhhddEilq9|5{ibx`PGS@f)x4RiPg^;?d_GGcVuB__-MV+CJk-%hi$fg3a%) zrxm?EDU#1Q?JL|H%8|dY4xT~!6gF2BIO10m(3aGI*l}|!K0-`v0Sf+YVzYe@fSwg; zdPLobCExQx`>FGFR{L9viZDkqm*QXa;v(TdK0ZI2bwu5<;0D8~%$Vm}K}6=7Yolte z>PJ4V?~k{MM;QxuPfW}8-)z?|)xl^YOj=ZE!dh`TszT+QX$Jk(#kpMzr_*%X_xR9a zNVF~D!P`la|HMmDYx^8WPEc*hq>GKm4eKjzIod8$PPw?aDk&-HD_t!0emyB&cE!6| z+jsWJ*_d3ptRDjkIHD~oIXjyDamc~M$=2nITcCJi9!UgYdL;smX+LalBIYM=>;W>6 zsxnBgpNmak`tG+Wlz7xDSfmz4JPetfDHXwGkMk0$yhcydK=1$Ve)!Yo%KDGfoqiuw zR*5pHZ$kQ4-w6Y?WvlVNrK44stJe$1H?oQf>`@P#g8Vv?&ff%K>gEM0QMUKro-i5z z{tM!1WASUX(PH)Oww)KHk(siGA|gj3Qm|Vp?t&ww*2A8{hx7X#X1; z_S8=O@FRNu$4m#28y&gEHe?lIWnNs4Pg@(bO1OnJmfwO#D=CTHt)m8zgovL-^0CKT z5{p`6+|CZ{cx-5~fAQPm!n;GARF{T0l`>DRFobt0CyjrOBii-lUt*lToV+;w`o`x$ z>lD|Z6XH{L{gLAENBC~CN_u`QzfT?B^EnsiW&{HPfudao`N5Nu#Z5kS&!Pf%P-52` z=%CNVk77;r{dX_=!%-02vd~D!i6;`C=4cYg;SMMN58mE9s>yS0`=;Ag_jaPlq>Njv zARy4lJf>BKR)ds=5M-=Shy)08n4zszCV{QY2_#$41QG}$1V}=l3W74l5CSq!hA@SB zNFa&tZJ+mfw|njNt#7UOThEvO?zO_bLhhC8IAEc`}X>r5LSpLyR(9nfGd!j$8)dLYU5fKlLNiHiWh+YQr=|5h7EU# z>Fl%4IDPdd(Z|X{F+ksCy}v1vwm32@E zafsAFR%ivxlsNCjshY3$XYq@0sCD)af??=QdHI`WL&47dvAdOg4Pj~WH)rhsRxMGI z?n?@{k|hSHDqhMb7v%q9c_~+H;lHk5hKhbdG}AwuFLoCFrJLh>=Y}owt*jb7{I!xD zX1ltfElGVaFKlF1e&xrSf9mwW-gkAs?t4wm%nV|TtdBS|(2E2liN28F0Fs+6E#yhI%S}CL-z6#;86`vRN8ItT6bhbBHv^CT$?{$>Z@4-C zR|oYwVtt=maq9QhehE$S47``VS~}$ zQUuW$n()F0a~c~j->GVPO(pC?l^V;eOXU<@0%JR)D)M&8m|*d0 zCU+My84c?jj@9S-^bE8|YwyMasUtdYnn;6C%$*IvVFui1jbYdh3F{vD*07PJv6as3 z?%VD5`mQ_ui~znFI#pNf$)h82zNe$rrhfhw(Yd1X%M1Ey{=-hW)lNBq} z7w*;d4t>WBVRB~Gqy#QJbg!@ZYY)|y!+g{*rZc36w;<}$yx5?;3HqpPsBCSqykiZ8 z{dK%ogGZ#}gUnkY(qmh5OP_s^30v~50ivYGp!?zHMsA8k7pB`s;XzD5ebI5)caREJ z(_R_3r4-uS6jpcD9(F-;taXwX=HA1fvZJQVBVJXo-1RX*loUVNvF>}H--w#9jfWU0 zp`yE5C%0-ER%2^eAX-*K-O*Z;5&R=9Tifr`j>D^?h#OZYuI#xxuQ1jPEoPPm3CX|^r`+zv5wqwuhlQN^1$Fbhl!~cpJ!}vRk=L&&V2Oz_JS_i8vkD!>kT=cD=6#-_#XkH{~S1Nc|%j zbt*LLN^GbnI7g*lVQPrN(#0wWgS!dIL!yLuB>#N|Z~PdMykh0}>#uQcBc?V!;M0B4 zv^4Eqvs$3GbL+HQpQ2?k%=LLBkBt(qb0`(8Qss5syfs8S&Ua>Z{4OC*CgvojK6uhn zr91`=SrW!hR&K*V3akad5kRavf}{6 zyY5;!NweKd_DMQ<+6#INA6To+Tk{rEeM>gds;W`5gX7u2W~=rMhuV)VeE5(!8|=Pm zwO<26CJ|#O^vXgXW_i3IVrO5E3M*5m>*r{nzah}jn$kC6qPdyQuY%Eq8MgzP5&x-SyA+iQNBKWdSr$1CpNzi{YK z0(-f2Bl?Zh=y&b$6A#(1q?~q@zAe{94lZf;eeTlAXG(JjIg`_htNqs!*Q{IXpH=Zt z{igQbuNk%lo|X9fB;t-eM5yJ8yhP%;I>^=ZbTQD`3eMyCPeCeuyY?65K@evc#NH{i zPo$|7*VdcOd>NOTshl|JOWe3eX$G4cHs34p_E@TNI^KK zU~b$om}o{%nuo!iW8iWyQ>e|Hf3o};X{q%~sdc2z@AUE-W_`;Qy^gFo@&U@BhvGk- zciCCqHox~^Xscwqk$krm{?_8n^T@dS_XfBy$Y|dy5+!!-JydSEB6)LMUY?hk8P#yP zV$JVqw2dBuxbX13wd;MBc35YGp_9?kgxEa$oweU*{ph!15<2I)h8cA9-bJN--|QfA z5vd|Cr97yl6ss5|z_d2H;2U1p7JYu_cD?e~&He%!FFi!_*M`#D%N>3>!Q{!MJO~Kw z|IyuEQUZiZFKkX61Vjt~M*3H!g~R}dTB9g0sbW`FK%t2@DagoGQ!&ysYRe&FHrre_ zwal4>;`D>atoT*+_><1@A!R##-75mV4B|g>?*AWPnSjocYS-k~6O;M|iPirk)_&(E zNAyaguFIXzUN4#4m3}FcqcbDiH_v5LecUN)wHjHAfSVjSK$Vx*I9sw3@5kC40UW$Z zG2znGk;cQhmE|Hst7)Wp+go9Kw+~h#V7H47ec9sJ(e|lHRlvhR6{z{7{1`dRaAoe5 z1`ZO}f1ASRx$c;aAwGSNvE~!0uXdcqey;CnSQ%E?_zuQ!l%~jri&ShBoqm3jWa{iT z7cva)*!*37=`TFR8G~2G^1DC;8CooZA$=Q}cw%!ZBI>Yr?ZN1wrXH#84jeTyid+wa zgBZz$Xf7lzq*lGbO_$T3UR+4zy<@%nsGo-vOf{hYv;f*H{i&ay8S0w7)O`zUy0e|A zQ_JZwwx&56mcb~w@hiC{(t`vqD@(YOp~>tfIbC?b922l>mn7akUK+T8+Qr=7hnl05 z3$+@-d<`dt1bL!i)%$hcz}PXK%;HlN8Wt<$}*Ac?tIWTM$7vO4HQ>e z=Pm!*9%T?|CGm;n42sJxW_CL21?OJ5aJTMe*?|mS95FYQ|DyaZmSM~&TpjS~xY?xFlu!;jQ4{1GOeJHkSjAOmMsFYEMXrrey*&6 zsv0vnV(2^(eh#)U(fWWnt?(Cl`F+nN0Ow|)u zE=!?1#n0eY4?Fial>x`6f4u&KX>1bg+2n3YiDpf~xQrf~sRMya;`Fy`c|&mL*gKw2 zUuW`7xYd(9u%>RN1XbNZITt#mum}?{^PY0={u-xMLt3Ordbu!k6+ye2L@V8ZLZUX% zmgm|c?|0u8k|V8FqMH<(vW-jdsdveAtG6pD1Qor6K zRWY|W51*$(^Gcz`^mIo}O@GY^wsFfI)umUo6-^YLg$3fxib#9W_{SO-@Y>&!bQIX})k zWKmSS%#V^DwH@QLVD3w$lB)YdUKymx0i4H%r>0ZfGREi~?#|4B#6S7`?l<v(9eIYWSI^AB9;aIAfp%1^Emqmr`Vh9KEHte0tV^I zA>N*aYTUtCHw&10;`*%+xqvV1oou=q1QG>1?z~=C&`1#CQRz%~<=r>)HF;x565tXJ z^7l^wKu8ybRvGiREdIubYGxfn6BY*Q>Iw^q9ESrj)thRJA`xdxD-hd6AfFkhz2_v; zcn}UB&bGQANU}SgC>EvC;&y#s4B5xKlcanrDEZ;PPzuP7sZfD=k&zJ8B9i#BU zS=z2GInX!d7u*A4p3P~yeA&XKz?GNDE^jH^C%3&yR|!~SlL->|INz6&8k}dG%gniE zCMDwYtKM^mnT3greH|7I0AsBbQ>YPp0kTM}+qV6k?NoC`Uvqh1t+qr0B7SeD91gz5 z1)0|BYquu%sqXyj!LZ-L7`lQ?SWD?uSNiO`9t~$=5FY%H^;71Bx#vUGk0l1M6&!2t zp(HW(+sod(9(tOot6S>NrM~nN$Y!d>=N{e6s1T_vH>$phZ*$Oi2(07MCpCJMu3Hc6 zv>2}a@ty~?%wOGRrN{LmG7NE{>#6UU*qp2C130tcX@%@=ZGG=eB*(%{3r7>bSzWz9_GG) zfhclpuYx(7LeTpsKwM(+i(zcG%>q+3riCq3e7DsR+hU&H zE}6u>V-&Ky4`~|rUq562-W%$fn-!3}#cFeK+`k&v=7^`F7hZJIOgJ?^Pq2EIS)t?g zatcuJ=OfXzo8$LrkrcC?+hb)>BN3*87cIMGCtA)nWTS@F#+IFJgUR^z3IskJ|K?(4TI}61Yd7iXWLJjSI;5TZ&8T}jA%b(bPHR6%o5c6?I$YM< z7Jx4n0EU#LZv2!4rNab zR0~Rp#F+0PyRbD&+@Fq41AZKgl>WT8Nk6SRPd^Dau#QLRk9ykqwD!8M?Vo-c>uPgA z1%9>#LY-pWZHVb+!tgOUe}*UPvWtE5^T|g8Uwia=AKcVOE$D_8S!S(oZjTAJxpJe5=a$-X z-%ZEb)SG*cRJur>J)RW4`s!Sc@&&P*6Ftbr1n5}*AR}|E;XmcGfSdmj(3Km*i~YD8 zw?4=?dB4L0*2L)7fBCB6ob8}$chP|;&S>c(%jd)=jIdf8qY2kZ4Oxo?J3vk*clmmI zhlprq&o;wg=-q=QDk>}46y~;-k(V3zEa^h1|7tD1LZD^{ML7LYpYH4`K|Pg&a5wup zS^PlaXD0aBHj~w|zg5=Ruap#{pmv@H6Isi7YzVbfc`Uo(WphYd>IwP9^;2>VV#s#i zD{C5}OGeJ2fHj3vyZL6q=4$usloF7FJ}T&Sn`n119*w@jvspl}xD~+}+Yl}v_P#kg zQQ}3+JS0cJKFBm9MR48RWD#^yTQ@_frFH&{=h+i-_d8rsRu`rRx7(s0kiYJp?1WjZ zxGhbpJzSFsqhLo!JwRhOdk3vGsy3n zL6kIS@WeOuNdHS*gTS9A`Cu;A6t21M^^}kWP*E;BJovdEJeQLyKf^%lsJa{J5itB) z6+w8!S6z$cws#-ykVoD3+mAFWT{H_?a4$ugLVSJC(hyAv$uZ86qRGf*%`J{laj$FR#G|B<7Ag#mSRZ%>t0 zr`4*r5-9xe?KtZgNU8$kxp{}Pkx)L}%kMjkRpIT$ckX(bxll!DPzHYF%p<)CpV9UV z%KM!@=DDKVm4Ew<>JRRKI5CQ+^z)q8^m(g>svcu>Lm1lBb|k7bfrg^MJOOA!I0O=} zO`$3z!(a;@3voMp6Y`|UN=-)siHME8{4zM*q7d-oh0Xl5#RDR@KJBY7Z{J-@iNI*bSxKhx zmMn_NtGspQuIBTMJ1bU+iSgUbTiQA-x*!ygET;~2W-`Ox+w=Umnu<}M*+Tzk*?^aI zzV*|LpS~EB+T&?AaQYKv<;a+eO`f}*KK7^f<9OfXzo$Z8flOf_IrWAs5(kSqk{{c` zhq3zrNpF7Ecv+ks%_`QbuJ`Uj=2DzxLS9Oigm?VZb$j}^?P z?#90B=^;%inx?Vm*tT9KTU$x*GVwNjtir$A*j5ZTqp)rc3foQ>`kU9`nGD!Uek}~r zxBvQ(p&Ez8o`_qr?r>t51P0%7``NW8Nk0RhVlP&N4(QAjztp5cKW5JQjj(ZgRBym? z1?p876udPpbMAf|%((lPph&9C4a=egVPf&6tR)FlHs$q!4zf8mHIH#sa@Y{XD+_tY zg|O^gQIa0rygmP7Z&*pTxASuCE~INI(fUZnR;vL+Lh_I6sBtP{Gcsqh%Hwxt{-@}l1-i)B8xJJ8`1&0Upf>abAl_}m@ll`?rVlGs@E$G*} zgV8zheP=f&$P(gg7Mv-`Ya@f=f+PoPE|6aKC`#k&5^Hx|AczIhnDt7G-1IUEh~TRt z7HP0|L(PG`MIj&8E3b}bE|yt8gCUSE3H?L1FXvm)6Hw>4Et5C%ouNZ)ld@1$o!tO4 z8n%RIDeLC-pAzTEo_!Dqf}2FGE$lDO2~w?UPQ$#%%k{|D1IAfvneZ=_w6cNaN&}K6 zdR5m!+-nWj28-uLW;us`k0iP1-lgg2&Gr|S3mxwg58@`o;Tv~E&-N5ewwWN8(O-)t zMs`92uJmHwM>s#0LW%v`>j@pCGS!k}zM{4p7q3t{( zNX-0oXUCNNFj-@>p&`}xkAp;&#rt7SQ{!uR#oC>?g%Qb}4H<`FeYNH^(P(XQW&RG; z?#2orr*AiSikx(okjaJhPNV4$U`1`iFFPUiT4KFZPL{jV~)@Ahi8Tu#plGP}-w#km3qG87htOy?$Uj#WKg=`pZ06`!pnVrYpvV^u8{^)wbZEJ=WSm6rYFkvp84F!dDt! zueTY66r0x0k^!Bfalr0WH6}7LcngXGNW7Pi9bfewyxK-3xfDCY@3ZA4iQ>=F53?aHE)*I|Q?CTV_rd{BE;*QB}FgN(qpO z-1_E7+r3{T1PqyUsiKrbA{GEU(QA{A$GCxJs)gc{Kp3Jrzs{RM@-59v0l|E{(y-MI z#+s@$yJNCDJtkq9%`q4Qj=g`dM^j>B_a(kF$v@4{d>U55Xh@aB=@0@JSDR0rg{YGi zKFHiJ$&0&GX}9RR_xjBQBRsvxFskcCC)xdV2Ciq_heVFC7n^WU)p?s26UsER%fH-1 zoQ-=b5l~R&akAQyYFGJozTgOO*9@7Ev4m`ii^3==Q)qd}?ux(ZM=`AL77vrAC-)Q^Vd@7qx zooH=69`5Q;hMS)tXBRCu+oEda?2Z$Xw5|PBO2qslSsiesc5KP}_qf!&B;uo0N_g?S zz#mD_(k&TTaWXeKq{hAd@@ZrB)MC&CwfGr&cqPj}JeXb^54B+=l^;Ugq$p}u+V%U5 z4TJ&38cH6$e+3_wS)87j_i}BBbEsbwOk`L`g}eyn8f$816^)ZYA!e9)u^Yz@v>_As zkGCHykWXKbPsi~6Tj1&cZLrVj$LzfB;a<_ryio&aAi@!>>1D*T0{={P{@YlZMI~3* zGjU+Mt=iW9Qbz8HBxk%x%Upvjr&eJcF8Qi0WC<0%od**q0*8Ay5jiNYLDt0QFnUVn zAmHPtI~KBdm$rZZ*Ditl5#(r{_Hcdls`Cxi+McZX)G#&`y1F7>ppdzpUoHQeVe zC(&`69g(;DnQvNZp+4xf@r*iIWxSOEdhZns4Rb@IcLR!<9)$@w025yiHJg8AX}Tg6 z73X&IMz&U)F31_zLSJ$kJ}y9YEB4_i3O zM18cOaR9i6E+L=;$WEl`pL39r?H(CRa`Bs1O+OJ5mSVMlep=<7?H@Nou_H`2#!D+=Qn#haI)AG(S|cbbvZVV?2DA zm;iMEH+{5*0oqOHRZ}_Bn-2%@+>fp?n3cWVKc0AB-~ZP1MkzeP0^S6wnd2BkkSevt zKD`emBm*c&Awg%_+3)1FoaGcl`qkw^$kd$rp+etw7O4L6tqh?h+up?}*QeLo`T@h` zc&+X_&JSIcYJ`evHHA8;=}AnwwM8ZSrl0>Tb^0#Vg6B)x9nf8~Al038E%#B7-XZv( zkFz?160lo^(5mI6h6u#UIrJ`Lueu$ZO6GE$qNsrE1T_XAP6_eWft$H+3}-?&xm@{4 zvY`w0T{2(seN!!0{>eZC@#;&Nxu>Kgz`Xp&C^$Dr+S1Ox0n`GvY)IT9876s+6bSN*mtfy#1ER)f^BY7TaU z9d3WX>KtvuoGz^Tfc5pOhu6$PXk30TUN0yCglTWWr6z&)7<{dQNIP$-K`)a_K#U%PVcDG z;4kubV)t8emy-kcez`WBZO>8&$#cX2uA2G_C$1=AFh=F@|;RC-(|GsJG)+c)V z4B2bE-P_j4JO*$*@79lxXeX zT;K1Sk>GICeD~63Lo+_G!i~0YbUO~7>4ROCb;-XSBy%AUcHKNcaUix#<&9oxINrW? zH!#jn?oLbNNDuk&{!m}k2Ir=&2tQ)d9)cF&P!I26p1aqnuTN2GIF8Ny}f#={j-T11+~0DiIf!ibx6 zw*636Q{0}MJP|&9vRDMP(8yB#0^Pdp2TRh-DBD<juCVq?%dSNI?tE1^mB?xc9cQve6bgKBA~Xne?U?9((8!0XJ{lrVg+GUlHXFA zSSBxnTF7x<7j9JO4kl<@#^PFjITm{w*x{1?gF)A2@}G8dIrZufGOr|lU*LCQ`!l6^ z`!>I5-2mlJo^MSEuPcs{KJwmuOTQMsHSK4}lYB*6=Dd`=QfJR>=LYbLQ;@BJ@90_{ z)U+pNgM?i0s%6H z*)_r@ga%hB)CIO>zd36@E&&-s@ai$q6{Rr}JG(lGb|{xUuR{NgHdq%ajfVhn@LH z=+Fn5N$xW1!FkQ^mDeP68pqSzVi9@Rz1d+S;;MsWIw4(_y8d+liMEs1TziM=b+ z=1cl5f_G@tu;q66eOK6U_p z+1zhX>8Q@~7$wfB%d_k6YJcJGIw#$=zUDF9u+B#WE}bav03E0en0) zcd{Z3ZsKCUM6>LedfYUw&M49pMxZWBj1>%vxszM-;Pu{m)ajbb?(Lz zFE07)GsD51f)xL8>~GuT)W-Oi-(sbjX+z|#UV~pejjTRa&VP9sqqw=Bv*nIheOkFX zv#3A6uKK=)HG0G8t?iTT*Si68w5Agq)w}$c$LyBA7=3YSvsc>Ddte!(V3ZRNL#k;^ z31hrgM&iPkE1_o^|HG9DyV%r>u`D z3q^j;P?`ntTJrUJx{Ux^2xG05_A=CQe?8RVfu$oM?&p4A$^KIe5~)D~OHz^)gx?US z7O4t1r$*u0B`Z*DDa55n>rV3k*e&(m3#eaAfOgd%?@A)0pOeS#jaBnzO9-9zQaaZ1 ztB|~pN+397;ljoCI#HU5?$;;I+5eApb_&<-3_0}s9i8+&{yYo{##JST1F)B~2f2p! zT!mNUA^1SDTu)WOUP1v=tn08LUw5-c(eeil4_Vj%dFJySFSGE zhCv_z9;}-9D8aWRGc)I>ARS0T>5@7l4G=n(-Br+i0~ibQdMkUB^@zWJS+50Lu$^}b zl#R+8w|`=74Bn4TY?%Kmc<^%wuOM+#gpAmbFZ}q>Z2%a-cD7%-iy(gLzq>W<7Z240 z#hf<&eA->7{`60Z0@FNtcOSwLrGiZ_zF2Kq%wN0t^tDz!ds*qj{8V>VCP z>3c1%_tzb;XJoQ#+$}$C%M=e!evsh@QMYnk28TrY{vXeKzK1=G_n+-`(Wm&f#(QQW za>3Thj1#y&AsXg1vBg=Tb};)%EIW#0!%bVTIzs^l{{DnFC7RyiahR`>_g6pFi}vh% zkId!LX}8y(G;BP0|1u@6oQCt87_$wHX}{0e-a`Cv0>tMF{=He#ac=S7jfrvw)eBT$ z%PrlBW_{dpZT~5!i0h%`!%@ETQ+pJi_k!v5#k?#`aE8S7wEt4d#n$BYv_gvXb+p6N zyW2^rHSspQ(yjTr#NGJUM*=Hs1*a#?sZ2YrUx+V^gqXw3E;4h>wLqq7-ZXN-EvCa8 zoVO^7qyuOnv@46T2)qihTRXm*AE(+dI@_;(9Ib6KG!EG(ckJ1^(TNH z`R}j)`PE6sL!$zAJp8^3%W3=Tj8;;+T7 zUw574q6=nmJpZ>=KXN3p5Za;6f|&;SmXOK~cU?iIEMOd20wnos5tC=pvB-!`BmlkZ z#>Gz0neO47jqRKXC7pC|2N_RF{mugump?CCA>b}!rEjKO9@u3!!%5+XMs=5{V>uhb zt;;T3%ah=*E<0QIM5eRR%e&4WWCFMLWo6?Q20NOo*2=N9!DpLM`>Jsb5vW@g zP#qp_WL^MsXuprK)+bB8Q3)zFguy^gw=jV9;}afb;s3oi|>q08)5iiFu{D| z&8Uq&)3|i3{Iyv^|KOhc6xC#QsmOoYw9#gZU*?M^~cae|(Ip)bve-A0&j?K*9g$j$)1MNtRHCoHE z^Ch0TxzRl~4R(LcyWDqeXjFA1d{Z`L1|_L0-E%Cj@>&@u1r)mVx#(6@No!p}ps$HO z))tfE3ss&o3ln|(oO>`!6>f}6U|g%&YINoXRO6sZI>eEbI$6nWwxQkEa4Ksjt8-K% zCo?)I^a|as0bUPY_BZT9IhWa3J7siP5zj*wsGXGU@H`-~bAH6EssCJGpt#I$6w}Vy zTEx3ls2o4?dr6hK^V;WW3cJ#SLxe2(Nk|+WQ%;US2L!}^edLjuM8mzxR654qs|etf$lbF7Q>`(HX-E1eQg+<`aZK7YqzI=hNN)x02A zc}*_Cf5bw(_teqC>17zV%V08(x;K0g>g0*pj@Bb26{+W@9`K?M5}>oBr1PXhm(V3I zqtK-!7kjGNMogJke34eNv9m&FG=P?HxsT{IzLG64)XSjWRMA<1tk_PII)TX=Jddo+ zUB?1@XV6k9$H%%7&)ogxni3s%STP-8<}zQ}eq}JvNER5gcI0QNC3f53($>q@$uIN5 zA5;k%#mMzoa1k)h?!Pf3M59mmBQc==^1aD_>U+y`@;=P0O4W~BxS_IgnAm3dpADha zKN~`DiI$|s9B`ykg+R9KXyVljBU<`#22iJBai18zpazM$DH~X$&EEEJBdfo2 z$Cf|3F5}QHyHqMm48M8oL?VJM2%Uhs%A6l!ltPcOZC-LO#cfnCJb4z zRPZYN`ti4?OMTR+z8B`_H_(WPkUsonzFTQXva*1z?Q>n(ejzjF< zLTVs2YS@y5cO#Kom$@e1RCHzqT`%t>Fpoxl z3V1`cu`y%^;?iaLbnaNg%Ded8w$4< z7YJJBj=vQhR?sD2N#EGs8r1lMj6RF$R0OW9n2@Gz;UCA8=5yqeU70QX8rPgu!?`;q zu9fdF$!daVY&*_yBnr$;_e0e5PlUqR5Qy0BQrm?8yleqCoIuN%v|^<*JAZK*s{Hq?es3Vi~T^ofaiw=^0s^{tgGKOcvxr8L0C;&!_swjg z8Bh50d{>RcT5m#&s5Yacx0}^jU!IA^HeCthpt&)uKsOiw@tn`R4>DQAUlvFM!y;_$Qwi|%QWj&M-I{Mug+tt20v32J}Nm?mfM&wjPBH;jUh5-<&NeCPwRRMEpZvG?J)d8-T zbtxw(p~7-l^Pi^&+R2;O+$Q%gZ+E_pS+0E*t#LAYH}(!s`cyd$`b`<9a{XAng?>kk zPu*nLdt`#*Ku~qQJ=*&XNlP1(%=GlvD%svD1!nS|E}|HRdIv#qZn7KAM|XEgo%G zH|b(-zOfTN{4V9~WPa*YT~mB!9+Ff8)coJQA?fZn!X2PdLw%yAU3NA{V2N~(ZE;g{XxoAc z(7>yoR;zEvj=hdFnk)14auB8x_tocj??fCXt*^fRW0V2^k-N5AfgvhukgA%EC3NX< zh7ehjE`UMpBS_`vw^5UE$Si}-K9+q{kDVdnZwE)F*Ia8O@46Ev_AN;{7hGt=CFEj6 zEK|K4KU#?g3lbF8T^k(j9_RZHMO92LFA{9nijZsYQ@Qoo6w>8^R&~>5UQDFO&iFDF zwWf!YmG#j|5Sj3Eb5r-JO%b}>IPLtWBQBn0eJf|THR35elMgZr?LUgI?BmrR7%N?BEZnzTsa!N%h(3|ElRF7hTkLjT}z`<8nbu1I7ShdI#>a;t#x*U{5oa zjfq5Jo^_g*fAS$^Y9L|#dFo$tr&8r5ZerN$&v$Rs{?CqAcvk)|`oN)u)p6lrmq_1u z???8IY_QFit%r~j_M2EQC1K;&nSqY(p@`=uV!9UNoIAN8s#HoO>4 zWYB}hFk3^jCsmq;hpKsnPZp+LGB&s<8X?H;Z@d9J^EW=YQl<*EKgqo=+Xg&H;ZHG9 znAozDiB=;)cL-W#*)dLGzI$4F8G_YJp3O4vx;`)_hKu4Uy86hQaGhOy`~h|Tg!N|+ zDpi9Fp#Wc&Yh=s61)Hc;hGjq8jXh`>QP-?{DsE@EQ~VeX*>29T3DPA(3BZTi%1AqL z?d^VLZau@?OjbS)T^y~7T7qA=a5Q_T-xTp4I&RN_bcc};O~?&Mr+xJP#B={m_YE{b z@MdBE;Ovz?`d)A*@l=o{0+(1x07}2wmnl!JmG3h`g5ju348l@Vm>NA|zn752{s-D|F$%&Ov;#4~+B;9&Ibn5YvN z{pcVsnoT3Rm zKY!t#V9oF{ukqayrD{^G0U*-L+$@-f9vDd05B1-R4m^S3tDj!D&nGYNfoWb2JiFTg zL&U8=Sm7~8x(%^gU*r*5-xeh${Zqp-X8IqOQ%w0#MDm{XQ;qSumpa2wZ++uZK=u+E zQAQ_PFOI47XDzg}SI%)@&{@o4vjSYYYpR{adTW%-Zn1DJY&4o)2@ES6t0DkPxb0fp zCH&rDO=@5XOn7LV-Z_Fw)Q*cu!ezXvkId;^ozBGs_zK_SQ!8?l9%Hp6IcdObIgNg3 zfRPeYN1GJ9-{{>8gB$d*a3mC5Zo|vh#3^gSj2+)lPc?W*iLRIml!ImObX(Q0bH-5u zu!1n4S02Rsxfc}qTPFvdKqJ!Am>$vpX9;JiZ}zH+m^E4QH!p2uCr70F(jKp$(&Ax) zsvm@o>0;`iFXnyWzOvzhxL>-@=4D(Rc4ibz67(x#Gk<{BOms|O;lUVWZagmHj5@xf zf4hDA!m*$*=NoX^aF!lfRfAMJUMihrHCEWE5Y8XMV%TbW#P5>Fn|;PAvLlU+*=o=8 zPL#eJ_*FT~e}od51SjYd`eEaPF^6S9d;sS&y#HH5T2L-)r!^}Yi_EqxULDVM8)v{w z#I9Gk9RW4|D(Qm1;* z4F8d5`aveBs%X6QRO!Du)S@J>A1d9)tsKeW#ZcoTnp!|^A2v>?lGIgIlXA5EeT$nx zFgef=fYN))pZEc^rvm^U996p zm3#4VORs3&;}zoZl4h9eECDdKi)D{&`}j4;t1W$+ya%<1B6sho=3gHPUWw*3ga$gf zC%Cjy^j0OOa;Q<+!&OXV3*}=;OtO)epD6$%b#dx+ru>Fynp14&XuA`{*|<&Tz4Q+U zck7E5^A$HI=Z|gmMEX=sqM|L6 z7^b4QHp}%eIW9rmy{BE0g)GT^Lo5>}>C*dq>rLjK4Z$Hh!M1=O6ET_sfDLFtErX_| zc@W5!%l_bzmYuN0(Uz7MEs>@v2(JoH8P4kCn!v7|I6f~0I-q214Du#j!84fI&MmDuRbt?R}!U;`7t zcs>VWVEn2_L$?2vnJLNOR)f7)vx8g@&_4$t!|yZFAA0y3-P97mkxQk;kDqyXMtFq8 zBNM7Ka^8Ld6mYlnPD~U&pl&Vb^wCHEv}9TyItg!H;1i`nS!Na;*T#Yss&^Xz8=axSz&|=3{wE1xVZu8 zWoCMe=#e**HqUmnujLTG?ydF9S{Hs=g^!LvtYF}EjM_eksGPT*k09pc=hRIZHEV5_*^#=WG%la4{E>SSrN}95{Knd#C zUlU9T+h?A%w6s0$2WU!t^MpSfpP%|;9$!rC-<8P+#+CNuiRUdLsQ}+PqimNhD1`%J zq^%L7J2A!N(Xc0p5bD_SO+(^x?7`TX@4j$8yj%DI?(-0d$?l0}Qbj#g7lxEX>h*Rp z)8ViHYO|f59@2A;k#%*VO8=TRJVvOW7^5yvdoL2y!oE{2Ut>Qro45W|%ewKnIaq&? zO*cBFAX#rDogWNH)c3bE zqMo+K0nKJGW4;WHmADNy?jE7X!co+T(6GXoy;zE!!yrh}^+tL)cNx~%d~s&0(v?wz z+}l#82J=A3a4xtc-^-+{Yo{JC#1G$y$?1k>CJml7Hj#!?*P|;XzQt3s95Gv4_0Vj9 zwtKu)Zz|;awuDZLB^;o+DbA^34Bel*6nL5`wSRd>eVbLyuuM&jvPz}wI7;>SQAIx)Xa+CSSA<=2<<5XbW!!Bn>6ZQjr}` zhpW#t5X=?m!!l**)C;RzsE^~m{_3)A4fIOyvO$HBETU)i#;ay#wY61hFVr;HjiT&N zf*9u_2Kzjx5P)7~FFD&>A@pEf=iuk=H(~)-w`KjdAE2QGQ?+5vY^=R{5B^qd9pf>X z{>YoNfBp4rrJ6k@Um4XTPd@~+?q#{tz+B5{!4Lx^k?_o5fEFBm?X$LVk@xb(wMy%! zT)71LN_XpCUx>FyJvIYHLj=JAYO=5{fV}fJK0#f6V9d>BrR|!E$dTbQ4)!@@UTRED zgT)L;L)fvTd)^4#_)X>Vudr+n32AG?E)P7BXAZTPt`8a^N;}CcfiY0`FzD7u&#Bvc zqun#(IGsDl#aiFNcG|6oyyEzgIa07IIj4Z^&QZFhd92eTtuXl2c=iDi-a!zEBw&O> zJEvBK>XDr_f=Ew5O3uq&YvC$-1evqLE7U^$of}5)l{$An@1n{E0wm6wB?6Ej`6m_d z3;3ND<|`~2p%uCQa&+*-=%{xN$JcK=d-7YXCB}X!mKPVqtKRI}dyS6h7WL?DXq#!6 zxL3#E;)v~V5T8)G-0INb{c2Ao%?@VS>e!w6Av_F*&MT?wQ^TEi+`wY`@3};0d9tZE z8gT$XF}H@fHgUI=%ToN-*P_FeF!Oh#&OW#vP*92F200*180kW+Rp@jcLA8>7@#!Rf z&s%|b{C;s{>Ya1inXT>+WrNLG8dB-FUmz0SEK*Jr_Z97%Ykq`->3a_gj5H3p;qf)$ zaR#=XOAyty(E`7Fd$F2fi#*rvVxkwUo0g+iORA4>u#7@cq9b4mPkw1=x^lp(ixT}B zGDyoHiqcdx^cH3_(9!Yt+&6;z(JD{KSupTEn@do6(d`UwlFVhoIc$zOh&$?=H+}rG z)QA9KUQ&v8iGiTl(xwSdw3AlU3QRqlyZK~=!iiw+0>pIu2)f-sN~7)j)3A&1Buq){dR9;VhDnvp3sRwZoVb9(;aF~^xX6O;e5*L zKzpEK1PW8i)JsUoHZxT7Nz7}IXwPl3x~yKKg^7C*f*aKkL8s za!H~sFy3Q0!*uBiv{5!H0pvZmIg)&1JgyHosy|+%gl^w?Bj!=b{PZNzqHfwB&wM4%Yn=Xy^V-IQU9DyJ`0ppfjI1i}?1P7j7o9#lryO z@YjKff1w{(;Ieey^SVI&b9~kxgq)!oQmc(U>y3Oz7L{I_S|5$hj-@NaVtNGznDkKA zXv>bne3)IwM3OL%ZA_0SkeQ<)4D>*dZpZf1yl3kC+CBQF{nDTugq(4D!|Tvm8x*0! zlr;%&ay57!Y#x+uEXv0$Yf|r3OgPw?;_~2e^HrXkGpk%w*)n{GSgY{m&kezR9Xn8k z!Ph6rxq&PRS@oU<4MBP?&tk+RyMT@VVaUnOB&txC?JJP#BhrRR2YME_(I{;1tfAh5 z*8sqe?#nAMEKAWIrrN>)J%sC)fR2Jq-jtH8t~-4z%XX`~Jo{qp#i7;|<)WApmFLG_ z@nWgL3-QM_F~JqCZAAn=r;nDf;f^0Cs5HZ2<{7paAg>t*pqasP-Y!0rh9HhXzo{jr ztHeEaf}r$4ls_prf5|QFD>5dH;6jQG79iwH1&YqZ+Olo+?C%9W*L|l(nVod_@Q$no zEkXe6Cd~u#NUUa%4zWiweYa9R@+YCCd+TfcSyErtJ;Zg6<#sTl^GN{t0cOqS0`|Dc z)V#QAr|>;**F&Cr^~~HIrJCp|KV!N!ba`e93w7U%G5=U>L7DmaJ3Q6T-zic!xfBDu zy~NfTyW)LKi80`w=#_WGr$MIuYFj;RJlPwrk$_$#f8LoEkg3 z|C;!VmVx{(4S@+b2MV1XCVtUDR{D-}>B6fjG&lA(3 zITNW~LVM8qY{Y|Vx^l@&r82nkcBhnp;N|l9Oq}#&uxLD8cql*Iuc9KMsyzBD5lQmu zM%FE31e-OSZr}XLS`*e?Rj;VQHkZAx#y-MQp+-dZ>g8Iu8-AZR=_3U-o)#rBlau`l zulwE;Oec?ZLnS?r(l+EV~#=1$T z_i$jd6ntglmOLX{IaSg^PlauIeA&W|P|UaBGhG|}YD0vP#^lLV2dK#TMU_)X8b!Y# zlRw@=tv0c$@4L9Z7abS=Rm8ocQLx9;sRf8@vu6;Z?Mn%a)SNeBE1E*YyxlE4vSX3; zQGH(Vl`7xXa&xe_eybi=l6YIg^vd=wfE3giIr!^za88dCDPXdD3*ZJVJ(QuzPegAk z%d`FX;Qt61%%&6K|98Of@4~y=xXm!zQnqzl+)Q!d2#wb@m%Sz6R7*@Q6||(&678Ep zEN(Th$!b5&+tc^bW|A}7wW4g{BPVx5W&AFe6?yNi1WuodP$b^*cHle-nwk)}5kv)j zb19|uRu0`7$=DON;Dyzh)*g=9ou@7X!)r9(AeYKRXr>hiDKbUjMjiN+e#juf%$rJP zi4a>~_OIKqA5PBGBH^vQPxl*QHqoJ!)-Z&Ue6;rqJ$~{+7ADuHAH7#7H#xTs^_-)x z+HRdJ8cY${XEBC|1V|{?LiV*aHS%P{u>(R%WHzg(CZ&Sml$z(<+mB9KgLw|ab{?IV z(?`IiUJ}A`yaXg&*zfL>ncmq_c=A#0 zQ=XDy!q9y%O54g4(DbZLFd90m@m*@{Kr;lDmtt}8{j|-# zw%4mhstbLgPnl*iCL>J=6bDwjot{Ds9CF!9)vx`8BgX)GEVs|?H=cLlH|fzi1?XV& zb2ny8hI4KT-I_U1=M6kx(b0goJVTU+a{!nxbCX2bjw{tE`8j8z?vyUc&yf1eJ7{;0 zfmslKswE49pA_X2S@7?1VL7uV_x~1;o`8k-s%3J^ClIqUh;|Cjw}mQ%pM+}_}%+o{M1lsjnjr6-zF00 z^Qdz~YZi9=z$sUh1VD^63!kmSPxlK2(w0%KS=bD3UBx~R?Kxc+x}`hyt=3Hd!MhNE z#Cu)4FYd#(d6W(5XlvsWr9hf#pX4pZ_!1GOjW2{2Y~<>ePQpjDn8F<>T|_V__6hg$ z?$Bzhu>prOx}^^84{1hyL_CsGbb%C3h*6FqvLUleo|62Qu9jZCAit|VuI+8FN_1S` zCQVWw*aAe{Z&g3QkJml}cLuAf8r&-*&B{5|-;T8HdphF2Z^q`+E!3J52nDm_#*N6y_VH6svUAgYC;&} zXOn*1Uz&pvzcU=8`8In#ayi7-HafbWRRd{x+00pRNWGQpC&#Q4*wG9pQv9*{mJwff zS?GAwM~b+hG1I0%e)+Y-=_F!Wx@f-&wMS1}s1@G)F`$>& zA(%@dQ_7aD^rS#qfm{s&9eSxjBbh+n0+v|S_kieAzqkj{n4gu2zPK_EG-u2^Af4t3 z0%z4cGF{lIE442Wn=AY>q zhnJ7=`Yug{#MAJ%)QNuORCHIhpt( zol~vTy*_ob)R?f6DgR2x^?)U8z?b*dtis$&3bN;bhXKStYK6AZ{DV(5%T7!reh{G~ zyN(JA65-oyUGm81G5*{m(>&G*%hmKy@Ii`TXINQvBu$4>!;Mm+`319VlrA~LtX%`3M3&4Hr^4~`gHQP*yC zkDT4Doyb>J)w(`HU?vyeEeMr{wi=+Fi_~m-o+_BOW&Ao@*N||^!2F8wKwnu+Fb{(A zCn$fmXaZ;*MRA@QYt{zz8_B?BK_M_l|J`uu7SGOl#mnC9wwUyqgb##5Kn{m;sCkic zf#h2@gMD3nyYq>e0g`HGIGY~5!vb%aiv4OXA9FdlDDk0PbnKWDrQA*+MRdUST=T~w60Ni&NV zk)5gNFn~wBK0q~@l$s6XPa9?yfEJtnB%#9N3D+9<{DWa4&d+W(LQT^86K3RMJixUZ zi_b=Ci}T#i@a;D{DlNhmPRf4QSwHAu7xk1AQ<*LRlZtx|jcr;*kJ^yr08CI^Y07L8 z-sqUXf%kX`Eh?#7i-0;+9(5R2bWWztMU7~;6SMR2gSttpfiJrd4}p{wL%*fIEtTDQ ziZ4vOXfb-jNkI zw^wzy>TdeU6y@A?OPe1)V12xu`n1lo_KA`GGFO{F;gU??N$D9~(n05?M$9gA-B*`w zngJ?JpEWCKcanOEL0&wMW|glhXz$4t>V22MIic|)6%x9aLvK>D0zE_jEF$o6AO zO1|fuXMN<=#eKQP-c?rTK*?sY=|N3e{>)xOG>}iBHh*y(E{{sIYN7)jo^iz%SKLS@ zp6|ZW7zrsHdF#JEBX()UJUDbdD_Z;^O2A2YtMQ!w$-AYOxxghHBMd(rzHPbNOTO^o zYF0Szew_Q#m#ta~o{$5_8~G0skIz*NcN7?Op=q55AC=@k+XsxTxWj^Hb*AsAwfT_F z5X~0ISiq(19J?^dZ(Rw!_@IUh>rdN;&eS~vO+*Aa&Yp&1dNy45yicjU@ZHL(U)ytS zBC{UsjSd0mFocsTn9vpAh+(+L@vjE@vfZ9{jqAZ4N!vf|TC?1Mmc(;L>G;;vthA!E z0FbzHpSAg}vVdGmPMM)3r-#Bp3Yk)h&e7jxQGp=X+}zEkCmg^lc~A*nb7vxfCveu# zpB7vPFd3?z@2)nzxGZkEK1P2jQp_i|`{s*ahfHb91fs*)pfOs&;#}@x-d*~>qLNf+ z0?#0_1)7TUFH($B!uQ*aD9Q%SP|{&`h?}!Cz)*Vy2*I2YTd=M8>51`)K}NMDn!qC| z|AVt*M~i)W%hKldivl1hZaS1seBwM<7S9GkWW}Z;?Z0w$UE4U9R(1PNyVZCJ!nu$S z2PlDU${QW^ZY`bI zSgQ^~ta3g+%K)001vC(8pH5Cr%Eg6hOd7x7{?rPWL&G~2$9~=!jO)42(kbyupi7?S zD(22^GIZaFDOK9IzFrSv5JuTs$Fh=3$ER$Z77gL~!NU}Y94h(VGm{LERQcxyFlkGU zW56d9gS=C_=E7DuH)Kb1gLVDdf0_%KmU3cynH2igc^H=kGmrqWNRlI;?=r4 z5w~Jw(gkgqx$RXRtXenDMVF=T+;Ho-DMRA3y^@NZAeRdkZ%+=i@+p0c)~aA8DZC6& z9|RyuHa9C@eEe(Y?BczshG8Xb__}ndYiRYMH#BaWq)eB^reAIUO=W-8-oXMYH5MI)cc zF>TVic5^_(SIfapat2T$d~zXDCdS(*Anw{QwbrmK3tPQ8jYrYA9Jo`{PZOw=;C`fe z=E!a)ASdD=$R{ZKJ@A+}0{S(r_TW~I0E;65D5=U%xSe@+bVT7aJTmi++*agM^vL|l ze1KR&!gK{A2@rU36w|`7-g^i|T%(G1Tz&GIPC2@6ePiWpfS?PS7rv3TBcg1_1u5~3 zu}&_%?{`J-?EM#7>b4ljXmR>Ey+;RKKtcTdG3HNKP|+2Mh!?)`@@o@`_yg9BzgYP_ zDSk-B7A>vTj18W;@eeQ|JEA3z%ClmDPrrCigP-{E22Lg8uaW?$h_Z5=r2cYsIk~emHM?;nc9J}m zyMSZ2K_ddaAaj-LEYC>KEebv<=j1l=iE-txu*!uBRG&|2QtGDP=vW&iu?#)3$$=>S z7>!BJ6JFfEpvi_Hv1o6-rtxW7@GXH9-?^CE!Nt&^}-zmn0@Awdd_UMD6MUw z<0|vkxs6AbLUzk4;}=b5Nve6=HNb(FQW&DXaII}@i3IbK_J(M}miID#`v0yp^*-#S zXx`>j)U98aV)Mg!5q9TnG8TimUO-&OD0pj$M2{~11|^X9-% z39WZtubrhgzTh*sX`xOve4MrH<>xY$EZA(JEUn$YahQTJ4}mUXg=g3Yr>A2^i+SoF za}RF+un;Spo;lnRdIBz^oyB?HVQ88X+ujf05N7XB%2|{YvfMa(kCY__j88Ed6a1EN z;rnCjoK@u5?>ACBro4=w3r>UBQ)&eFri3SW8vP8o4Q!Yzh&im!j2ENcv zl-C?o@MwWae|duJoFAT4;+H)4HMTdUKn^AVOnN1Cx+ZCP%Oaap*>jnzQBau_AE9$ zf{Th~BV2KD(_s1fu82)^#cfZiJ2m(5sdTyKSlzBr6Xc?WI0BFhn8Df4PW_|j@)_%I z4@UI+v+f#+H?O_B@EWt(*YskfkZ$pPm4~5K{szhfZspKfy`OWPaTj2;@lrLrW>?9~ zuN)!E@xom42|*lWDBO|5dZOy3QnIih;3?ITq!>-=5cIClWl*yg)t=iE?I zMlASQ<>ja0r%tXXPpBQe0M{B<7sW$2Ns$b>WgqVffM*A_~{(45LnX%CP^&^(+Wsf!v>exlDqp9M5FoZw2EXbnjsO95P{Fq>$sn0Us~mx zyv96j2Zt*iH+6K5cO4v2sPC&lEfr_qk1A?lhHzfsZ`*{S_oiVws-dxop%|w$MC^Rd zrM(BNf$gU@7zQJG)s3oqL+lmQL6%BC6T`YB$T1yn#+2N#WVakD=Y zwnV-jXs2{zeppHc(cTj}DFeFDTQU|-h5E?P7GOHOa1MN2T>T@9cYc7Mbya@;e1sH0 zN_SajF+Z)T*=a2Z8!lP;+&W{!9~a`?u%0=qoyO=g7e6k0V}xDGUL2ztxOb(lMFd;v zbv|%_>L5Muz2tu}*31|2gIdWB55G=LV|aFjbgM}@)pX}~XUMaOHlJqQtd4c#Gd_N5 zz7lCi{tj=`aX-0@u!JtaZF=XpJy>1dc_e*SvqT4`4`+h!%TW5g1V%TCRP&P4xBuZ5 z?fBak{rUGT%I%GReV_?~b~IC8K5IZV`O?Ceu5@q-3dm9c*zRpdK(?uC=SBTb&j(%v z$f$EX5?qR9H7|9C)<5GIcWk>WgiR$00ri^nUye;?>)gG!czf2=8W0RMxJlKS;(HA- z@+T3*vG5Bi(Qm}81XGVDVY0WX(vniw=ZQvIjN8O);hC-y6#2O4@jHZP8DQRuChd2t zh~H_`PqZ?@QHfiZE%lqOj+-g&>@PH3#1o|5yd}(FGQKv&JehgR$zAf2fTUi1VB+aH4le@%-1?Um8dQuE|egrapBvYb3zN_CPAg*iGN(P5sy+hg^Q1-$mh2y#IdyPT!9 z%3`WC2YCejRBe}v2m_#`kP0w+;oXN|eDB-fjNHP6BHE^EFTJGg-lnHpgD;?D!lUKr zxR(;io%PV-Vz>5AY7({_0{iLZNNR0aPw6@<(oNCGzZ(3q)j80Ld4p`{ecKjePnWC& zi<#OVDPRA7k8kKXnUnD2?=z@4JM`|cg52#e`Q$Qed8@$vJsmoQ9sWTJha+= z^pHbY?hl*U*aqpxb$TdzoP$TlC4W8j7GDf?-7!;}A=!v*IY^Mg&4LN_lm#xJEe*Z> z*=C<`#LUcvF=FQF+`%!BcWvlgR9=FxsaJ*`LST=O?*g&tr{YKbnPo^LZYrC^! z$qcu7(NUb{V2p1|_;lqSjQHJX0~aB30q`K2dLt`UJKHhYlbweT)<|(P#!mg%y4*7MpKhMZO`Imgf0& z@9NY21ylo2VhDkwMD=SNfPO<OQKrN^e(~RmRg<+L1llt4gVzc&S)B?ulGluLXRfW@SCk7U zr1?>zg z<>{4f^$5GT`c+{^^eQqoVTO`n)o^18mbc`kvPie6|Ncv2>ho(W4WYjoOA8D+Tj)H3 zzcUrS9OW9&F2$r2u9ye>Lwor~>~99M_&*KiXA?3DMLUh*JfX40HGm4!Z>Q9-G*{B!YJX`UHhL80_aSt0CW%NoQQGn-S&Od}=lc=&JQk?m>8Z z$NrjI<5rW}5|2fvW(;CL-_WFC780TL=Ed9Tw34u{nS=7dMJhF3bcw=RjUF)aCm(d6 zuzg)st@P>v&FTt0{VgcVv09vZmZE5Ez%T;6VpAjJBuJh&XpN^+riN5^Sr>#H?g z*ZSn<3aqs`rdz#>8xr|#(poFY#1hJIXFMmzE+xAOlVga>joTyj`4!uFi($OVEV3R1 zfPCW|9h7c=d_SEctJ8dSCy@PcW378VK#!%jQ>m&k)fJAho|zgI&b$}JEB68w)0qllG*zUu#Rc# zf{236IWkLTevWG!r+|8J6;tKnBy|?7`2fAa`23An{Ngn7X>>M1(kitWL5lVsV=l0X zau&7;*!&vYJSK)qZ&w_GFJSBQ~90 zbHm+}lT(6yxz^gH#hORj@m|LMb}#aZ*Fsrbvr`jIx>KHR#>9>0`* zcf#Va`iiz=SagD5cEvEzHkypXz*&ERHsz%!d~i?wIEq^kp+4?PP&WSnrzV?t4jnw9 znNOO}>wPbavLr7(8{Yzv@){W4O*_44PWR3-TwbNv8CA_JY}Hnx^HRLPr@7KF#c%FB z94a!|J`ZHVtg90phj*lHnuxkG!ES_vk3`}1jA?9gp?79V`_0@2LPJ@PAHl@JvOs5O zgr!}g?cn)Q?sN(sY5pv83FRI}p4ripwvl?e2$SCn9K*g5^PZe90yS9N=$oLK)gG1s z64qD8d87p0#M6v<->W@D-m7+M(c0h+GQ>wF=;mCNQkwr7QD;#s>i5Rq+@*Z81&PTk$9V92NCGd zU``BkNG;0|0kA7MLUF3f2pb8W%nRZtOp_7qSCz`z99a^T#5v9N)Q#7Z3V33&w(x!E z-n+)=)_*ZYW1qZxQaLsLRo=6@jd!q*srse=p&Rj|Zh7zi3|T@FlWc@NQ|-dBOvRR-~nv>8W$1_3%kwqxY$IBW5~= zso^OY{oQ3R=Cjf&ecO?eMyd&clIY)=<9El)qR`uB9hNsAlNk2!>!Re2$GNn^pgBNn zZHHEO65sWt69T5=V2wh-eRBXFz1`URAVI#z1$fGc*X#gRy+R;|K zUn2hXeYvUyeyG_E4{A)Vz#}134{opz@~uzC-pj%)TSlGEb*_6xJDIjO7agO86PM{}VrM~fz3$t%=pSbpoFIq!bi6=fP47QjR7=VT@+&KQohwb4?W zk&m(pvh?(m_a_MlS>pTfH zZ>7Jwm*8F>4K}BET;e}@rt?YTC8jAfZr`T@I|S|oRkwIi0_+=RAL%i9AODA2ISbaB z6>rt~c%-DSZ$z5M@uJkkc!Zb@WJT{dfB+Pw7F)k-C%XKwd+V#sMx;!62tA{i$V-WK zf5i#rWCW9*tysmomSJxfUDh!fC?|iIij(dziJAO4v2hEd0}QE2xKM?e+kk4t8cc8A z;H0S#ENqyrtnhj|i8Ckcte?K-L8#pFCt0}7C2HWXjhRo!_BBVFwHSsGe&V2ZxX04Z zUqX9Mc}qSVE{V^4Bc@t3S9EdLe706~f~fEJ>1g#xFb0pcxGZqmAPR3Uud zr=6BWL6Ks7!^M08($`*4a@}qCP6lbmzfUnzz2&8x8kHBRTF`d^J2ylh)>E3{N&`Au z@@K9#-K|N%--;=^M*Wd7fu4UBAyZGNv}rRT4zcM~9Q==R0+~{7C2B}|cf#zU&qTP0 z4e@{v=L6?R^0w4RrcPmTlw6W=5z!KgV{R9-^)I~+)f_DU&8hXC%5fdu???%w~U)b%NT1$Q$@i zdiTx!^GQHeT^uiZxQ*QYdtK+lu!%^QH@5{>hv3Sq3IUbY5Z-XWoSDf>Ms|d40 z!CAKw(0VIXrTOG}CJ5?E%YvHVV0u95b{ze2MEL;qUWxWlnzAI=L+8+RVXOsi05`uR z*3lOhECoV6Id(N8D%aEwBOS=lkqCT;02b1zr zv?e_%q{a^fHuoldUQZ`1@Wc1uv5ody2VZuDaZ>T&o~xem!o?p0PZ~0vYOVXY28FnR z)I5y6cD`S`MIWg$HOoS-Y{l=Pg;X6Qf^3F&U6gZ2^iv;Qvm9zI@qPhztK z+&9H%vfjxQbMnG&&tj6>c&P!tUV#BaPz0ne$VC=3vE_5RU%{E6&Ed~)NAE~K3vg|J z?4+6cz~LdoNNb;W!k+6p&}raIk90+)y*-^4emL%+kiY?xlGiTJPwbVrT0^u8qxnwP zw=~1pTOP%qqu+>)lo@kc$F;nlPR{n*2fL&v2w~blzQ;!V)%^JK)Bc~;3XmofG5wLh zCueNljcNT4Up$X6Ut0@Lj9aS&7@7#hKijo11@d2y4J~e_SuC9C!)SKg_pj%fJ%Ij* zqh1h>FR%V|T>*6=HLMkoR!}yG5Fp4T0j9jGivTlJRvn6e(Cb^rcw)+O?WGbTd zG-riW+S@YzcpC^-B_U=zJgs9PX`O2BK&;AUog-$Bu;ZIJO+UKU$joy6`_^N*==nBl zdH0gMea&#F@&4;P*I7^Y+=e+SD({xk(Wsr%toho`YweZ3kF)HbG95(NpX~xds!dfc z&z4kPXZ%#7(U?`FC}Ox$RA<+=4RyN?NlHgtXRDqoD3=l1_^jTYD9Fp_^?DZDMNTM* zj)(wpsZKadgw335dU&Fvv?u?B)@S*{-+OwK7U>EbJ6FmMP!saGE5(dcyZeuN z4{JhCU8~x1+_JgtcTQ+z?!O}D8}Nq@{;3y#E|C?NHg@Pg@2PhEKpINfIoGt$>1(ua z-_^*NPYgEW6pTe8!m7HCK3@CcPtD=)UHs=bASb?#i@TSzj-Jtp?-6ggyS*c!J0oDc zJUCETnRqY_@r&dFzMAR#z0uGA-dKPBz5nOftUoiBDa%T?QOf7gByvW_Ks{4ld^AQ^ zBC48dgyZk2Y@1zqMFHrWt3<7lCU&IRbjL0RWC-6mj$9IqJ;#a`B@i~XNupyCl1VKv zI7!vpK7Ge!Pcnb}v9V_MijhCTmmZeK$^6DS=M_L}IE|}WjexQp`AwZox0HrQ6e-xC zHL8-m{RgOXiLmD_hZhlvYNs{|9J~KwX&3IGr%>(b7g!hOllzLKmQvIn&-=B5kW!*| zdJTHT{0EoIfB7@Z{JYowv7yU#-D|>kkZ*K)VNo=^>3-GWb_N!d>Z^n3r>Nxk880lj zEB(IcyTSo2YZd9{8p|$!`B5&pDzEnV(QIb9)sR2=4(MTb(Z^NqZWEv~n3MRv1+~r` zsW^1Lm6BH|KPnFz8Aezh%2!%AaYDSjTf5Gbq|?Jz(`%3kuS6pB@=oxjf?nInDTII>@$L);)Ip}pG@<;~_-b6~sN z7L&US9*n1WvhY9ppjzI`EC16s|8M+(KN!0|s5@L7*dxW_UsR{972uw3{{S-h;lJ@R z{_NELJyzw<&gx%&{r?Mz<$w9y{*?p#VPpR(*^+;C8H2I7=ISh)W=x-oslA0P95{C~mj{b#56KS#G~ q-Mv3pxc`&l*gyNt{xlEs;Qs>q{#983 literal 0 HcmV?d00001 diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md new file mode 100644 index 000000000..551fc2959 --- /dev/null +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md @@ -0,0 +1,13 @@ +--- +title: ML profiling with ExecuteNetwork +weight: 6 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## PLACEHOLDER HEADER OF SECOND STEP +YOUR CONTENT GOES HERE + +IMAGE HERE: +![example image alt-text#center](example-picture.png "Figure 1. Example image caption") diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md new file mode 100644 index 000000000..ea589f59a --- /dev/null +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md @@ -0,0 +1,13 @@ +--- +title: Profiling the Neural Network +weight: 5 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## PLACEHOLDER HEADER OF SECOND STEP +YOUR CONTENT GOES HERE + +IMAGE HERE: +![example image alt-text#center](example-picture.png "Figure 1. Example image caption") diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/plan.txt b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/plan.txt new file mode 100644 index 000000000..70e766717 --- /dev/null +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/plan.txt @@ -0,0 +1,20 @@ + +want the performance of your ML app +memory and compute + +how can you find that out + +different steps: +- ML network +- app around the ML network, especially pre and post processing, and the network as a whole + +for around the ML network - streamline profiler +here's how to do that... +Also Android Profiler, memory example + +Ml network, it will depend on the inference engine you are using +- here's an example for if you are using ArmNN with TFLite +- if you're not using it, it may still have some useful information, but different operators will be used and their performance will be different +can see structure with netron or google model explorer to compare operators or different versions of networks +may need to use a conversion tool to convert to TFLite (or whatever your inference engine wants) + diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md new file mode 100644 index 000000000..3864750f6 --- /dev/null +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md @@ -0,0 +1,23 @@ +--- +title: What do you need to profile? +weight: 2 + +### FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Performance +Working out what is taking the time and memory in your application is the first step to getting the performance you want. Profiling can help you identify the bottlenecks in your application and understand how to optimize it. + +With Machine Learning (ML) applications, the inference of the Neural Network (NN) itself is often the heaviest part of the application in terms of computation and memory usage. This is not guaranteed however, so it is important to profile the application as a whole to see if pre- or post-processing or other code is an issue. + +We will be looking at an Android example using TFLite in this learning path, but most of the tools also work with Linux to cover a wide range of Arm devices. The principles are the same for other inference engines and platforms, but the tools are different. + +## Tools + +Currently different tools are needed if you want to look inside the NN inference, or at the application's performance as a whole. + +For profiling the ML inference we will look at ArmNN's ExecuteNetwork. + +For profiling the application as a whole we will look at Arm Performance Studio's Streamline, and at the Android Studio Profiler. + From a593790d21d0b6c379ba26ddd45671b5a6a4d6ee Mon Sep 17 00:00:00 2001 From: Ben Clark Date: Mon, 21 Oct 2024 17:15:15 +0100 Subject: [PATCH 02/17] network profiling and ExecuteNetwork pages --- .../profiling-ml-on-arm/_index.md | 2 +- .../app-profiling-android-studio.md | 6 +- .../profiling-ml-on-arm/example-picture.png | Bin 63167 -> 0 bytes .../nn-profiling-executenetwork.md | 68 ++++++++++++++++-- .../nn-profiling-general.md | 11 +-- 5 files changed, 74 insertions(+), 13 deletions(-) delete mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/example-picture.png diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md index 2bd02eb5c..a57070750 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md @@ -17,7 +17,7 @@ author_primary: Ben Clark ### Tags skilllevels: Intermediate -subjects: PLACEHOLDER SUBJECT +subjects: Machine Learning armips: - Cortex-X - Cortex-A diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md index 1d63e0df0..e2873f0af 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md @@ -6,8 +6,6 @@ weight: 4 layout: learningpathall --- -## PLACEHOLDER HEADER OF SECOND STEP -YOUR CONTENT GOES HERE +## Android Memory Profiling +Memory is often a problem in ML, with ever bigger models and data. For profiling an Android app's memory, Android Studio has a built-in profiler. This can be used to monitor the memory usage of your app, and to find memory leaks. -IMAGE HERE: -![example image alt-text#center](example-picture.png "Figure 1. Example image caption") diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/example-picture.png b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/example-picture.png deleted file mode 100644 index c69844bed44b65c7f5bc6cf511f93987fdcd7b95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63167 zcmeFa2UL^U+6EeXMMVUZIs+pJ3K&D^keLz00^~3ugw9BmUWCvCWE@9n0!I-cw2Yt$ zBoKrEAw)o=Nl9XeA@m-4?}T>aIsboV=3oC^_ny1%x@+CD+#$)E@7wuy`QH7O=Y4nB z>)aazoVk7D)(ybEeE`5d;RCQYy#Laz>(`zC_7n8REi;pUoY;RJAS?&30sua~fdN06 z{`ifJt=%_Yj{SGJi$p#6Z~A|E7hZR*QAlB>1>rL=K-jpj zv-gDbIk$h(py+Yc+ z$2;gtTVKkT9-qAL3x^5cZG=x501EIEz!dPKkp6$Q{4t+?IRJppDgbcc?|&R~!2$r( z#{j_j?mv!w_d5V^`ZoZeob}*tz}7u}=WNar^)7=pWzx z<6iuqjP)DgcVvX)^b>R&We2t{K4`k|Kf9+cLN^2s%0NhxCR2342er9!hT)&(Iw|YyX1G*pD$YNbpuWc z2fAPMfG7Y0SXxBI8koEvu3o9F9q37tmzIAprB%>XMjXhA4}>KLsNmCG$d;nQBKz!U zYNUm-z_d@U;^SIB>%#Vf`Jxs_=rrOCKi7ppD}!qz$W({{}+t$RX6@e=*G_Y zXfZ#EbdqXKPu5b}BChF_VEfJI-7^1EW}&Q+=*Xy_rZ9FD(U2>VTtoKYPU9wnWf$@N zh4lCTLJI%?PaI476P`EP^mJDzgvVDWtde3-B1x5mN&{(~0bSZOH0A*43$*>8QuYBy zAc?Z8n|JbeJcniea_{dJuUoB~K5~;D*EaN61h{(rr;Pc_IFt*Cl6*a65!jEw&DQYuWqt=E0h z)CcR66Up?;>|G_)@52`S2MrtW7smdJP`lc>MMUS;QWBOkvP(C90fB${4;r`FpBcOP z&k}A-T0RIG7^>x8jY4(c&K!1q`yVvy{eNNXzeu<`I(m3~1~44;nV$ zFO2;c376*m57piERdxU8-0!cd`>X2ys=B|b?ysu*KR~8`Ro#d)|DM+^#ymKiB^J6E z;x(Jq^mxq`o9D*yQfdk$Cr%pIuLb3$5h0p&-|qpQ?Ey?RZgf=L$8L>Zme1&FosLtl zZ)@{vCNR$$WViyu_{5^SQ+Nes3)}3%a0T06zy~(J2@F{AaqFkRpRZ)Mj)_Hr;}a_#>h3zDPZnzd@`U-16{#~a9!#;Nm!Y~;hBms3><*e zsuAn-W1I-??jpj2VgmLu43Fpzd(tpcG6N1Jm9aHBQp{w%T^rbfZ2kBD&dS*r5Dr{% z95NNxfyUC;UDXLF%c|65*UAD{Mx|aUq9xm^J}k?A^TY$OJ-{y=JNFUWa!!x3ztNn3 zfr@%Iz+JnW=2AFJwlryuiOo(Kcz!R;XS=eY^`%NWKHb&TMc2&)z58SD!9BnrxW*Q~ z2RL+ZGO|`JsWt)WGdz=FTR!Vq(Iu(DNq*KBxhifc3Ixe!r9h|L1xe_ffsi%ma9E8I z$L(U1iyzV>hmQibHiIT!KIyo(aZ(8uFdMJQv3d~ZqM$tcWA-nZDqj*K|0rQ^XDu=6 z4e^-*syfVgX<-RF%0@>X4n5{rc{vMWzy7&?r=7HWa+(u0F}w#zGG#t#MeYH9@LNz^ zQ2ImoUcpSCj2^D;Jft zSK#OV$Jpj}z@hpcY-zU%j%KkQpO=QN0@o6!^a$@ck(jiau5jQwjI9~GdHyilpn$&~fzUf3_ zloT}~CAMz8(>l$(z%=b^RS8$$0~h)>&c zY;0m6*K7}9m!9L|5>b4$GevscICxG@eW+WS$gT8f{tOIwPy`nh?Z7jv;AX6BOegQe-y&S5+ zT5OmbU#0ijKW`d@)L;#$3FfndQ$req(>V<r`EP+m`3EotXa&HJRz#w_i*M2(G= zhzaj<$cn@sU_Zn~u?(_NLmH&)Cen%_?A`IdAH3yy4gFd>No{p$&bj?gcBSM^KRNqp zes9g|R71N^=Zf4)13CY;h^6^L#M582q`v=4tAF`$;)l7&(4LO!@98URc86Ik)O2Hi z+0vl_Ldhr11MU$5^sAs5?V)o5?x{QN^!f09Ol-HHfod1vlrn(sSl+hab*RxQH1w#` zrcb}SP&2f?bGznBN#~)Q<=_9(4B&vZK!3gu6qET)Pdf9^lxJ0Zv=@{?WewOhQ;aPg z%))e+;&KOxvfn<-)EVyB0}L4voCwA1hh{ERwbDmesx!_p2C$*Aj5DowRZ&H2e2nO{n~b3 zcm<`v4rPmM3nwT3s#^_IPGPdAC{`-!Q~R~TQQPhfZcj5gE{BLzpS9G!6q}@`$@W!d zAnXjTZfuR?*DtI`iOg!4RS{;}(2JT}r!3E+5?$yMh1no8<$?a=gZY=GZ+&53VGU zX+lYrKMn#7VNKILH7|FQy+1S~rZEnaH z=GtHfHQ1I=YV=-{22xPs3Av9gDq%9k43SC`ALg#&9v9>@&kczx#WDJFMyxL6}(Nggf#h>ZFB+C|r`* zp~=f7Unp-?e1E?}Rei{3!81KacRb_PG}iz9*#^&l4gLQX@&7zrwC}SXa6{0AQDJXg zBzhP8NeaHwhmM~Mueo54Gp$C3@HW2RuZb(BqcEA_MI*f3=LANi8e`XgswT-UhGM3QFG1?LLhPJv~f6OGAOssN^_AncelX2$7-Q;Jn4FV z^5DYe6ZK3jh4KBWqp=((rwB=8Z+#mfe+&>V|pajy;{)?m1~2p6OxNN6L}b?WMCJ zcUsv&-gm-mY&*P~K2id7IRSl^EqOS`mAsLnV`b_hi>DzTe3)Y>9NMMlYht-$qy{s* zwK4L7gQzpxK2?s$gr&i?rU;L$Pyx#yz@_NRPNu#Y9n(W>gJeCA*DFEGw1rdM3P$9t z(sk>igbS4xU0js^m}^>9(>W7;q@D3htt4)K^O)_&5b!2HcF( zqM%rJZ6lt|NlF5{r~8HV6=GZUEz2aqqz=+-SpveyW+(eNX@R>NeQCiuXHw2NmL5-$ zB*SWX8T7(~tZUmww(*&2@yX6dvI9A{rpB{MdSgT4S{sdCZ-jSjvydygzGruBkD~jMc6u zvGS1X6Jno%kUT({4OpIqAtvzm*G7JKmQ_-4o$E>ZHR$*rAeepkm32E(DNG@4EsD&Q zK9s_df`eJ*MrPfgD^L3`L#d8Eb~jS8&V>QXq?9~2aw^_1sfYui^pZj@CSYO9wt)iG zC9Z1emsKKJ;GSui=)$rWY{^A67M~XzJClaHJlD^0@xT?CnW67K*#oe5_gCzSwB+L~ zlI28)8`ychhza_K?8~l+J~B8;V7+ zH*M57&uAvftdiFC2eSQx>l1T}I))gLNmOD#7 zZ@S>zLG4aV+?ZHcp?x}4qG`~X78d@*{N0t4_FcM?#5lDsiZRbIC@d#!7Q2xx`L~HW zkW6Hk0bvg?Wx1^CQiX~ugERB6y`3Lyo?0lxgY+KY6(c61|KQT(KNf%a8RI=b_~l&( zza0tZ9X-k(U;?*;9BVY_mFd$~9Xpj9jgeGpTlKZA@^vT2E}MgTPVZ+2?sNsY_nNh@ zr^H)Y7!AIU4^dLw1GpCh&0!E(ar>RKYkJpK3~4n$Aa!1>(7EB0pJ`w%C&#sKW-21} zGEPK-(A-*HboyQZcK(KkYvx5Adh%#Vr94E^$<4{$MF(cKynG`|%+MiO{*Ygf z^yLsg2iD-uoAOmzr#*lX%tFZ!p;z-5D3iZ2c9$1u@mMCRL(OEm2YtkBe8-_zphARz zW&MO|hn+<)*IHw@&$`o*CUu;v-t{IDKp&Gzwk+xLZ$5(3>3Jc+TC( zt(%#7iiY^04->B;mrZEtH89u{DXmmVvmJMQWb(3if9J{a%0MbSkQD)~eR|>i=J`}o zV@q)WqX)$$_qDjD=i@Z%*XkO%{Z}5Gj+XhEL+7DBPmJp73XU1o$TpcuL@gt-`8eS!IgsTUNsZcY^fB+ehi zmjzn!F+1p6@mN8z85&~M-~XQf0`?{d0U8ipaMh~$H2wPUBjes(C0HI?6l^wlzncz} zf5cS9#VKYy_p&=oqk=p+)Wb;`c)sNjCDnxl-;N;0WILa@FS;}SHaO%=X-2yGVozr{ zUaiGdLBl?lJWywX@iE>8UhS%z1%J%aV2jBmLg#zgjXQEfQ+T%{!7ky%c4UOH8M<>r zfBsf>e0TJr5|v(h_|B}Ur>oOkpaV^2{w@OIU{6TF}n$>Wq{}&$w}0FU`{n5nSBCRnM4gb1V!KsBzDH z7UJW7TB1p}iH5qte`blUygw(TDP(La0ulIf(70cPW?^r)c1*r$|3PU_q)q6a70 zTo=rroEZPfwEdG7bGXlTWirF-I+J^Cir>P#7)R#HY*WtFFC{%e%aU?UO&ExT3(k#> z4FPKzrT)GQ@&4SBwV;m+Jrt(CO42l9FzFyFJJRt;7y5|X!tzb(tC_w7Vt49u6qK&8 zTj1sSQ_G`wNL-UWcr@b9CV7+^XEa&qOI}6+0;@l+2f#p=ZbgzGDP+4+KB)x=cRQGwtg>67k;)+JKnPz)ZL89{V z-|Z`f!^|x;xuQT|i%Y~?@^-`onzE6akX)f6Z2FZ`T~2Ztlm-}wOL_>jyH3(+8Za<)ONnQV`_cKxmvqn9H+=^gDnP;mb+ zXKrvxFS3jB%w;r~Z55RtyHMYBufD!+>Gyic&{q5K2uj8sUA zZq3d4xqY8d^@p>T68+ls1to3ULI==D<42(fK4gRW3AfL*itR_=QeHF|z_RHY2Xcr$03Ca5xbJS>pq%#=gDO*X=HbKO-ptI57u^(Bt{6Pz zGBM0Vvp%@3jinA{y3H83O`bk6Ibo0VpL<$S+mkL4MR*2kr41vw!5E0O^7Eku(C=jJ z&JB9TQ{H7Vzr}?wB_1azHhrnE)8dxN(h$*H;`2!#srqPd9|nQIe&dsM`pBJns;H>j z*#@o2nM8;27s0GL!@M&`+!6wbb?1!0w#563ed=k54@d}}{Bhjs{!}U?R z=Js4A$!+RIPp1qyt({21&L{l_x??*5YuZujLtL4Cr*`K>oAKT89-#McNRC5f1{m4Jxu4P5Swxc?r&FPP}YdEN9Oa^|j-Y-9FsJ(B2=0q#baZ(|ov z7w%w}qja^za~W=oG2O5-RqyYmb`U1hdlz((w6RzSVpyS|Esl0(^TdD?j|aq z7F=^kvuP5`7iGGB8xi`$C(@Ix5oI2M^pc%8ls>%X=(nu5nn;}B*bo*Q9 zId)&jE7nbsQ+kUOmCqhA zwN{}UFK?*E@)wDzQi5Y1QVE#}m`Bu+1J`tU)=9|$t_=gHb;<(J?l>?QmGmUl`ABK7 zpP6Np4v5E+&jF^-C|y2b)?3SMG!8_;XC`ogf^+WZ%8q!FPaop)bzb1~hSU@BX3DdK zsMs8OP}6f4%c6qKmMjV<7jLuIxiGLr`bUsQiA!+t7D#AnF1_QjE<)P;(5ICtUH5KW)7}Om8U~ zHnEEolNm19CRt+;cAiPBV`|k8-vyClh{STCTiRo8_t;@%#XilwViYb^8`(GUhRMsf zW@k$~AxsF--H`=C}jI6;@VXOx6hD(P>h5OB`2(ATLe$i44 z3HOEGV$W+TG0V$k;D9G@Pt(zN;_y*bK>d;7Cd|YhK!Xf<>?pJ`%|at=YQh_4yvl4o zQXEMypsIOfES~7b02&=x;2F+;P?z?XmMZWWqO8mah_Nv>S~>A6W}6-~sA>*IUo-ss znZm3(rmE)_XJv++JxSG}rg61~v2i)z z>4b?Jm=a!zs=`WdTpqSvPuXeyh0uZda0Now^1J7VXT-yMX%0*HI29~0U$`V5qja=C zUBCHxr9gyTU&va!pE-T*Uf26}-vFxCG+q_&Sp)H5Dk=BZM~JIwwGJtZRG?ilq_4Y9 zrbk-UqpHkfh^sI;TN*+SkI{p~cV7X=ru)=$^>Z;38TaWTNsTZ`4X(r_&U-HDDMitD z;q=oUa<9{;4Zp&EssYV`p46*?W1&dL<}yA-Cv`t2s`q_bX}d&9t!n=4(_p#SVCeed zlpzCO&s|fA8GxL_v)H@N#uy1c99m)|Hq6A0iZ?-a*1A_8W9Sh+&aa$rim38}%F3^< zo?dyddIAm?sHWRF0XhF#riSQ4DR3!co?PeVwbQ{5>S8ja+&20s;7Ikj2yMR+xI|4) z5?a81!Ww95YN1#g!Q(>;5i-OaJ`fHztrHtUFo7#qhgfI)m%xTNmku5epH9qq=c()B zT$Fmxp-kRO7UyHC?l2Yx9}K#hamSZ7IIJ=#K)%#QZRFBkzIURS^}g>N+5@}{Q|>b0 z%(5S%^F@vLJtW=DmqvyD!?fDZ~a0CYDpX3E?=kY@%rn?74awkI=C zzM~$%W}v|WKoFsJgtj{3XScb3p3~(n4KZXDNr&@3N=9Y3e*a12)$-)rW8T|=-(b^L zx*E6VtER(tmA$4V`aGJ$5s~xutVMlioAR;2cT)p}a##QEx(A3JSXJFFY5iFup83lc zow8Oss{!k{mV4qBr-Txq8cVz~VoT(sM0-G7yi(Zpsr7$BE~%~)mq9Y&O|uJ=wz!g) zNs61#`nG*2Y#G26YQAHkicX z4A>5)4cAB1S#Hu%S9mwl1-78Rgr~Vjbm$?jGFqgPr_Q~fvm#2su|X~kF8Lv z*CkAg)1ESWU4UT!;PH$yAa5ecY|hOo;Zt%_Wm&qP^QY2TE!ADJ?<-@tyo_ZB8e4Tp zXED~r&#v)P$rN4*ot0oZ0No1Y$QS13#_HdC%5xMNyl)oY+B(2qGs0J=<&|#wS)5pe zMwgn;4wQfmPKX**f6Q=fXYF1T)7&jpE0y%ItMVlw3ONCBBPmu~86k2ERHe3`c;!3L zSJ9}hGa)!FBUQ88^-@C{?&K=6*0UzQpY>Al!_?2^iScD7=hK7?oYC_+act{I zh=|b7g@fxcPoj7w$mi(NB+rLQ$iH!x0}EynKtDCm6H;S?N!l}gcn_gZ?IvtdY%nb? zEqqeb;@#UKS0&|JfT$XIH0A0%~WtBO~7>~=8V3NPDt`ZVQ>MU76AMg^7rbhX-J;;yU0&=8Q z|5vZd?jK&&xrWGAC5AO=iuG%FnK4wwyVWrA)6tj_^$Y{L+xNvQyo@m45No47fS9I7 zGl)4hzV)r&#agCn1_g2DM!E-U*81nO=guFgdF5``IL=)Rl&!%Jus(x)O$s8==YmKy zt4#&S@`5o$$wkpN5@yB&nga`3KSi1!@SOAECa=kL3oU|tbfz&oHo>tgDTyT3x=f}X z);l_3=NK1bbF0gyQ(1iUk+=q!BrwI_-%w^19j-WF^u*KM@pSn2)9;A8 z-&x>{n{-GJb#4*2BRzLG?bfA<3r%(taYT}@B}lfEn+In?OlVKy6HV-IJ;jd3A-f=& z*+TC=urUShu!S5t*~gjyH@#E6OlD@}j+uzEUK-^>b!V1L{BQ50g&X-3JZwqI4nvI; zUxtzNOYfa$!u6$vC;zQObluOx--^Y zsVpFt4;SZXa?LjJ%I|lj_|-a)ItxW4Jc+&*oRtN)1e)*iCFa?zR`ZrHxcnPzFS?6< zJ$l=!qdcma)!ND_?Rn8nEJ)8G&h}5$^ZW`$W!>>^sYVW)^-a&dX+_0{CBTefK&u;7 z{#8d=Yj$fU#!kcvVr-UTPSD)u9o#YX4?~SB!@*Rk!_A)pz*oqY@a7y{dx|kjy{cur zpACgvX<1r;y;5ouM)#4^z1PVdqa71`2c$VaA&$FzU4ZCpGq-77bt1h9;fFhUHiz0O4-s6nQ{p4-As?-c3dl-L%6up-44$NB4isAJBccM2=>hZBm1Px%9-A{ zpbkw>w=Ol^Ik`+j_(EV-5XUJtDPFE7MtWX|u7?ZJb<7#B>$8o$9%G49k3&2Yy~0KCyCva?p$P1W*p{m_bu8T z4lDVmh5NO66tRpC=(diiHaUENA&#qXQZup@qBN$sq*St{FfWGeK(m6GoNLl0y48xx z*+zB^t?k6}^%b3CH?`JF1Tu0l*;l+f)5hiNI_06)9i=XieXQ*rH5>G%CxgrVT-{lP zy)<|;;So@#dwI)d{m*dCP2r`md}&2ztT50bQZ-Y4CIItK6!xsMAjnM!J3|CbjQBD( zyb>QbneK@XGcyyyMxe#j^@z4PhOa9c^IJgFOTx!HlUXho5eVr1d_vy7l})t3dVp8f zKfQe{$5Sf$0lzP*p^-cf!x=gH7C_Y_2&oXw>gYe@o4p?@+ifOtRc1?1fSIYLee8f3 zkq*TW>n+LYfdcRpbjdNEn(?!HBRt$Ay=;`@$sIZsLA-9%zo8!CpV;Hq2S1bJ986*(8}bGt-SmQ>}9T;4jZw3hV@ zwIltaA$Vkkjan&vApL{RI}T=VdtpyjMs!j)P?JT=%eJ#ds`VIG*Bofsq=Rc{VE z#}NY=J`?3fGLlO|G|sH6%W=BHeZndeeIo5H5lYfkcFTgegZQ+>F6@HlorhUs<;ur^ z-c#X?Mn;3Z13pecTMn}}xS38WLWhvLHa-B2rqs%s)oD^vIjftV+3vfWujD?ig@|V( z3=rHL-KlKfiD}$ipyg}|o0NbSFy2+2M!MS9(`6=_8EK7FtFU2TGqYXy7lLe|k3x(g zd-l9&YceXB5=SLHDjCq|VEdn^l~xc5Q^v-A8wL8(`(CmwQay?J(;bR^ghtyR8l3ho zNlnN^H!{izPAB3OT=n&lB@u7Oy{L2XuI%j#C4n2Hf%S+Uu4%en zd5-d0z5?u}i!btOX+Mpnw;VD-){54kq>O=wyv-PzlPp%Ns8Qlux!uRVPwV3l4WEK{ zGcb_9F=!G6$j;nC#}-1f=pF#~>$f$abB!elv21O&Yg1 zW@Ak8MO0AdAmIle+V5RWyb4-C0`ezfx>tfK7j?d3d5oNw9pY+q%4!W`r*EBln_Zf4 z;&^{njz?&E)Wtl$5DeGs&cVf{yL>C%=p&l}dtcXdJbW{E6&g_WsD9WZKCQc=B0Dj> zs!DWz&b2Z2Q`75H6yx3^4;xPI9$*<&XbIZP$ENlrK8!$RJIwp!ZLIz?cGXPs045te z`vO|0C;ZwnnV_0J-Xnk1)wS%)C6fFq?YphP=a(8Kf{0@fFwBhRG~P*Xy+3N9KGQA8 zP7Y9=YU&E*_Tck3RMYr~v6ppK=FnU1s|EV$!Nmlmn@d05gXX5d)xJbjZr0?Ao$Lrs zUj=R3DInR+%bqUPNe@z*cFMZHM6=|NA$6)V{U*RvZIO7v9^mL!b^;M5j<8M*plyjM zL>S~@$F+z{#*u_avk|Ib@`N6)Ia|v1-gyO4+x@h`NN;73k$p``(TG!?OQk-T$lnf0csNIQysI`CniC)PadrA zR6CXe2Z>u&V}=>8Ue|mK5#H&YSfYSAzYQJLXYT=a>$#C`A-fs_{burTVK(T-PAvm% z<%ip#xO-?U$qMbrJ%Ed6HH9urg^(Pn{>0Xjl+;%L)brA}n-kbZ^g*(NM|+9su6^QA zJwiF!^X1$Lt>PrIPj_sGqLcG3&9<6>yk@W2U(e7pn`{OdRGO`t{&a9@`2M{?zAdA! z#_{P>^ozc-;5ZuGB#@;epQZGp+j0Iu_LeP5 z#7%S$TXe^6Sa(}Y-1NC@*bA8>!*g$H6TiLdTVO++6Jc$t6B6WCI?K$0XqY$9OTx^# zv?Y}1%lLvxbo|XaUa476Sg6$FxNH7JJvg*5=Fh|?F^rDQK90<~-+vwR*f{bwtxE3k zP)XSMY=rXu86kF=cx$D}#Hk+#Mfdp|rMx?v`&34sj=oiouWJ3h!8ZK9CA6jrs<9;G ztJ6*jN{T`sWH2_>Tc*uWu)y=6`(>X!>3gaJa@t91#mn51Fg+l%(9oSvjQf+KOdW1n z=@^V&JQ8ktMr&8xYQjE!7CsPnX+4d`>2Wm7dM3WcgVyn4W`6U_aXUzefA?dqHlk_T zr>_eBuIhTB+}cjWW>1qabI-*U!^RgGT=7Jm0N*tzawg$x2vP6i8ry=K=aZ=nW&n?{0I@P=jneKdML8r~a0vKS<{NjTMP1u5YWD2YHbJEG%EfC=^5~{>q z!V57$zNl!6f;@3vJhn(OoWxybt>>(?K9DGBQ#)^O@VRkQ2wWs$n$*=i9HfSJgQuCq zxMkJYCJvA|yQQd_m;DALx?{r!!;Rc=S3ZO!Cnr2k2myf<`r;)n5odd-s&VdA6Cl%* z=vJbjpyYZ#O;%~6FS#-C8>f~J^x%Z5*9@CVIF=X&H-=W%07r?V_0VjUIONB^mTQ|$ z1MNk{GL)q?nm#o9#+^sl984_YBILqa=mcM|ODE1n`sw?7VT10CPa&q8o9T!r^c1LW zw$sgJ<6vV$fK9Qena6QeB3_unl;vttIB}r?Hz?AD{V;29biq&Dbi?hX-Uwb>%K=f4oe?3&3ARqIK!J+*Q-UY5l0_cpB?RmK^8tKEaV|pD zgKuSKsyhyB2@6O)I1p)6kzB|Nk-q2N9o64}P0N{WiE3`1+6E!s#ct$pPslz^y$}@` zrJ# zF-b?BizW^2gezxyg>CNvE)?ym7wT&SAg3K-vS*{NCOQa=DdLz@^=;vvF&ohM`-hz# z5Z)+@S0ITDsamTMOD{dK z90KL~=QS5wt-(dDf;m=UsWFx`b#BSJNE(rOpO&GWW4H_6h@A^@-|)b3WQNg7KNT}`Dhs*dY&|pm zR3FQz-fo%{2l%?_RibpRuO}ViKV@%kU)+mYDac5pPA&yakWzJ)>ooc(~6)|PmLhK&=&t?)qr(jZo|m>y={X0wcHD1JVV=ssQXcoZahMx6n=kUIPmyz z$kAXwNnmM&AwMB%HB0($xt0_Y;&2*Wv%bEY##GL#%!ynvRmrw&xeLmPQ?oRu2MR5E zW0<*S)1{cCgT|28$e3P}?q0R-E_-_L_zfdDNL5Z8+Si#TjMVl)I*4IWUD=jmSBkYY z9{Aj#aAkMQJ@e~^T;G}7!3rWht3-K5zh$~5?oReKMAqWMv#@@reI~0)dvY=~2R;hp z@VtPEwAk(Qzky6AgW3<6wqz1RW@nhC%fxr1UI*_Al@2qmzehIoda5$+K`09O~a%CX+*Yxw%$f z--aSkQ;qyVa;MftT&}KPr7Ced+wWd^KT_aottk40WaqZk9;tA;fq8mnSJQ{6#hlMo ziVybVJWEQ6g`c};LpCtHO~mKL5cQRmlrtlMVqy;y`&wq)lVVb9?UM zEG^7(K5=(8LEnA0K&O#Y+Ip^&V(MlW7V1TeD1#eJ5hExdjgr;n<%QCBG6{DqTc`=~ z@xCNpkpqcjUa6881P6`A#Qc=45xCZI`Lo}|_BWj3nY&#?_XK+_ULY+TDd?DmR^f5l zc1msxxx@XEhho~ivem)U*o{^!)^$TBj$sfnDf5{l+S<&OwVZj}f5AWGP4vwZLX75v zSiN_*=X4M~MXS)HXiXv8AxpTUW8S<9_Q3a~c}4>%^qKXmfQ<9$<%ShyqQUumbM3q& zv?!=W@ADEL)FVSjVnit$bcwN159=(4-BVgee3p8BCMZC-n1L|e+hY#P4gfqzmTc{l z_Pg0HjkfF-tf}crMG=ymz*|AaP(9B?hY{Sb$P$-`WYH_nhEFkBLu+dt<}?H4JxE05ygT5rbrL!JnZNND-GHut8C+J9&x_cha!;F^6@ zxOju5Cc_da*40`&h`n7O95+R^LKsh8&Fm{P*$T4zrvz}g^XXHdnzFZhg+2Pm57bz~ zy zv~gKaLM_t(1Qffa9c^I&o|9?iy6dLtqYqd6n>=;!^hF4BdV6VN2D|6^i+VN&B=I!U z3&sIKto4?`v5Z@(_mU;lnPsLM9>QPkor>Arl+wGl2e>{d4BuY=IJa1%;bz=sZoOPQ z>x4%#dZ0SnoU`RwGL?=V4vtJJh3YGkrHFzXGa&)Qs3zuAlU`0DikZG?%(4z!PCB@$ zsIH;daQ9M1@*7K8^9YLfwHfA&O@eTvMulB~K*7Z=wZ`P>zQ)@rN%*4u1@k@x=d){T z=P;*zwm{YnmZD-QkD)#e+pCs6RuQu9von00$nSK|zAboXl?k|qX2x~|o9Ymibj|K4 zg$}*-9KwlfOEB@-HXB$J>TFm*Y!gj1fTsab^^9{HiZxsFlh(eJ2}Z4jA?Yg{#DuCA zkK*8`A3l4CFTn@cMx8vT(Q^l1IhH2>J{}{Y&zBi^9kLGiQ}(&7YgAZB2Tt;p7G|LU zk`MhQw||1#x0Ae)?Z+y8r)oGCA34wki5=VCGB1c`O{{I)!ItBG?VBeo3pd-m{rupQ zMf8r;!kT()d_9Bz(7dlT-!8sF%a_C2(3i`bnZX_E&IxPV@Q95=zF4JoIK>*MP#fgb z?luyVBm*P&r+r?|$Cc5zMEw-n@+yhXG$`f3EG*4)+EjDRF4D%wHzPVMK8yxB@vhZK zP3l?7Wv5qVvL|^&Ktv&zw&Ivd1Cl_rQ;(&Am;r`bu)}0 z_J=B`WUeT&vT^5|Zfb!02fHDdEJ)9*PYPOtaw}c}F3oVB#Ygo`!<+QHs8(=u%LTLG zJ0Cw*J!~L<`=H4x*Q%>019ZwIk2q$~o4z<-kFn;{*2_$%m(4Vja_41M5_P>dxihwe z(}?%P45{pMa2CxWZCsqqPgmuG#1_oLWVTzC=&77WXf+Kn5P2UtU0IzMDzV{##R#{N=N=!5ZCUUAQkF1cZZx7DjCJ zLpMR_0<*t!SVCfl`{jX@mwoS>#t&JGKgLp?E(|ij1^IM$l7N zo{y8DC)Uq}m_B0aCJA?25Eq}Vm#eq%LSyNgeOcv;Tjf!2!qqHUB^iMmp5*)`;qD(0 zXe_$c`P4(1OJ%vU4*i!s)7WdiG`LN8AXm10QH|SDnakkO%$gc}4Q4L9ymnP5jLu=m z?g0iaqrPn+GJ&6mYU)^4tH!ALu_QBk)8UOD%5{LHSA4SeGbFF6#`$_);Fw;qMKuGKNpf6$g3zvR6)y5u}i-MSIfKc1*cgQuwmbW_94sp6fk<|VAZRo zy{az04r#)mDVA@3jw4$J2X%=aht!|KIb7#b=In;%k{|y*xzg4^$7lzh zLTx!0jJ9QmjwNT_I`?nIZ~XmCo2sIN^KuGdP^zW_g(cv2&&K7lxO^kI<^}B{@3m`O zgG=q?N&b4h?s-RAOR=OvpMxrRlBfs`Y?({4H~(C^gM>D60}EPpL&Jjet6X-{hl%Qz zR;alAw1xV*t_Nen(2SXaOJ0YJ{2R#|I~q^z!{>%R`TLB_i(G4Cs!h45Y-#lw)*ySA zH^Wn)zoHGquJCGH*1*$gU0S5FU@pw0HAslqn^+p)m6U6NMmIiz)(OtXd}hrT6Y6~w zCG!b$QKk1Afb;H5yy42WYZ}DAUe>dL1ffJmf=}a}ZWU9OJm};RB zhBxD;H&pRS`o^LnLa8_uc9AwJU@khEgG8EYzyI|>O-V}%2VPf9&)Qz5RT`>ta(OX^KxP399$D!y*fR8Z) zC9{1#Henf9M6t%69Q-6eEe_nN@vSobTYC^%b7|VH`F&1eX_Pp*fFAW>{rg~Rl2)HrL2+RHp}60Q)evJM3&@NNMp$)uxXL_ZMh-%qJit z3KDnvD)djgdg<3$64Q!b5A`;uVfj3wVn1h*i?GHqKW3q9n7w+;;Hvz-44N=Ow2idd zw&6w2Ct@7P5VN_z>t7Fiuzb5~+o$PsHf211Ah5+m7yso#8v{N1Fa4< zhhddEilq9|5{ibx`PGS@f)x4RiPg^;?d_GGcVuB__-MV+CJk-%hi$fg3a%) zrxm?EDU#1Q?JL|H%8|dY4xT~!6gF2BIO10m(3aGI*l}|!K0-`v0Sf+YVzYe@fSwg; zdPLobCExQx`>FGFR{L9viZDkqm*QXa;v(TdK0ZI2bwu5<;0D8~%$Vm}K}6=7Yolte z>PJ4V?~k{MM;QxuPfW}8-)z?|)xl^YOj=ZE!dh`TszT+QX$Jk(#kpMzr_*%X_xR9a zNVF~D!P`la|HMmDYx^8WPEc*hq>GKm4eKjzIod8$PPw?aDk&-HD_t!0emyB&cE!6| z+jsWJ*_d3ptRDjkIHD~oIXjyDamc~M$=2nITcCJi9!UgYdL;smX+LalBIYM=>;W>6 zsxnBgpNmak`tG+Wlz7xDSfmz4JPetfDHXwGkMk0$yhcydK=1$Ve)!Yo%KDGfoqiuw zR*5pHZ$kQ4-w6Y?WvlVNrK44stJe$1H?oQf>`@P#g8Vv?&ff%K>gEM0QMUKro-i5z z{tM!1WASUX(PH)Oww)KHk(siGA|gj3Qm|Vp?t&ww*2A8{hx7X#X1; z_S8=O@FRNu$4m#28y&gEHe?lIWnNs4Pg@(bO1OnJmfwO#D=CTHt)m8zgovL-^0CKT z5{p`6+|CZ{cx-5~fAQPm!n;GARF{T0l`>DRFobt0CyjrOBii-lUt*lToV+;w`o`x$ z>lD|Z6XH{L{gLAENBC~CN_u`QzfT?B^EnsiW&{HPfudao`N5Nu#Z5kS&!Pf%P-52` z=%CNVk77;r{dX_=!%-02vd~D!i6;`C=4cYg;SMMN58mE9s>yS0`=;Ag_jaPlq>Njv zARy4lJf>BKR)ds=5M-=Shy)08n4zszCV{QY2_#$41QG}$1V}=l3W74l5CSq!hA@SB zNFa&tZJ+mfw|njNt#7UOThEvO?zO_bLhhC8IAEc`}X>r5LSpLyR(9nfGd!j$8)dLYU5fKlLNiHiWh+YQr=|5h7EU# z>Fl%4IDPdd(Z|X{F+ksCy}v1vwm32@E zafsAFR%ivxlsNCjshY3$XYq@0sCD)af??=QdHI`WL&47dvAdOg4Pj~WH)rhsRxMGI z?n?@{k|hSHDqhMb7v%q9c_~+H;lHk5hKhbdG}AwuFLoCFrJLh>=Y}owt*jb7{I!xD zX1ltfElGVaFKlF1e&xrSf9mwW-gkAs?t4wm%nV|TtdBS|(2E2liN28F0Fs+6E#yhI%S}CL-z6#;86`vRN8ItT6bhbBHv^CT$?{$>Z@4-C zR|oYwVtt=maq9QhehE$S47``VS~}$ zQUuW$n()F0a~c~j->GVPO(pC?l^V;eOXU<@0%JR)D)M&8m|*d0 zCU+My84c?jj@9S-^bE8|YwyMasUtdYnn;6C%$*IvVFui1jbYdh3F{vD*07PJv6as3 z?%VD5`mQ_ui~znFI#pNf$)h82zNe$rrhfhw(Yd1X%M1Ey{=-hW)lNBq} z7w*;d4t>WBVRB~Gqy#QJbg!@ZYY)|y!+g{*rZc36w;<}$yx5?;3HqpPsBCSqykiZ8 z{dK%ogGZ#}gUnkY(qmh5OP_s^30v~50ivYGp!?zHMsA8k7pB`s;XzD5ebI5)caREJ z(_R_3r4-uS6jpcD9(F-;taXwX=HA1fvZJQVBVJXo-1RX*loUVNvF>}H--w#9jfWU0 zp`yE5C%0-ER%2^eAX-*K-O*Z;5&R=9Tifr`j>D^?h#OZYuI#xxuQ1jPEoPPm3CX|^r`+zv5wqwuhlQN^1$Fbhl!~cpJ!}vRk=L&&V2Oz_JS_i8vkD!>kT=cD=6#-_#XkH{~S1Nc|%j zbt*LLN^GbnI7g*lVQPrN(#0wWgS!dIL!yLuB>#N|Z~PdMykh0}>#uQcBc?V!;M0B4 zv^4Eqvs$3GbL+HQpQ2?k%=LLBkBt(qb0`(8Qss5syfs8S&Ua>Z{4OC*CgvojK6uhn zr91`=SrW!hR&K*V3akad5kRavf}{6 zyY5;!NweKd_DMQ<+6#INA6To+Tk{rEeM>gds;W`5gX7u2W~=rMhuV)VeE5(!8|=Pm zwO<26CJ|#O^vXgXW_i3IVrO5E3M*5m>*r{nzah}jn$kC6qPdyQuY%Eq8MgzP5&x-SyA+iQNBKWdSr$1CpNzi{YK z0(-f2Bl?Zh=y&b$6A#(1q?~q@zAe{94lZf;eeTlAXG(JjIg`_htNqs!*Q{IXpH=Zt z{igQbuNk%lo|X9fB;t-eM5yJ8yhP%;I>^=ZbTQD`3eMyCPeCeuyY?65K@evc#NH{i zPo$|7*VdcOd>NOTshl|JOWe3eX$G4cHs34p_E@TNI^KK zU~b$om}o{%nuo!iW8iWyQ>e|Hf3o};X{q%~sdc2z@AUE-W_`;Qy^gFo@&U@BhvGk- zciCCqHox~^Xscwqk$krm{?_8n^T@dS_XfBy$Y|dy5+!!-JydSEB6)LMUY?hk8P#yP zV$JVqw2dBuxbX13wd;MBc35YGp_9?kgxEa$oweU*{ph!15<2I)h8cA9-bJN--|QfA z5vd|Cr97yl6ss5|z_d2H;2U1p7JYu_cD?e~&He%!FFi!_*M`#D%N>3>!Q{!MJO~Kw z|IyuEQUZiZFKkX61Vjt~M*3H!g~R}dTB9g0sbW`FK%t2@DagoGQ!&ysYRe&FHrre_ zwal4>;`D>atoT*+_><1@A!R##-75mV4B|g>?*AWPnSjocYS-k~6O;M|iPirk)_&(E zNAyaguFIXzUN4#4m3}FcqcbDiH_v5LecUN)wHjHAfSVjSK$Vx*I9sw3@5kC40UW$Z zG2znGk;cQhmE|Hst7)Wp+go9Kw+~h#V7H47ec9sJ(e|lHRlvhR6{z{7{1`dRaAoe5 z1`ZO}f1ASRx$c;aAwGSNvE~!0uXdcqey;CnSQ%E?_zuQ!l%~jri&ShBoqm3jWa{iT z7cva)*!*37=`TFR8G~2G^1DC;8CooZA$=Q}cw%!ZBI>Yr?ZN1wrXH#84jeTyid+wa zgBZz$Xf7lzq*lGbO_$T3UR+4zy<@%nsGo-vOf{hYv;f*H{i&ay8S0w7)O`zUy0e|A zQ_JZwwx&56mcb~w@hiC{(t`vqD@(YOp~>tfIbC?b922l>mn7akUK+T8+Qr=7hnl05 z3$+@-d<`dt1bL!i)%$hcz}PXK%;HlN8Wt<$}*Ac?tIWTM$7vO4HQ>e z=Pm!*9%T?|CGm;n42sJxW_CL21?OJ5aJTMe*?|mS95FYQ|DyaZmSM~&TpjS~xY?xFlu!;jQ4{1GOeJHkSjAOmMsFYEMXrrey*&6 zsv0vnV(2^(eh#)U(fWWnt?(Cl`F+nN0Ow|)u zE=!?1#n0eY4?Fial>x`6f4u&KX>1bg+2n3YiDpf~xQrf~sRMya;`Fy`c|&mL*gKw2 zUuW`7xYd(9u%>RN1XbNZITt#mum}?{^PY0={u-xMLt3Ordbu!k6+ye2L@V8ZLZUX% zmgm|c?|0u8k|V8FqMH<(vW-jdsdveAtG6pD1Qor6K zRWY|W51*$(^Gcz`^mIo}O@GY^wsFfI)umUo6-^YLg$3fxib#9W_{SO-@Y>&!bQIX})k zWKmSS%#V^DwH@QLVD3w$lB)YdUKymx0i4H%r>0ZfGREi~?#|4B#6S7`?l<v(9eIYWSI^AB9;aIAfp%1^Emqmr`Vh9KEHte0tV^I zA>N*aYTUtCHw&10;`*%+xqvV1oou=q1QG>1?z~=C&`1#CQRz%~<=r>)HF;x565tXJ z^7l^wKu8ybRvGiREdIubYGxfn6BY*Q>Iw^q9ESrj)thRJA`xdxD-hd6AfFkhz2_v; zcn}UB&bGQANU}SgC>EvC;&y#s4B5xKlcanrDEZ;PPzuP7sZfD=k&zJ8B9i#BU zS=z2GInX!d7u*A4p3P~yeA&XKz?GNDE^jH^C%3&yR|!~SlL->|INz6&8k}dG%gniE zCMDwYtKM^mnT3greH|7I0AsBbQ>YPp0kTM}+qV6k?NoC`Uvqh1t+qr0B7SeD91gz5 z1)0|BYquu%sqXyj!LZ-L7`lQ?SWD?uSNiO`9t~$=5FY%H^;71Bx#vUGk0l1M6&!2t zp(HW(+sod(9(tOot6S>NrM~nN$Y!d>=N{e6s1T_vH>$phZ*$Oi2(07MCpCJMu3Hc6 zv>2}a@ty~?%wOGRrN{LmG7NE{>#6UU*qp2C130tcX@%@=ZGG=eB*(%{3r7>bSzWz9_GG) zfhclpuYx(7LeTpsKwM(+i(zcG%>q+3riCq3e7DsR+hU&H zE}6u>V-&Ky4`~|rUq562-W%$fn-!3}#cFeK+`k&v=7^`F7hZJIOgJ?^Pq2EIS)t?g zatcuJ=OfXzo8$LrkrcC?+hb)>BN3*87cIMGCtA)nWTS@F#+IFJgUR^z3IskJ|K?(4TI}61Yd7iXWLJjSI;5TZ&8T}jA%b(bPHR6%o5c6?I$YM< z7Jx4n0EU#LZv2!4rNab zR0~Rp#F+0PyRbD&+@Fq41AZKgl>WT8Nk6SRPd^Dau#QLRk9ykqwD!8M?Vo-c>uPgA z1%9>#LY-pWZHVb+!tgOUe}*UPvWtE5^T|g8Uwia=AKcVOE$D_8S!S(oZjTAJxpJe5=a$-X z-%ZEb)SG*cRJur>J)RW4`s!Sc@&&P*6Ftbr1n5}*AR}|E;XmcGfSdmj(3Km*i~YD8 zw?4=?dB4L0*2L)7fBCB6ob8}$chP|;&S>c(%jd)=jIdf8qY2kZ4Oxo?J3vk*clmmI zhlprq&o;wg=-q=QDk>}46y~;-k(V3zEa^h1|7tD1LZD^{ML7LYpYH4`K|Pg&a5wup zS^PlaXD0aBHj~w|zg5=Ruap#{pmv@H6Isi7YzVbfc`Uo(WphYd>IwP9^;2>VV#s#i zD{C5}OGeJ2fHj3vyZL6q=4$usloF7FJ}T&Sn`n119*w@jvspl}xD~+}+Yl}v_P#kg zQQ}3+JS0cJKFBm9MR48RWD#^yTQ@_frFH&{=h+i-_d8rsRu`rRx7(s0kiYJp?1WjZ zxGhbpJzSFsqhLo!JwRhOdk3vGsy3n zL6kIS@WeOuNdHS*gTS9A`Cu;A6t21M^^}kWP*E;BJovdEJeQLyKf^%lsJa{J5itB) z6+w8!S6z$cws#-ykVoD3+mAFWT{H_?a4$ugLVSJC(hyAv$uZ86qRGf*%`J{laj$FR#G|B<7Ag#mSRZ%>t0 zr`4*r5-9xe?KtZgNU8$kxp{}Pkx)L}%kMjkRpIT$ckX(bxll!DPzHYF%p<)CpV9UV z%KM!@=DDKVm4Ew<>JRRKI5CQ+^z)q8^m(g>svcu>Lm1lBb|k7bfrg^MJOOA!I0O=} zO`$3z!(a;@3voMp6Y`|UN=-)siHME8{4zM*q7d-oh0Xl5#RDR@KJBY7Z{J-@iNI*bSxKhx zmMn_NtGspQuIBTMJ1bU+iSgUbTiQA-x*!ygET;~2W-`Ox+w=Umnu<}M*+Tzk*?^aI zzV*|LpS~EB+T&?AaQYKv<;a+eO`f}*KK7^f<9OfXzo$Z8flOf_IrWAs5(kSqk{{c` zhq3zrNpF7Ecv+ks%_`QbuJ`Uj=2DzxLS9Oigm?VZb$j}^?P z?#90B=^;%inx?Vm*tT9KTU$x*GVwNjtir$A*j5ZTqp)rc3foQ>`kU9`nGD!Uek}~r zxBvQ(p&Ez8o`_qr?r>t51P0%7``NW8Nk0RhVlP&N4(QAjztp5cKW5JQjj(ZgRBym? z1?p876udPpbMAf|%((lPph&9C4a=egVPf&6tR)FlHs$q!4zf8mHIH#sa@Y{XD+_tY zg|O^gQIa0rygmP7Z&*pTxASuCE~INI(fUZnR;vL+Lh_I6sBtP{Gcsqh%Hwxt{-@}l1-i)B8xJJ8`1&0Upf>abAl_}m@ll`?rVlGs@E$G*} zgV8zheP=f&$P(gg7Mv-`Ya@f=f+PoPE|6aKC`#k&5^Hx|AczIhnDt7G-1IUEh~TRt z7HP0|L(PG`MIj&8E3b}bE|yt8gCUSE3H?L1FXvm)6Hw>4Et5C%ouNZ)ld@1$o!tO4 z8n%RIDeLC-pAzTEo_!Dqf}2FGE$lDO2~w?UPQ$#%%k{|D1IAfvneZ=_w6cNaN&}K6 zdR5m!+-nWj28-uLW;us`k0iP1-lgg2&Gr|S3mxwg58@`o;Tv~E&-N5ewwWN8(O-)t zMs`92uJmHwM>s#0LW%v`>j@pCGS!k}zM{4p7q3t{( zNX-0oXUCNNFj-@>p&`}xkAp;&#rt7SQ{!uR#oC>?g%Qb}4H<`FeYNH^(P(XQW&RG; z?#2orr*AiSikx(okjaJhPNV4$U`1`iFFPUiT4KFZPL{jV~)@Ahi8Tu#plGP}-w#km3qG87htOy?$Uj#WKg=`pZ06`!pnVrYpvV^u8{^)wbZEJ=WSm6rYFkvp84F!dDt! zueTY66r0x0k^!Bfalr0WH6}7LcngXGNW7Pi9bfewyxK-3xfDCY@3ZA4iQ>=F53?aHE)*I|Q?CTV_rd{BE;*QB}FgN(qpO z-1_E7+r3{T1PqyUsiKrbA{GEU(QA{A$GCxJs)gc{Kp3Jrzs{RM@-59v0l|E{(y-MI z#+s@$yJNCDJtkq9%`q4Qj=g`dM^j>B_a(kF$v@4{d>U55Xh@aB=@0@JSDR0rg{YGi zKFHiJ$&0&GX}9RR_xjBQBRsvxFskcCC)xdV2Ciq_heVFC7n^WU)p?s26UsER%fH-1 zoQ-=b5l~R&akAQyYFGJozTgOO*9@7Ev4m`ii^3==Q)qd}?ux(ZM=`AL77vrAC-)Q^Vd@7qx zooH=69`5Q;hMS)tXBRCu+oEda?2Z$Xw5|PBO2qslSsiesc5KP}_qf!&B;uo0N_g?S zz#mD_(k&TTaWXeKq{hAd@@ZrB)MC&CwfGr&cqPj}JeXb^54B+=l^;Ugq$p}u+V%U5 z4TJ&38cH6$e+3_wS)87j_i}BBbEsbwOk`L`g}eyn8f$816^)ZYA!e9)u^Yz@v>_As zkGCHykWXKbPsi~6Tj1&cZLrVj$LzfB;a<_ryio&aAi@!>>1D*T0{={P{@YlZMI~3* zGjU+Mt=iW9Qbz8HBxk%x%Upvjr&eJcF8Qi0WC<0%od**q0*8Ay5jiNYLDt0QFnUVn zAmHPtI~KBdm$rZZ*Ditl5#(r{_Hcdls`Cxi+McZX)G#&`y1F7>ppdzpUoHQeVe zC(&`69g(;DnQvNZp+4xf@r*iIWxSOEdhZns4Rb@IcLR!<9)$@w025yiHJg8AX}Tg6 z73X&IMz&U)F31_zLSJ$kJ}y9YEB4_i3O zM18cOaR9i6E+L=;$WEl`pL39r?H(CRa`Bs1O+OJ5mSVMlep=<7?H@Nou_H`2#!D+=Qn#haI)AG(S|cbbvZVV?2DA zm;iMEH+{5*0oqOHRZ}_Bn-2%@+>fp?n3cWVKc0AB-~ZP1MkzeP0^S6wnd2BkkSevt zKD`emBm*c&Awg%_+3)1FoaGcl`qkw^$kd$rp+etw7O4L6tqh?h+up?}*QeLo`T@h` zc&+X_&JSIcYJ`evHHA8;=}AnwwM8ZSrl0>Tb^0#Vg6B)x9nf8~Al038E%#B7-XZv( zkFz?160lo^(5mI6h6u#UIrJ`Lueu$ZO6GE$qNsrE1T_XAP6_eWft$H+3}-?&xm@{4 zvY`w0T{2(seN!!0{>eZC@#;&Nxu>Kgz`Xp&C^$Dr+S1Ox0n`GvY)IT9876s+6bSN*mtfy#1ER)f^BY7TaU z9d3WX>KtvuoGz^Tfc5pOhu6$PXk30TUN0yCglTWWr6z&)7<{dQNIP$-K`)a_K#U%PVcDG z;4kubV)t8emy-kcez`WBZO>8&$#cX2uA2G_C$1=AFh=F@|;RC-(|GsJG)+c)V z4B2bE-P_j4JO*$*@79lxXeX zT;K1Sk>GICeD~63Lo+_G!i~0YbUO~7>4ROCb;-XSBy%AUcHKNcaUix#<&9oxINrW? zH!#jn?oLbNNDuk&{!m}k2Ir=&2tQ)d9)cF&P!I26p1aqnuTN2GIF8Ny}f#={j-T11+~0DiIf!ibx6 zw*636Q{0}MJP|&9vRDMP(8yB#0^Pdp2TRh-DBD<juCVq?%dSNI?tE1^mB?xc9cQve6bgKBA~Xne?U?9((8!0XJ{lrVg+GUlHXFA zSSBxnTF7x<7j9JO4kl<@#^PFjITm{w*x{1?gF)A2@}G8dIrZufGOr|lU*LCQ`!l6^ z`!>I5-2mlJo^MSEuPcs{KJwmuOTQMsHSK4}lYB*6=Dd`=QfJR>=LYbLQ;@BJ@90_{ z)U+pNgM?i0s%6H z*)_r@ga%hB)CIO>zd36@E&&-s@ai$q6{Rr}JG(lGb|{xUuR{NgHdq%ajfVhn@LH z=+Fn5N$xW1!FkQ^mDeP68pqSzVi9@Rz1d+S;;MsWIw4(_y8d+liMEs1TziM=b+ z=1cl5f_G@tu;q66eOK6U_p z+1zhX>8Q@~7$wfB%d_k6YJcJGIw#$=zUDF9u+B#WE}bav03E0en0) zcd{Z3ZsKCUM6>LedfYUw&M49pMxZWBj1>%vxszM-;Pu{m)ajbb?(Lz zFE07)GsD51f)xL8>~GuT)W-Oi-(sbjX+z|#UV~pejjTRa&VP9sqqw=Bv*nIheOkFX zv#3A6uKK=)HG0G8t?iTT*Si68w5Agq)w}$c$LyBA7=3YSvsc>Ddte!(V3ZRNL#k;^ z31hrgM&iPkE1_o^|HG9DyV%r>u`D z3q^j;P?`ntTJrUJx{Ux^2xG05_A=CQe?8RVfu$oM?&p4A$^KIe5~)D~OHz^)gx?US z7O4t1r$*u0B`Z*DDa55n>rV3k*e&(m3#eaAfOgd%?@A)0pOeS#jaBnzO9-9zQaaZ1 ztB|~pN+397;ljoCI#HU5?$;;I+5eApb_&<-3_0}s9i8+&{yYo{##JST1F)B~2f2p! zT!mNUA^1SDTu)WOUP1v=tn08LUw5-c(eeil4_Vj%dFJySFSGE zhCv_z9;}-9D8aWRGc)I>ARS0T>5@7l4G=n(-Br+i0~ibQdMkUB^@zWJS+50Lu$^}b zl#R+8w|`=74Bn4TY?%Kmc<^%wuOM+#gpAmbFZ}q>Z2%a-cD7%-iy(gLzq>W<7Z240 z#hf<&eA->7{`60Z0@FNtcOSwLrGiZ_zF2Kq%wN0t^tDz!ds*qj{8V>VCP z>3c1%_tzb;XJoQ#+$}$C%M=e!evsh@QMYnk28TrY{vXeKzK1=G_n+-`(Wm&f#(QQW za>3Thj1#y&AsXg1vBg=Tb};)%EIW#0!%bVTIzs^l{{DnFC7RyiahR`>_g6pFi}vh% zkId!LX}8y(G;BP0|1u@6oQCt87_$wHX}{0e-a`Cv0>tMF{=He#ac=S7jfrvw)eBT$ z%PrlBW_{dpZT~5!i0h%`!%@ETQ+pJi_k!v5#k?#`aE8S7wEt4d#n$BYv_gvXb+p6N zyW2^rHSspQ(yjTr#NGJUM*=Hs1*a#?sZ2YrUx+V^gqXw3E;4h>wLqq7-ZXN-EvCa8 zoVO^7qyuOnv@46T2)qihTRXm*AE(+dI@_;(9Ib6KG!EG(ckJ1^(TNH z`R}j)`PE6sL!$zAJp8^3%W3=Tj8;;+T7 zUw574q6=nmJpZ>=KXN3p5Za;6f|&;SmXOK~cU?iIEMOd20wnos5tC=pvB-!`BmlkZ z#>Gz0neO47jqRKXC7pC|2N_RF{mugump?CCA>b}!rEjKO9@u3!!%5+XMs=5{V>uhb zt;;T3%ah=*E<0QIM5eRR%e&4WWCFMLWo6?Q20NOo*2=N9!DpLM`>Jsb5vW@g zP#qp_WL^MsXuprK)+bB8Q3)zFguy^gw=jV9;}afb;s3oi|>q08)5iiFu{D| z&8Uq&)3|i3{Iyv^|KOhc6xC#QsmOoYw9#gZU*?M^~cae|(Ip)bve-A0&j?K*9g$j$)1MNtRHCoHE z^Ch0TxzRl~4R(LcyWDqeXjFA1d{Z`L1|_L0-E%Cj@>&@u1r)mVx#(6@No!p}ps$HO z))tfE3ss&o3ln|(oO>`!6>f}6U|g%&YINoXRO6sZI>eEbI$6nWwxQkEa4Ksjt8-K% zCo?)I^a|as0bUPY_BZT9IhWa3J7siP5zj*wsGXGU@H`-~bAH6EssCJGpt#I$6w}Vy zTEx3ls2o4?dr6hK^V;WW3cJ#SLxe2(Nk|+WQ%;US2L!}^edLjuM8mzxR654qs|etf$lbF7Q>`(HX-E1eQg+<`aZK7YqzI=hNN)x02A zc}*_Cf5bw(_teqC>17zV%V08(x;K0g>g0*pj@Bb26{+W@9`K?M5}>oBr1PXhm(V3I zqtK-!7kjGNMogJke34eNv9m&FG=P?HxsT{IzLG64)XSjWRMA<1tk_PII)TX=Jddo+ zUB?1@XV6k9$H%%7&)ogxni3s%STP-8<}zQ}eq}JvNER5gcI0QNC3f53($>q@$uIN5 zA5;k%#mMzoa1k)h?!Pf3M59mmBQc==^1aD_>U+y`@;=P0O4W~BxS_IgnAm3dpADha zKN~`DiI$|s9B`ykg+R9KXyVljBU<`#22iJBai18zpazM$DH~X$&EEEJBdfo2 z$Cf|3F5}QHyHqMm48M8oL?VJM2%Uhs%A6l!ltPcOZC-LO#cfnCJb4z zRPZYN`ti4?OMTR+z8B`_H_(WPkUsonzFTQXva*1z?Q>n(ejzjF< zLTVs2YS@y5cO#Kom$@e1RCHzqT`%t>Fpoxl z3V1`cu`y%^;?iaLbnaNg%Ded8w$4< z7YJJBj=vQhR?sD2N#EGs8r1lMj6RF$R0OW9n2@Gz;UCA8=5yqeU70QX8rPgu!?`;q zu9fdF$!daVY&*_yBnr$;_e0e5PlUqR5Qy0BQrm?8yleqCoIuN%v|^<*JAZK*s{Hq?es3Vi~T^ofaiw=^0s^{tgGKOcvxr8L0C;&!_swjg z8Bh50d{>RcT5m#&s5Yacx0}^jU!IA^HeCthpt&)uKsOiw@tn`R4>DQAUlvFM!y;_$Qwi|%QWj&M-I{Mug+tt20v32J}Nm?mfM&wjPBH;jUh5-<&NeCPwRRMEpZvG?J)d8-T zbtxw(p~7-l^Pi^&+R2;O+$Q%gZ+E_pS+0E*t#LAYH}(!s`cyd$`b`<9a{XAng?>kk zPu*nLdt`#*Ku~qQJ=*&XNlP1(%=GlvD%svD1!nS|E}|HRdIv#qZn7KAM|XEgo%G zH|b(-zOfTN{4V9~WPa*YT~mB!9+Ff8)coJQA?fZn!X2PdLw%yAU3NA{V2N~(ZE;g{XxoAc z(7>yoR;zEvj=hdFnk)14auB8x_tocj??fCXt*^fRW0V2^k-N5AfgvhukgA%EC3NX< zh7ehjE`UMpBS_`vw^5UE$Si}-K9+q{kDVdnZwE)F*Ia8O@46Ev_AN;{7hGt=CFEj6 zEK|K4KU#?g3lbF8T^k(j9_RZHMO92LFA{9nijZsYQ@Qoo6w>8^R&~>5UQDFO&iFDF zwWf!YmG#j|5Sj3Eb5r-JO%b}>IPLtWBQBn0eJf|THR35elMgZr?LUgI?BmrR7%N?BEZnzTsa!N%h(3|ElRF7hTkLjT}z`<8nbu1I7ShdI#>a;t#x*U{5oa zjfq5Jo^_g*fAS$^Y9L|#dFo$tr&8r5ZerN$&v$Rs{?CqAcvk)|`oN)u)p6lrmq_1u z???8IY_QFit%r~j_M2EQC1K;&nSqY(p@`=uV!9UNoIAN8s#HoO>4 zWYB}hFk3^jCsmq;hpKsnPZp+LGB&s<8X?H;Z@d9J^EW=YQl<*EKgqo=+Xg&H;ZHG9 znAozDiB=;)cL-W#*)dLGzI$4F8G_YJp3O4vx;`)_hKu4Uy86hQaGhOy`~h|Tg!N|+ zDpi9Fp#Wc&Yh=s61)Hc;hGjq8jXh`>QP-?{DsE@EQ~VeX*>29T3DPA(3BZTi%1AqL z?d^VLZau@?OjbS)T^y~7T7qA=a5Q_T-xTp4I&RN_bcc};O~?&Mr+xJP#B={m_YE{b z@MdBE;Ovz?`d)A*@l=o{0+(1x07}2wmnl!JmG3h`g5ju348l@Vm>NA|zn752{s-D|F$%&Ov;#4~+B;9&Ibn5YvN z{pcVsnoT3Rm zKY!t#V9oF{ukqayrD{^G0U*-L+$@-f9vDd05B1-R4m^S3tDj!D&nGYNfoWb2JiFTg zL&U8=Sm7~8x(%^gU*r*5-xeh${Zqp-X8IqOQ%w0#MDm{XQ;qSumpa2wZ++uZK=u+E zQAQ_PFOI47XDzg}SI%)@&{@o4vjSYYYpR{adTW%-Zn1DJY&4o)2@ES6t0DkPxb0fp zCH&rDO=@5XOn7LV-Z_Fw)Q*cu!ezXvkId;^ozBGs_zK_SQ!8?l9%Hp6IcdObIgNg3 zfRPeYN1GJ9-{{>8gB$d*a3mC5Zo|vh#3^gSj2+)lPc?W*iLRIml!ImObX(Q0bH-5u zu!1n4S02Rsxfc}qTPFvdKqJ!Am>$vpX9;JiZ}zH+m^E4QH!p2uCr70F(jKp$(&Ax) zsvm@o>0;`iFXnyWzOvzhxL>-@=4D(Rc4ibz67(x#Gk<{BOms|O;lUVWZagmHj5@xf zf4hDA!m*$*=NoX^aF!lfRfAMJUMihrHCEWE5Y8XMV%TbW#P5>Fn|;PAvLlU+*=o=8 zPL#eJ_*FT~e}od51SjYd`eEaPF^6S9d;sS&y#HH5T2L-)r!^}Yi_EqxULDVM8)v{w z#I9Gk9RW4|D(Qm1;* z4F8d5`aveBs%X6QRO!Du)S@J>A1d9)tsKeW#ZcoTnp!|^A2v>?lGIgIlXA5EeT$nx zFgef=fYN))pZEc^rvm^U996p zm3#4VORs3&;}zoZl4h9eECDdKi)D{&`}j4;t1W$+ya%<1B6sho=3gHPUWw*3ga$gf zC%Cjy^j0OOa;Q<+!&OXV3*}=;OtO)epD6$%b#dx+ru>Fynp14&XuA`{*|<&Tz4Q+U zck7E5^A$HI=Z|gmMEX=sqM|L6 z7^b4QHp}%eIW9rmy{BE0g)GT^Lo5>}>C*dq>rLjK4Z$Hh!M1=O6ET_sfDLFtErX_| zc@W5!%l_bzmYuN0(Uz7MEs>@v2(JoH8P4kCn!v7|I6f~0I-q214Du#j!84fI&MmDuRbt?R}!U;`7t zcs>VWVEn2_L$?2vnJLNOR)f7)vx8g@&_4$t!|yZFAA0y3-P97mkxQk;kDqyXMtFq8 zBNM7Ka^8Ld6mYlnPD~U&pl&Vb^wCHEv}9TyItg!H;1i`nS!Na;*T#Yss&^Xz8=axSz&|=3{wE1xVZu8 zWoCMe=#e**HqUmnujLTG?ydF9S{Hs=g^!LvtYF}EjM_eksGPT*k09pc=hRIZHEV5_*^#=WG%la4{E>SSrN}95{Knd#C zUlU9T+h?A%w6s0$2WU!t^MpSfpP%|;9$!rC-<8P+#+CNuiRUdLsQ}+PqimNhD1`%J zq^%L7J2A!N(Xc0p5bD_SO+(^x?7`TX@4j$8yj%DI?(-0d$?l0}Qbj#g7lxEX>h*Rp z)8ViHYO|f59@2A;k#%*VO8=TRJVvOW7^5yvdoL2y!oE{2Ut>Qro45W|%ewKnIaq&? zO*cBFAX#rDogWNH)c3bE zqMo+K0nKJGW4;WHmADNy?jE7X!co+T(6GXoy;zE!!yrh}^+tL)cNx~%d~s&0(v?wz z+}l#82J=A3a4xtc-^-+{Yo{JC#1G$y$?1k>CJml7Hj#!?*P|;XzQt3s95Gv4_0Vj9 zwtKu)Zz|;awuDZLB^;o+DbA^34Bel*6nL5`wSRd>eVbLyuuM&jvPz}wI7;>SQAIx)Xa+CSSA<=2<<5XbW!!Bn>6ZQjr}` zhpW#t5X=?m!!l**)C;RzsE^~m{_3)A4fIOyvO$HBETU)i#;ay#wY61hFVr;HjiT&N zf*9u_2Kzjx5P)7~FFD&>A@pEf=iuk=H(~)-w`KjdAE2QGQ?+5vY^=R{5B^qd9pf>X z{>YoNfBp4rrJ6k@Um4XTPd@~+?q#{tz+B5{!4Lx^k?_o5fEFBm?X$LVk@xb(wMy%! zT)71LN_XpCUx>FyJvIYHLj=JAYO=5{fV}fJK0#f6V9d>BrR|!E$dTbQ4)!@@UTRED zgT)L;L)fvTd)^4#_)X>Vudr+n32AG?E)P7BXAZTPt`8a^N;}CcfiY0`FzD7u&#Bvc zqun#(IGsDl#aiFNcG|6oyyEzgIa07IIj4Z^&QZFhd92eTtuXl2c=iDi-a!zEBw&O> zJEvBK>XDr_f=Ew5O3uq&YvC$-1evqLE7U^$of}5)l{$An@1n{E0wm6wB?6Ej`6m_d z3;3ND<|`~2p%uCQa&+*-=%{xN$JcK=d-7YXCB}X!mKPVqtKRI}dyS6h7WL?DXq#!6 zxL3#E;)v~V5T8)G-0INb{c2Ao%?@VS>e!w6Av_F*&MT?wQ^TEi+`wY`@3};0d9tZE z8gT$XF}H@fHgUI=%ToN-*P_FeF!Oh#&OW#vP*92F200*180kW+Rp@jcLA8>7@#!Rf z&s%|b{C;s{>Ya1inXT>+WrNLG8dB-FUmz0SEK*Jr_Z97%Ykq`->3a_gj5H3p;qf)$ zaR#=XOAyty(E`7Fd$F2fi#*rvVxkwUo0g+iORA4>u#7@cq9b4mPkw1=x^lp(ixT}B zGDyoHiqcdx^cH3_(9!Yt+&6;z(JD{KSupTEn@do6(d`UwlFVhoIc$zOh&$?=H+}rG z)QA9KUQ&v8iGiTl(xwSdw3AlU3QRqlyZK~=!iiw+0>pIu2)f-sN~7)j)3A&1Buq){dR9;VhDnvp3sRwZoVb9(;aF~^xX6O;e5*L zKzpEK1PW8i)JsUoHZxT7Nz7}IXwPl3x~yKKg^7C*f*aKkL8s za!H~sFy3Q0!*uBiv{5!H0pvZmIg)&1JgyHosy|+%gl^w?Bj!=b{PZNzqHfwB&wM4%Yn=Xy^V-IQU9DyJ`0ppfjI1i}?1P7j7o9#lryO z@YjKff1w{(;Ieey^SVI&b9~kxgq)!oQmc(U>y3Oz7L{I_S|5$hj-@NaVtNGznDkKA zXv>bne3)IwM3OL%ZA_0SkeQ<)4D>*dZpZf1yl3kC+CBQF{nDTugq(4D!|Tvm8x*0! zlr;%&ay57!Y#x+uEXv0$Yf|r3OgPw?;_~2e^HrXkGpk%w*)n{GSgY{m&kezR9Xn8k z!Ph6rxq&PRS@oU<4MBP?&tk+RyMT@VVaUnOB&txC?JJP#BhrRR2YME_(I{;1tfAh5 z*8sqe?#nAMEKAWIrrN>)J%sC)fR2Jq-jtH8t~-4z%XX`~Jo{qp#i7;|<)WApmFLG_ z@nWgL3-QM_F~JqCZAAn=r;nDf;f^0Cs5HZ2<{7paAg>t*pqasP-Y!0rh9HhXzo{jr ztHeEaf}r$4ls_prf5|QFD>5dH;6jQG79iwH1&YqZ+Olo+?C%9W*L|l(nVod_@Q$no zEkXe6Cd~u#NUUa%4zWiweYa9R@+YCCd+TfcSyErtJ;Zg6<#sTl^GN{t0cOqS0`|Dc z)V#QAr|>;**F&Cr^~~HIrJCp|KV!N!ba`e93w7U%G5=U>L7DmaJ3Q6T-zic!xfBDu zy~NfTyW)LKi80`w=#_WGr$MIuYFj;RJlPwrk$_$#f8LoEkg3 z|C;!VmVx{(4S@+b2MV1XCVtUDR{D-}>B6fjG&lA(3 zITNW~LVM8qY{Y|Vx^l@&r82nkcBhnp;N|l9Oq}#&uxLD8cql*Iuc9KMsyzBD5lQmu zM%FE31e-OSZr}XLS`*e?Rj;VQHkZAx#y-MQp+-dZ>g8Iu8-AZR=_3U-o)#rBlau`l zulwE;Oec?ZLnS?r(l+EV~#=1$T z_i$jd6ntglmOLX{IaSg^PlauIeA&W|P|UaBGhG|}YD0vP#^lLV2dK#TMU_)X8b!Y# zlRw@=tv0c$@4L9Z7abS=Rm8ocQLx9;sRf8@vu6;Z?Mn%a)SNeBE1E*YyxlE4vSX3; zQGH(Vl`7xXa&xe_eybi=l6YIg^vd=wfE3giIr!^za88dCDPXdD3*ZJVJ(QuzPegAk z%d`FX;Qt61%%&6K|98Of@4~y=xXm!zQnqzl+)Q!d2#wb@m%Sz6R7*@Q6||(&678Ep zEN(Th$!b5&+tc^bW|A}7wW4g{BPVx5W&AFe6?yNi1WuodP$b^*cHle-nwk)}5kv)j zb19|uRu0`7$=DON;Dyzh)*g=9ou@7X!)r9(AeYKRXr>hiDKbUjMjiN+e#juf%$rJP zi4a>~_OIKqA5PBGBH^vQPxl*QHqoJ!)-Z&Ue6;rqJ$~{+7ADuHAH7#7H#xTs^_-)x z+HRdJ8cY${XEBC|1V|{?LiV*aHS%P{u>(R%WHzg(CZ&Sml$z(<+mB9KgLw|ab{?IV z(?`IiUJ}A`yaXg&*zfL>ncmq_c=A#0 zQ=XDy!q9y%O54g4(DbZLFd90m@m*@{Kr;lDmtt}8{j|-# zw%4mhstbLgPnl*iCL>J=6bDwjot{Ds9CF!9)vx`8BgX)GEVs|?H=cLlH|fzi1?XV& zb2ny8hI4KT-I_U1=M6kx(b0goJVTU+a{!nxbCX2bjw{tE`8j8z?vyUc&yf1eJ7{;0 zfmslKswE49pA_X2S@7?1VL7uV_x~1;o`8k-s%3J^ClIqUh;|Cjw}mQ%pM+}_}%+o{M1lsjnjr6-zF00 z^Qdz~YZi9=z$sUh1VD^63!kmSPxlK2(w0%KS=bD3UBx~R?Kxc+x}`hyt=3Hd!MhNE z#Cu)4FYd#(d6W(5XlvsWr9hf#pX4pZ_!1GOjW2{2Y~<>ePQpjDn8F<>T|_V__6hg$ z?$Bzhu>prOx}^^84{1hyL_CsGbb%C3h*6FqvLUleo|62Qu9jZCAit|VuI+8FN_1S` zCQVWw*aAe{Z&g3QkJml}cLuAf8r&-*&B{5|-;T8HdphF2Z^q`+E!3J52nDm_#*N6y_VH6svUAgYC;&} zXOn*1Uz&pvzcU=8`8In#ayi7-HafbWRRd{x+00pRNWGQpC&#Q4*wG9pQv9*{mJwff zS?GAwM~b+hG1I0%e)+Y-=_F!Wx@f-&wMS1}s1@G)F`$>& zA(%@dQ_7aD^rS#qfm{s&9eSxjBbh+n0+v|S_kieAzqkj{n4gu2zPK_EG-u2^Af4t3 z0%z4cGF{lIE442Wn=AY>q zhnJ7=`Yug{#MAJ%)QNuORCHIhpt( zol~vTy*_ob)R?f6DgR2x^?)U8z?b*dtis$&3bN;bhXKStYK6AZ{DV(5%T7!reh{G~ zyN(JA65-oyUGm81G5*{m(>&G*%hmKy@Ii`TXINQvBu$4>!;Mm+`319VlrA~LtX%`3M3&4Hr^4~`gHQP*yC zkDT4Doyb>J)w(`HU?vyeEeMr{wi=+Fi_~m-o+_BOW&Ao@*N||^!2F8wKwnu+Fb{(A zCn$fmXaZ;*MRA@QYt{zz8_B?BK_M_l|J`uu7SGOl#mnC9wwUyqgb##5Kn{m;sCkic zf#h2@gMD3nyYq>e0g`HGIGY~5!vb%aiv4OXA9FdlDDk0PbnKWDrQA*+MRdUST=T~w60Ni&NV zk)5gNFn~wBK0q~@l$s6XPa9?yfEJtnB%#9N3D+9<{DWa4&d+W(LQT^86K3RMJixUZ zi_b=Ci}T#i@a;D{DlNhmPRf4QSwHAu7xk1AQ<*LRlZtx|jcr;*kJ^yr08CI^Y07L8 z-sqUXf%kX`Eh?#7i-0;+9(5R2bWWztMU7~;6SMR2gSttpfiJrd4}p{wL%*fIEtTDQ ziZ4vOXfb-jNkI zw^wzy>TdeU6y@A?OPe1)V12xu`n1lo_KA`GGFO{F;gU??N$D9~(n05?M$9gA-B*`w zngJ?JpEWCKcanOEL0&wMW|glhXz$4t>V22MIic|)6%x9aLvK>D0zE_jEF$o6AO zO1|fuXMN<=#eKQP-c?rTK*?sY=|N3e{>)xOG>}iBHh*y(E{{sIYN7)jo^iz%SKLS@ zp6|ZW7zrsHdF#JEBX()UJUDbdD_Z;^O2A2YtMQ!w$-AYOxxghHBMd(rzHPbNOTO^o zYF0Szew_Q#m#ta~o{$5_8~G0skIz*NcN7?Op=q55AC=@k+XsxTxWj^Hb*AsAwfT_F z5X~0ISiq(19J?^dZ(Rw!_@IUh>rdN;&eS~vO+*Aa&Yp&1dNy45yicjU@ZHL(U)ytS zBC{UsjSd0mFocsTn9vpAh+(+L@vjE@vfZ9{jqAZ4N!vf|TC?1Mmc(;L>G;;vthA!E z0FbzHpSAg}vVdGmPMM)3r-#Bp3Yk)h&e7jxQGp=X+}zEkCmg^lc~A*nb7vxfCveu# zpB7vPFd3?z@2)nzxGZkEK1P2jQp_i|`{s*ahfHb91fs*)pfOs&;#}@x-d*~>qLNf+ z0?#0_1)7TUFH($B!uQ*aD9Q%SP|{&`h?}!Cz)*Vy2*I2YTd=M8>51`)K}NMDn!qC| z|AVt*M~i)W%hKldivl1hZaS1seBwM<7S9GkWW}Z;?Z0w$UE4U9R(1PNyVZCJ!nu$S z2PlDU${QW^ZY`bI zSgQ^~ta3g+%K)001vC(8pH5Cr%Eg6hOd7x7{?rPWL&G~2$9~=!jO)42(kbyupi7?S zD(22^GIZaFDOK9IzFrSv5JuTs$Fh=3$ER$Z77gL~!NU}Y94h(VGm{LERQcxyFlkGU zW56d9gS=C_=E7DuH)Kb1gLVDdf0_%KmU3cynH2igc^H=kGmrqWNRlI;?=r4 z5w~Jw(gkgqx$RXRtXenDMVF=T+;Ho-DMRA3y^@NZAeRdkZ%+=i@+p0c)~aA8DZC6& z9|RyuHa9C@eEe(Y?BczshG8Xb__}ndYiRYMH#BaWq)eB^reAIUO=W-8-oXMYH5MI)cc zF>TVic5^_(SIfapat2T$d~zXDCdS(*Anw{QwbrmK3tPQ8jYrYA9Jo`{PZOw=;C`fe z=E!a)ASdD=$R{ZKJ@A+}0{S(r_TW~I0E;65D5=U%xSe@+bVT7aJTmi++*agM^vL|l ze1KR&!gK{A2@rU36w|`7-g^i|T%(G1Tz&GIPC2@6ePiWpfS?PS7rv3TBcg1_1u5~3 zu}&_%?{`J-?EM#7>b4ljXmR>Ey+;RKKtcTdG3HNKP|+2Mh!?)`@@o@`_yg9BzgYP_ zDSk-B7A>vTj18W;@eeQ|JEA3z%ClmDPrrCigP-{E22Lg8uaW?$h_Z5=r2cYsIk~emHM?;nc9J}m zyMSZ2K_ddaAaj-LEYC>KEebv<=j1l=iE-txu*!uBRG&|2QtGDP=vW&iu?#)3$$=>S z7>!BJ6JFfEpvi_Hv1o6-rtxW7@GXH9-?^CE!Nt&^}-zmn0@Awdd_UMD6MUw z<0|vkxs6AbLUzk4;}=b5Nve6=HNb(FQW&DXaII}@i3IbK_J(M}miID#`v0yp^*-#S zXx`>j)U98aV)Mg!5q9TnG8TimUO-&OD0pj$M2{~11|^X9-% z39WZtubrhgzTh*sX`xOve4MrH<>xY$EZA(JEUn$YahQTJ4}mUXg=g3Yr>A2^i+SoF za}RF+un;Spo;lnRdIBz^oyB?HVQ88X+ujf05N7XB%2|{YvfMa(kCY__j88Ed6a1EN z;rnCjoK@u5?>ACBro4=w3r>UBQ)&eFri3SW8vP8o4Q!Yzh&im!j2ENcv zl-C?o@MwWae|duJoFAT4;+H)4HMTdUKn^AVOnN1Cx+ZCP%Oaap*>jnzQBau_AE9$ zf{Th~BV2KD(_s1fu82)^#cfZiJ2m(5sdTyKSlzBr6Xc?WI0BFhn8Df4PW_|j@)_%I z4@UI+v+f#+H?O_B@EWt(*YskfkZ$pPm4~5K{szhfZspKfy`OWPaTj2;@lrLrW>?9~ zuN)!E@xom42|*lWDBO|5dZOy3QnIih;3?ITq!>-=5cIClWl*yg)t=iE?I zMlASQ<>ja0r%tXXPpBQe0M{B<7sW$2Ns$b>WgqVffM*A_~{(45LnX%CP^&^(+Wsf!v>exlDqp9M5FoZw2EXbnjsO95P{Fq>$sn0Us~mx zyv96j2Zt*iH+6K5cO4v2sPC&lEfr_qk1A?lhHzfsZ`*{S_oiVws-dxop%|w$MC^Rd zrM(BNf$gU@7zQJG)s3oqL+lmQL6%BC6T`YB$T1yn#+2N#WVakD=Y zwnV-jXs2{zeppHc(cTj}DFeFDTQU|-h5E?P7GOHOa1MN2T>T@9cYc7Mbya@;e1sH0 zN_SajF+Z)T*=a2Z8!lP;+&W{!9~a`?u%0=qoyO=g7e6k0V}xDGUL2ztxOb(lMFd;v zbv|%_>L5Muz2tu}*31|2gIdWB55G=LV|aFjbgM}@)pX}~XUMaOHlJqQtd4c#Gd_N5 zz7lCi{tj=`aX-0@u!JtaZF=XpJy>1dc_e*SvqT4`4`+h!%TW5g1V%TCRP&P4xBuZ5 z?fBak{rUGT%I%GReV_?~b~IC8K5IZV`O?Ceu5@q-3dm9c*zRpdK(?uC=SBTb&j(%v z$f$EX5?qR9H7|9C)<5GIcWk>WgiR$00ri^nUye;?>)gG!czf2=8W0RMxJlKS;(HA- z@+T3*vG5Bi(Qm}81XGVDVY0WX(vniw=ZQvIjN8O);hC-y6#2O4@jHZP8DQRuChd2t zh~H_`PqZ?@QHfiZE%lqOj+-g&>@PH3#1o|5yd}(FGQKv&JehgR$zAf2fTUi1VB+aH4le@%-1?Um8dQuE|egrapBvYb3zN_CPAg*iGN(P5sy+hg^Q1-$mh2y#IdyPT!9 z%3`WC2YCejRBe}v2m_#`kP0w+;oXN|eDB-fjNHP6BHE^EFTJGg-lnHpgD;?D!lUKr zxR(;io%PV-Vz>5AY7({_0{iLZNNR0aPw6@<(oNCGzZ(3q)j80Ld4p`{ecKjePnWC& zi<#OVDPRA7k8kKXnUnD2?=z@4JM`|cg52#e`Q$Qed8@$vJsmoQ9sWTJha+= z^pHbY?hl*U*aqpxb$TdzoP$TlC4W8j7GDf?-7!;}A=!v*IY^Mg&4LN_lm#xJEe*Z> z*=C<`#LUcvF=FQF+`%!BcWvlgR9=FxsaJ*`LST=O?*g&tr{YKbnPo^LZYrC^! z$qcu7(NUb{V2p1|_;lqSjQHJX0~aB30q`K2dLt`UJKHhYlbweT)<|(P#!mg%y4*7MpKhMZO`Imgf0& z@9NY21ylo2VhDkwMD=SNfPO<OQKrN^e(~RmRg<+L1llt4gVzc&S)B?ulGluLXRfW@SCk7U zr1?>zg z<>{4f^$5GT`c+{^^eQqoVTO`n)o^18mbc`kvPie6|Ncv2>ho(W4WYjoOA8D+Tj)H3 zzcUrS9OW9&F2$r2u9ye>Lwor~>~99M_&*KiXA?3DMLUh*JfX40HGm4!Z>Q9-G*{B!YJX`UHhL80_aSt0CW%NoQQGn-S&Od}=lc=&JQk?m>8Z z$NrjI<5rW}5|2fvW(;CL-_WFC780TL=Ed9Tw34u{nS=7dMJhF3bcw=RjUF)aCm(d6 zuzg)st@P>v&FTt0{VgcVv09vZmZE5Ez%T;6VpAjJBuJh&XpN^+riN5^Sr>#H?g z*ZSn<3aqs`rdz#>8xr|#(poFY#1hJIXFMmzE+xAOlVga>joTyj`4!uFi($OVEV3R1 zfPCW|9h7c=d_SEctJ8dSCy@PcW378VK#!%jQ>m&k)fJAho|zgI&b$}JEB68w)0qllG*zUu#Rc# zf{236IWkLTevWG!r+|8J6;tKnBy|?7`2fAa`23An{Ngn7X>>M1(kitWL5lVsV=l0X zau&7;*!&vYJSK)qZ&w_GFJSBQ~90 zbHm+}lT(6yxz^gH#hORj@m|LMb}#aZ*Fsrbvr`jIx>KHR#>9>0`* zcf#Va`iiz=SagD5cEvEzHkypXz*&ERHsz%!d~i?wIEq^kp+4?PP&WSnrzV?t4jnw9 znNOO}>wPbavLr7(8{Yzv@){W4O*_44PWR3-TwbNv8CA_JY}Hnx^HRLPr@7KF#c%FB z94a!|J`ZHVtg90phj*lHnuxkG!ES_vk3`}1jA?9gp?79V`_0@2LPJ@PAHl@JvOs5O zgr!}g?cn)Q?sN(sY5pv83FRI}p4ripwvl?e2$SCn9K*g5^PZe90yS9N=$oLK)gG1s z64qD8d87p0#M6v<->W@D-m7+M(c0h+GQ>wF=;mCNQkwr7QD;#s>i5Rq+@*Z81&PTk$9V92NCGd zU``BkNG;0|0kA7MLUF3f2pb8W%nRZtOp_7qSCz`z99a^T#5v9N)Q#7Z3V33&w(x!E z-n+)=)_*ZYW1qZxQaLsLRo=6@jd!q*srse=p&Rj|Zh7zi3|T@FlWc@NQ|-dBOvRR-~nv>8W$1_3%kwqxY$IBW5~= zso^OY{oQ3R=Cjf&ecO?eMyd&clIY)=<9El)qR`uB9hNsAlNk2!>!Re2$GNn^pgBNn zZHHEO65sWt69T5=V2wh-eRBXFz1`URAVI#z1$fGc*X#gRy+R;|K zUn2hXeYvUyeyG_E4{A)Vz#}134{opz@~uzC-pj%)TSlGEb*_6xJDIjO7agO86PM{}VrM~fz3$t%=pSbpoFIq!bi6=fP47QjR7=VT@+&KQohwb4?W zk&m(pvh?(m_a_MlS>pTfH zZ>7Jwm*8F>4K}BET;e}@rt?YTC8jAfZr`T@I|S|oRkwIi0_+=RAL%i9AODA2ISbaB z6>rt~c%-DSZ$z5M@uJkkc!Zb@WJT{dfB+Pw7F)k-C%XKwd+V#sMx;!62tA{i$V-WK zf5i#rWCW9*tysmomSJxfUDh!fC?|iIij(dziJAO4v2hEd0}QE2xKM?e+kk4t8cc8A z;H0S#ENqyrtnhj|i8Ckcte?K-L8#pFCt0}7C2HWXjhRo!_BBVFwHSsGe&V2ZxX04Z zUqX9Mc}qSVE{V^4Bc@t3S9EdLe706~f~fEJ>1g#xFb0pcxGZqmAPR3Uud zr=6BWL6Ks7!^M08($`*4a@}qCP6lbmzfUnzz2&8x8kHBRTF`d^J2ylh)>E3{N&`Au z@@K9#-K|N%--;=^M*Wd7fu4UBAyZGNv}rRT4zcM~9Q==R0+~{7C2B}|cf#zU&qTP0 z4e@{v=L6?R^0w4RrcPmTlw6W=5z!KgV{R9-^)I~+)f_DU&8hXC%5fdu???%w~U)b%NT1$Q$@i zdiTx!^GQHeT^uiZxQ*QYdtK+lu!%^QH@5{>hv3Sq3IUbY5Z-XWoSDf>Ms|d40 z!CAKw(0VIXrTOG}CJ5?E%YvHVV0u95b{ze2MEL;qUWxWlnzAI=L+8+RVXOsi05`uR z*3lOhECoV6Id(N8D%aEwBOS=lkqCT;02b1zr zv?e_%q{a^fHuoldUQZ`1@Wc1uv5ody2VZuDaZ>T&o~xem!o?p0PZ~0vYOVXY28FnR z)I5y6cD`S`MIWg$HOoS-Y{l=Pg;X6Qf^3F&U6gZ2^iv;Qvm9zI@qPhztK z+&9H%vfjxQbMnG&&tj6>c&P!tUV#BaPz0ne$VC=3vE_5RU%{E6&Ed~)NAE~K3vg|J z?4+6cz~LdoNNb;W!k+6p&}raIk90+)y*-^4emL%+kiY?xlGiTJPwbVrT0^u8qxnwP zw=~1pTOP%qqu+>)lo@kc$F;nlPR{n*2fL&v2w~blzQ;!V)%^JK)Bc~;3XmofG5wLh zCueNljcNT4Up$X6Ut0@Lj9aS&7@7#hKijo11@d2y4J~e_SuC9C!)SKg_pj%fJ%Ij* zqh1h>FR%V|T>*6=HLMkoR!}yG5Fp4T0j9jGivTlJRvn6e(Cb^rcw)+O?WGbTd zG-riW+S@YzcpC^-B_U=zJgs9PX`O2BK&;AUog-$Bu;ZIJO+UKU$joy6`_^N*==nBl zdH0gMea&#F@&4;P*I7^Y+=e+SD({xk(Wsr%toho`YweZ3kF)HbG95(NpX~xds!dfc z&z4kPXZ%#7(U?`FC}Ox$RA<+=4RyN?NlHgtXRDqoD3=l1_^jTYD9Fp_^?DZDMNTM* zj)(wpsZKadgw335dU&Fvv?u?B)@S*{-+OwK7U>EbJ6FmMP!saGE5(dcyZeuN z4{JhCU8~x1+_JgtcTQ+z?!O}D8}Nq@{;3y#E|C?NHg@Pg@2PhEKpINfIoGt$>1(ua z-_^*NPYgEW6pTe8!m7HCK3@CcPtD=)UHs=bASb?#i@TSzj-Jtp?-6ggyS*c!J0oDc zJUCETnRqY_@r&dFzMAR#z0uGA-dKPBz5nOftUoiBDa%T?QOf7gByvW_Ks{4ld^AQ^ zBC48dgyZk2Y@1zqMFHrWt3<7lCU&IRbjL0RWC-6mj$9IqJ;#a`B@i~XNupyCl1VKv zI7!vpK7Ge!Pcnb}v9V_MijhCTmmZeK$^6DS=M_L}IE|}WjexQp`AwZox0HrQ6e-xC zHL8-m{RgOXiLmD_hZhlvYNs{|9J~KwX&3IGr%>(b7g!hOllzLKmQvIn&-=B5kW!*| zdJTHT{0EoIfB7@Z{JYowv7yU#-D|>kkZ*K)VNo=^>3-GWb_N!d>Z^n3r>Nxk880lj zEB(IcyTSo2YZd9{8p|$!`B5&pDzEnV(QIb9)sR2=4(MTb(Z^NqZWEv~n3MRv1+~r` zsW^1Lm6BH|KPnFz8Aezh%2!%AaYDSjTf5Gbq|?Jz(`%3kuS6pB@=oxjf?nInDTII>@$L);)Ip}pG@<;~_-b6~sN z7L&US9*n1WvhY9ppjzI`EC16s|8M+(KN!0|s5@L7*dxW_UsR{972uw3{{S-h;lJ@R z{_NELJyzw<&gx%&{r?Mz<$w9y{*?p#VPpR(*^+;C8H2I7=ISh)W=x-oslA0P95{C~mj{b#56KS#G~ q-Mv3pxc`&l*gyNt{xlEs;Qs>q{#983 diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md index 551fc2959..aeafa6bc1 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md @@ -6,8 +6,68 @@ weight: 6 layout: learningpathall --- -## PLACEHOLDER HEADER OF SECOND STEP -YOUR CONTENT GOES HERE +## ArmNN's Network Profiler +One way of running tflite models is with ArmNN. This is available as a delegate to the standard tflite interpreter. But to profile the model, there is a command-line utility called `ExecuteNetwork`. This program just runs the model without the rest of an app. It is able to output layer timings and other useful information to let you know where there might be bottlenecks within your model. -IMAGE HERE: -![example image alt-text#center](example-picture.png "Figure 1. Example image caption") +If you are not using tflite, you'll need to look at other tools from your framework to profile your model. If you are using tflite, but not ArmNN, then the output from `ExecuteNetwork` will be more of an indication than a definitive answer. But it can still be useful to see if there are any obvious problems. + +To get `ExecuteNetwork` you can download it from the [ArmNN GitHub](https://github.com/ARM-software/armnn/releases). Download the version appropriate for the Android phone you wish to test on - the Android version and the architecture of the phone. If you are unsure of the architecture, you can use a lower one, but you may miss out on some optimizations. Inside the tar.gz that you download, `ExecuteNetwork` is included. Note among the other release downloads on the ArmNN Github is the separate file for the `aar` delegate which is the easy way to include the ArmNN delegate into your app. + +To run `ExecuteNetwork` you'll need to use `adb` to push the model and the executable to your phone, and then run it from the adb shell. `adb` is included with Android Studio, but you may need to add it to your path. Android Studio normally installs it to a location like \\AppData\Local\Android\Sdk\platform-tools. `adb` can also be downloaded separately from the [Android Developer site](https://developer.android.com/studio/releases/platform-tools). + +From a command prompt, you can run the following commands to push the files to your phone: + +```bash +adb push model.tflite /data/local/tmp/ +adb push ExecuteNetwork /data/local/tmp/ +adb push libarm_compute.so /data/local/tmp/ +adb push libarmnn.so /data/local/tmp/ +adb push libarmnn_support_library.so /data/local/tmp/ +``` +Push all the `.so` library files that are in the base folder of the tar.gz you downloaded, alongside `ExecuteNetwork`, and all the `.so` files in the `delegate` sub-folder. If you are using a recent version on of Android Studio this copying can be done much more easily with drag and drop in the *Device Explorer > Files*. + +Then you need to set the permissions on the files: + +```bash +adb shell # to get into the adb shell on the phone +cd /data/local/tmp +chmod 777 ExecuteNetwork # to make the file executable +chmod 777 *.so # to make the library files executable +``` + +Then you can run the model with the following command: + +```bash +LD_LIBRARY_PATH=. ./ExecuteNetwork -m model.tflite -c CpuAcc -T delegate --iterations 2 --do-not-print-output --enable-fast-math --fp16-turbo-mode -e --output-network-details > modelout.txt +``` + +This will run the model twice, outputting the layer timings to `modelout.txt`. Specifically, the `-e` and `--output-network-details` flags will output a lot of timeline information about the model, including the layer timings. The `--do-not-print-output` flag will stop the output of the model, which can be very large, and without sensible input, meaningless. The `--enable-fast-math` and `--fp16-turbo-mode` flags enable some maths optimizations. The `--iterations 2` flag will run the model twice: the first run includes a lot of startup costs and one-off optimizations, so the second run is more indicative of the real performance. + +After running the model, you can pull the output file back to your computer with the following commands: + +```bash +exit # to leave the adb shell +adb pull /data/local/tmp/modelout.txt +``` +Once again, this can be done with drag and drop in Android Studio's *Device Explorer > Files*. + +Depending on the size of your model, the output will probably be quite large. You can use a text editor or a tool like `less` to view the file. The output is in JSON format, so you can use a JSON viewer to make it more readable. Usually some scripting can be used to extract the information you need more easily out of the very raw data in the file. + +At the top is the summary, with the setup time and inference time of your 2 runs, which will look something like this: +```text +Info: ArmNN v33.2.0 +Info: Initialization time: 7.20 ms. +Info: ArmnnSubgraph creation +Info: Parse nodes to ArmNN time: 50.99 ms +Info: Optimize ArmnnSubgraph time: 85.94 ms +Info: Load ArmnnSubgraph time: 91.11 ms +Info: Overall ArmnnSubgraph creation time: 228.47 ms + +Info: Execution time: 721.91 ms. +Info: Inference time: 722.02 ms + +Info: Execution time: 468.42 ms. +Info: Inference time: 468.58 ms +``` + +After the summary comes the graph of the model, and then the layers and their timings from the second run. At the start of the layers there are a few optimizations & their timings recorded before the network itself, with the layers' "Wall clock time" in microseconds of how long they took to run. These layers and their timings can then be analysed to see which layers, and which operators, took the most time. diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md index ea589f59a..da4fe08de 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md @@ -6,8 +6,11 @@ weight: 5 layout: learningpathall --- -## PLACEHOLDER HEADER OF SECOND STEP -YOUR CONTENT GOES HERE +## Profiling your model +App profilers will give you a good overall view of your performance, but often you might want to look inside the model and work out bottlenecks within the network. The network is often the bulk of the time, in which case it will warrant closer analysis. -IMAGE HERE: -![example image alt-text#center](example-picture.png "Figure 1. Example image caption") +General profilers are unable to do this, as there needs to be annotations inside the ML framework code to get the information. It is a large task to write the profiling annotations throughout the framework, so it is easier if we use tools from a framework or inference engine that can already do the job. + +Depending on your model the tools available will differ. For example, if you are using TensorFlow Lite, Arm provides the ArmNN delegate that you can run the model with on Linux or Android. ArmNN in turn provides a tool called `ExecuteNetwork` that can run the model and give you layer timings and other useful information. + +If you are using PyTorch, you will probably want ExecuTorch on an Android phone, and this also has a profiler available alongside it. From 3e4ad22a25afae7ad077fb229a0766dddba3debd Mon Sep 17 00:00:00 2001 From: Ben Clark Date: Sun, 27 Oct 2024 18:08:00 +0000 Subject: [PATCH 03/17] done, pending final read-through --- .../profiling-ml-on-arm/_next-steps.md | 18 +++------ .../profiling-ml-on-arm/_review.md | 38 +++++++++--------- .../android-profiling-version.png | Bin 0 -> 18717 bytes .../app-profiling-android-studio.md | 34 ++++++++++++++++ .../app-profiling-streamline.md | 20 ++++----- .../profiler-jk-allocations-legend.png | Bin 0 -> 32173 bytes .../start-profile-dropdown.png | Bin 0 -> 6980 bytes .../profiling-ml-on-arm/why-profile.md | 6 +-- 8 files changed, 72 insertions(+), 44 deletions(-) create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/android-profiling-version.png create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/profiler-jk-allocations-legend.png create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/start-profile-dropdown.png diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_next-steps.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_next-steps.md index c4ae77cc9..aafea4126 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_next-steps.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_next-steps.md @@ -1,21 +1,15 @@ --- -next_step_guidance: PLACEHOLDER TEXT 1 +next_step_guidance: Continue Learning -recommended_path: /learning-paths/PLACEHOLDER_CATEGORY/PLACEHOLDER_LEARNING_PATH/ +recommended_path: /learning-paths/smartphones-and-mobile/build-llama3-chat-android-app-using-executorch-and-xnnpack/ +recommended_path: /learning-paths/smartphones-and-mobile/kleidiai-on-android-with-mediapipe-and-xnnpack/ further_reading: - resource: - title: PLACEHOLDER MANUAL - link: PLACEHOLDER MANUAL LINK + title: Arm Streamline User Guide + link: https://developer.arm.com/documentation/101816/latest/ type: documentation - - resource: - title: PLACEHOLDER BLOG - link: PLACEHOLDER BLOG LINK - type: blog - - resource: - title: PLACEHOLDER GENERAL WEBSITE - link: PLACEHOLDER GENERAL WEBSITE LINK - type: website + # ================================================================================ diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md index 9b1bfb96f..814fe6c32 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md @@ -2,37 +2,37 @@ review: - questions: question: > - PLACEHOLDER QUESTION 1? + Streamline Profiling lets you profile: answers: - - PLACEHOLDER ANSWER A - - PLACEHOLDER ANSWER B - correct_answer: 1 + - Arm CPU activity + - Arm GPU activity + - when your Neural Network is running + - All of the above + correct_answer: 4 explanation: > - PLACEHOLDER EXPLANATION 1 + Streamline will show you CPU and GPU activity (and a lot more counters!), and if Custom Activity Maps are used, you can see when your Neural Network and other parts of your application are running. - questions: question: > - PLACEHOLDER QUESTION 2? + Does Android Studio have a profiler? answers: - - PLACEHOLDER ANSWER A - - PLACEHOLDER ANSWER B - - PLACEHOLDER ANSWER C - - PLACEHOLDER ANSWER D - correct_answer: 4 + - Yes + - No + correct_answer: 1 explanation: > - PLACEHOLDER EXPLANATION 2 + Yes, Android Studio has a built-in profiler that can be used to monitor the memory usage of your app among other things - questions: question: > - PLACEHOLDER QUESTION 3? + Is there a way to profile what is happening inside your Neural Network? answers: - - PLACEHOLDER ANSWER A - - PLACEHOLDER ANSWER B - - PLACEHOLDER ANSWER C - - PLACEHOLDER ANSWER D - correct_answer: 2 + - Yes, Streamline just shows you out of the box + - No + - Yes, ArmNN's ExecuteNetwork can do this + - Yes, Android Studio Profiler can do this + correct_answer: 3 explanation: > - PLACEHOLDER EXPLANATION 3 + Standard profilers don't have an easy way to see what is happening inside an ML framework to see a model running inside it. ArmNN's ExecuteNetwork can do this for TensorFlow Lite models, and ExecuTorch has tools that can do this for PyTorch models. diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/android-profiling-version.png b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/android-profiling-version.png new file mode 100644 index 0000000000000000000000000000000000000000..7e058f009ffd14bd91ba049ae488d3b7d832fe22 GIT binary patch literal 18717 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 GO!yBZ4e@RO literal 0 HcmV?d00001 diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md index e2873f0af..03ba77f99 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md @@ -9,3 +9,37 @@ layout: learningpathall ## Android Memory Profiling Memory is often a problem in ML, with ever bigger models and data. For profiling an Android app's memory, Android Studio has a built-in profiler. This can be used to monitor the memory usage of your app, and to find memory leaks. +To find the Profiler, open your project in Android Studio and click on the *View* menu, then *Tool Windows*, and then *Profiler*. This opens the Profiler window. Attach your device, and then you should be able to select your app's process. Here there are a number of different profiling tasks available. + +Most likely with an Android ML app you'll need to look at memory both from the Java/Kotlin side and the native side. The Java/Kotlin side is where the app runs, and may be where buffers are allocated for input and output if you're using LiteRT (formerly TensorFlow Lite). The native side is where the ML framework will run. Looking at the memory consumption for Java/Kotlin and native is 2 separate tasks in the Profiler: *Track Memory Consumption (Java/Kotlin Allocations)* and *Track Memory Consumption (Native Allocations)*. + +Before we start either task we want to build our profileable app. The instructions for this and for general profiling setup can be found [here](https://developer.android.com/studio/profile). We will want to start the correct profiling version of the app depending on the task. + +![Android Studio profiling run types alt-text#center](android-profiling-version.png "Figure 1. Profiling run versions") + +For the Java/Kotlin side, you want the **debuggable** "Profile 'app' with complete data", which is based off the debug variant. For the native side, you want the **profileable** "Profile 'app' with low overhead", which is based off the release variant. + +### Java/Kotlin + +If we start looking at the [Java/Kotlin side](https://developer.android.com/studio/profile/record-java-kotlin-allocations), choose *Profiler: Run 'app' as debuggable*, and then select the *Track Memory Consumption (Java/Kotlin Allocations)* task. Navigate to the part of the app you wish to profile and then we can start profiling. At the bottom of the Profiling window it should look like Figure 2 below. Click *Start Profiler Task*. + +![Android Studio Start Profile alt-text#center](start-profile-dropdown.png "Figure 2. Start Profile") + +When you're ready, *Stop* the profiling again. Now there'll be a nice timeline graph of memory usage. Unfortunately, while Android Studio has a nicer interface for the Java/Kotlin side than the native side, the key to the timeline graph may be missing. This key is shown in below in Figure 3. +![Android Studio memory key alt-text#center](profiler-jk-allocations-legend.png "Figure 3. Memory key for the Java/Kotlin Memory Timeline") + +The default height of the Profiling view is usually too small, so that will need adjusting to get a sensible graph. You can click at different points of the graph to see the memory allocations at that time. If you look according to the key you can see how much memory is allocated by Java, Native, Graphics, Code etc. + +Looking further down you can see the Table of Java/Kotlin allocations for your selected time on the timeline. With ML a lot of your allocations are likely to be byte[] for byte buffers, or possibly int[] for image data, etc. Clicking on the data type will open up the particular allocations, showing their size and when they were allocated. This will help to quickly narrow down their use, and whether they are all needed etc. + +### Native + +For the [native side](https://developer.android.com/studio/profile/record-native-allocations), the process is similar but with different options. Choose *Profiler: Run 'app' as profileable*, and then select the *Track Memory Consumption (Native Allocations)* task. Here you need to *Start profiler task from: Process Start*. Choose *Stop* once you've captured enough data. + +The Native view doesn't have the same nice timeline graph as the Java/Kotlin side, but it does have the Table and Visualization tabs. The Table tab no longer has a list of allocations, but options to *Arrange by allocation method* or *callstack*. Choose callstack and then you can trace down which functions were allocating signifcant memory. Potentially more useful, you can also see Remaining Size. + +In the Visualization tab you can see the callstack as a graph, and once again you can look at total Allocations Size or Remaining Size. If you look at Remaining Size, you can see what is still allocated at the end of the profiling, and by looking a few steps up the stack, probably see which allocations are related to the ML model, by seeing functions that relate to the framework you are using. A lot of the memory may be allocated by that framework rather than in your code, and you may not have much control over it, but it is useful to know where the memory is going. + +## Other platforms + +On other platforms, you will need a different memory profiler. The objective of working out where the memory is being used is the same, and whether there are issues with leaks or just too much memory being used. There are often trade-offs between memory and speed, and they can be considered more sensibly if the numbers involved are known. diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md index 65ccd6eb7..af5a13a97 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md @@ -9,22 +9,22 @@ layout: learningpathall ## Application Profiling Application profiling can be split into 2 main types - *Instrumentation* and *Sampling*. Streamline, for example, is a sampling profiler, that takes regular samples of various counters and registers in the system to provide a detailed view of the system's performance. Sampling will only provide a statistical view, but it is less intrusive and has less processing overhead than instrumentation. -The profiler can look at memory, CPU activity and cycles, cache misses, and may parts of the GPU as well as other performance metrics. It can also provide a timeline view of these counters to show the application's performance over time. This will show bottlenecks, and help you understand where to focus your optimization efforts. +The profiler can look at memory, CPU activity and cycles, cache misses, and many parts of the GPU as well as other performance metrics. It can also provide a timeline view of these counters to show the application's performance over time. This will show bottlenecks, and help you understand where to focus your optimization efforts. ![Streamline image alt-text#center](Streamline.png "Figure 1. Streamline timeline view") ## Streamline -Streamline (and Performance Studio) will be installed on a host machine, and will connect to your target Arm device to capture the data. In our example, this will be an Android phone. The data is captured over a USB connection, and the data is then analyzed on the host machine. +[Streamline](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio#Downloads) (and Performance Studio) will be installed on a host machine, and will connect to your target Arm device to capture the data. In our example, this will be an Android phone. The data is captured over a USB connection, and then analyzed on the host machine. -There are many tutorials and training videos on Streamline, which you can refer to for more depth. Our example will be Android-based, but you can use these instructions for Linux setup and capture. +There are many [tutorials and training videos](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio) on Streamline, which you can refer to for more depth. Our example will be Android-based, but you can use [these instructions for Linux](https://developer.arm.com/documentation/101816/0903/Getting-started-with-Streamline/Profile-your-Linux-application) setup and capture. -For now, as per these setup instructions, make sure you have `adb` (Android Debug Bridge) installed. We will be looking at Android Studio profiling shortly, and if you have installed Android Studio, it will have installed adb. Otherwise, you can get it as part of the Android SDK platform tools here. +For now, as per these [setup instructions](https://developer.arm.com/documentation/102477/0900/Setup-tasks?lang=en), make sure you have `adb` (Android Debug Bridge) installed. We will be looking at Android Studio profiling shortly, and if you have installed Android Studio, it will have installed adb. Otherwise, you can get it as part of the Android SDK platform tools [here](https://developer.android.com/studio/releases/platform-tools.html). -Make sure adb is in your path. You can check this by running `adb` in a terminal. If it is not in your path, you can add it by adding the platform-tools directory to your path. The instructions for this will depend on your host machine's operating system. +Make sure adb is in your path. You can check this by running `adb` in a terminal. If it is not in your path, you can add it by adding the `platform-tools` directory to your path. The instructions for this (and location of the directory) will depend on your host machine's operating system. -Next, install Arm Performance Studio, which includes Streamline. +Next, install [Arm Performance Studio](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio#Downloads), which includes Streamline. -Connect your device to your computer through USB. Ensure that your device is set to Developer mode. +Connect your Android phone to your computer through USB. Ensure that your device is set to [Developer mode](https://developer.android.com/studio/debug/dev-options). On your device, go to `Settings > Developer Options` and enable USB Debugging. If your device asks you to authorize connection to your computer, confirm this. Test the connection by running `adb devices` in a terminal. You should see your device ID listed. @@ -38,11 +38,11 @@ You can now run Streamline, and do a capture of your application. This can be us ## Custom Annotations -In Streamline it is possible to add custom annotations to the timeline view. This can be useful to mark the start and end of specific parts of your application, or to mark when a specific event occurs. This can help you understand the performance of your application in relation to these events. In the picture above there are annotations to show when inference, pre-processing, and post-processing are happening. +In Streamline it is possible to add custom annotations to the timeline view. This can be useful to mark the start and end of specific parts of your application, or to mark when a specific event occurs. This can help you understand the performance of your application in relation to these events. At the bottom of the picture above there are annotations to show when inference, pre-processing, and post-processing are happening. -To add annotations, we need to add some files into our project from the Gator daemon that Streamline uses. These files are `streamline_annotate.c`, `streamline_annotate.h` and `streamline_annotate_logging.h` from here. Then we will be able to show log strings, markers, counters and Custom Activity Maps. +To add annotations, we need to add some files into our project from the Gator daemon that Streamline uses. These files are `streamline_annotate.c`, `streamline_annotate.h` and `streamline_annotate_logging.h` from [here](https://github.com/ARM-software/gator/tree/main/annotate). Then we will be able to show log strings, markers, counters and Custom Activity Maps. -These files are obviously C code, so if your Android Studio project is in Java or Kotlin, you will need to add a C library to your project. This is skightly trickier than just adding a Java or Kotlin file, but it is not difficult. You can find instructions on how to do this here. +These files are obviously C code, so if your Android Studio project is in Java or Kotlin, you will need to add a C library to your project. This is slightly trickier than just adding a Java or Kotlin file, but it is not difficult. You can find instructions on how to do this [here](https://developer.android.com/studio/projects/add-native-code). For us, we create a file the we will call `annotate_jni_wrapper.c`. This will be a wrapper around the Gator daemon's functions, and will be called from our Kotlin code. It starts as below and continues with very similar wrapper functions for the other Gator daemon functions you want. diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/profiler-jk-allocations-legend.png b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/profiler-jk-allocations-legend.png new file mode 100644 index 0000000000000000000000000000000000000000..a9dfadfe0d23673de36ba850e04bf4caa84ba7bd GIT binary patch literal 32173 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 T=hy$JD=9CnA_bKA7V`f9ihY}h literal 0 HcmV?d00001 diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/start-profile-dropdown.png b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/start-profile-dropdown.png new file mode 100644 index 0000000000000000000000000000000000000000..e7d16270f82b18ea40f37e6762428cc6a2d582da GIT binary patch literal 6980 zcmZu$Wl&tpw#FGCxCOUh!GZ>dK@aW{f&@4~a2YIv4h%tp28S?cfZzmomq2hE9D@7c z4sXuA_uYCwURCeiyQ`~KuU`G_uUGdMsjaDuk4ue@|y{Og?uMS z>{%fzRFJN+97@F~?H;m$VF%OzqM%gA;XPPlBHK7_f4u{tpb+%@^Pmp67XOWcLOrjd z0Mz$2Kgz=PC0Cpq&;rZ-g$BsQitvmNt|a>&K}N%|9748O$`R3hkCT^I8Agd3AVW^p zhXshrW=6})VO9iV?`aSLm^CK<@=&?G3OXJgv8`!feY-VuD>Wv4ef<0QcY6AW^!b>W z;9Ewio)onZM!8{?a^{#(pROft}Zeo!IY5AWfnk4wmYX_DlFYOpQQ-Iv7915FNO+^bz>zV zOH(7xh3HqBFltcKs%~|k!LW%v<*GdnZ|tL@0r`z4)!-;bfZQ+lKbuslYGVb>b)|cp z$XPsfMZ^i%U!QUld&o&M9#;IIQ`dW@Dl8hL7SDYNOkfPh#DjS1@&lZ(0EsYy zP%Tpsza!H~f3Kx?)RO`!e8!Fy7!93x>Z@16HApVZn&Q z0OGmuPAra}wwgrHNvsp5`FItiDKwg#2p>&1EExUW6j5c}yDPP3k`$6A=%mJStQh zR9ID`Aa2(}ug|aZ5O?rOer)dx?*i zvs9mO2$Wx^>Cl(&EN@G^%VVnB6jjmc=qggUSIotcv$5^sJn5C zWoF>jbzxwe_(KC?IAi1=0EK89zFcMxfgLaa$%hwT1#0Knde5olyYV3+3U8u zeP8gysily0KX>!v)iF1Ptg44V0KZSg_c@p0?Gep3l}7s8sJ8nn@GJe_*Xh6jRVOsB zws~ndzPQhxT)9a@VR11B_~3|hy2gl4vjNSfrG)0vq^_YVV6#k8aI^xF=D1M6*-)tz zLk%vW17+v%T6d%a=?ouDCZnl^Ri6#-oR(@69cGG^jLZyxTJ9qg*6bfcz2heQY?HTL zJD&ouV|VSI##YOvSbkBP~($35E%37yVVq(WZp}!Ixk#MLG0@oAd#$ea%Civ*t z|1MLT4)VawQW?s9IywyDea#%~V1!e9v4G#s`TNIPoH-T?oi;1RnTo?e%+yI-Lwy+}>yRG!oO=>M1>bJ*X zsTU^%M1SV;6!9EZ+e2Y;o?~s-lgmvn^Su?a}+pye3#jM49 z!!d@@39&R^bJ5+n)3k(5|56TTgtS=4x@8CFR)+7rlC_eI24y0z?#W63{9vx_-Z=@D zpm|M5rJkOiKCMXVR^_@s%}LPG;Icfl$B`d!e?`W?p!H1k{2HHDD568YRq_g+ZwhO2 ziO2w7{%JaXS7WO!D=XXH{#u=39oBMponPlT=SE*~w33g#Lv;G1(y_G>^n8!yHF4MBu{C5$aQAoStc+9s zY&&1a!`D%mSbpR~>fRSV>7Ac%K5w52B&MWjLLd+_Is;9u)7abdotj-~pJUqZg@w8U zv2>TTd8rnG@BD0=#V6mGGX&l+X`~B;1wP%{xv;eQt!4SFtP6SZbc-s-(yH+D^Lt*- z7=frOZnraCi{Cf6_`6_Yz4yzfZg;p<0Kk1S_!)=usH2MNowV-u> zC{6!N$>^nNW4uDkHEn^z%0EB*^;j^z^2R zRkupdmMd?3w6B-SI1K7R8;BuHMRzi6(OB4 z8?M=j46pa|u<>}J<`P|)wzm!6ow$TVrb&at=nl#i-=n?oPFJ9?60Y4XtR7px+~Ju9 zwZB?9P(h(ln!te8+CgC^?rhzxcHa&jA|xC;L~#x`YA>;Bx9eGki~D(#RrJ$e^I9}P zhDGMG((Ustd>B5&)m2MdKzt6$#PEu(!akM|B|di)D92?L^sQFrq~Kh2fQ$+X%qO81 zyvcFgP0!4DA&g{UbjqL`4sJp({QN0Oko~XvVKDB*P6zzs6BZ3#EK^nwywvMxrfXV= zH^T6E)JkiyfN85Z@RD(VK@wUyfAv0v4FfcKP=cj6#QPCRUkp0(Pf{l7KJ^6O#SKDshwDVH?(k3O zN3DoOYVBXjt-91#2S}NOi5|8$*>Du)N5`+BEchFfR%OIU#M++w0IKcfhie*z=kS47 z6NocYpMkvooxnUVsfY)?q@%{Vs7!&x}FBvOaDx#t`< zg3*mt_fI$2$G`BkcRE%xGDe$cA$d=%o4iQa+S-bU?~>P)#sJKug;B z&hPY*?6rqmP_6Y2@155iJ**&({``g6TuCxpdvgsok-g#JQd45e6M{7LeqtbdT1L~+Y@1(s*~p6*;gnSYN6q+4 z6f9wT`H`gT+SnRy#jOipcl@<9BApaT_E^p$SDdY$YvZ}{l7+kXqggHE*76KC zmf>K-GSlxkixnB22g7r(wPnsGp73dEaSqzs{9~`sHsBQOJ@kVf zW3S8d=cDPIKstw&GA8G#-tOP?S04Po$_+}XgF2cV{TwEXVK&sVgA8o<6Z~60F1<$f z4(IVMjxWZHg;3NRbtunt#(pIh?Zq@mdvBt{i76ObhpJm&LV(B5a%5Zd{xq*ICT zGGu4}zFQ!+jkrs7{PW#1wE0_y-x!m!#P20|*OO^3&ka2>{iyfaU5|2XO+a;Za--Cj z_8NjOy_Z$&Vw}mt!6?A{Dqg(Cnz^b!U>7ffC5)c|`>aUg`P;dq^H_*$>K0zI zaBRTQ!pz9I^);!=0}mJ0SE_VAibWvsu-%_XS1}1@<-J{z$;t{b_44)VhOxa=-5V zM?}DAKG#3n-`^C@?dr}nSm$>F06>1KeV0-ui|OfiK3;oe@tuZo=-^m~d7(sq(fDB8 zlqf@pA~A)Wkfph}mp^a1lr@XAdcKVCMB~ZdB7P_dwu*JQ5TWC9Pu}bMa*^gzGmb9| zeSNj2)a8D}mRyIhJ2R~8d}(-?a4@2q>ge zKX<*q93B?iAp5O&9LQ?L7)=%czV_M-s`(&|Pj{ClKbX^Aq#T!9xwEBlD2XXoW%2xk zxxez0m2cB+EvHK}teDCtfQ*z*-qEnqcA~Jt;0Oir8t5rT3aXH8%_lP}ooa}{P186wWq*&7*N2eVBVqmZc}*p`-XBxc&?)j`_HW%4pW}7xq@baIeD4HG1`j^2tuGIdl1j<)sAh)h=>3r_mXcINbQI@QQ7T z=e^Ln|MYq1TDyOT`|^^EiO7~eeDZNtGwEx_Hjylsk#pYbWGPACPDVqfaBXTx;yzBLIJYz|Hxk+`O_rmZtrlV)!JFbR!>It2zMMLg zL!FoC$L&264abMVA!pY|GTqLG8^QcQx{n=V7BN(Z;daCC{J!ex;?-j3rlZ*8`CF&o z9OL*ZMSJJ1GB%SL&Bf%m+^zI`&6d228E9A80LR*)TQg8o%bim`49?NqUz){{^!k0etx%J+9Dm0&2Rbz5%c^CibLnOkAvqwifouN6ib5Avgjo5&bw z2JrzaV_mw5s2c0`xNM5?7q=!ry&t?yZM4d8ENCKRF|#i1Yn;939tkG zM6)k~BEJ}wh+T=Fm^`b)G(ww2HJ%I$0EF_FY^)3ba7^XVq4&;xSS00g7;l1CB7Ns~l>`6h;0ZWp&v*aS2Jd92n3`_o< zb44fgV(Zl?@5ShH;rZvhb?%a@eCKhU2 zuNDK%0qp(sW4IXXvK9tEbU7^mg(T4ZK;Kz?iSZ)K++6O>;L_^2xn9=b0fI4682cvG z!D~*&{d(us9&-5?~+Bu#JTl4pwau z7G015#954o?Z~3+scwhE0K#WR4(sw-Oc=zxC9xZJAPy0>%H#82E6GPCacqHEqyJhZ zNT8@>M{s+t&YQ5X&6y)LT!1)$;#}mG$RHG(Fn41h?tt?aGKZZTo9!=ZSa*?qJ4i_{tV(-NOl_9n9uf;|LaJ41+fWfn{RZE2j^Y$X*A>MqR7 z=_Q$+OouS~dccXU41u1E3WyO-!FlUKH=9cG^}+-9a-B^uoXKq> z%WIa>_DzLShH&`_kux$YoO{6_9^V6Pa9SK0E9OtCE7+Slu-z}E`{yzMRAoETsv#|@ zXxwAKG-;y!L4!(;PUeO`vH4LVy@!riU>7fAdWck*NVJ+C;wjzN6klR2-4WwZG}?_q zNVi}miF-f?no~v$F})yT`T-yhYjD{u|MZNa_>#L7v|KsN;IWT~dqKojhrrT+2~Dgs zg}h9cy4P!7|4egZYH7alz4H>jK0#U~GE81V_1IXcSHv0_$K`r5DtJM zbaE3{LbOLzNG(9qF>VUJbFJhuuq$H8V4_LcPrtujHls?~5+wpS!zi`pw|Izl<}8BH zE9dn-lqGDJSq$R>vY_Dv2OH77eSPEz^O8$%RXDJdPSQ7i#s6Hxq5KjR28xg@%jyA( z`>dzr$f*kjy{@E$0wk5p#LdPmUD95Lhf})zjMJ8e{_1jsdN@oEzArNRVf7-&3O|K- z+LcVUBH}f}uS~-nr}Nxap0w7U8o~Wv*tF|mFkGypa!DoJy3eI~E*(_UU&iHYZ}$=i z^$JI};b*I)e&i0OYs5kpc$Mix9S9?Hi(Io^8M`C->q88Gica(l=l1k@rEl z7r}ElD>=$8ql>I0Rv4M-w2y)v@dA~nx@+J=#4ZlJwfA39zqCzH1-&yhfgpxI3!i!S z{x{+kI83q4r|-QG6`xvK3W@?S2pOS5q7UJ10qbm9uXb(YjNTDC~ySfNme|Q-%MR9>T1m6EeY}!y{PV0IPup&E> zr{9NO6Ub0mV&$e^9=u(nlf>iNU&($#rIP?h-_tqw7T-X|gUIKtuVC_sd$`tGt%W%|g zL2CXhb;)m+!sVyV3@)l^xL_see!vO8UokV3O@!RNo`TTv83DqpLZ91cxNwtp&AN8H zUU?G9dg}~i$SFgmlW%g->fvrXVu{eHCHz!Oy3!(6imSxQBqXTP;`%4vLz>hJb&nU# zYCT3gIc@O$rJun3fC4o=X9T4MO4sS**YB-@ERrTGNq7+BG!5f2M7@g-g9QKc0!b&-~CZbUO>u!fnIw=bxLB6!VP|N26?=!0Rvs7@loEp6G20lu2I6T`Pm zL#zPd5C}Th|a zk=odxTZU`cnN!nG!bUDV9Px;NwIflmz}2pr(HPTN*7AwNVV2Ye;@DE2;*v1-XB0pj zsUP55;51M6bL?WQT9J9eFb7gd;06LE{_}+BWJ3gqR`S#|bc8yJuPa&Fnia`m-%Js;yC=Q8c#(3;@AY=@zdfk{v6gAaNvzvoT{qT@EehZX#=@3D{fz>)_5*7t z-nEx38jJKY&1!UKvj21cZur6ISJH*RfyCXScA=DKNRS>iee+i|b1GN%)9z&aC!8wB zF(AR7Cu=jtDhvHT&c<|n3D@M1e(0BH2iTA!)1`(F8q~9DQE8;e%o?LBH6n*JDyB0S zW#||0LmUt(rQD#kh9jg&Fn|b3xzNZEG}Z{sDy;vi2EpvioPF&e7*f5khg`?|Dq#W< z>>2%-Its<=Q<#njr!^{_!9->8Y$z%XEP&)!E-U?f8 z%wH|aL>Mv~y0*Mhf{RMZnmgLfJmEhz}sa1SKA=Td&YJd Xwh>1A+s75De4(f)YARI7eF*s<(7$n3 literal 0 HcmV?d00001 diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md index 3864750f6..8a0d20d1a 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md @@ -15,9 +15,9 @@ We will be looking at an Android example using TFLite in this learning path, but ## Tools -Currently different tools are needed if you want to look inside the NN inference, or at the application's performance as a whole. +Currently, you need to use different tools to profile the ML inference or the application's performance as a whole. -For profiling the ML inference we will look at ArmNN's ExecuteNetwork. +For profiling the ML inference we will look at [ArmNN](https://github.com/ARM-software/armnn/releases)'s ExecuteNetwork. -For profiling the application as a whole we will look at Arm Performance Studio's Streamline, and at the Android Studio Profiler. +For profiling the application as a whole we will look at [Arm Performance Studio](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio)'s Streamline, and at the Android Studio Profiler. From faac583d06636047bcab940010d635951dc95dc8 Mon Sep 17 00:00:00 2001 From: Ben Clark Date: Mon, 28 Oct 2024 13:47:35 +0000 Subject: [PATCH 04/17] editing on self-review --- .../profiling-ml-on-arm/_index.md | 2 +- .../profiling-ml-on-arm/_review.md | 2 +- .../app-profiling-android-studio.md | 16 ++++++++-------- .../app-profiling-streamline.md | 16 ++++++++++------ .../nn-profiling-executenetwork.md | 15 ++++++++------- .../profiling-ml-on-arm/nn-profiling-general.md | 2 +- .../profiling-ml-on-arm/streamline_marker.png | Bin 0 -> 52790 bytes 7 files changed, 29 insertions(+), 24 deletions(-) create mode 100644 content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/streamline_marker.png diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md index a57070750..593c7e111 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md @@ -3,7 +3,7 @@ title: How to Profile ML on Arm minutes_to_complete: 30 -who_is_this_for: ML App developers who want to see the performance of their models on Arm devices. +who_is_this_for: Machine Learning App developers who want to see the performance of their models on Arm devices. learning_objectives: - Profile timings of ML models on Arm devices. diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md index 814fe6c32..a1f46d1ed 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md @@ -27,7 +27,7 @@ review: Is there a way to profile what is happening inside your Neural Network? answers: - Yes, Streamline just shows you out of the box - - No + - No. - Yes, ArmNN's ExecuteNetwork can do this - Yes, Android Studio Profiler can do this correct_answer: 3 diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md index 03ba77f99..7d49a7303 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md @@ -1,5 +1,5 @@ --- -title: App Profiling with Android Studio +title: Memory Profiling with Android Studio weight: 4 ### FIXED, DO NOT MODIFY @@ -9,9 +9,9 @@ layout: learningpathall ## Android Memory Profiling Memory is often a problem in ML, with ever bigger models and data. For profiling an Android app's memory, Android Studio has a built-in profiler. This can be used to monitor the memory usage of your app, and to find memory leaks. -To find the Profiler, open your project in Android Studio and click on the *View* menu, then *Tool Windows*, and then *Profiler*. This opens the Profiler window. Attach your device, and then you should be able to select your app's process. Here there are a number of different profiling tasks available. +To find the Profiler, open your project in Android Studio and click on the *View* menu, then *Tool Windows*, and then *Profiler*. This opens the Profiler window. Attach your device in Developer Mode with a USB cable, and then you should be able to select your app's process. Here there are a number of different profiling tasks available. -Most likely with an Android ML app you'll need to look at memory both from the Java/Kotlin side and the native side. The Java/Kotlin side is where the app runs, and may be where buffers are allocated for input and output if you're using LiteRT (formerly TensorFlow Lite). The native side is where the ML framework will run. Looking at the memory consumption for Java/Kotlin and native is 2 separate tasks in the Profiler: *Track Memory Consumption (Java/Kotlin Allocations)* and *Track Memory Consumption (Native Allocations)*. +Most likely with an Android ML app you'll need to look at memory both from the Java/Kotlin side and the native side. The Java/Kotlin side is where the app runs, and may be where buffers are allocated for input and output if, for example, you're using LiteRT (formerly known as TensorFlow Lite). The native side is where the ML framework will run. Looking at the memory consumption for Java/Kotlin and native is 2 separate tasks in the Profiler: *Track Memory Consumption (Java/Kotlin Allocations)* and *Track Memory Consumption (Native Allocations)*. Before we start either task we want to build our profileable app. The instructions for this and for general profiling setup can be found [here](https://developer.android.com/studio/profile). We will want to start the correct profiling version of the app depending on the task. @@ -25,18 +25,18 @@ If we start looking at the [Java/Kotlin side](https://developer.android.com/stud ![Android Studio Start Profile alt-text#center](start-profile-dropdown.png "Figure 2. Start Profile") -When you're ready, *Stop* the profiling again. Now there'll be a nice timeline graph of memory usage. Unfortunately, while Android Studio has a nicer interface for the Java/Kotlin side than the native side, the key to the timeline graph may be missing. This key is shown in below in Figure 3. +When you're ready, *Stop* the profiling again. Now there'll be a nice timeline graph of memory usage. Unfortunately, while Android Studio has a nicer interface for the Java/Kotlin side than the native side, the key to the timeline graph may be missing. This key is shown below in Figure 3, so you can refer to the colors from this. ![Android Studio memory key alt-text#center](profiler-jk-allocations-legend.png "Figure 3. Memory key for the Java/Kotlin Memory Timeline") -The default height of the Profiling view is usually too small, so that will need adjusting to get a sensible graph. You can click at different points of the graph to see the memory allocations at that time. If you look according to the key you can see how much memory is allocated by Java, Native, Graphics, Code etc. +The default height of the Profiling view - as well as the timeline graph within it - is usually too small, so adjust these heights to get a sensible graph. You can click at different points of the graph to see the memory allocations at that time. If you look according to the key you can see how much memory is allocated by Java, Native, Graphics, Code etc. -Looking further down you can see the Table of Java/Kotlin allocations for your selected time on the timeline. With ML a lot of your allocations are likely to be byte[] for byte buffers, or possibly int[] for image data, etc. Clicking on the data type will open up the particular allocations, showing their size and when they were allocated. This will help to quickly narrow down their use, and whether they are all needed etc. +Looking further down you can see the *Table* of Java/Kotlin allocations for your selected time on the timeline. With ML a lot of your allocations are likely to be byte[] for byte buffers, or possibly int[] for image data, etc. Clicking on the data type will open up the particular allocations, showing their size and when they were allocated. This will help to quickly narrow down their use, and whether they are all needed etc. ### Native -For the [native side](https://developer.android.com/studio/profile/record-native-allocations), the process is similar but with different options. Choose *Profiler: Run 'app' as profileable*, and then select the *Track Memory Consumption (Native Allocations)* task. Here you need to *Start profiler task from: Process Start*. Choose *Stop* once you've captured enough data. +For the [native side](https://developer.android.com/studio/profile/record-native-allocations), the process is similar but with different options. Choose *Profiler: Run 'app' as profileable*, and then select the *Track Memory Consumption (Native Allocations)* task. Here you have to *Start profiler task from: Process Start*. Choose *Stop* once you've captured enough data. -The Native view doesn't have the same nice timeline graph as the Java/Kotlin side, but it does have the Table and Visualization tabs. The Table tab no longer has a list of allocations, but options to *Arrange by allocation method* or *callstack*. Choose callstack and then you can trace down which functions were allocating signifcant memory. Potentially more useful, you can also see Remaining Size. +The Native view doesn't have the same nice timeline graph as the Java/Kotlin side, but it does have the *Table* and *Visualization* tabs. The *Table* tab no longer has a list of allocations, but options to *Arrange by allocation method* or *callstack*. Choose *Arrange by callstack* and then you can trace down which functions were allocating signifcant memory. Potentially more useful, you can also see Remaining Size. In the Visualization tab you can see the callstack as a graph, and once again you can look at total Allocations Size or Remaining Size. If you look at Remaining Size, you can see what is still allocated at the end of the profiling, and by looking a few steps up the stack, probably see which allocations are related to the ML model, by seeing functions that relate to the framework you are using. A lot of the memory may be allocated by that framework rather than in your code, and you may not have much control over it, but it is useful to know where the memory is going. diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md index af5a13a97..976a3d0b7 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md @@ -38,13 +38,13 @@ You can now run Streamline, and do a capture of your application. This can be us ## Custom Annotations -In Streamline it is possible to add custom annotations to the timeline view. This can be useful to mark the start and end of specific parts of your application, or to mark when a specific event occurs. This can help you understand the performance of your application in relation to these events. At the bottom of the picture above there are annotations to show when inference, pre-processing, and post-processing are happening. +In Streamline it is possible to add custom annotations to the timeline view. This can be useful to mark the start and end of specific parts of your application, or to mark when a specific event occurs. This can help you understand the performance of your application in relation to these events. At the bottom of *Figure 1* above there are custom annotations to show when inference, pre-processing, and post-processing are happening. To add annotations, we need to add some files into our project from the Gator daemon that Streamline uses. These files are `streamline_annotate.c`, `streamline_annotate.h` and `streamline_annotate_logging.h` from [here](https://github.com/ARM-software/gator/tree/main/annotate). Then we will be able to show log strings, markers, counters and Custom Activity Maps. These files are obviously C code, so if your Android Studio project is in Java or Kotlin, you will need to add a C library to your project. This is slightly trickier than just adding a Java or Kotlin file, but it is not difficult. You can find instructions on how to do this [here](https://developer.android.com/studio/projects/add-native-code). -For us, we create a file the we will call `annotate_jni_wrapper.c`. This will be a wrapper around the Gator daemon's functions, and will be called from our Kotlin code. It starts as below and continues with very similar wrapper functions for the other Gator daemon functions you want. +For us, we create a file that we will call `annotate_jni_wrapper.c` in the `src/main/cpp/` folder under our project. This will be a wrapper around the Gator daemon's functions, and will be called from our Kotlin code. It starts as below and continues with very similar wrapper functions for the other Gator daemon functions you want. ```c #include @@ -94,7 +94,7 @@ target_link_libraries( # Specifies the target library. ${log-lib} ) ``` -If you add the following to your `build.gradle` file, you will be able to call the functions from your Kotlin code: +If you add the following to the `build.gradle` file of the Module you wish to profile, you will be able to call the functions from your Kotlin code: ```gradle externalNativeBuild { @@ -158,12 +158,16 @@ class AnnotateStreamline { The `AnnotateStreamline` class can now be used in your Kotlin code to add annotations to the Streamline timeline view. Make sure that `AnnotateStreamline.setup()` is called first, and then you can add annotations like this: ```kotlin - AnnotateStreamline.annotateMarkerColorStr(AnnotateStreamline.ANNOTATE_BLUE, "Important event") + AnnotateStreamline.annotateMarkerColorStr(AnnotateStreamline.ANNOTATE_BLUE, "Model Load") ``` +This colored marker with a string will add the string and time to Streamline's log view, and look like the below image in Streamline's timeline: + +![Streamline image alt-text#center](streamline_marker.png "Figure 2. Streamline timeline markers") + ## Custom Activity Maps (CAMs) -In addition to adding strings to the log and colored markers to the timeline, a particularly useful set of annotations is the Custom Activity Maps. These are the named colored bands you can see at the bottom of the Streamline timeline view shown above. They can be used to show when specific parts of your application are running, such as the pre-processing or inference, and layered for functions within functions etc. +In addition to adding strings to the log and colored markers to the timeline, a particularly useful set of annotations is the Custom Activity Maps. These are the named colored bands you can see at the bottom of the Streamline timeline view shown in *Figure 1*. They can be used to show when specific parts of your application are running, such as the pre-processing or inference, and layered for functions within functions etc. To add these you'll need to import the functions that start `gator_cam_` from `streamline_annotate.h` through your wrapper files in the same way as the functions above. Then you can use CAMs, but first you'll need to set up the tracks the annotations will appear on and an id system for each annotation. The `baseId` code below is to ensure that in the case of multiple places in your code adding annotations, the ids are unique. @@ -197,4 +201,4 @@ Then they can be used like this: AnnotateStreamline.camJobEnd(camViewId, preprocess, AnnotateStreamline.getTime()) ``` -Now when you build and deploy a debug version of your application, you can run Streamline and see the annotations and CAMs in the timeline view. This will make it obvious whether the time spent in your application is on the inference, ML pre-processing, ML post-processing, or other parts of your application. +Now when you build and deploy a debug version of your application, you can run Streamline and see the annotations and CAMs in the timeline view. See the [Streamline documentation](https://developer.arm.com/documentation/101816/latest/) for how to make a capture for profiling. Once the capture is made and analyzed, you will be able to see when your application is running the inference, ML pre-processing, ML post-processing, or other parts of your application. From there you can see where the most time is spent, and how hard the CPU or GPU is working during different parts of the application. From this you can then decide if work is needed to improve performance and where that work needs doing. diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md index aeafa6bc1..125474190 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md @@ -7,24 +7,25 @@ layout: learningpathall --- ## ArmNN's Network Profiler -One way of running tflite models is with ArmNN. This is available as a delegate to the standard tflite interpreter. But to profile the model, there is a command-line utility called `ExecuteNetwork`. This program just runs the model without the rest of an app. It is able to output layer timings and other useful information to let you know where there might be bottlenecks within your model. +One way of running tflite models is with ArmNN. This is available as a delegate to the standard tflite interpreter. But to profile the model, ArmNN comes with a command-line utility called `ExecuteNetwork`. This program just runs the model without the rest of an app. It is able to output layer timings and other useful information to let you know where there might be bottlenecks within your model. -If you are not using tflite, you'll need to look at other tools from your framework to profile your model. If you are using tflite, but not ArmNN, then the output from `ExecuteNetwork` will be more of an indication than a definitive answer. But it can still be useful to see if there are any obvious problems. +If you are not using tflite, you'll need to look at other tools from your framework to profile your model. If you are using tflite without ArmNN, then the output from `ExecuteNetwork` will be more of an indication than a definitive answer. But it can still be useful to see if there are any obvious problems. To get `ExecuteNetwork` you can download it from the [ArmNN GitHub](https://github.com/ARM-software/armnn/releases). Download the version appropriate for the Android phone you wish to test on - the Android version and the architecture of the phone. If you are unsure of the architecture, you can use a lower one, but you may miss out on some optimizations. Inside the tar.gz that you download, `ExecuteNetwork` is included. Note among the other release downloads on the ArmNN Github is the separate file for the `aar` delegate which is the easy way to include the ArmNN delegate into your app. To run `ExecuteNetwork` you'll need to use `adb` to push the model and the executable to your phone, and then run it from the adb shell. `adb` is included with Android Studio, but you may need to add it to your path. Android Studio normally installs it to a location like \\AppData\Local\Android\Sdk\platform-tools. `adb` can also be downloaded separately from the [Android Developer site](https://developer.android.com/studio/releases/platform-tools). -From a command prompt, you can run the following commands to push the files to your phone: +Unzip the tar.gz folder you downloaded to somewhere convenient. From a command prompt, you can then adapt and run the following commands to push the files to your phone. The `/data/local/tmp` folder of your Android device is a place with relaxed permissions that you can use to run this profiling. ```bash -adb push model.tflite /data/local/tmp/ +adb push model.tflite /data/local/tmp/ # the tflite NN model file that you wish to profile adb push ExecuteNetwork /data/local/tmp/ adb push libarm_compute.so /data/local/tmp/ adb push libarmnn.so /data/local/tmp/ adb push libarmnn_support_library.so /data/local/tmp/ +# more ArmNN .so library files ``` -Push all the `.so` library files that are in the base folder of the tar.gz you downloaded, alongside `ExecuteNetwork`, and all the `.so` files in the `delegate` sub-folder. If you are using a recent version on of Android Studio this copying can be done much more easily with drag and drop in the *Device Explorer > Files*. +Push all the `.so` library files that are in the base folder of the tar.gz you downloaded, alongside `ExecuteNetwork`, and all the `.so` files in the `delegate` sub-folder. If you are using a recent version of Android Studio this copying can be done much more easily with drag and drop in the *Device Explorer > Files*. Then you need to set the permissions on the files: @@ -51,7 +52,7 @@ adb pull /data/local/tmp/modelout.txt ``` Once again, this can be done with drag and drop in Android Studio's *Device Explorer > Files*. -Depending on the size of your model, the output will probably be quite large. You can use a text editor or a tool like `less` to view the file. The output is in JSON format, so you can use a JSON viewer to make it more readable. Usually some scripting can be used to extract the information you need more easily out of the very raw data in the file. +Depending on the size of your model, the output will probably be quite large. You can use a text editor to view the file. The output is in JSON format, so you can use a JSON viewer to make it more readable. Usually some scripting can be used to extract the information you need more easily out of the very raw data in the file. At the top is the summary, with the setup time and inference time of your 2 runs, which will look something like this: ```text @@ -70,4 +71,4 @@ Info: Execution time: 468.42 ms. Info: Inference time: 468.58 ms ``` -After the summary comes the graph of the model, and then the layers and their timings from the second run. At the start of the layers there are a few optimizations & their timings recorded before the network itself, with the layers' "Wall clock time" in microseconds of how long they took to run. These layers and their timings can then be analysed to see which layers, and which operators, took the most time. +After the summary comes the graph of the model, and then the layers and their timings from the second run. At the start of the layers there are a few optimizations and their timings recorded before the network itself, so you can skip past the graph and the optimization timings to get to the part that wants analyzing. The layers' "Wall clock time" in microseconds shows how long they took to run. These layers and their timings can then be analyzed to see which layers, and which operators, took the most time. diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md index da4fe08de..7ca228759 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md @@ -11,6 +11,6 @@ App profilers will give you a good overall view of your performance, but often y General profilers are unable to do this, as there needs to be annotations inside the ML framework code to get the information. It is a large task to write the profiling annotations throughout the framework, so it is easier if we use tools from a framework or inference engine that can already do the job. -Depending on your model the tools available will differ. For example, if you are using TensorFlow Lite, Arm provides the ArmNN delegate that you can run the model with on Linux or Android. ArmNN in turn provides a tool called `ExecuteNetwork` that can run the model and give you layer timings and other useful information. +Depending on your model the tools available will differ. For example, if you are using LiteRT (formerly TensorFlow Lite), Arm provides the ArmNN delegate that you can run the model with on Linux or Android, CPU or GPU. ArmNN in turn provides a tool called `ExecuteNetwork` that can run the model and give you layer timings and other useful information. If you are using PyTorch, you will probably want ExecuTorch on an Android phone, and this also has a profiler available alongside it. diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/streamline_marker.png b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/streamline_marker.png new file mode 100644 index 0000000000000000000000000000000000000000..e7ec90f36eb7b3abb82022bc81819462fb34d2c1 GIT binary patch literal 52790 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 Date: Mon, 4 Nov 2024 09:11:34 -0500 Subject: [PATCH 05/17] Update _index.md --- .../profiling-ml-on-arm/_index.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md index 593c7e111..1c0e05223 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md @@ -1,22 +1,21 @@ --- -title: How to Profile ML on Arm +title: Profile the performance of ML models on Arm minutes_to_complete: 30 -who_is_this_for: Machine Learning App developers who want to see the performance of their models on Arm devices. +who_is_this_for: This is an introductory topic for software developers who want to learn how to profile the performance of their ML models running on Arm devices. learning_objectives: - - Profile timings of ML models on Arm devices. + - Profile the execution times of ML models on Arm devices. - Profile ML application performance on Arm devices. prerequisites: - - Some application development. - - Arm device with Android OS. + - An Arm-powered Android smartphone. author_primary: Ben Clark ### Tags -skilllevels: Intermediate +skilllevels: Introductory subjects: Machine Learning armips: - Cortex-X From 1c9ff903299f163763370724055f588be7f3461a Mon Sep 17 00:00:00 2001 From: pareenaverma Date: Mon, 4 Nov 2024 10:11:23 -0500 Subject: [PATCH 06/17] Update _index.md --- .../smartphones-and-mobile/profiling-ml-on-arm/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md index 1c0e05223..3bd9669e9 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md @@ -16,7 +16,7 @@ author_primary: Ben Clark ### Tags skilllevels: Introductory -subjects: Machine Learning +subjects: ML armips: - Cortex-X - Cortex-A From f87f6dd5ef55dce5feaefe96fed3a6bdd2d6dcfb Mon Sep 17 00:00:00 2001 From: pareenaverma Date: Mon, 4 Nov 2024 10:17:52 -0500 Subject: [PATCH 07/17] Update why-profile.md --- .../profiling-ml-on-arm/why-profile.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md index 8a0d20d1a..75ac1724f 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md @@ -1,5 +1,5 @@ --- -title: What do you need to profile? +title: Why do you need to profile your ML application? weight: 2 ### FIXED, DO NOT MODIFY @@ -11,13 +11,13 @@ Working out what is taking the time and memory in your application is the first With Machine Learning (ML) applications, the inference of the Neural Network (NN) itself is often the heaviest part of the application in terms of computation and memory usage. This is not guaranteed however, so it is important to profile the application as a whole to see if pre- or post-processing or other code is an issue. -We will be looking at an Android example using TFLite in this learning path, but most of the tools also work with Linux to cover a wide range of Arm devices. The principles are the same for other inference engines and platforms, but the tools are different. +In this Learning Path, you will be profiling at an Android example using TFLite, but most of the tools also work with Linux and cover a wide range of Arm devices. The principles for profiling your application are the same for use with other inference engines and platforms, but the tools are different. ## Tools -Currently, you need to use different tools to profile the ML inference or the application's performance as a whole. +You will need to use different tools to profile the ML inference or the application's performance running on your Arm device. -For profiling the ML inference we will look at [ArmNN](https://github.com/ARM-software/armnn/releases)'s ExecuteNetwork. +For profiling the ML inference, you will use [ArmNN](https://github.com/ARM-software/armnn/releases)'s ExecuteNetwork. -For profiling the application as a whole we will look at [Arm Performance Studio](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio)'s Streamline, and at the Android Studio Profiler. +For profiling the application as a whole, you will use [Arm Performance Studio](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio)'s Streamline, and at the Android Studio Profiler. From 1c8d85fb52f9cbfb7b16f3b1d83ac907052c99de Mon Sep 17 00:00:00 2001 From: pareenaverma Date: Mon, 4 Nov 2024 10:37:16 -0500 Subject: [PATCH 08/17] Update app-profiling-streamline.md --- .../app-profiling-streamline.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md index 976a3d0b7..86fd7702f 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md @@ -1,5 +1,5 @@ --- -title: App Profiling with Streamline +title: Profile your application with Streamline weight: 3 ### FIXED, DO NOT MODIFY @@ -7,26 +7,26 @@ layout: learningpathall --- ## Application Profiling -Application profiling can be split into 2 main types - *Instrumentation* and *Sampling*. Streamline, for example, is a sampling profiler, that takes regular samples of various counters and registers in the system to provide a detailed view of the system's performance. Sampling will only provide a statistical view, but it is less intrusive and has less processing overhead than instrumentation. +Application profiling can be split into 2 main types - *Instrumentation* and *Sampling*. [Streamline](https://developer.arm.com/Tools%20and%20Software/Streamline%20Performance%20Analyzer), for example, is a sampling profiler, that takes regular samples of various counters and registers in the system to provide a detailed view of the system's performance. Sampling will only provide a statistical view, but it is less intrusive and has less processing overhead than instrumentation. The profiler can look at memory, CPU activity and cycles, cache misses, and many parts of the GPU as well as other performance metrics. It can also provide a timeline view of these counters to show the application's performance over time. This will show bottlenecks, and help you understand where to focus your optimization efforts. ![Streamline image alt-text#center](Streamline.png "Figure 1. Streamline timeline view") ## Streamline -[Streamline](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio#Downloads) (and Performance Studio) will be installed on a host machine, and will connect to your target Arm device to capture the data. In our example, this will be an Android phone. The data is captured over a USB connection, and then analyzed on the host machine. +You will install [Streamline](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio#Downloads) (and Performance Studio) on your host machine, and will connect to your target Arm device to capture the data. In this example, the target device is an Arm-powered Android phone. The data is captured over a USB connection, and then analyzed on your host machine. -There are many [tutorials and training videos](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio) on Streamline, which you can refer to for more depth. Our example will be Android-based, but you can use [these instructions for Linux](https://developer.arm.com/documentation/101816/0903/Getting-started-with-Streamline/Profile-your-Linux-application) setup and capture. +There are many [tutorials and training videos](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio) on Streamline, which you can refer to for more depth. This example will be Android based, but you can use [these instructions for Linux](https://developer.arm.com/documentation/101816/0903/Getting-started-with-Streamline/Profile-your-Linux-application) setup and capture. -For now, as per these [setup instructions](https://developer.arm.com/documentation/102477/0900/Setup-tasks?lang=en), make sure you have `adb` (Android Debug Bridge) installed. We will be looking at Android Studio profiling shortly, and if you have installed Android Studio, it will have installed adb. Otherwise, you can get it as part of the Android SDK platform tools [here](https://developer.android.com/studio/releases/platform-tools.html). +First, follow these [setup instructions](https://developer.arm.com/documentation/102477/0900/Setup-tasks?lang=en), to make sure you have `adb` (Android Debug Bridge) installed. If you have installed [Android Studio](https://developer.android.com/studio), you will have installed adb already. Otherwise, you can get it as part of the Android SDK platform tools [here](https://developer.android.com/studio/releases/platform-tools.html). -Make sure adb is in your path. You can check this by running `adb` in a terminal. If it is not in your path, you can add it by adding the `platform-tools` directory to your path. The instructions for this (and location of the directory) will depend on your host machine's operating system. +Make sure `adb` is in your path. You can check this by running `adb` in a terminal. If it is not in your path, you can add it by adding the Android SDK `platform-tools` directory to your path. The instructions for this (and location of the directory) will depend on your host machine's operating system. Next, install [Arm Performance Studio](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio#Downloads), which includes Streamline. -Connect your Android phone to your computer through USB. Ensure that your device is set to [Developer mode](https://developer.android.com/studio/debug/dev-options). +Connect your Android phone to your host machine through USB. Ensure that your Android phone is set to [Developer mode](https://developer.android.com/studio/debug/dev-options). -On your device, go to `Settings > Developer Options` and enable USB Debugging. If your device asks you to authorize connection to your computer, confirm this. Test the connection by running `adb devices` in a terminal. You should see your device ID listed. +On your phone, go to `Settings > Developer Options` and enable USB Debugging. If your phone asks you to authorize connection to your host machine, confirm this. Test the connection by running `adb devices` in a terminal. You should see your device ID listed. Next, you need a debuggable build of the application you want to profile. - In Android Studio, ensure your *Build Variant* is set to `debug`. You can then build the application and install it on your device. @@ -34,17 +34,17 @@ Next, you need a debuggable build of the application you want to profile. - In Unreal Engine, open Project Settings > Project > Packaging > Project, and ensure that the For Distribution checkbox is not set. - In the general case, you can set `android:debuggable=true` in the application manifest file. -You can now run Streamline, and do a capture of your application. This can be used to do a general performance analysis of your application, but we intend to add additional useful information first. +You can now run Streamline, and do a capture of your application. This can be used to do a general performance analysis of your application, but you will add some useful information first. ## Custom Annotations In Streamline it is possible to add custom annotations to the timeline view. This can be useful to mark the start and end of specific parts of your application, or to mark when a specific event occurs. This can help you understand the performance of your application in relation to these events. At the bottom of *Figure 1* above there are custom annotations to show when inference, pre-processing, and post-processing are happening. -To add annotations, we need to add some files into our project from the Gator daemon that Streamline uses. These files are `streamline_annotate.c`, `streamline_annotate.h` and `streamline_annotate_logging.h` from [here](https://github.com/ARM-software/gator/tree/main/annotate). Then we will be able to show log strings, markers, counters and Custom Activity Maps. +To add annotations, you will need to add some files into your project from the Gator daemon that Streamline uses. These files are `streamline_annotate.c`, `streamline_annotate.h` and `streamline_annotate_logging.h` available [here](https://github.com/ARM-software/gator/tree/main/annotate). Then you will be able to show log strings, markers, counters and Custom Activity Maps. -These files are obviously C code, so if your Android Studio project is in Java or Kotlin, you will need to add a C library to your project. This is slightly trickier than just adding a Java or Kotlin file, but it is not difficult. You can find instructions on how to do this [here](https://developer.android.com/studio/projects/add-native-code). +These files are written in C, so if your Android Studio project is in Java or Kotlin, you will need to add a C library to your project. This is slightly trickier than just adding a Java or Kotlin file, but it is not difficult. You can find instructions on how to do this [here](https://developer.android.com/studio/projects/add-native-code). -For us, we create a file that we will call `annotate_jni_wrapper.c` in the `src/main/cpp/` folder under our project. This will be a wrapper around the Gator daemon's functions, and will be called from our Kotlin code. It starts as below and continues with very similar wrapper functions for the other Gator daemon functions you want. +Create a file that you will call `annotate_jni_wrapper.c` in the `src/main/cpp/` folder under your project. This will be a wrapper around the Gator daemon's functions, and will be called from your Kotlin code. It starts as below and continues with very similar wrapper functions for the other Gator daemon functions you want. ```c #include @@ -69,7 +69,7 @@ JNIEXPORT void JNICALL Java_AnnotateStreamline_AnnotateMarkerColorStr(JNIEnv* en } ``` -In Android Studio `cmake` is used to create your C library, so we need a CMakelists.txt file in the same directory as the C file. This will look like: +In Android Studio `cmake` is used to create your C library, so you will need a `CMakelists.txt` file in the same directory as the C file. This will look like: ```cmake # Sets the minimum CMake version required for this project. @@ -105,7 +105,7 @@ If you add the following to the `build.gradle` file of the Module you wish to pr } ``` -This will create a `libStreamlineAnnotationJNI.so` library that you can load in your Kotlin code, and then you can call the functions. Here we create a singleton `AnnotateStreamline.kt` that then enables Kotlin calls from the rest of our code: +This will create a `libStreamlineAnnotationJNI.so` library that you can load in your Kotlin code, and then you can call the functions. Here you will create a singleton `AnnotateStreamline.kt` that then enables Kotlin calls from the rest of your code: ```kotlin // Kotlin wrapper class for integration into Android project @@ -169,9 +169,9 @@ This colored marker with a string will add the string and time to Streamline's l In addition to adding strings to the log and colored markers to the timeline, a particularly useful set of annotations is the Custom Activity Maps. These are the named colored bands you can see at the bottom of the Streamline timeline view shown in *Figure 1*. They can be used to show when specific parts of your application are running, such as the pre-processing or inference, and layered for functions within functions etc. -To add these you'll need to import the functions that start `gator_cam_` from `streamline_annotate.h` through your wrapper files in the same way as the functions above. Then you can use CAMs, but first you'll need to set up the tracks the annotations will appear on and an id system for each annotation. The `baseId` code below is to ensure that in the case of multiple places in your code adding annotations, the ids are unique. +To add these you will need to import the functions that start `gator_cam_` from `streamline_annotate.h` through your wrapper files in the same way as the functions above. Then you can use CAMs, but first you will need to set up the tracks the annotations will appear on and an id system for each annotation. The `baseId` code below is to ensure that in the case of multiple places in your code adding annotations, the ids are unique. -Here is an example setup in a class's companion object. +Here is an example setup in a class's companion object: ```kotlin companion object { From e8c1c1bea1ef25dbcbc00dbdfb87e00c8ac6b389 Mon Sep 17 00:00:00 2001 From: Ben Clark Date: Thu, 7 Nov 2024 13:19:58 +0000 Subject: [PATCH 09/17] added example (app/network) information --- .../profiling-ml-on-arm/_index.md | 4 +- .../app-profiling-streamline.md | 60 ++++++++++++++++--- .../nn-profiling-executenetwork.md | 21 +++++-- 3 files changed, 69 insertions(+), 16 deletions(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md index 3bd9669e9..1271520b0 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_index.md @@ -1,7 +1,7 @@ --- title: Profile the performance of ML models on Arm -minutes_to_complete: 30 +minutes_to_complete: 60 who_is_this_for: This is an introductory topic for software developers who want to learn how to profile the performance of their ML models running on Arm devices. @@ -10,7 +10,7 @@ learning_objectives: - Profile ML application performance on Arm devices. prerequisites: - - An Arm-powered Android smartphone. + - An Arm-powered Android smartphone, and USB cable to connect with it. author_primary: Ben Clark diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md index 86fd7702f..294365aac 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md @@ -13,6 +13,8 @@ The profiler can look at memory, CPU activity and cycles, cache misses, and many ![Streamline image alt-text#center](Streamline.png "Figure 1. Streamline timeline view") +If you want a ready-made application to profile for this section you can use [this example](https://github.com/dawidborycki/Arm.PyTorch.MNIST.Inference). Clone it to your computer and open it in a recent Android Studio. It is generally safest to not update the Gradle version when asked, to ensure nothing else needs updating. + ## Streamline You will install [Streamline](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio#Downloads) (and Performance Studio) on your host machine, and will connect to your target Arm device to capture the data. In this example, the target device is an Arm-powered Android phone. The data is captured over a USB connection, and then analyzed on your host machine. @@ -34,17 +36,19 @@ Next, you need a debuggable build of the application you want to profile. - In Unreal Engine, open Project Settings > Project > Packaging > Project, and ensure that the For Distribution checkbox is not set. - In the general case, you can set `android:debuggable=true` in the application manifest file. -You can now run Streamline, and do a capture of your application. This can be used to do a general performance analysis of your application, but you will add some useful information first. +If you're using the example application, the Build Variant is `debug` by default, but you can verify this by going to `Build > Select Build Variant` in Android Studio. Build and install the application on your device. + +You can now run Streamline, and do a [capture](https://developer.arm.com/documentation/102477/0900/Capture-a-profile?lang=en) of your application. This can be used to do a general performance analysis of your application, but you will add some useful information first. ## Custom Annotations In Streamline it is possible to add custom annotations to the timeline view. This can be useful to mark the start and end of specific parts of your application, or to mark when a specific event occurs. This can help you understand the performance of your application in relation to these events. At the bottom of *Figure 1* above there are custom annotations to show when inference, pre-processing, and post-processing are happening. -To add annotations, you will need to add some files into your project from the Gator daemon that Streamline uses. These files are `streamline_annotate.c`, `streamline_annotate.h` and `streamline_annotate_logging.h` available [here](https://github.com/ARM-software/gator/tree/main/annotate). Then you will be able to show log strings, markers, counters and Custom Activity Maps. +To add annotations, you will need to add some files into your project from the **gator** daemon that Streamline uses. These files are `streamline_annotate.c`, `streamline_annotate.h` and `streamline_annotate_logging.h` available [here](https://github.com/ARM-software/gator/tree/main/annotate). Then you will be able to show log strings, markers, counters and Custom Activity Maps. If you are using the example project, create a `cpp` folder under the `app/src/main` folder, and add these files there. These files are written in C, so if your Android Studio project is in Java or Kotlin, you will need to add a C library to your project. This is slightly trickier than just adding a Java or Kotlin file, but it is not difficult. You can find instructions on how to do this [here](https://developer.android.com/studio/projects/add-native-code). -Create a file that you will call `annotate_jni_wrapper.c` in the `src/main/cpp/` folder under your project. This will be a wrapper around the Gator daemon's functions, and will be called from your Kotlin code. It starts as below and continues with very similar wrapper functions for the other Gator daemon functions you want. +Create a file in the `app/src/main/cpp/` folder under your project and name it `annotate_jni_wrapper.c`. This will be a wrapper around the gator daemon's functions, and will be called from your Kotlin code. It starts as below and continues with very similar wrapper functions for the other gator daemon functions you want. ```c #include @@ -69,7 +73,7 @@ JNIEXPORT void JNICALL Java_AnnotateStreamline_AnnotateMarkerColorStr(JNIEnv* en } ``` -In Android Studio `cmake` is used to create your C library, so you will need a `CMakelists.txt` file in the same directory as the C file. This will look like: +In Android Studio `cmake` is used to create your C library, so you will need a `CMakelists.txt` file in the same directory as the C files (`app/src/main/cpp/` in the example). This will look like: ```cmake # Sets the minimum CMake version required for this project. @@ -94,7 +98,7 @@ target_link_libraries( # Specifies the target library. ${log-lib} ) ``` -If you add the following to the `build.gradle` file of the Module you wish to profile, you will be able to call the functions from your Kotlin code: +If you add the following to the `build.gradle` file of the Module you wish to profile (`:app` in the example), you will be able to call the functions from your Kotlin code: ```gradle externalNativeBuild { @@ -105,7 +109,7 @@ If you add the following to the `build.gradle` file of the Module you wish to pr } ``` -This will create a `libStreamlineAnnotationJNI.so` library that you can load in your Kotlin code, and then you can call the functions. Here you will create a singleton `AnnotateStreamline.kt` that then enables Kotlin calls from the rest of your code: +This will create a `libStreamlineAnnotationJNI.so` library that you can load in your Kotlin code, and then you can call the functions. Here you will create a singleton `AnnotateStreamline.kt`. Place the file alongside `MainActivity.kt` in `app\src\main\java\com\arm\armpytorchmnistinference` for the example. Add the following code to `AnnotateStreamline.kt` to enable Kotlin calls to the gator daemon from the rest of your code: ```kotlin // Kotlin wrapper class for integration into Android project @@ -155,13 +159,17 @@ class AnnotateStreamline { } ``` -The `AnnotateStreamline` class can now be used in your Kotlin code to add annotations to the Streamline timeline view. Make sure that `AnnotateStreamline.setup()` is called first, and then you can add annotations like this: +Fill in all the function calls to match the functions you added into `annotate_jni_wrapper.c`. + +The `AnnotateStreamline` class can now be used in your Kotlin code to add annotations to the Streamline timeline view. The first thing is to make sure `AnnotateStreamline.setup()` is called before any other gator functions. For the example project, add it into the `onCreate()` function of `MainActivity.kt`. Then you can add annotations like this: ```kotlin AnnotateStreamline.annotateMarkerColorStr(AnnotateStreamline.ANNOTATE_BLUE, "Model Load") ``` -This colored marker with a string will add the string and time to Streamline's log view, and look like the below image in Streamline's timeline: +In the example app you could add this in the `onCreate()` function of `MainActivity.kt` after the `Module.load()` call to load the `model.pth`. + +This 'colored marker with a string' annotation will add the string and time to Streamline's log view, and look like the below image in Streamline's timeline (in the example app ArmNN isn't used, so there are no white ArmNN markers): ![Streamline image alt-text#center](streamline_marker.png "Figure 2. Streamline timeline markers") @@ -188,6 +196,8 @@ Here is an example setup in a class's companion object: } ``` +If you're using the example app, add this to the `MainActivity` class. + Then they can be used like this: ```kotlin @@ -201,4 +211,36 @@ Then they can be used like this: AnnotateStreamline.camJobEnd(camViewId, preprocess, AnnotateStreamline.getTime()) ``` -Now when you build and deploy a debug version of your application, you can run Streamline and see the annotations and CAMs in the timeline view. See the [Streamline documentation](https://developer.arm.com/documentation/101816/latest/) for how to make a capture for profiling. Once the capture is made and analyzed, you will be able to see when your application is running the inference, ML pre-processing, ML post-processing, or other parts of your application. From there you can see where the most time is spent, and how hard the CPU or GPU is working during different parts of the application. From this you can then decide if work is needed to improve performance and where that work needs doing. +In the example app the CAM annotations would be added to the `runInference()` function, which would end up looking like this: + +```kotlin + private fun runInference(bitmap: Bitmap) { + val preprocess = currentId++ + AnnotateStreamline.camJobStart(camViewId, preprocess, "Preprocess", trackRoot, AnnotateStreamline.getTime(), AnnotateStreamline.ANNOTATE_YELLOW) + // Convert bitmap to a float array and create a tensor with shape [1, 1, 28, 28] + val inputTensor = createTensorFromBitmap(bitmap) // could add a child CAM job inside function call, but probably too simple + AnnotateStreamline.camJobEnd(camViewId, preprocess, AnnotateStreamline.getTime()) + + // Run inference and measure time + val inferenceTimeMicros = measureTimeMicros { + // Forward pass through the model + val inference = currentId++ + AnnotateStreamline.camJobStart(camViewId, inference, "Inference", trackRoot, AnnotateStreamline.getTime(), AnnotateStreamline.ANNOTATE_RED) + val outputTensor = model.forward(IValue.from(inputTensor)).toTensor() + AnnotateStreamline.camJobEnd(camViewId, inference, AnnotateStreamline.getTime()) + // and then post-processing is simplistic in this case, so not worth a CAM job + val scores = outputTensor.dataAsFloatArray + + // Get the index of the class with the highest score + val maxIndex = scores.indices.maxByOrNull { scores[it] } ?: -1 + predictedLabel.text = "Predicted Label: $maxIndex" + } + + // Update inference time TextView in microseconds + inferenceTime.text = "Inference Time: $inferenceTimeMicros µs" + } +``` + +The example app is very fast and simple, so the CAMs will not show much, but in a more complex application you could add more CAMs, including child-level ones, to give more detailed annotations to show where time is spent in your application. Indeed for the example app with its very fast inference, you will be best in Streamline to put the timeline view on the 10µs scale to see the CAM annotations better. + +Once you've added in useful CAM annotations, you can build and deploy a debug version of your application, you can run Streamline and see the annotations and CAMs in the timeline view. See the [Streamline documentation](https://developer.arm.com/documentation/101816/latest/) for how to make a capture for profiling. Once the capture is made and analyzed, you will be able to see when your application is running the inference, ML pre-processing, ML post-processing, or other parts of your application. From there you can see where the most time is spent, and how hard the CPU or GPU is working during different parts of the application. From this you can then decide if work is needed to improve performance and where that work needs doing. diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md index 125474190..b046364a8 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md @@ -11,6 +11,8 @@ One way of running tflite models is with ArmNN. This is available as a delegate If you are not using tflite, you'll need to look at other tools from your framework to profile your model. If you are using tflite without ArmNN, then the output from `ExecuteNetwork` will be more of an indication than a definitive answer. But it can still be useful to see if there are any obvious problems. +If you want to have a tflite to practice this Learning Path with, you can download one from the [Arm Model Zoo](https://github.com/ARM-software/ML-zoo). As an example we'll use a [mobilenet tflite](https://github.com/ARM-software/ML-zoo/blob/master/models/image_classification/mobilenet_v2_1.0_224/tflite_int8/mobilenet_v2_1.0_224_INT8.tflite). + To get `ExecuteNetwork` you can download it from the [ArmNN GitHub](https://github.com/ARM-software/armnn/releases). Download the version appropriate for the Android phone you wish to test on - the Android version and the architecture of the phone. If you are unsure of the architecture, you can use a lower one, but you may miss out on some optimizations. Inside the tar.gz that you download, `ExecuteNetwork` is included. Note among the other release downloads on the ArmNN Github is the separate file for the `aar` delegate which is the easy way to include the ArmNN delegate into your app. To run `ExecuteNetwork` you'll need to use `adb` to push the model and the executable to your phone, and then run it from the adb shell. `adb` is included with Android Studio, but you may need to add it to your path. Android Studio normally installs it to a location like \\AppData\Local\Android\Sdk\platform-tools. `adb` can also be downloaded separately from the [Android Developer site](https://developer.android.com/studio/releases/platform-tools). @@ -18,7 +20,8 @@ To run `ExecuteNetwork` you'll need to use `adb` to push the model and the execu Unzip the tar.gz folder you downloaded to somewhere convenient. From a command prompt, you can then adapt and run the following commands to push the files to your phone. The `/data/local/tmp` folder of your Android device is a place with relaxed permissions that you can use to run this profiling. ```bash -adb push model.tflite /data/local/tmp/ # the tflite NN model file that you wish to profile +adb push mobilenet_v2_1.0_224_INT8.tflite /data/local/tmp/ # if you are using the example tflite model +# adb push yourmodel.tflite /data/local/tmp/ # where yourmodel is the tflite NN model file that you wish to profile adb push ExecuteNetwork /data/local/tmp/ adb push libarm_compute.so /data/local/tmp/ adb push libarmnn.so /data/local/tmp/ @@ -36,13 +39,17 @@ chmod 777 ExecuteNetwork # to make the file executable chmod 777 *.so # to make the library files executable ``` -Then you can run the model with the following command: +Then you can run ExecuteNetwork to profile the model. If you are using the example tflite, you can use the following command: ```bash -LD_LIBRARY_PATH=. ./ExecuteNetwork -m model.tflite -c CpuAcc -T delegate --iterations 2 --do-not-print-output --enable-fast-math --fp16-turbo-mode -e --output-network-details > modelout.txt +LD_LIBRARY_PATH=. ./ExecuteNetwork -m mobilenet_v2_1.0_224_INT8.tflite -c CpuAcc -T delegate --iterations 2 --do-not-print-output --enable-fast-math --fp16-turbo-mode -e --output-network-details > modelout.txt ``` -This will run the model twice, outputting the layer timings to `modelout.txt`. Specifically, the `-e` and `--output-network-details` flags will output a lot of timeline information about the model, including the layer timings. The `--do-not-print-output` flag will stop the output of the model, which can be very large, and without sensible input, meaningless. The `--enable-fast-math` and `--fp16-turbo-mode` flags enable some maths optimizations. The `--iterations 2` flag will run the model twice: the first run includes a lot of startup costs and one-off optimizations, so the second run is more indicative of the real performance. +If you are using your own tflite, replace `mobilenet_v2_1.0_224_INT8.tflite` with the name of your tflite file. + +This will run the model twice, outputting the layer timings to `modelout.txt`. The `--iterations 2` flag is the command that means it runs twice: the first run includes a lot of startup costs and one-off optimizations, so the second run is more indicative of the real performance. + +For the other flags, of note are the `-e` and `--output-network-details` flags which will output a lot of timeline information about the model, including the layer timings. The `--do-not-print-output` flag will stop the output of the model, which can be very large, and without sensible input, meaningless. The `--enable-fast-math` and `--fp16-turbo-mode` flags enable some maths optimizations. `CpuAcc` is the acclerated CPU backend, it can be replaced with `GpuAcc` for the accelerated GPU backend. After running the model, you can pull the output file back to your computer with the following commands: @@ -71,4 +78,8 @@ Info: Execution time: 468.42 ms. Info: Inference time: 468.58 ms ``` -After the summary comes the graph of the model, and then the layers and their timings from the second run. At the start of the layers there are a few optimizations and their timings recorded before the network itself, so you can skip past the graph and the optimization timings to get to the part that wants analyzing. The layers' "Wall clock time" in microseconds shows how long they took to run. These layers and their timings can then be analyzed to see which layers, and which operators, took the most time. +After the summary comes the graph of the model, and then the layers and their timings from the second run. At the start of the layers there are a few optimizations and their timings recorded before the network itself, so you can skip past the graph and the optimization timings to get to the part that wants analyzing. + +In the mobilenet example output, the graph is from lines 18 to 1629. After this come the optimization timings, which are part of the runtime, but not the network - these go until line 1989. Next there are a few wall clock recordings for the loading of the network, before the first layer "Convolution2dLayer_CreateWorkload_#18" at line 2036. Here is where the layer info that wants analyzing starts. + +The layers' "Wall clock time" in microseconds shows how long they took to run. These layers and their timings can then be analyzed to see which layers, and which operators, took the most time. \ No newline at end of file From c57c3d0f0b390bc857ab3157ee86232600b524e9 Mon Sep 17 00:00:00 2001 From: pareenaverma Date: Thu, 14 Nov 2024 11:14:56 -0500 Subject: [PATCH 10/17] Update why-profile.md --- .../smartphones-and-mobile/profiling-ml-on-arm/why-profile.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md index 75ac1724f..7d688a4ad 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/why-profile.md @@ -11,7 +11,7 @@ Working out what is taking the time and memory in your application is the first With Machine Learning (ML) applications, the inference of the Neural Network (NN) itself is often the heaviest part of the application in terms of computation and memory usage. This is not guaranteed however, so it is important to profile the application as a whole to see if pre- or post-processing or other code is an issue. -In this Learning Path, you will be profiling at an Android example using TFLite, but most of the tools also work with Linux and cover a wide range of Arm devices. The principles for profiling your application are the same for use with other inference engines and platforms, but the tools are different. +In this Learning Path, you will profile an Android example using TFLite, but most of the steps shown will also work with Linux and cover a wide range of Arm devices. The principles for profiling your application are the same for use with other inference engines and platforms, but the tools are different. ## Tools @@ -19,5 +19,5 @@ You will need to use different tools to profile the ML inference or the applicat For profiling the ML inference, you will use [ArmNN](https://github.com/ARM-software/armnn/releases)'s ExecuteNetwork. -For profiling the application as a whole, you will use [Arm Performance Studio](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio)'s Streamline, and at the Android Studio Profiler. +For profiling the application as a whole, you will use [Arm Performance Studio](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio)'s Streamline, and the Android Studio Profiler. From a03f8357d8fd1d833beb79dfb8dccc3174972d8a Mon Sep 17 00:00:00 2001 From: pareenaverma Date: Thu, 14 Nov 2024 12:13:30 -0500 Subject: [PATCH 11/17] Update app-profiling-streamline.md --- .../app-profiling-streamline.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md index 294365aac..a6ebb950b 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md @@ -13,16 +13,19 @@ The profiler can look at memory, CPU activity and cycles, cache misses, and many ![Streamline image alt-text#center](Streamline.png "Figure 1. Streamline timeline view") -If you want a ready-made application to profile for this section you can use [this example](https://github.com/dawidborycki/Arm.PyTorch.MNIST.Inference). Clone it to your computer and open it in a recent Android Studio. It is generally safest to not update the Gradle version when asked, to ensure nothing else needs updating. +## Example Android Application + +In this Learning Path, you will use profile [an example Android application](https://github.com/dawidborycki/Arm.PyTorch.MNIST.Inference) using Streamline. +Start by cloning the repository containing this example on your machine and open it in a recent Android Studio. It is generally safest to not update the Gradle version when prompted. ## Streamline -You will install [Streamline](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio#Downloads) (and Performance Studio) on your host machine, and will connect to your target Arm device to capture the data. In this example, the target device is an Arm-powered Android phone. The data is captured over a USB connection, and then analyzed on your host machine. +You will install Streamline and Performance Studio on your host machine and connect to your target Arm device to capture the data. In this example, the target device is an Arm-powered Android phone. The data is captured over a USB connection, and then analyzed on your host machine. -There are many [tutorials and training videos](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio) on Streamline, which you can refer to for more depth. This example will be Android based, but you can use [these instructions for Linux](https://developer.arm.com/documentation/101816/0903/Getting-started-with-Streamline/Profile-your-Linux-application) setup and capture. +For more details on Streamline usage you can refer to these [tutorials and training videos](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio). While the example you are running is based on Android, you can use [the setup and capture instructions for Linux](https://developer.arm.com/documentation/101816/0903/Getting-started-with-Streamline/Profile-your-Linux-application). First, follow these [setup instructions](https://developer.arm.com/documentation/102477/0900/Setup-tasks?lang=en), to make sure you have `adb` (Android Debug Bridge) installed. If you have installed [Android Studio](https://developer.android.com/studio), you will have installed adb already. Otherwise, you can get it as part of the Android SDK platform tools [here](https://developer.android.com/studio/releases/platform-tools.html). -Make sure `adb` is in your path. You can check this by running `adb` in a terminal. If it is not in your path, you can add it by adding the Android SDK `platform-tools` directory to your path. The instructions for this (and location of the directory) will depend on your host machine's operating system. +Make sure `adb` is in your path. You can check this by running `adb` in a terminal. If it is not in your path, you can add it by installing the [Android SDK `platform-tools`](https://developer.android.com/tools/releases/platform-tools#downloads) directory to your path. Next, install [Arm Performance Studio](https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Studio#Downloads), which includes Streamline. @@ -36,7 +39,7 @@ Next, you need a debuggable build of the application you want to profile. - In Unreal Engine, open Project Settings > Project > Packaging > Project, and ensure that the For Distribution checkbox is not set. - In the general case, you can set `android:debuggable=true` in the application manifest file. -If you're using the example application, the Build Variant is `debug` by default, but you can verify this by going to `Build > Select Build Variant` in Android Studio. Build and install the application on your device. +For the example application that you cloned earlier, the Build Variant is `debug` by default, but you can verify this by going to `Build > Select Build Variant` in Android Studio. Build and install the application on your device. You can now run Streamline, and do a [capture](https://developer.arm.com/documentation/102477/0900/Capture-a-profile?lang=en) of your application. This can be used to do a general performance analysis of your application, but you will add some useful information first. @@ -237,10 +240,10 @@ In the example app the CAM annotations would be added to the `runInference()` fu } // Update inference time TextView in microseconds - inferenceTime.text = "Inference Time: $inferenceTimeMicros µs" + inferenceTime.text = "Inference Time: $inferenceTimeMicros µs" } ``` -The example app is very fast and simple, so the CAMs will not show much, but in a more complex application you could add more CAMs, including child-level ones, to give more detailed annotations to show where time is spent in your application. Indeed for the example app with its very fast inference, you will be best in Streamline to put the timeline view on the 10µs scale to see the CAM annotations better. +The example app is very fast and simple, so the CAMs will not show much, but in a more complex application you could add more CAMs, including child-level ones, to give more detailed annotations to show where time is spent in your application. Indeed for the example app with its very fast inference, you will be best in Streamline to put the timeline view on the 10µs scale to see the CAM annotations better. Once you've added in useful CAM annotations, you can build and deploy a debug version of your application, you can run Streamline and see the annotations and CAMs in the timeline view. See the [Streamline documentation](https://developer.arm.com/documentation/101816/latest/) for how to make a capture for profiling. Once the capture is made and analyzed, you will be able to see when your application is running the inference, ML pre-processing, ML post-processing, or other parts of your application. From there you can see where the most time is spent, and how hard the CPU or GPU is working during different parts of the application. From this you can then decide if work is needed to improve performance and where that work needs doing. From 4289d2e6f895f0aa1a3e839b75281ab0d59058c5 Mon Sep 17 00:00:00 2001 From: pareenaverma Date: Thu, 14 Nov 2024 15:12:50 -0500 Subject: [PATCH 12/17] Update app-profiling-streamline.md --- .../app-profiling-streamline.md | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md index a6ebb950b..e55e4e172 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-streamline.md @@ -39,19 +39,19 @@ Next, you need a debuggable build of the application you want to profile. - In Unreal Engine, open Project Settings > Project > Packaging > Project, and ensure that the For Distribution checkbox is not set. - In the general case, you can set `android:debuggable=true` in the application manifest file. -For the example application that you cloned earlier, the Build Variant is `debug` by default, but you can verify this by going to `Build > Select Build Variant` in Android Studio. Build and install the application on your device. +For the example application that you cloned earlier, the Build Variant is `debug` by default, but you can verify this by going to `Build > Select Build Variant` in Android Studio. Build and install this application on your device. -You can now run Streamline, and do a [capture](https://developer.arm.com/documentation/102477/0900/Capture-a-profile?lang=en) of your application. This can be used to do a general performance analysis of your application, but you will add some useful information first. +You can now run Streamline and [capture a profile](https://developer.arm.com/documentation/102477/0900/Capture-a-profile?lang=en) of your application. But before you do, lets add some useful annotations to your code that can help with more specific performance analysis of your application. ## Custom Annotations -In Streamline it is possible to add custom annotations to the timeline view. This can be useful to mark the start and end of specific parts of your application, or to mark when a specific event occurs. This can help you understand the performance of your application in relation to these events. At the bottom of *Figure 1* above there are custom annotations to show when inference, pre-processing, and post-processing are happening. +In Streamline, it is possible to add custom annotations to the timeline view. This can be useful to mark the start and end of specific parts of your application, or to mark when a specific event occurs. This can help you understand the performance of your application in relation to these events. At the bottom of *Figure 1* above there are custom annotations to show when inference, pre-processing, and post-processing are happening. -To add annotations, you will need to add some files into your project from the **gator** daemon that Streamline uses. These files are `streamline_annotate.c`, `streamline_annotate.h` and `streamline_annotate_logging.h` available [here](https://github.com/ARM-software/gator/tree/main/annotate). Then you will be able to show log strings, markers, counters and Custom Activity Maps. If you are using the example project, create a `cpp` folder under the `app/src/main` folder, and add these files there. +To add annotations, you will need to add some files into your project from the **gator** daemon that Streamline uses. These files are named `streamline_annotate.c`, `streamline_annotate.h` and `streamline_annotate_logging.h` and made available [here](https://github.com/ARM-software/gator/tree/main/annotate). Using these annotations, you will be able to show log strings, markers, counters and Custom Activity Maps. WIthin your example project, create a `cpp` folder under the `app/src/main` folder, and add these three files there. These files are written in C, so if your Android Studio project is in Java or Kotlin, you will need to add a C library to your project. This is slightly trickier than just adding a Java or Kotlin file, but it is not difficult. You can find instructions on how to do this [here](https://developer.android.com/studio/projects/add-native-code). -Create a file in the `app/src/main/cpp/` folder under your project and name it `annotate_jni_wrapper.c`. This will be a wrapper around the gator daemon's functions, and will be called from your Kotlin code. It starts as below and continues with very similar wrapper functions for the other gator daemon functions you want. +Create a file in the `app/src/main/cpp/` folder under your project and name it `annotate_jni_wrapper.c`. This will be a wrapper around the gator daemon's functions, and will be called from your Kotlin code. Copy the code below into this file. You can also create very similar wrapper functions for other gator daemon functions. ```c #include @@ -66,7 +66,7 @@ JNIEXPORT jlong JNICALL Java_AnnotateStreamline_GetTime(JNIEnv* env, jobject obj } ``` -Some functions have `unsigned int`, but that needs to be a `jint` in the wrapper, with some casting required in your Kotlin code to enforce type correctness at that end. Some functions have strings as arguments, and you will need to do a small conversion: +Some functions have `unsigned int`, but that needs to be a `jint` in the wrapper, with some casting required in your Kotlin code to enforce type correctness at that end. Some functions have strings as arguments, and you will need to do a small conversion as shown below: ```c JNIEXPORT void JNICALL Java_AnnotateStreamline_AnnotateMarkerColorStr(JNIEnv* env, jobject obj, jint color, jstring str) { @@ -76,7 +76,7 @@ JNIEXPORT void JNICALL Java_AnnotateStreamline_AnnotateMarkerColorStr(JNIEnv* en } ``` -In Android Studio `cmake` is used to create your C library, so you will need a `CMakelists.txt` file in the same directory as the C files (`app/src/main/cpp/` in the example). This will look like: +In Android Studio `cmake` is used to create your C library, so you will need a `CMakelists.txt` file in the same directory as the C files (`app/src/main/cpp/` in the example). Copy the contents shown below into `CMakelists.txt`: ```cmake # Sets the minimum CMake version required for this project. @@ -101,7 +101,7 @@ target_link_libraries( # Specifies the target library. ${log-lib} ) ``` -If you add the following to the `build.gradle` file of the Module you wish to profile (`:app` in the example), you will be able to call the functions from your Kotlin code: +Now add the code below to the `build.gradle` file of the Module you wish to profile (`:app` in the example). You will be able to call the functions from your Kotlin code: ```gradle externalNativeBuild { @@ -172,7 +172,7 @@ The `AnnotateStreamline` class can now be used in your Kotlin code to add annota In the example app you could add this in the `onCreate()` function of `MainActivity.kt` after the `Module.load()` call to load the `model.pth`. -This 'colored marker with a string' annotation will add the string and time to Streamline's log view, and look like the below image in Streamline's timeline (in the example app ArmNN isn't used, so there are no white ArmNN markers): +This 'colored marker with a string' annotation will add the string and time to Streamline's log view, and look like the image shown below in Streamline's timeline (in the example app ArmNN isn't used, so there are no white ArmNN markers): ![Streamline image alt-text#center](streamline_marker.png "Figure 2. Streamline timeline markers") @@ -180,7 +180,7 @@ This 'colored marker with a string' annotation will add the string and time to S In addition to adding strings to the log and colored markers to the timeline, a particularly useful set of annotations is the Custom Activity Maps. These are the named colored bands you can see at the bottom of the Streamline timeline view shown in *Figure 1*. They can be used to show when specific parts of your application are running, such as the pre-processing or inference, and layered for functions within functions etc. -To add these you will need to import the functions that start `gator_cam_` from `streamline_annotate.h` through your wrapper files in the same way as the functions above. Then you can use CAMs, but first you will need to set up the tracks the annotations will appear on and an id system for each annotation. The `baseId` code below is to ensure that in the case of multiple places in your code adding annotations, the ids are unique. +To add these you will need to import the functions that start `gator_cam_` from `streamline_annotate.h` through your wrapper files in the same way as the functions above. Then you can use CAMs, but first you will need to set up the tracks the annotations will appear on and an id system for each annotation. The `baseId` code below is to ensure that if you add annotations in multiple places in your code, the ids are unique. Here is an example setup in a class's companion object: @@ -199,9 +199,9 @@ Here is an example setup in a class's companion object: } ``` -If you're using the example app, add this to the `MainActivity` class. +For the example app, add this to the `MainActivity` class. -Then they can be used like this: +Then it can be used like this: ```kotlin val preprocess = currentId++ @@ -214,7 +214,7 @@ Then they can be used like this: AnnotateStreamline.camJobEnd(camViewId, preprocess, AnnotateStreamline.getTime()) ``` -In the example app the CAM annotations would be added to the `runInference()` function, which would end up looking like this: +In the example app, the CAM annotations are added to the `runInference()` function, which should look like this: ```kotlin private fun runInference(bitmap: Bitmap) { @@ -244,6 +244,6 @@ In the example app the CAM annotations would be added to the `runInference()` fu } ``` -The example app is very fast and simple, so the CAMs will not show much, but in a more complex application you could add more CAMs, including child-level ones, to give more detailed annotations to show where time is spent in your application. Indeed for the example app with its very fast inference, you will be best in Streamline to put the timeline view on the 10µs scale to see the CAM annotations better. +The example application is very fast and simple, so the CAMs will not show much information. In a more complex application you could add more CAMs, including child-level ones, to give more detailed annotations to show where time is spent in your application. For this example app with its very fast inference, it's best to change the Streamline timeline view scale to 10µs in order to see the CAM annotations better. -Once you've added in useful CAM annotations, you can build and deploy a debug version of your application, you can run Streamline and see the annotations and CAMs in the timeline view. See the [Streamline documentation](https://developer.arm.com/documentation/101816/latest/) for how to make a capture for profiling. Once the capture is made and analyzed, you will be able to see when your application is running the inference, ML pre-processing, ML post-processing, or other parts of your application. From there you can see where the most time is spent, and how hard the CPU or GPU is working during different parts of the application. From this you can then decide if work is needed to improve performance and where that work needs doing. +Once you've added in useful CAM annotations, you can build and deploy a debug version of your application. You can run Streamline and see the annotations and CAMs in the timeline view. See the [Streamline documentation](https://developer.arm.com/documentation/101816/latest/) for how to make a capture for profiling. After the capture is made and analyzed, you will be able to see when your application is running the inference, ML pre-processing, ML post-processing, or other parts of your application. From there you can see where the most time is spent, and how hard the CPU or GPU is working during different parts of the application. From this you can then decide if work is needed to improve performance and where that work needs doing. From 0c8b302bbe418985a1add2a9a05f8dcf475b2000 Mon Sep 17 00:00:00 2001 From: pareenaverma Date: Thu, 14 Nov 2024 15:17:17 -0500 Subject: [PATCH 13/17] Update nn-profiling-general.md --- .../profiling-ml-on-arm/nn-profiling-general.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md index 7ca228759..91a35381f 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-general.md @@ -9,8 +9,8 @@ layout: learningpathall ## Profiling your model App profilers will give you a good overall view of your performance, but often you might want to look inside the model and work out bottlenecks within the network. The network is often the bulk of the time, in which case it will warrant closer analysis. -General profilers are unable to do this, as there needs to be annotations inside the ML framework code to get the information. It is a large task to write the profiling annotations throughout the framework, so it is easier if we use tools from a framework or inference engine that can already do the job. +With general profilers this is hard to do, as there needs to be annotations inside the ML framework code to get the information. It is a large task to write the profiling annotations throughout the framework, so it is easier to use tools from a framework or inference engine that already has the required instrumentation. -Depending on your model the tools available will differ. For example, if you are using LiteRT (formerly TensorFlow Lite), Arm provides the ArmNN delegate that you can run the model with on Linux or Android, CPU or GPU. ArmNN in turn provides a tool called `ExecuteNetwork` that can run the model and give you layer timings and other useful information. +Depending on your model, your choice of tools will differ. For example, if you are using LiteRT (formerly TensorFlow Lite), Arm provides the ArmNN delegate that you can run with the model running on Linux or Android, CPU or GPU. ArmNN in turn provides a tool called `ExecuteNetwork` that can run the model and give you layer timings among other useful information. -If you are using PyTorch, you will probably want ExecuTorch on an Android phone, and this also has a profiler available alongside it. +If you are using PyTorch, you will probably use ExecuTorch the ons-device inference runtime for your Android phone. ExecuTorch has a profiler available alongside it. From 09d1b819a1cffe3184f16cb379080804e75fcdf2 Mon Sep 17 00:00:00 2001 From: pareenaverma Date: Thu, 14 Nov 2024 15:45:38 -0500 Subject: [PATCH 14/17] Update nn-profiling-executenetwork.md --- .../nn-profiling-executenetwork.md | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md index b046364a8..f4ca26994 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/nn-profiling-executenetwork.md @@ -1,5 +1,5 @@ --- -title: ML profiling with ExecuteNetwork +title: ML profiling of a tflite model with ExecuteNetwork weight: 6 ### FIXED, DO NOT MODIFY @@ -7,39 +7,38 @@ layout: learningpathall --- ## ArmNN's Network Profiler -One way of running tflite models is with ArmNN. This is available as a delegate to the standard tflite interpreter. But to profile the model, ArmNN comes with a command-line utility called `ExecuteNetwork`. This program just runs the model without the rest of an app. It is able to output layer timings and other useful information to let you know where there might be bottlenecks within your model. +One way of running tflite models is with ArmNN. This is available as a delegate to the standard tflite interpreter. But to profile the model, ArmNN comes with a command-line utility called `ExecuteNetwork`. This program just runs the model without the rest of the app. It is able to output layer timings and other useful information to let you know where there might be bottlenecks within your model. -If you are not using tflite, you'll need to look at other tools from your framework to profile your model. If you are using tflite without ArmNN, then the output from `ExecuteNetwork` will be more of an indication than a definitive answer. But it can still be useful to see if there are any obvious problems. +If you are using tflite without ArmNN, then the output from `ExecuteNetwork` will be more of an indication than a definitive answer. But it can still be useful to spot any obvious problems. -If you want to have a tflite to practice this Learning Path with, you can download one from the [Arm Model Zoo](https://github.com/ARM-software/ML-zoo). As an example we'll use a [mobilenet tflite](https://github.com/ARM-software/ML-zoo/blob/master/models/image_classification/mobilenet_v2_1.0_224/tflite_int8/mobilenet_v2_1.0_224_INT8.tflite). +To try this out, you can download a tflite model from the [Arm Model Zoo](https://github.com/ARM-software/ML-zoo). In this Learning Path, you will download [mobilenet tflite](https://github.com/ARM-software/ML-zoo/blob/master/models/image_classification/mobilenet_v2_1.0_224/tflite_int8/mobilenet_v2_1.0_224_INT8.tflite). -To get `ExecuteNetwork` you can download it from the [ArmNN GitHub](https://github.com/ARM-software/armnn/releases). Download the version appropriate for the Android phone you wish to test on - the Android version and the architecture of the phone. If you are unsure of the architecture, you can use a lower one, but you may miss out on some optimizations. Inside the tar.gz that you download, `ExecuteNetwork` is included. Note among the other release downloads on the ArmNN Github is the separate file for the `aar` delegate which is the easy way to include the ArmNN delegate into your app. +To get `ExecuteNetwork` you can download it from the [ArmNN GitHub](https://github.com/ARM-software/armnn/releases). Download the version appropriate for the Android phone you wish to test on - the Android version and the architecture of the phone. If you are unsure of the architecture, you can use a lower one, but you may miss out on some optimizations. Inside the `tar.gz` archive that you download, `ExecuteNetwork` is included. Note among the other release downloads on the ArmNN Github is the separate file for the `aar` delegate which is the easy way to include the ArmNN delegate into your app. -To run `ExecuteNetwork` you'll need to use `adb` to push the model and the executable to your phone, and then run it from the adb shell. `adb` is included with Android Studio, but you may need to add it to your path. Android Studio normally installs it to a location like \\AppData\Local\Android\Sdk\platform-tools. `adb` can also be downloaded separately from the [Android Developer site](https://developer.android.com/studio/releases/platform-tools). +To run `ExecuteNetwork` you'll need to use `adb` to push the model and the executable to your phone, and then run it from the adb shell. `adb` is included with Android Studio, but you may need to add it to your path. Android Studio normally installs it to a location like `\\AppData\Local\Android\Sdk\platform-tools`. `adb` can also be downloaded separately from the [Android Developer site](https://developer.android.com/studio/releases/platform-tools). -Unzip the tar.gz folder you downloaded to somewhere convenient. From a command prompt, you can then adapt and run the following commands to push the files to your phone. The `/data/local/tmp` folder of your Android device is a place with relaxed permissions that you can use to run this profiling. +Unzip the `tar.gz` folder you downloaded. From a command prompt, you can then adapt and run the following commands to push the files to your phone. The `/data/local/tmp` folder of your Android device is a place with relaxed permissions that you can use to run this profiling. ```bash -adb push mobilenet_v2_1.0_224_INT8.tflite /data/local/tmp/ # if you are using the example tflite model -# adb push yourmodel.tflite /data/local/tmp/ # where yourmodel is the tflite NN model file that you wish to profile +adb push mobilenet_v2_1.0_224_INT8.tflite /data/local/tmp/ adb push ExecuteNetwork /data/local/tmp/ adb push libarm_compute.so /data/local/tmp/ adb push libarmnn.so /data/local/tmp/ adb push libarmnn_support_library.so /data/local/tmp/ # more ArmNN .so library files ``` -Push all the `.so` library files that are in the base folder of the tar.gz you downloaded, alongside `ExecuteNetwork`, and all the `.so` files in the `delegate` sub-folder. If you are using a recent version of Android Studio this copying can be done much more easily with drag and drop in the *Device Explorer > Files*. +Push all the `.so` library files that are in the base folder of the `tar.gz` archive you downloaded, alongside `ExecuteNetwork`, and all the `.so` files in the `delegate` sub-folder. If you are using a recent version of Android Studio this copying can be done much more easily with drag and drop in the *Device Explorer > Files*. Then you need to set the permissions on the files: ```bash -adb shell # to get into the adb shell on the phone +adb shell cd /data/local/tmp -chmod 777 ExecuteNetwork # to make the file executable -chmod 777 *.so # to make the library files executable +chmod 777 ExecuteNetwork +chmod 777 *.so ``` -Then you can run ExecuteNetwork to profile the model. If you are using the example tflite, you can use the following command: +Now you can run ExecuteNetwork to profile the model. With the example tflite, you can use the following command: ```bash LD_LIBRARY_PATH=. ./ExecuteNetwork -m mobilenet_v2_1.0_224_INT8.tflite -c CpuAcc -T delegate --iterations 2 --do-not-print-output --enable-fast-math --fp16-turbo-mode -e --output-network-details > modelout.txt @@ -49,12 +48,12 @@ If you are using your own tflite, replace `mobilenet_v2_1.0_224_INT8.tflite` wit This will run the model twice, outputting the layer timings to `modelout.txt`. The `--iterations 2` flag is the command that means it runs twice: the first run includes a lot of startup costs and one-off optimizations, so the second run is more indicative of the real performance. -For the other flags, of note are the `-e` and `--output-network-details` flags which will output a lot of timeline information about the model, including the layer timings. The `--do-not-print-output` flag will stop the output of the model, which can be very large, and without sensible input, meaningless. The `--enable-fast-math` and `--fp16-turbo-mode` flags enable some maths optimizations. `CpuAcc` is the acclerated CPU backend, it can be replaced with `GpuAcc` for the accelerated GPU backend. +The other flags to note are the `-e` and `--output-network-details` flags which will output a lot of timeline information about the model, including the layer timings. The `--do-not-print-output` flag will stop the output of the model, which can be very large, and without sensible input it is meaningless. The `--enable-fast-math` and `--fp16-turbo-mode` flags enable some math optimizations. `CpuAcc` is the acclerated CPU backend, it can be replaced with `GpuAcc` for the accelerated GPU backend. -After running the model, you can pull the output file back to your computer with the following commands: +After running the model, you can pull the output file back to your host machine with the following commands: ```bash -exit # to leave the adb shell +exit adb pull /data/local/tmp/modelout.txt ``` Once again, this can be done with drag and drop in Android Studio's *Device Explorer > Files*. @@ -62,6 +61,7 @@ Once again, this can be done with drag and drop in Android Studio's *Device Expl Depending on the size of your model, the output will probably be quite large. You can use a text editor to view the file. The output is in JSON format, so you can use a JSON viewer to make it more readable. Usually some scripting can be used to extract the information you need more easily out of the very raw data in the file. At the top is the summary, with the setup time and inference time of your 2 runs, which will look something like this: + ```text Info: ArmNN v33.2.0 Info: Initialization time: 7.20 ms. @@ -78,8 +78,8 @@ Info: Execution time: 468.42 ms. Info: Inference time: 468.58 ms ``` -After the summary comes the graph of the model, and then the layers and their timings from the second run. At the start of the layers there are a few optimizations and their timings recorded before the network itself, so you can skip past the graph and the optimization timings to get to the part that wants analyzing. +After the summary comes the graph of the model, then the layers and their timings from the second run. At the start of the layers there are a few optimizations and their timings recorded before the network itself. You can skip past the graph and the optimization timings to get to the part that needs analyzing. -In the mobilenet example output, the graph is from lines 18 to 1629. After this come the optimization timings, which are part of the runtime, but not the network - these go until line 1989. Next there are a few wall clock recordings for the loading of the network, before the first layer "Convolution2dLayer_CreateWorkload_#18" at line 2036. Here is where the layer info that wants analyzing starts. +In the mobilenet example output, the graph is from lines 18 to 1629. After this is the optimization timings, which are part of the runtime, but not the network - these go until line 1989. Next there are a few wall clock recordings for the loading of the network, before the first layer "Convolution2dLayer_CreateWorkload_#18" at line 2036. Here is where the layer info that needs analyzing starts. -The layers' "Wall clock time" in microseconds shows how long they took to run. These layers and their timings can then be analyzed to see which layers, and which operators, took the most time. \ No newline at end of file +The layers' "Wall clock time" in microseconds shows how long they took to run. These layers and their timings can then be analyzed to see which layers, and which operators, took the most time. From 73461abce4dcab18f35759b6ca283726b6880697 Mon Sep 17 00:00:00 2001 From: pareenaverma Date: Thu, 14 Nov 2024 15:57:55 -0500 Subject: [PATCH 15/17] Update app-profiling-android-studio.md --- .../app-profiling-android-studio.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md index 7d49a7303..9f8508f3a 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/app-profiling-android-studio.md @@ -13,7 +13,7 @@ To find the Profiler, open your project in Android Studio and click on the *View Most likely with an Android ML app you'll need to look at memory both from the Java/Kotlin side and the native side. The Java/Kotlin side is where the app runs, and may be where buffers are allocated for input and output if, for example, you're using LiteRT (formerly known as TensorFlow Lite). The native side is where the ML framework will run. Looking at the memory consumption for Java/Kotlin and native is 2 separate tasks in the Profiler: *Track Memory Consumption (Java/Kotlin Allocations)* and *Track Memory Consumption (Native Allocations)*. -Before we start either task we want to build our profileable app. The instructions for this and for general profiling setup can be found [here](https://developer.android.com/studio/profile). We will want to start the correct profiling version of the app depending on the task. +Before you start either task, you have to build your app for profiling. The instructions for this and for general profiling setup can be found [here](https://developer.android.com/studio/profile). You will want to start the correct profiling version of the app depending on the task. ![Android Studio profiling run types alt-text#center](android-profiling-version.png "Figure 1. Profiling run versions") @@ -21,14 +21,14 @@ For the Java/Kotlin side, you want the **debuggable** "Profile 'app' with comple ### Java/Kotlin -If we start looking at the [Java/Kotlin side](https://developer.android.com/studio/profile/record-java-kotlin-allocations), choose *Profiler: Run 'app' as debuggable*, and then select the *Track Memory Consumption (Java/Kotlin Allocations)* task. Navigate to the part of the app you wish to profile and then we can start profiling. At the bottom of the Profiling window it should look like Figure 2 below. Click *Start Profiler Task*. +If you start looking at the [Java/Kotlin side](https://developer.android.com/studio/profile/record-java-kotlin-allocations), choose *Profiler: Run 'app' as debuggable*, and then select the *Track Memory Consumption (Java/Kotlin Allocations)* task. Navigate to the part of the app you wish to profile and then you can start profiling. At the bottom of the Profiling window it should look like Figure 2 below. Click *Start Profiler Task*. ![Android Studio Start Profile alt-text#center](start-profile-dropdown.png "Figure 2. Start Profile") -When you're ready, *Stop* the profiling again. Now there'll be a nice timeline graph of memory usage. Unfortunately, while Android Studio has a nicer interface for the Java/Kotlin side than the native side, the key to the timeline graph may be missing. This key is shown below in Figure 3, so you can refer to the colors from this. +When you're ready, *Stop* the profiling again. Now there will be a nice timeline graph of memory usage. While Android Studio has a nicer interface for the Java/Kotlin side than the native side, the key to the timeline graph may be missing. This key is shown below in Figure 3, so you can refer to the colors from this. ![Android Studio memory key alt-text#center](profiler-jk-allocations-legend.png "Figure 3. Memory key for the Java/Kotlin Memory Timeline") -The default height of the Profiling view - as well as the timeline graph within it - is usually too small, so adjust these heights to get a sensible graph. You can click at different points of the graph to see the memory allocations at that time. If you look according to the key you can see how much memory is allocated by Java, Native, Graphics, Code etc. +The default height of the Profiling view, as well as the timeline graph within it is usually too small, so adjust these heights to get a sensible graph. You can click at different points of the graph to see the memory allocations at that time. If you look according to the key you can see how much memory is allocated by Java, Native, Graphics, Code etc. Looking further down you can see the *Table* of Java/Kotlin allocations for your selected time on the timeline. With ML a lot of your allocations are likely to be byte[] for byte buffers, or possibly int[] for image data, etc. Clicking on the data type will open up the particular allocations, showing their size and when they were allocated. This will help to quickly narrow down their use, and whether they are all needed etc. @@ -36,7 +36,7 @@ Looking further down you can see the *Table* of Java/Kotlin allocations for your For the [native side](https://developer.android.com/studio/profile/record-native-allocations), the process is similar but with different options. Choose *Profiler: Run 'app' as profileable*, and then select the *Track Memory Consumption (Native Allocations)* task. Here you have to *Start profiler task from: Process Start*. Choose *Stop* once you've captured enough data. -The Native view doesn't have the same nice timeline graph as the Java/Kotlin side, but it does have the *Table* and *Visualization* tabs. The *Table* tab no longer has a list of allocations, but options to *Arrange by allocation method* or *callstack*. Choose *Arrange by callstack* and then you can trace down which functions were allocating signifcant memory. Potentially more useful, you can also see Remaining Size. +The Native view doesn't have the same nice timeline graph as the Java/Kotlin side, but it does have the *Table* and *Visualization* tabs. The *Table* tab no longer has a list of allocations, but options to *Arrange by allocation method* or *callstack*. Choose *Arrange by callstack* and then you can trace down which functions were allocating significant memory. Potentially more useful, you can also see Remaining Size. In the Visualization tab you can see the callstack as a graph, and once again you can look at total Allocations Size or Remaining Size. If you look at Remaining Size, you can see what is still allocated at the end of the profiling, and by looking a few steps up the stack, probably see which allocations are related to the ML model, by seeing functions that relate to the framework you are using. A lot of the memory may be allocated by that framework rather than in your code, and you may not have much control over it, but it is useful to know where the memory is going. From 46c451bbc9543de98759ecd8db8d87a690217a31 Mon Sep 17 00:00:00 2001 From: pareenaverma Date: Thu, 14 Nov 2024 16:03:49 -0500 Subject: [PATCH 16/17] Update _review.md --- .../smartphones-and-mobile/profiling-ml-on-arm/_review.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md index a1f46d1ed..7eae5a8b1 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_review.md @@ -16,8 +16,8 @@ review: question: > Does Android Studio have a profiler? answers: - - Yes - - No + - "Yes" + - "No" correct_answer: 1 explanation: > Yes, Android Studio has a built-in profiler that can be used to monitor the memory usage of your app among other things From fc1a47d07e157058499d528eb6fa85ca267708bd Mon Sep 17 00:00:00 2001 From: pareenaverma Date: Thu, 14 Nov 2024 16:07:53 -0500 Subject: [PATCH 17/17] Update _next-steps.md --- .../profiling-ml-on-arm/_next-steps.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_next-steps.md b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_next-steps.md index aafea4126..f468cb1b8 100644 --- a/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_next-steps.md +++ b/content/learning-paths/smartphones-and-mobile/profiling-ml-on-arm/_next-steps.md @@ -1,8 +1,7 @@ --- -next_step_guidance: Continue Learning +next_step_guidance: You might be interested in learning how to profile your Unity apps on Android. -recommended_path: /learning-paths/smartphones-and-mobile/build-llama3-chat-android-app-using-executorch-and-xnnpack/ -recommended_path: /learning-paths/smartphones-and-mobile/kleidiai-on-android-with-mediapipe-and-xnnpack/ +recommended_path: /learning-paths/smartphones-and-mobile/profiling-unity-apps-on-android/ further_reading: - resource: