[PATCH v9 17/48] perf jevents: Add upc metric for uops per cycle for AMD

Ian Rogers posted 48 patches 1 week, 1 day ago
[PATCH v9 17/48] perf jevents: Add upc metric for uops per cycle for AMD
Posted by Ian Rogers 1 week, 1 day ago
The metric adjusts for whether or not SMT is on.

Signed-off-by: Ian Rogers <irogers@google.com>
Reviewed-by: Sandipan Das <sandipan.das@amd.com>
---
 tools/perf/pmu-events/amd_metrics.py | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/tools/perf/pmu-events/amd_metrics.py b/tools/perf/pmu-events/amd_metrics.py
index f51a044b8005..42e46b33334d 100755
--- a/tools/perf/pmu-events/amd_metrics.py
+++ b/tools/perf/pmu-events/amd_metrics.py
@@ -3,14 +3,26 @@
 import argparse
 import math
 import os
+from typing import Optional
 from metric import (d_ratio, has_event, max, Event, JsonEncodeMetric,
-                    JsonEncodeMetricGroupDescriptions, LoadEvents, Metric,
-                    MetricGroup, Select)
+                    JsonEncodeMetricGroupDescriptions, Literal, LoadEvents,
+                    Metric, MetricGroup, Select)
 
 # Global command line arguments.
 _args = None
-
+_zen_model: int = 1
 interval_sec = Event("duration_time")
+ins = Event("instructions")
+cycles = Event("cycles")
+# Number of CPU cycles scaled for SMT.
+smt_cycles = Select(cycles / 2, Literal("#smt_on"), cycles)
+
+
+def AmdUpc() -> Metric:
+    ops = Event("ex_ret_ops", "ex_ret_cops")
+    upc = d_ratio(ops, smt_cycles)
+    return Metric("lpm_upc", "Micro-ops retired per core cycle (higher is better)",
+                  upc, "uops/cycle")
 
 
 def Idle() -> Metric:
@@ -45,6 +57,7 @@ def Rapl() -> MetricGroup:
 
 def main() -> None:
     global _args
+    global _zen_model
 
     def dir_path(path: str) -> str:
         """Validate path is a directory for argparse."""
@@ -67,7 +80,10 @@ def main() -> None:
     directory = f"{_args.events_path}/x86/{_args.model}/"
     LoadEvents(directory)
 
+    _zen_model = int(_args.model[6:])
+
     all_metrics = MetricGroup("", [
+        AmdUpc(),
         Idle(),
         Rapl(),
     ])
-- 
2.52.0.158.g65b55ccf14-goog
Re: [PATCH v9 17/48] perf jevents: Add upc metric for uops per cycle for AMD
Posted by Sandipan Das 2 days, 10 hours ago
On 12/2/2025 11:20 PM, Ian Rogers wrote:
> The metric adjusts for whether or not SMT is on.
> 
> Signed-off-by: Ian Rogers <irogers@google.com>
> Reviewed-by: Sandipan Das <sandipan.das@amd.com>
> ---
>  tools/perf/pmu-events/amd_metrics.py | 22 +++++++++++++++++++---
>  1 file changed, 19 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/pmu-events/amd_metrics.py b/tools/perf/pmu-events/amd_metrics.py
> index f51a044b8005..42e46b33334d 100755
> --- a/tools/perf/pmu-events/amd_metrics.py
> +++ b/tools/perf/pmu-events/amd_metrics.py
> @@ -3,14 +3,26 @@
>  import argparse
>  import math
>  import os
> +from typing import Optional
>  from metric import (d_ratio, has_event, max, Event, JsonEncodeMetric,
> -                    JsonEncodeMetricGroupDescriptions, LoadEvents, Metric,
> -                    MetricGroup, Select)
> +                    JsonEncodeMetricGroupDescriptions, Literal, LoadEvents,
> +                    Metric, MetricGroup, Select)
>  
>  # Global command line arguments.
>  _args = None
> -
> +_zen_model: int = 1
>  interval_sec = Event("duration_time")
> +ins = Event("instructions")
> +cycles = Event("cycles")
> +# Number of CPU cycles scaled for SMT.
> +smt_cycles = Select(cycles / 2, Literal("#smt_on"), cycles)

The CPU architects said that while there are some fairness guarantees, the distribution
of resources amongst sibling threads is not always equal. There is also no easy way to
determine this.

> +
> +
> +def AmdUpc() -> Metric:
> +    ops = Event("ex_ret_ops", "ex_ret_cops")
> +    upc = d_ratio(ops, smt_cycles)
> +    return Metric("lpm_upc", "Micro-ops retired per core cycle (higher is better)",
> +                  upc, "uops/cycle")

Zen 3 onwards, PMCx0C1, which is used by ex_ret_ops and ex_ret_cops, counts retired
macro-ops.

>  
>  
>  def Idle() -> Metric:
> @@ -45,6 +57,7 @@ def Rapl() -> MetricGroup:
>  
>  def main() -> None:
>      global _args
> +    global _zen_model
>  
>      def dir_path(path: str) -> str:
>          """Validate path is a directory for argparse."""
> @@ -67,7 +80,10 @@ def main() -> None:
>      directory = f"{_args.events_path}/x86/{_args.model}/"
>      LoadEvents(directory)
>  
> +    _zen_model = int(_args.model[6:])
> +
>      all_metrics = MetricGroup("", [
> +        AmdUpc(),
>          Idle(),
>          Rapl(),
>      ])