carm-roofline 1.0.0.dev3__tar.gz → 1.0.0.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/PKG-INFO +1 -1
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/benchmarking.py +4 -4
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/output/arithmetic.py +67 -64
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/output/roofline.py +24 -5
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/suites/arithmetic.py +12 -26
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/suites/roofline.py +1 -17
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/carm_roofline.egg-info/PKG-INFO +1 -1
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/pyproject.toml +1 -1
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/LICENSE +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/README.md +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/__init__.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/architecture.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/arm.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/config.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/detect.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/frequency.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/memory.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/riscv.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/arm/features.c +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/arm/frequency.h +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/arm/vlen.c +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/frequency.c +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/riscv/frequency.h +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/riscv/rvv_version.c +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/riscv/vlen.c +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/x86/cache.c +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/x86/features.c +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/x86/frequency.h +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/x86/x86_avx512/frequency.h +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/x86.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/arguments.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/__init__.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/benchmark.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/__init__.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/arm.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/code_gen/__init__.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/code_gen/data_type.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/code_gen/instruction.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/code_gen/operation.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/code_gen/register.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/isa.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/parameters.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/riscv.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/x86.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/interface.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/output/__init__.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/output/base.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/output/common.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/output/memory.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/output/memory_sweep.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/output/mixed.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/result.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/suites/__init__.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/suites/base.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/suites/memory.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/suites/memory_sweep.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/suites/mixed.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/carm.py +1 -1
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/carm_roofline.egg-info/SOURCES.txt +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/carm_roofline.egg-info/dependency_links.txt +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/carm_roofline.egg-info/entry_points.txt +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/carm_roofline.egg-info/requires.txt +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/carm_roofline.egg-info/top_level.txt +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/context.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/error.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/exec_interface.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/gui/__init__.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/gui/assets/CARM_icon.svg +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/gui/assets/CHAMP_logo.svg +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/gui/assets/menu_icon.png +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/gui/assets/style.css +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/gui/config.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/gui/dashboard.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/gui/gui_utils.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/output_utils.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/results_paths.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/run_config.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/setup.cfg +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/test_bench/__init__.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/test_bench/builder.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/test_bench/test_bench.c +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/test_bench/test_bench.h +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/test_bench/wrapper.inl +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/units.py +0 -0
- {carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/utils.py +0 -0
|
@@ -102,7 +102,7 @@ class Benchmarking(InsertsArguments):
|
|
|
102
102
|
self.data_type: DataType = args.data_type
|
|
103
103
|
self.threads: int = args.threads
|
|
104
104
|
self.interleaved: bool = args.interleaved
|
|
105
|
-
self.
|
|
105
|
+
self.instructions: set[ArithmeticOperation] = set(args.instruction)
|
|
106
106
|
self.num_ops: Operations = Operations(args.num_ops)
|
|
107
107
|
self.ld_st_ratio: LoadStoreRatio = args.ld_st_ratio
|
|
108
108
|
self.arith_mem_ratio: int = args.arith_mem_ratio
|
|
@@ -163,10 +163,10 @@ class Benchmarking(InsertsArguments):
|
|
|
163
163
|
)
|
|
164
164
|
parser.add_argument(
|
|
165
165
|
"--instruction",
|
|
166
|
-
default=ArithmeticOperation.fma,
|
|
167
|
-
nargs="
|
|
166
|
+
default=[ArithmeticOperation.add, ArithmeticOperation.fma],
|
|
167
|
+
nargs="+",
|
|
168
168
|
action=enum_action(ArithmeticOperation),
|
|
169
|
-
help="Arithmetic instruction
|
|
169
|
+
help="Arithmetic instruction(s) to benchmark (Default: add fma)",
|
|
170
170
|
)
|
|
171
171
|
parser.add_argument(
|
|
172
172
|
"--ld-st-ratio",
|
|
@@ -29,26 +29,19 @@ def _collect_gops_by_isa(isa_suites: dict[str, ISABenchmarkSuite]) -> dict[str,
|
|
|
29
29
|
gops_by_isa: dict[str, float] = {}
|
|
30
30
|
|
|
31
31
|
for isa, suite in sorted(isa_suites.items(), key=lambda kv: kv[0]):
|
|
32
|
-
benches: dict[str, Any]
|
|
33
|
-
if hasattr(suite, "get_arithmetic_benchmarks"):
|
|
34
|
-
benches = suite.get_arithmetic_benchmarks()
|
|
35
|
-
else:
|
|
36
|
-
benches = getattr(suite, "benchmarks", {})
|
|
37
|
-
|
|
38
32
|
values: list[float] = []
|
|
39
|
-
for bench in
|
|
40
|
-
|
|
41
|
-
if not isinstance(res, ArithmeticBenchmarkResult):
|
|
33
|
+
for bench in suite.get_arithmetic_benchmarks().values():
|
|
34
|
+
if not isinstance(bench.results, ArithmeticBenchmarkResult):
|
|
42
35
|
continue
|
|
43
36
|
|
|
44
|
-
gops_value = float(
|
|
37
|
+
gops_value = float(bench.results.performance.value) / 1e9
|
|
45
38
|
if not math.isfinite(gops_value):
|
|
46
39
|
warn(f"Skipping invalid GOPS value for ISA {isa}: {gops_value}")
|
|
47
40
|
continue
|
|
48
41
|
values.append(gops_value)
|
|
49
42
|
|
|
50
43
|
if values:
|
|
51
|
-
gops_by_isa[isa] =
|
|
44
|
+
gops_by_isa[isa] = max(values)
|
|
52
45
|
|
|
53
46
|
return gops_by_isa
|
|
54
47
|
|
|
@@ -64,47 +57,53 @@ def _print_table(context: CARMContext, isa_suites: dict[str, ISABenchmarkSuite])
|
|
|
64
57
|
isa_cls.name: isa_cls.from_architecture(context.architecture) for isa_cls in context.architecture.isa
|
|
65
58
|
}
|
|
66
59
|
|
|
67
|
-
arithmetic_metrics:
|
|
60
|
+
arithmetic_metrics: list[dict[str, Any]] = []
|
|
68
61
|
|
|
69
62
|
for isa, suite in sorted(isa_suites.items(), key=lambda kv: kv[0]):
|
|
70
63
|
frequency = context.architecture.get_frequency_for_isa(isa)
|
|
71
|
-
benches = suite.get_arithmetic_benchmarks()
|
|
72
|
-
assert len(benches) == 1, "Expected exactly one arithmetic benchmark per ISA for summary output"
|
|
73
|
-
benchmark_name, benchmark = next(iter(benches.items()))
|
|
74
|
-
res = benchmark.results
|
|
75
|
-
assert isinstance(res, ArithmeticBenchmarkResult), "Expected ArithmeticBenchmarkResult for arithmetic summary"
|
|
76
|
-
|
|
77
64
|
isa_instance = isa_instances.get(isa)
|
|
78
65
|
if isa_instance is None:
|
|
79
66
|
warn(f"No ISA instance available for {isa}; skipping metrics")
|
|
80
67
|
continue
|
|
81
68
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
69
|
+
benches = suite.get_arithmetic_benchmarks()
|
|
70
|
+
for benchmark_name, benchmark in benches.items():
|
|
71
|
+
res = benchmark.results
|
|
72
|
+
assert isinstance(res, ArithmeticBenchmarkResult), (
|
|
73
|
+
"Expected ArithmeticBenchmarkResult for arithmetic summary"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
ops_per_inst = isa_instance.ops_per_inst(benchmark.params.data_type, benchmark.params.operation)
|
|
77
|
+
total_insts = (benchmark.params.num_ops.value // ops_per_inst) * res.num_repetitions if ops_per_inst else 0
|
|
78
|
+
cycles = Cycles.from_time_and_frequency(res.time_taken, frequency)
|
|
79
|
+
ipc = 0.0 if cycles.value == 0 else total_insts / cycles.value
|
|
80
|
+
ops_per_cycle = ops_per_inst * ipc
|
|
81
|
+
|
|
82
|
+
arithmetic_metrics.append(
|
|
83
|
+
{
|
|
84
|
+
"isa": isa,
|
|
85
|
+
"operation": benchmark.params.operation.name,
|
|
86
|
+
"benchmark": benchmark_name,
|
|
87
|
+
"gops": float(res.performance.value) / 1e9,
|
|
88
|
+
"gops_display": str(res.performance),
|
|
89
|
+
"ipc": ipc,
|
|
90
|
+
"frequency_hz": float(frequency.value),
|
|
91
|
+
"frequency_display": str(frequency),
|
|
92
|
+
"ops_per_instruction": ops_per_inst,
|
|
93
|
+
"ops_per_cycle": ops_per_cycle,
|
|
94
|
+
"time_seconds": float(res.time_taken.value),
|
|
95
|
+
"time_display": str(res.time_taken),
|
|
96
|
+
"repetitions": int(res.num_repetitions),
|
|
97
|
+
"cycles": float(cycles.value),
|
|
98
|
+
"cycles_display": str(cycles),
|
|
99
|
+
}
|
|
100
|
+
)
|
|
103
101
|
|
|
104
102
|
table = Table(title="Arithmetic Performance Summary")
|
|
105
103
|
|
|
106
104
|
# normal output columns
|
|
107
105
|
table.add_column("ISA", style="cyan")
|
|
106
|
+
table.add_column("Op", style="magenta")
|
|
108
107
|
table.add_column("GOPS", justify="right")
|
|
109
108
|
table.add_column("IPC", justify="right")
|
|
110
109
|
table.add_column("Frequency", justify="right")
|
|
@@ -116,7 +115,8 @@ def _print_table(context: CARMContext, isa_suites: dict[str, ISABenchmarkSuite])
|
|
|
116
115
|
table.add_column("Repetitions", justify="right")
|
|
117
116
|
table.add_column("Cycles", justify="right")
|
|
118
117
|
|
|
119
|
-
|
|
118
|
+
# sort rows by ISA and operation
|
|
119
|
+
for metrics in sorted(arithmetic_metrics, key=lambda row: (row["isa"], row["operation"])):
|
|
120
120
|
ipc = float(metrics["ipc"])
|
|
121
121
|
|
|
122
122
|
if print_extra:
|
|
@@ -130,7 +130,8 @@ def _print_table(context: CARMContext, isa_suites: dict[str, ISABenchmarkSuite])
|
|
|
130
130
|
extra_args = ()
|
|
131
131
|
|
|
132
132
|
table.add_row(
|
|
133
|
-
isa,
|
|
133
|
+
metrics["isa"],
|
|
134
|
+
metrics["operation"],
|
|
134
135
|
str(metrics["gops_display"]),
|
|
135
136
|
f"{ipc:.2f}",
|
|
136
137
|
str(metrics["frequency_display"]),
|
|
@@ -152,34 +153,36 @@ def _write_json(context: CARMContext, isa_suites: dict[str, ISABenchmarkSuite])
|
|
|
152
153
|
|
|
153
154
|
for isa, suite in sorted(isa_suites.items(), key=lambda kv: kv[0]):
|
|
154
155
|
frequency = context.architecture.get_frequency_for_isa(isa)
|
|
155
|
-
benches = suite.get_arithmetic_benchmarks()
|
|
156
|
-
assert len(benches) == 1, "Expected exactly one arithmetic benchmark per ISA for JSON output"
|
|
157
|
-
benchmark_name, benchmark = next(iter(benches.items()))
|
|
158
|
-
res = benchmark.results
|
|
159
|
-
assert isinstance(res, ArithmeticBenchmarkResult), "Expected ArithmeticBenchmarkResult for arithmetic JSON"
|
|
160
|
-
|
|
161
156
|
isa_instance = isa_instances.get(isa)
|
|
162
157
|
if isa_instance is None:
|
|
163
158
|
warn(f"No ISA instance available for {isa}; skipping metrics")
|
|
164
159
|
continue
|
|
165
160
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
161
|
+
benches = suite.get_arithmetic_benchmarks()
|
|
162
|
+
isa_results: dict[str, object] = {}
|
|
163
|
+
for benchmark_name, benchmark in benches.items():
|
|
164
|
+
res = benchmark.results
|
|
165
|
+
assert isinstance(res, ArithmeticBenchmarkResult), "Expected ArithmeticBenchmarkResult for arithmetic JSON"
|
|
166
|
+
|
|
167
|
+
ops_per_inst = isa_instance.ops_per_inst(benchmark.params.data_type, benchmark.params.operation)
|
|
168
|
+
total_insts = (benchmark.params.num_ops.value // ops_per_inst) * res.num_repetitions if ops_per_inst else 0
|
|
169
|
+
cycles = Cycles.from_time_and_frequency(res.time_taken, frequency)
|
|
170
|
+
ipc = 0.0 if cycles.value == 0 else total_insts / cycles.value
|
|
171
|
+
|
|
172
|
+
isa_results[benchmark.params.operation.name] = {
|
|
173
|
+
"benchmark": benchmark_name,
|
|
174
|
+
"operation": benchmark.params.operation.name,
|
|
175
|
+
"gops": float(res.performance.value) / 1e9,
|
|
176
|
+
"ipc": ipc,
|
|
177
|
+
"frequency_hz": float(frequency.value),
|
|
178
|
+
"ops_per_instruction": ops_per_inst,
|
|
179
|
+
"ops_per_cycle": ops_per_inst * ipc,
|
|
180
|
+
"time_seconds": float(res.time_taken.value),
|
|
181
|
+
"repetitions": int(res.num_repetitions),
|
|
182
|
+
"cycles": float(cycles.value),
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
results[isa] = isa_results
|
|
183
186
|
|
|
184
187
|
out_dir = context.run_config.output_dir / "arithmetic"
|
|
185
188
|
out_dir.mkdir(parents=True, exist_ok=True)
|
|
@@ -8,6 +8,7 @@ from datetime import datetime
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from typing import TYPE_CHECKING
|
|
10
10
|
|
|
11
|
+
from benchmark.generation.code_gen.operation import ArithmeticOperation
|
|
11
12
|
from output_utils import info, warn
|
|
12
13
|
from units import Cycles
|
|
13
14
|
|
|
@@ -167,7 +168,12 @@ def _collect_memory_metrics(
|
|
|
167
168
|
return bandwidth_by_level, ipc_by_level
|
|
168
169
|
|
|
169
170
|
|
|
170
|
-
def _collect_fp_metrics(
|
|
171
|
+
def _collect_fp_metrics(
|
|
172
|
+
context: CARMContext,
|
|
173
|
+
suite: ISABenchmarkSuite,
|
|
174
|
+
isa_name: str,
|
|
175
|
+
operation: ArithmeticOperation | None = None,
|
|
176
|
+
) -> tuple[float, float]:
|
|
171
177
|
frequency = context.architecture.get_frequency_for_isa(isa_name)
|
|
172
178
|
fp_gflops = 0.0
|
|
173
179
|
fp_ipc = 0.0
|
|
@@ -179,6 +185,8 @@ def _collect_fp_metrics(context: CARMContext, suite: ISABenchmarkSuite, isa_name
|
|
|
179
185
|
for bench in suite.get_arithmetic_benchmarks().values():
|
|
180
186
|
if bench.results is None:
|
|
181
187
|
continue
|
|
188
|
+
if operation is not None and bench.params.operation != operation:
|
|
189
|
+
continue
|
|
182
190
|
fp_gflops = float(bench.results.performance.value) / 1e9
|
|
183
191
|
ops_per_inst = isa_instance.ops_per_inst(bench.params.data_type, bench.params.operation)
|
|
184
192
|
total_insts = (
|
|
@@ -214,8 +222,19 @@ def _write_csv(context: CARMContext, isa_suites: dict[str, ISABenchmarkSuite], o
|
|
|
214
222
|
|
|
215
223
|
bandwidth_by_level, icycle_by_level = _collect_memory_metrics(context, suite, isa)
|
|
216
224
|
|
|
217
|
-
|
|
218
|
-
|
|
225
|
+
# Select primary instruction: prefer non-fma if available, else fall back to fma
|
|
226
|
+
primary_instruction = next(
|
|
227
|
+
(op for op in context.benchmarking.instructions if op != ArithmeticOperation.fma),
|
|
228
|
+
ArithmeticOperation.fma,
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
fp_inst = primary_instruction.name
|
|
232
|
+
fp_gflops, fp_icycle = _collect_fp_metrics(context, suite, isa, operation=primary_instruction)
|
|
233
|
+
|
|
234
|
+
fma_gflops = 0.0
|
|
235
|
+
fma_icycle = 0.0
|
|
236
|
+
if ArithmeticOperation.fma in context.benchmarking.instructions:
|
|
237
|
+
fma_gflops, fma_icycle = _collect_fp_metrics(context, suite, isa, operation=ArithmeticOperation.fma)
|
|
219
238
|
|
|
220
239
|
def round_helper(x: float) -> str:
|
|
221
240
|
return f"{x:.3g}" if x < 1 else f"{x:.3f}"
|
|
@@ -240,8 +259,8 @@ def _write_csv(context: CARMContext, isa_suites: dict[str, ISABenchmarkSuite], o
|
|
|
240
259
|
round_helper(icycle_by_level["DRAM"]),
|
|
241
260
|
round_helper(fp_gflops),
|
|
242
261
|
round_helper(fp_icycle),
|
|
243
|
-
|
|
244
|
-
|
|
262
|
+
round_helper(fma_gflops),
|
|
263
|
+
round_helper(fma_icycle),
|
|
245
264
|
]
|
|
246
265
|
|
|
247
266
|
secondary_headers = [
|
|
@@ -5,8 +5,6 @@ from __future__ import annotations
|
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
from typing import TYPE_CHECKING
|
|
7
7
|
|
|
8
|
-
from units import Performance
|
|
9
|
-
|
|
10
8
|
from ..benchmark import ArithmeticBenchmark
|
|
11
9
|
from ..generation import ArithmeticBenchmarkParams
|
|
12
10
|
from .base import ISABenchmarkSuite
|
|
@@ -19,7 +17,7 @@ if TYPE_CHECKING:
|
|
|
19
17
|
class ArithmeticBenchmarkSuite(ISABenchmarkSuite):
|
|
20
18
|
"""Suite for arithmetic-only benchmarks (TestType.ARITHMETIC).
|
|
21
19
|
|
|
22
|
-
Measures peak arithmetic performance
|
|
20
|
+
Measures peak arithmetic performance across one or more operations.
|
|
23
21
|
"""
|
|
24
22
|
|
|
25
23
|
@classmethod
|
|
@@ -61,29 +59,17 @@ class ArithmeticBenchmarkSuite(ISABenchmarkSuite):
|
|
|
61
59
|
# This also helps us deal with SMT, ensuring threads are properly distributed across cores
|
|
62
60
|
thread_affinity = architecture.memory_topology.plan_thread_affinity(benchmark.threads, 1)
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
62
|
+
for operation in benchmark.instructions:
|
|
63
|
+
params = ArithmeticBenchmarkParams(
|
|
64
|
+
data_type=benchmark.data_type,
|
|
65
|
+
thread_affinity=thread_affinity.cpu_ids,
|
|
66
|
+
operation=operation,
|
|
67
|
+
num_ops=benchmark.num_ops,
|
|
68
|
+
)
|
|
69
|
+
spec = isa.generate_arithmetic(params, context)
|
|
72
70
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
# Add to ISA suite using the benchmark's authoritative name
|
|
72
|
+
arith_benchmark = ArithmeticBenchmark(params=params, spec=spec)
|
|
73
|
+
suite.add_benchmark(arith_benchmark.name, arith_benchmark)
|
|
76
74
|
|
|
77
75
|
return suite
|
|
78
|
-
|
|
79
|
-
def get_peak_performance(self) -> Performance:
|
|
80
|
-
"""Get peak GOPS from arithmetic portion of roofline suite.
|
|
81
|
-
|
|
82
|
-
Returns:
|
|
83
|
-
Peak GOPS from arithmetic benchmarks, or None if unavailable.
|
|
84
|
-
"""
|
|
85
|
-
arith_benchmarks = self.get_arithmetic_benchmarks()
|
|
86
|
-
if len(arith_benchmarks) > 1:
|
|
87
|
-
raise ValueError("Expected exactly one arithmetic benchmark for peak performance calculation")
|
|
88
|
-
|
|
89
|
-
return super().get_peak_performance()
|
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
from typing import TYPE_CHECKING
|
|
7
7
|
|
|
8
|
-
from units import ArithmeticIntensity, Bandwidth
|
|
8
|
+
from units import ArithmeticIntensity, Bandwidth
|
|
9
9
|
|
|
10
10
|
from .arithmetic import ArithmeticBenchmarkSuite
|
|
11
11
|
from .base import ISABenchmarkSuite
|
|
@@ -53,22 +53,6 @@ class RooflineBenchmarkSuite(ISABenchmarkSuite):
|
|
|
53
53
|
|
|
54
54
|
return suite
|
|
55
55
|
|
|
56
|
-
def get_peak_performance(self) -> Performance:
|
|
57
|
-
"""Get peak GOPS from arithmetic portion of roofline suite.
|
|
58
|
-
|
|
59
|
-
Returns:
|
|
60
|
-
Peak GOPS from arithmetic benchmarks, or None if unavailable.
|
|
61
|
-
"""
|
|
62
|
-
arith_benchmarks = self.get_arithmetic_benchmarks()
|
|
63
|
-
if len(arith_benchmarks) > 1:
|
|
64
|
-
raise ValueError("Expected exactly one arithmetic benchmark for peak performance calculation")
|
|
65
|
-
|
|
66
|
-
arith_benchmark = next(iter(arith_benchmarks.values()))
|
|
67
|
-
if arith_benchmark.results is None:
|
|
68
|
-
raise ValueError("Arithmetic benchmark missing performance result for roofline benchmarking")
|
|
69
|
-
|
|
70
|
-
return arith_benchmark.results.performance
|
|
71
|
-
|
|
72
56
|
def get_bandwidth_by_level(self) -> dict[str, Bandwidth]:
|
|
73
57
|
"""Get peak bandwidth for each cache level from memory benchmarks.
|
|
74
58
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/riscv/rvv_version.c
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/architecture/tests/x86/x86_avx512/frequency.h
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/code_gen/__init__.py
RENAMED
|
File without changes
|
{carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/code_gen/data_type.py
RENAMED
|
File without changes
|
{carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/code_gen/instruction.py
RENAMED
|
File without changes
|
{carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/code_gen/operation.py
RENAMED
|
File without changes
|
{carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/benchmark/generation/code_gen/register.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/carm_roofline.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{carm_roofline-1.0.0.dev3 → carm_roofline-1.0.0.dev4}/carm_roofline.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|