|
| 1 | +--- |
| 2 | +title: Using Profile Guided Optimization (Windows) |
| 3 | +weight: 5 |
| 4 | + |
| 5 | +### FIXED, DO NOT MODIFY |
| 6 | +layout: learningpathall |
| 7 | +--- |
| 8 | + |
| 9 | +### Build with PGO |
| 10 | + |
| 11 | +To generate a binary optimized using runtime profile data, first build an instrumented binary that records usage data. Before building, open the Arm dev shell so that the compiler is in your PATH: |
| 12 | + |
| 13 | +```console |
| 14 | +& "C:\Program Files\Microsoft Visual Studio\18\Community\Common7\Tools\Launch-VsDevShell.ps1" -Arch arm64 |
| 15 | +``` |
| 16 | + |
| 17 | +(**note:** you may need to change the version number in your Visual Studio path, depending on which Visual Studio version you've installed.) |
| 18 | + |
| 19 | +Next, set an environment variable to refer to the installed packages directory: |
| 20 | + |
| 21 | +```console |
| 22 | +$VCPKG="C:\git\vcpkg\installed\arm64-windows-static" |
| 23 | +``` |
| 24 | + |
| 25 | +Next, run the following command, which includes the `/GENPROFILE` flag, to build the instrumented binary: |
| 26 | + |
| 27 | +```console |
| 28 | +cl /O2 /GL /D BENCHMARK_STATIC_DEFINE /I "$VCPKG\include" /Fe:div_bench.exe div_bench.cpp /link /LTCG /GENPROFILE /PGD:div_bench.pgd /LIBPATH:"$VCPKG\lib" benchmark.lib benchmark_main.lib shlwapi.lib |
| 29 | +``` |
| 30 | + |
| 31 | +The compiler options used in this command are: |
| 32 | + |
| 33 | +* **/O2**: Creates [fast code](https://learn.microsoft.com/en-us/cpp/build/reference/o1-o2-minimize-size-maximize-speed?view=msvc-170) |
| 34 | +* **/GL**: Enables [whole program optimization](https://learn.microsoft.com/en-us/cpp/build/reference/gl-whole-program-optimization?view=msvc-170). |
| 35 | +* **/D**: Enables the Benchmark [static preprocessor definition](https://learn.microsoft.com/en-us/cpp/build/reference/d-preprocessor-definitions?view=msvc-170). |
| 36 | +* **/I**: Adds the arm64 includes to the [list of include directories](https://learn.microsoft.com/en-us/cpp/build/reference/i-additional-include-directories?view=msvc-170). |
| 37 | +* **/Fe**: Specifies a name for the [executable file output](https://learn.microsoft.com/en-us/cpp/build/reference/fe-name-exe-file?view=msvc-170). |
| 38 | +* **/link**: Specifies [options to pass to linker](https://learn.microsoft.com/en-us/cpp/build/reference/link-pass-options-to-linker?view=msvc-170). |
| 39 | + |
| 40 | +The linker options used in this command are: |
| 41 | + |
| 42 | +* **/LTCG**: Specifies [link time code generation](https://learn.microsoft.com/en-us/cpp/build/reference/ltcg-link-time-code-generation?view=msvc-170). |
| 43 | +* **/GENPROFILE**: Specifies [generation of a .pgd file for PGO](https://learn.microsoft.com/en-us/cpp/build/reference/genprofile-fastgenprofile-generate-profiling-instrumented-build?view=msvc-170). |
| 44 | +* **/PGD**: Specifies a [database for PGO](https://learn.microsoft.com/en-us/cpp/build/reference/pgd-specify-database-for-profile-guided-optimizations?view=msvc-170). |
| 45 | +* **/LIBPATH**: Specifies the [additional library path](https://learn.microsoft.com/en-us/cpp/build/reference/libpath-additional-libpath?view=msvc-170). |
| 46 | + |
| 47 | +Next, run the instrumented binary to generate the profile data: |
| 48 | + |
| 49 | +```console |
| 50 | +.\div_bench.exe |
| 51 | +``` |
| 52 | + |
| 53 | +This execution creates profile data files (typically with a `.pgc` extension) in the same directory. |
| 54 | + |
| 55 | +Now recompile the program using the `/USEPROFILE` flag to apply optimizations based on the collected data: |
| 56 | + |
| 57 | +```console |
| 58 | +cl /O2 /GL /D BENCHMARK_STATIC_DEFINE /I "$VCPKG\include" /Fe:div_bench_opt.exe div_bench.cpp /link /LTCG:PGOptimize /USEPROFILE /PGD:div_bench.pgd /LIBPATH:"$VCPKG\lib" benchmark.lib benchmark_main.lib shlwapi.lib |
| 59 | +``` |
| 60 | + |
| 61 | +In this command, the [USEPROFILE linker option](https://learn.microsoft.com/en-us/cpp/build/reference/useprofile?view=msvc-170) instructs the linker to enable PGO with the profile generated during the previous run of the executable. |
| 62 | + |
| 63 | +### Run the optimized binary |
| 64 | + |
| 65 | +Now run the optimized binary: |
| 66 | + |
| 67 | +```console |
| 68 | +.\div_bench_opt.exe |
| 69 | +``` |
| 70 | + |
| 71 | +The following output shows the performance improvement: |
| 72 | + |
| 73 | +```output |
| 74 | +Running ./div_bench.opt |
| 75 | +Run on (4 X 2100 MHz CPU s) |
| 76 | +CPU Caches: |
| 77 | + L1 Data 64 KiB (x4) |
| 78 | + L1 Instruction 64 KiB (x4) |
| 79 | + L2 Unified 1024 KiB (x4) |
| 80 | + L3 Unified 32768 KiB (x1) |
| 81 | +Load Average: 0.10, 0.03, 0.01 |
| 82 | +***WARNING*** Library was built as DEBUG. Timings may be affected. |
| 83 | +------------------------------------------------------- |
| 84 | +Benchmark Time CPU Iterations |
| 85 | +------------------------------------------------------- |
| 86 | +baseDiv/1500 2.86 us 2.86 us 244429 |
| 87 | +``` |
| 88 | + |
| 89 | +As the terminal output above shows, the average execution time is reduced from 7.90 to 2.86 microseconds. This improvement occurs because the profile data informed the compiler that the input divisor was consistently 1500 during the profiled runs, allowing it to apply specific optimizations. |
0 commit comments