counted-float 0.9.2__tar.gz → 0.9.3__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.
Files changed (81) hide show
  1. {counted_float-0.9.2 → counted_float-0.9.3}/PKG-INFO +9 -6
  2. {counted_float-0.9.2 → counted_float-0.9.3}/README.md +7 -4
  3. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/__init__.py +0 -2
  4. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/counting/_builtin_data.py +18 -16
  5. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/models/__init__.py +5 -2
  6. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/models/_flop_weights.py +6 -12
  7. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/models/_flops_benchmark_result.py +0 -1
  8. counted_float-0.9.3/counted_float/_core/models/_instruction_latencies.py +146 -0
  9. {counted_float-0.9.2/counted_float/data/specs/arm → counted_float-0.9.3/counted_float/data/arm/v8_x/specs}/arm_v8_cortex_a76.json +29 -11
  10. counted_float-0.9.3/counted_float/data/arm/v8_x/specs/arm_v9_cortex_n1.json +70 -0
  11. counted_float-0.9.3/counted_float/data/arm/v8_x/specs/arm_v9_cortex_v1.json +70 -0
  12. {counted_float-0.9.2/counted_float/data/specs/arm → counted_float-0.9.3/counted_float/data/arm/v8_x/specs}/arm_v9_cortex_x1.json +29 -11
  13. counted_float-0.9.3/counted_float/data/arm/v9_0/specs/arm_v9_cortex_n2.json +70 -0
  14. counted_float-0.9.3/counted_float/data/arm/v9_0/specs/arm_v9_cortex_v2.json +70 -0
  15. {counted_float-0.9.2/counted_float/data/specs/arm → counted_float-0.9.3/counted_float/data/arm/v9_0/specs}/arm_v9_cortex_x2.json +29 -11
  16. {counted_float-0.9.2/counted_float/data/specs/arm → counted_float-0.9.3/counted_float/data/arm/v9_0/specs}/arm_v9_cortex_x3.json +29 -11
  17. counted_float-0.9.3/counted_float/data/arm/v9_2/specs/arm_v9_cortex_v3.json +70 -0
  18. counted_float-0.9.3/counted_float/data/arm/v9_2/specs/arm_v9_cortex_x4.json +70 -0
  19. counted_float-0.9.3/counted_float/data/arm/v9_2/specs/arm_v9_cortex_x925.json +70 -0
  20. counted_float-0.9.3/counted_float/data/x86/amd/2017_zen1/analysis_uops_info_zen1+.json +69 -0
  21. counted_float-0.9.3/counted_float/data/x86/amd/2020_zen3/analysis_agner_fog_r7_5800x.json +70 -0
  22. counted_float-0.9.3/counted_float/data/x86/amd/2020_zen3/analysis_uops_info_zen3.json +69 -0
  23. counted_float-0.9.3/counted_float/data/x86/amd/2022_zen4/analysis_agner_fog_r9_7900x.json +70 -0
  24. counted_float-0.9.3/counted_float/data/x86/amd/2022_zen4/analysis_uops_info_zen4.json +69 -0
  25. counted_float-0.9.3/counted_float/data/x86/amd/2022_zen4/specs_amd.json +70 -0
  26. counted_float-0.9.3/counted_float/data/x86/amd/2024_zen5/analysis_agner_fog_r7_9800x3d.json +70 -0
  27. counted_float-0.9.3/counted_float/data/x86/amd/2024_zen5/specs_amd.json +70 -0
  28. counted_float-0.9.3/counted_float/data/x86/intel/2017_coffee_lake_gen_8/analysis_agner_fog_coffee_lake.json +71 -0
  29. counted_float-0.9.3/counted_float/data/x86/intel/2017_coffee_lake_gen_8/analysis_uops_info_coffee_lake.json +69 -0
  30. counted_float-0.9.3/counted_float/data/x86/intel/2019_sunny_cove_gen_10/analysis_agner_fog_ice_lake.json +70 -0
  31. counted_float-0.9.3/counted_float/data/x86/intel/2019_sunny_cove_gen_10/analysis_uops_info_ice_lake.json +69 -0
  32. counted_float-0.9.3/counted_float/data/x86/intel/2019_sunny_cove_gen_10/analysis_uops_info_tiger_lake.json +69 -0
  33. counted_float-0.9.3/counted_float/data/x86/intel/2021_golden_cove_gen_12/analysis_uops_info_alder_lake_p.json +69 -0
  34. counted_float-0.9.3/counted_float/data/x86/intel/2021_golden_cove_gen_12/specs_intel.json +70 -0
  35. counted_float-0.9.3/counted_float/data/x86/intel/2022_raptor_cove_gen_13_14/specs_intel.json +71 -0
  36. counted_float-0.9.3/counted_float/data/x86/intel/2023_redwood_cove_ultra_1/specs_intel.json +70 -0
  37. {counted_float-0.9.2 → counted_float-0.9.3}/pyproject.toml +2 -2
  38. counted_float-0.9.2/counted_float/_core/models/_fpu_instruction.py +0 -22
  39. counted_float-0.9.2/counted_float/_core/models/_fpu_specs.py +0 -98
  40. counted_float-0.9.2/counted_float/data/benchmarks/x86/intel/gen7_i5_7200u.json +0 -103
  41. counted_float-0.9.2/counted_float/data/specs/arm/arm_v7a_cortex_a9.json +0 -52
  42. counted_float-0.9.2/counted_float/data/specs/arm/arm_v8_cortex_a55.json +0 -52
  43. counted_float-0.9.2/counted_float/data/specs/x86/amd/zen3_r7_5800x.json +0 -54
  44. counted_float-0.9.2/counted_float/data/specs/x86/amd/zen4_r9_7900x.json +0 -54
  45. counted_float-0.9.2/counted_float/data/specs/x86/amd/zen5_r7_9800x3d.json +0 -54
  46. counted_float-0.9.2/counted_float/data/specs/x86/intel/gen09_coffee_lake.json +0 -57
  47. counted_float-0.9.2/counted_float/data/specs/x86/intel/gen10_cannon_lake.json +0 -57
  48. counted_float-0.9.2/counted_float/data/specs/x86/intel/gen11_tiger_lake.json +0 -57
  49. {counted_float-0.9.2 → counted_float-0.9.3}/.gitignore +0 -0
  50. {counted_float-0.9.2 → counted_float-0.9.3}/LICENSE +0 -0
  51. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/__init__.py +0 -0
  52. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/_cli.py +0 -0
  53. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/benchmarking/__init__.py +0 -0
  54. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/benchmarking/_flops_benchmark_suite.py +0 -0
  55. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/benchmarking/_flops_micro_benchmark.py +0 -0
  56. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/benchmarking/_micro_benchmark.py +0 -0
  57. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/benchmarking/_time_utils.py +0 -0
  58. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/compatibility/__init__.py +0 -0
  59. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/compatibility/_numba.py +0 -0
  60. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/compatibility/_strenum.py +0 -0
  61. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/counting/__init__.py +0 -0
  62. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/counting/_context_managers.py +0 -0
  63. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/counting/_counted_float.py +0 -0
  64. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/counting/_global_counter.py +0 -0
  65. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/counting/config/__init__.py +0 -0
  66. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/counting/config/_config.py +0 -0
  67. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/counting/config/_defaults.py +0 -0
  68. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/models/_base.py +0 -0
  69. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/models/_flop_counts.py +0 -0
  70. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/models/_flop_type.py +0 -0
  71. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/models/_micro_benchmark_result.py +0 -0
  72. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/utils/__init__.py +0 -0
  73. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/utils/_formatting.py +0 -0
  74. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/utils/_geo_mean.py +0 -0
  75. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/utils/_latency.py +0 -0
  76. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/utils/_missing_data.py +0 -0
  77. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/_core/utils/_timer.py +0 -0
  78. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/benchmarking/__init__.py +0 -0
  79. {counted_float-0.9.2 → counted_float-0.9.3}/counted_float/config/__init__.py +0 -0
  80. {counted_float-0.9.2/counted_float/data/benchmarks/arm/apple → counted_float-0.9.3/counted_float/data/arm/v8_x/benchmarks}/m3_max_macbook_pro_16.json +0 -0
  81. /counted_float-0.9.2/counted_float/data/benchmarks/x86/intel/gen12_i7_1265u.json → /counted_float-0.9.3/counted_float/data/x86/intel/2021_golden_cove_gen_12/benchmark_core_i7_1265u.json +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: counted-float
3
- Version: 0.9.2
3
+ Version: 0.9.3
4
4
  Summary: Count floating-point operations in Python code & benchmark relative flop costs.
5
5
  Project-URL: Source, https://github.com/bertpl/counted-float
6
- Project-URL: ChangeLog, https://github.com/bertpl/counted-float/blob/develop/RELEASE_NOTES.md
6
+ Project-URL: ChangeLog, https://github.com/bertpl/counted-float/blob/develop/CHANGELOG.md
7
7
  Project-URL: Issues, https://github.com/bertpl/counted-float/issues
8
8
  Project-URL: Roadmap, https://github.com/bertpl/counted-float/milestones
9
9
  License-File: LICENSE
@@ -21,9 +21,9 @@ Description-Content-Type: text/markdown
21
21
 
22
22
  <!--START_SECTION:images-->
23
23
  ![shields.io-python-versions](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)
24
- ![genbadge-test-count](https://bertpl.github.io/counted-float/version_artifacts/v0.9.2/badge-test-count.svg)
25
- ![genbadge-test-coverage](https://bertpl.github.io/counted-float/version_artifacts/v0.9.2/badge-coverage.svg)
26
- ![counted_float logo](https://bertpl.github.io/counted-float/version_artifacts/v0.9.2/splash.webp)
24
+ ![genbadge-test-count](https://bertpl.github.io/counted-float/version_artifacts/v0.9.3/badge-test-count.svg)
25
+ ![genbadge-test-coverage](https://bertpl.github.io/counted-float/version_artifacts/v0.9.3/badge-coverage.svg)
26
+ ![counted_float logo](https://bertpl.github.io/counted-float/version_artifacts/v0.9.3/splash.webp)
27
27
  <!--END_SECTION:images-->
28
28
 
29
29
  # counted-float
@@ -148,7 +148,10 @@ counts.total_count() # 2
148
148
  ## 2.3. Weighted FLOP counting
149
149
 
150
150
  The `counted_float` package contains a set of default, built-in FLOP weights, based on both empirical measurements
151
- and theoretical estimates of the relative cost of different floating point operations.
151
+ and theoretical estimates of the relative cost of different floating point operations.
152
+
153
+ See [fpu_data_sources.md](https://github.com/bertpl/counted-float/tree/develop/docs/analysis_methodology.md) for
154
+ rationale behind choice of data sources and methodology.
152
155
 
153
156
  ```
154
157
  >>> from counted_float.config import get_flop_weights
@@ -1,8 +1,8 @@
1
1
  <!--START_SECTION:images-->
2
2
  ![shields.io-python-versions](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)
3
- ![genbadge-test-count](https://bertpl.github.io/counted-float/version_artifacts/v0.9.2/badge-test-count.svg)
4
- ![genbadge-test-coverage](https://bertpl.github.io/counted-float/version_artifacts/v0.9.2/badge-coverage.svg)
5
- ![counted_float logo](https://bertpl.github.io/counted-float/version_artifacts/v0.9.2/splash.webp)
3
+ ![genbadge-test-count](https://bertpl.github.io/counted-float/version_artifacts/v0.9.3/badge-test-count.svg)
4
+ ![genbadge-test-coverage](https://bertpl.github.io/counted-float/version_artifacts/v0.9.3/badge-coverage.svg)
5
+ ![counted_float logo](https://bertpl.github.io/counted-float/version_artifacts/v0.9.3/splash.webp)
6
6
  <!--END_SECTION:images-->
7
7
 
8
8
  # counted-float
@@ -127,7 +127,10 @@ counts.total_count() # 2
127
127
  ## 2.3. Weighted FLOP counting
128
128
 
129
129
  The `counted_float` package contains a set of default, built-in FLOP weights, based on both empirical measurements
130
- and theoretical estimates of the relative cost of different floating point operations.
130
+ and theoretical estimates of the relative cost of different floating point operations.
131
+
132
+ See [fpu_data_sources.md](https://github.com/bertpl/counted-float/tree/develop/docs/analysis_methodology.md) for
133
+ rationale behind choice of data sources and methodology.
131
134
 
132
135
  ```
133
136
  >>> from counted_float.config import get_flop_weights
@@ -8,7 +8,6 @@ from ._core.models import (
8
8
  FlopsBenchmarkResults,
9
9
  FlopType,
10
10
  FlopWeights,
11
- FPUInstruction,
12
11
  Quantiles,
13
12
  SystemInfo,
14
13
  )
@@ -23,7 +22,6 @@ __all__ = [
23
22
  "FlopsBenchmarkResults",
24
23
  "FlopType",
25
24
  "FlopWeights",
26
- "FPUInstruction",
27
25
  "PauseFlopCounting",
28
26
  "Quantiles",
29
27
  "SystemInfo",
@@ -3,10 +3,10 @@ from __future__ import annotations
3
3
  import math
4
4
  from importlib.resources import files
5
5
 
6
- from pydantic import ValidationError
6
+ from pydantic import BaseModel, ValidationError
7
7
  from rich.console import Console
8
8
 
9
- from counted_float._core.models import FlopsBenchmarkResults, FlopType, FlopWeights, InstructionLatencies
9
+ from counted_float._core.models import FlopsBenchmarkResults, FlopWeights, InstructionLatencies
10
10
 
11
11
  DATA_PACKAGE = "counted_float.data"
12
12
 
@@ -64,17 +64,8 @@ class BuiltInData:
64
64
  def benchmarks(cls) -> dict[str, FlopsBenchmarkResults]:
65
65
  return {
66
66
  key: FlopsBenchmarkResults.model_validate_json(json_str)
67
- for key, json_str in _load_json_files_as_dict(files(f"{DATA_PACKAGE}.benchmarks")).items()
68
- }
69
-
70
- # -------------------------------------------------------------------------
71
- # Specs
72
- # -------------------------------------------------------------------------
73
- @classmethod
74
- def specs(cls) -> dict[str, InstructionLatencies]:
75
- return {
76
- key: InstructionLatencies.model_validate_json(json_str)
77
- for key, json_str in _load_json_files_as_dict(files(f"{DATA_PACKAGE}.specs")).items()
67
+ for key, json_str in _load_json_files_as_dict(files(f"{DATA_PACKAGE}")).items()
68
+ if "benchmark" in key
78
69
  }
79
70
 
80
71
  # -------------------------------------------------------------------------
@@ -146,16 +137,27 @@ def _construct_flop_weights_from_json_str(json_str: str) -> FlopWeights:
146
137
  """
147
138
  Construct a FlopWeights instance from a JSON string, where the JSON string can represent either...
148
139
  - FlopsBenchmarkResults
149
- - InstructionLatencies
140
+ - InstructionLatencies_<x>
150
141
  :param json_str: (str) JSON string representing either of the aforementioned data structures.
151
142
  :return: FlopWeights instance extracted from the input data.
152
143
  """
153
144
 
154
145
  # try all supported classes, all of which have a .flop_weights property
155
- for pydantic_cls in [FlopsBenchmarkResults, InstructionLatencies]:
146
+ return _deserialize_as_any_pydantic_class(
147
+ json_str,
148
+ [
149
+ FlopsBenchmarkResults,
150
+ InstructionLatencies,
151
+ ],
152
+ ).flop_weights()
153
+
154
+
155
+ def _deserialize_as_any_pydantic_class(json_str: str, pydantic_classes: list[type[BaseModel]]):
156
+ # try all supported classes
157
+ for pydantic_cls in pydantic_classes:
156
158
  try:
157
159
  obj = pydantic_cls.model_validate_json(json_str)
158
- return obj.flop_weights
160
+ return obj
159
161
  except ValidationError:
160
162
  continue
161
163
 
@@ -8,6 +8,9 @@ from ._flops_benchmark_result import (
8
8
  FlopsBenchmarkResults,
9
9
  SystemInfo,
10
10
  )
11
- from ._fpu_instruction import FPUInstruction
12
- from ._fpu_specs import InstructionLatencies
11
+ from ._instruction_latencies import (
12
+ InstructionLatencies,
13
+ InstructionLatencies_ARM,
14
+ InstructionLatencies_SSE2,
15
+ )
13
16
  from ._micro_benchmark_result import MicroBenchmarkResult, Quantiles, SingleRunResult
@@ -38,11 +38,11 @@ class FlopWeights(MyBaseModel):
38
38
  # -------------------------------------------------------------------------
39
39
  @field_validator("weights")
40
40
  @classmethod
41
- def check_all_flop_types_present(cls, v: dict[FlopType, float | int]) -> dict[FlopType, float | int]:
41
+ def ensure_all_flop_types_present(cls, v: dict[FlopType, float | int]) -> dict[FlopType, float | int]:
42
42
  # make sure all FlopType enum members are present
43
- missing = [member for member in FlopType if member not in v]
44
- if missing:
45
- raise ValueError(f"Missing weights for flop types: {missing}")
43
+ for flop_type in FlopType:
44
+ if flop_type not in v:
45
+ v[flop_type] = math.nan
46
46
  return v
47
47
 
48
48
  @field_serializer("weights")
@@ -103,14 +103,8 @@ class FlopWeights(MyBaseModel):
103
103
  As a reference duration, we take the geometric mean of the costs for EQUALS, ADD, SUB, and MUL operations.
104
104
  """
105
105
 
106
- # step 1) compute reference duration based on 4 simple flop types that should be about equally fast on most CPUs
107
- ref_values = [
108
- flop_costs[FlopType.EQUALS],
109
- flop_costs[FlopType.ADD],
110
- flop_costs[FlopType.SUB],
111
- flop_costs[FlopType.MUL],
112
- ]
113
- ref_cost = geo_mean([v for v in ref_values if not math.isnan(v)]) # ignore any missing data
106
+ # step 1) compute reference duration based on 1 simple flop type (SUB, MUL and a few others are usually very close)
107
+ ref_cost = flop_costs[FlopType.ADD]
114
108
 
115
109
  # step 2) normalize and construct FlopWeights object
116
110
  return FlopWeights(
@@ -43,7 +43,6 @@ class FlopsBenchmarkResults(MyBaseModel):
43
43
  benchmark_settings: BenchmarkSettings
44
44
  results_ns: FlopsBenchmarkDurations
45
45
 
46
- @property
47
46
  def flop_weights(self) -> FlopWeights:
48
47
  """
49
48
  Returns normalized weights for each flop type based on the benchmark results.
@@ -0,0 +1,146 @@
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ from typing import Annotated, Literal, Union
5
+
6
+ from pydantic import Field, model_validator
7
+
8
+ from ._base import MyBaseModel
9
+ from ._flop_type import FlopType
10
+ from ._flop_weights import FlopWeights
11
+
12
+
13
+ # =================================================================================================
14
+ # Single-Instruction Latency
15
+ # =================================================================================================
16
+ class Latency(MyBaseModel):
17
+ note: str = ""
18
+ min_cycles: float | None = None
19
+ max_cycles: float | None = None
20
+
21
+ def geo_mean(self) -> float:
22
+ """Calculate the geometric mean of min and max cycles."""
23
+ if (self.min_cycles is None) or (self.max_cycles is None):
24
+ return math.nan
25
+ else:
26
+ return math.sqrt(self.min_cycles * self.max_cycles)
27
+
28
+ @model_validator(mode="before")
29
+ @classmethod
30
+ def check_min_max_cycles(cls, values):
31
+ # Fill in missing values if just 1 of 2 is missing
32
+ # (assuming min=max; which is making the least assumptions, as this is the case in most instructions)
33
+ if (values.get("min_cycles") is None) and (values.get("max_cycles") is not None):
34
+ values["min_cycles"] = values["max_cycles"]
35
+ elif (values.get("min_cycles") is not None) and (values.get("max_cycles") is None):
36
+ values["max_cycles"] = values["min_cycles"]
37
+
38
+ # Avoid 0 values. (which in principle can happen in corner cases, but which confuses our analysis)
39
+ if values.get("min_cycles") is not None:
40
+ values["min_cycles"] = max(1.0, values["min_cycles"])
41
+ if values.get("max_cycles") is not None:
42
+ values["max_cycles"] = max(1.0, values["max_cycles"])
43
+
44
+ # Return processed values
45
+ return values
46
+
47
+
48
+ # =================================================================================================
49
+ # InstructionLatencies - SSE2
50
+ # =================================================================================================
51
+ class InstructionLatencies_SSE2(MyBaseModel):
52
+ # SEE: https://github.com/bertpl/counted-float/tree/develop/counted_float/data/fpu_data_sources.md
53
+
54
+ # --- primary fields ----------------------------------
55
+ architecture: Literal["sse2"] = "sse2"
56
+
57
+ ANDPD: Latency = Latency() # abs(x)
58
+ CVTSD2SI: Latency = Latency() # double -> int
59
+ CVTSI2SD: Latency = Latency() # int -> double
60
+ XORPD: Latency = Latency() # -x
61
+ UCOMISD: Latency = Latency() # x < == > y, x < == > 0 NOTE: should be ranges of UCOMISD & COMISD merged
62
+ MAXSD: Latency = Latency() # max(x,y)
63
+ MINSD: Latency = Latency() # min(x,y)
64
+ ADDSD: Latency = Latency() # x+y
65
+ SUBSD: Latency = Latency() # x-y
66
+ MULSD: Latency = Latency() # x*y
67
+ DIVSD: Latency = Latency() # x/y
68
+ SQRTSD: Latency = Latency() # sqrt(x)
69
+
70
+ # --- helpers -----------------------------------------
71
+ def flop_weights(self) -> FlopWeights:
72
+ return FlopWeights.from_abs_flop_costs(
73
+ {
74
+ FlopType.ABS: self.ANDPD.geo_mean(),
75
+ FlopType.MINUS: self.XORPD.geo_mean(),
76
+ FlopType.EQUALS: self.UCOMISD.geo_mean(),
77
+ FlopType.GTE: self.UCOMISD.geo_mean(),
78
+ FlopType.LTE: self.UCOMISD.geo_mean(),
79
+ FlopType.CMP_ZERO: self.UCOMISD.geo_mean(),
80
+ FlopType.RND: self.CVTSD2SI.geo_mean(),
81
+ FlopType.ADD: self.ADDSD.geo_mean(),
82
+ FlopType.SUB: self.SUBSD.geo_mean(),
83
+ FlopType.MUL: self.MULSD.geo_mean(),
84
+ FlopType.DIV: self.DIVSD.geo_mean(),
85
+ FlopType.SQRT: self.SQRTSD.geo_mean(),
86
+ }
87
+ )
88
+
89
+
90
+ # =================================================================================================
91
+ # InstructionLatencies - ARM
92
+ # =================================================================================================
93
+ class InstructionLatencies_ARM(MyBaseModel):
94
+ # SEE: https://github.com/bertpl/counted-float/tree/develop/counted_float/data/fpu_data_sources.md
95
+
96
+ # --- primary fields ----------------------------------
97
+ architecture: Literal["arm"] = "arm"
98
+
99
+ FABS: Latency = Latency() # abs(x)
100
+ FCVTZS: Latency = Latency() # double -> int
101
+ SCVTF: Latency = Latency() # int -> double
102
+ FNEG: Latency = Latency() # -x
103
+ FCMP: Latency = Latency() # x < == > y, x < == > 0
104
+ FMAX: Latency = Latency() # max(x,y)
105
+ FMIN: Latency = Latency() # min(x,y)
106
+ FADD: Latency = Latency() # x+y
107
+ FSUB: Latency = Latency() # x-y
108
+ FMUL: Latency = Latency() # x*y
109
+ FDIV: Latency = Latency() # x/y
110
+ FSQRT: Latency = Latency() # sqrt(x)
111
+
112
+ # --- helpers -----------------------------------------
113
+ def flop_weights(self) -> FlopWeights:
114
+ return FlopWeights.from_abs_flop_costs(
115
+ {
116
+ FlopType.ABS: self.FABS.geo_mean(),
117
+ FlopType.MINUS: self.FNEG.geo_mean(),
118
+ FlopType.EQUALS: self.FCMP.geo_mean(),
119
+ FlopType.GTE: self.FCMP.geo_mean(),
120
+ FlopType.LTE: self.FCMP.geo_mean(),
121
+ FlopType.CMP_ZERO: self.FCMP.geo_mean(),
122
+ FlopType.RND: self.FCVTZS.geo_mean(),
123
+ FlopType.ADD: self.FADD.geo_mean(),
124
+ FlopType.SUB: self.FSUB.geo_mean(),
125
+ FlopType.MUL: self.FMUL.geo_mean(),
126
+ FlopType.DIV: self.FDIV.geo_mean(),
127
+ FlopType.SQRT: self.FSQRT.geo_mean(),
128
+ }
129
+ )
130
+
131
+
132
+ # =================================================================================================
133
+ # Union Class
134
+ # =================================================================================================
135
+ class InstructionLatencies(MyBaseModel):
136
+ notes: list[str] | None = [""]
137
+ latencies: Annotated[
138
+ Union[
139
+ InstructionLatencies_SSE2,
140
+ InstructionLatencies_ARM,
141
+ ],
142
+ Field(discriminator="architecture"),
143
+ ]
144
+
145
+ def flop_weights(self) -> FlopWeights:
146
+ return self.latencies.flop_weights()
@@ -2,51 +2,69 @@
2
2
  "notes": [
3
3
  "Data taken from:",
4
4
  "https://developer.arm.com/documentation/PJDOC-466751330-7215/latest/",
5
- "FPU data processing instructions - aarch64 - exec latency",
6
- "FCHS=FNEG, FTST=FCMPZ, FRNDINT=FCVT"
5
+ "FPU data processing instructions - aarch64 - exec latency"
7
6
  ],
8
7
  "latencies": {
8
+ "architecture": "arm",
9
9
  "FABS": {
10
+ "notes": "",
10
11
  "min_cycles": 2,
11
12
  "max_cycles": 2
12
13
  },
13
- "FCHS": {
14
+ "FCVTZS": {
15
+ "notes": "",
16
+ "min_cycles": 4,
17
+ "max_cycles": 4
18
+ },
19
+ "SCVTF": {
20
+ "notes": "",
21
+ "min_cycles": 6,
22
+ "max_cycles": 6
23
+ },
24
+ "FNEG": {
25
+ "notes": "",
14
26
  "min_cycles": 2,
15
27
  "max_cycles": 2
16
28
  },
17
- "FCOM": {
29
+ "FCMP": {
30
+ "notes": "",
18
31
  "min_cycles": 2,
19
32
  "max_cycles": 2
20
33
  },
21
- "FTST": {
34
+ "FMAX": {
35
+ "notes": "",
22
36
  "min_cycles": 2,
23
37
  "max_cycles": 2
24
38
  },
25
- "FRNDINT": {
26
- "min_cycles": 3,
27
- "max_cycles": 3
39
+ "FMIN": {
40
+ "notes": "",
41
+ "min_cycles": 2,
42
+ "max_cycles": 2
28
43
  },
29
44
  "FADD": {
45
+ "notes": "",
30
46
  "min_cycles": 2,
31
47
  "max_cycles": 2
32
48
  },
33
49
  "FSUB": {
50
+ "notes": "",
34
51
  "min_cycles": 2,
35
52
  "max_cycles": 2
36
53
  },
37
54
  "FMUL": {
55
+ "notes": "",
38
56
  "min_cycles": 3,
39
57
  "max_cycles": 3
40
58
  },
41
59
  "FDIV": {
60
+ "notes": "",
42
61
  "min_cycles": 7,
43
62
  "max_cycles": 15
44
63
  },
45
64
  "FSQRT": {
65
+ "notes": "",
46
66
  "min_cycles": 7,
47
67
  "max_cycles": 17
48
- },
49
- "F2XM1": null,
50
- "FYL2X": null
68
+ }
51
69
  }
52
70
  }
@@ -0,0 +1,70 @@
1
+ {
2
+ "notes": [
3
+ "Data taken from:",
4
+ "https://developer.arm.com/documentation/109896/0400/",
5
+ "FPU data processing instructions - aarch64 - exec latency"
6
+ ],
7
+ "latencies": {
8
+ "architecture": "arm",
9
+ "FABS": {
10
+ "notes": "",
11
+ "min_cycles": 2,
12
+ "max_cycles": 2
13
+ },
14
+ "FCVTZS": {
15
+ "notes": "",
16
+ "min_cycles": 4,
17
+ "max_cycles": 4
18
+ },
19
+ "SCVTF": {
20
+ "notes": "",
21
+ "min_cycles": 6,
22
+ "max_cycles": 6
23
+ },
24
+ "FNEG": {
25
+ "notes": "",
26
+ "min_cycles": 2,
27
+ "max_cycles": 2
28
+ },
29
+ "FCMP": {
30
+ "notes": "",
31
+ "min_cycles": 2,
32
+ "max_cycles": 2
33
+ },
34
+ "FMAX": {
35
+ "notes": "",
36
+ "min_cycles": 2,
37
+ "max_cycles": 2
38
+ },
39
+ "FMIN": {
40
+ "notes": "",
41
+ "min_cycles": 2,
42
+ "max_cycles": 2
43
+ },
44
+ "FADD": {
45
+ "notes": "",
46
+ "min_cycles": 2,
47
+ "max_cycles": 2
48
+ },
49
+ "FSUB": {
50
+ "notes": "",
51
+ "min_cycles": 2,
52
+ "max_cycles": 2
53
+ },
54
+ "FMUL": {
55
+ "notes": "",
56
+ "min_cycles": 3,
57
+ "max_cycles": 3
58
+ },
59
+ "FDIV": {
60
+ "notes": "",
61
+ "min_cycles": 7,
62
+ "max_cycles": 15
63
+ },
64
+ "FSQRT": {
65
+ "notes": "",
66
+ "min_cycles": 7,
67
+ "max_cycles": 17
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,70 @@
1
+ {
2
+ "notes": [
3
+ "Data taken from:",
4
+ "https://developer.arm.com/documentation/109897/0600/",
5
+ "FPU data processing instructions - aarch64 - exec latency"
6
+ ],
7
+ "latencies": {
8
+ "architecture": "arm",
9
+ "FABS": {
10
+ "notes": "",
11
+ "min_cycles": 2,
12
+ "max_cycles": 2
13
+ },
14
+ "FCVTZS": {
15
+ "notes": "",
16
+ "min_cycles": 3,
17
+ "max_cycles": 3
18
+ },
19
+ "SCVTF": {
20
+ "notes": "",
21
+ "min_cycles": 3,
22
+ "max_cycles": 3
23
+ },
24
+ "FNEG": {
25
+ "notes": "",
26
+ "min_cycles": 2,
27
+ "max_cycles": 2
28
+ },
29
+ "FCMP": {
30
+ "notes": "",
31
+ "min_cycles": 2,
32
+ "max_cycles": 2
33
+ },
34
+ "FMAX": {
35
+ "notes": "",
36
+ "min_cycles": 2,
37
+ "max_cycles": 2
38
+ },
39
+ "FMIN": {
40
+ "notes": "",
41
+ "min_cycles": 2,
42
+ "max_cycles": 2
43
+ },
44
+ "FADD": {
45
+ "notes": "",
46
+ "min_cycles": 2,
47
+ "max_cycles": 2
48
+ },
49
+ "FSUB": {
50
+ "notes": "",
51
+ "min_cycles": 2,
52
+ "max_cycles": 2
53
+ },
54
+ "FMUL": {
55
+ "notes": "",
56
+ "min_cycles": 3,
57
+ "max_cycles": 3
58
+ },
59
+ "FDIV": {
60
+ "notes": "",
61
+ "min_cycles": 7,
62
+ "max_cycles": 15
63
+ },
64
+ "FSQRT": {
65
+ "notes": "",
66
+ "min_cycles": 7,
67
+ "max_cycles": 16
68
+ }
69
+ }
70
+ }
@@ -2,51 +2,69 @@
2
2
  "notes": [
3
3
  "Data taken from:",
4
4
  "https://developer.arm.com/documentation/102174/latest/",
5
- "FPU data processing instructions - aarch64 - exec latency",
6
- "FCHS=FNEG, FTST=FCMPZ, FRNDINT=FCVT"
5
+ "FPU data processing instructions - aarch64 - exec latency"
7
6
  ],
8
7
  "latencies": {
8
+ "architecture": "arm",
9
9
  "FABS": {
10
+ "notes": "",
10
11
  "min_cycles": 2,
11
12
  "max_cycles": 2
12
13
  },
13
- "FCHS": {
14
+ "FCVTZS": {
15
+ "notes": "",
16
+ "min_cycles": 3,
17
+ "max_cycles": 3
18
+ },
19
+ "SCVTF": {
20
+ "notes": "",
21
+ "min_cycles": 3,
22
+ "max_cycles": 3
23
+ },
24
+ "FNEG": {
25
+ "notes": "",
14
26
  "min_cycles": 2,
15
27
  "max_cycles": 2
16
28
  },
17
- "FCOM": {
29
+ "FCMP": {
30
+ "notes": "",
18
31
  "min_cycles": 2,
19
32
  "max_cycles": 2
20
33
  },
21
- "FTST": {
34
+ "FMAX": {
35
+ "notes": "",
22
36
  "min_cycles": 2,
23
37
  "max_cycles": 2
24
38
  },
25
- "FRNDINT": {
26
- "min_cycles": 3,
27
- "max_cycles": 3
39
+ "FMIN": {
40
+ "notes": "",
41
+ "min_cycles": 2,
42
+ "max_cycles": 2
28
43
  },
29
44
  "FADD": {
45
+ "notes": "",
30
46
  "min_cycles": 2,
31
47
  "max_cycles": 2
32
48
  },
33
49
  "FSUB": {
50
+ "notes": "",
34
51
  "min_cycles": 2,
35
52
  "max_cycles": 2
36
53
  },
37
54
  "FMUL": {
55
+ "notes": "",
38
56
  "min_cycles": 3,
39
57
  "max_cycles": 3
40
58
  },
41
59
  "FDIV": {
60
+ "notes": "",
42
61
  "min_cycles": 7,
43
62
  "max_cycles": 15
44
63
  },
45
64
  "FSQRT": {
65
+ "notes": "",
46
66
  "min_cycles": 7,
47
67
  "max_cycles": 16
48
- },
49
- "F2XM1": null,
50
- "FYL2X": null
68
+ }
51
69
  }
52
70
  }