coreml-complexity-analyzer 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2025, Devavarapu Yashwanth, Ireddi Rakshitha. All rights reserved.
2
+ #
3
+ # Use of this source code is governed by a BSD-3-clause license that can be
4
+ # found in the LICENSE file.
5
+
6
+ """
7
+ Model Complexity Analyzer for Core ML Models.
8
+
9
+ Provides FLOPS estimation, memory footprint analysis, and
10
+ detailed per-layer profiling for Core ML models.
11
+ """
12
+
13
+ __version__ = "0.1.0"
14
+
15
+ from .flops_analyzer import FLOPSAnalyzer, LayerFLOPS
16
+ from .memory_estimator import MemoryEstimator, MemoryBreakdown
17
+ from .compute_cost_report import ComputeCostReport, generate_report
18
+ from .layer_profiler import LayerProfiler, LayerProfile
19
+
20
+ __all__ = [
21
+ "FLOPSAnalyzer",
22
+ "LayerFLOPS",
23
+ "MemoryEstimator",
24
+ "MemoryBreakdown",
25
+ "ComputeCostReport",
26
+ "generate_report",
27
+ "LayerProfiler",
28
+ "LayerProfile",
29
+ ]
@@ -0,0 +1,214 @@
1
+ # Copyright (c) 2025, Devavarapu Yashwanth, Ireddi Rakshitha. All rights reserved.
2
+ #
3
+ # Use of this source code is governed by a BSD-3-clause license that can be
4
+ # found in the LICENSE file.
5
+
6
+ """
7
+ Compute Cost Report Generator for Core ML Models.
8
+
9
+ Generates human-readable reports summarizing model complexity metrics
10
+ including FLOPS, memory, and computational cost analysis.
11
+ """
12
+
13
+ from dataclasses import dataclass, field
14
+ from typing import Dict, List, Optional, Any
15
+ from datetime import datetime
16
+
17
+ from .flops_analyzer import FLOPSAnalyzer, LayerFLOPS
18
+ from .memory_estimator import MemoryEstimator, MemoryBreakdown
19
+
20
+
21
+ @dataclass
22
+ class ComputeCostReport:
23
+ """Complete compute cost report for a Core ML model."""
24
+
25
+ model_name: str
26
+ total_flops: int
27
+ total_mac_ops: int
28
+ total_parameters: int
29
+ memory_breakdown: MemoryBreakdown
30
+ layer_breakdown: List[LayerFLOPS]
31
+ flops_by_op_type: Dict[str, int]
32
+ generated_at: str = field(default_factory=lambda: datetime.now().isoformat())
33
+
34
+ @property
35
+ def total_gflops(self) -> float:
36
+ """Total FLOPS in billions."""
37
+ return self.total_flops / 1e9
38
+
39
+ @property
40
+ def total_mflops(self) -> float:
41
+ """Total FLOPS in millions."""
42
+ return self.total_flops / 1e6
43
+
44
+ @property
45
+ def parameters_millions(self) -> float:
46
+ """Parameters in millions."""
47
+ return self.total_parameters / 1e6
48
+
49
+ def to_dict(self) -> Dict[str, Any]:
50
+ """Convert report to dictionary."""
51
+ return {
52
+ "model_name": self.model_name,
53
+ "generated_at": self.generated_at,
54
+ "summary": {
55
+ "total_flops": self.total_flops,
56
+ "total_gflops": self.total_gflops,
57
+ "total_mac_ops": self.total_mac_ops,
58
+ "total_parameters": self.total_parameters,
59
+ "parameters_millions": self.parameters_millions,
60
+ },
61
+ "memory": self.memory_breakdown.to_dict(),
62
+ "flops_by_op_type": self.flops_by_op_type,
63
+ "top_layers": [
64
+ {
65
+ "name": layer.name,
66
+ "op_type": layer.op_type,
67
+ "flops": layer.flops,
68
+ "mflops": layer.mflops,
69
+ }
70
+ for layer in self.layer_breakdown[:10]
71
+ ],
72
+ }
73
+
74
+ def to_markdown(self) -> str:
75
+ """Generate a markdown formatted report."""
76
+ lines = [
77
+ f"# Model Complexity Report: {self.model_name}",
78
+ "",
79
+ f"*Generated at: {self.generated_at}*",
80
+ "",
81
+ "## Summary",
82
+ "",
83
+ "| Metric | Value |",
84
+ "|--------|-------|",
85
+ f"| Total FLOPS | {self.total_flops:,} |",
86
+ f"| Total GFLOPS | {self.total_gflops:.2f} |",
87
+ f"| Total MAC Ops | {self.total_mac_ops:,} |",
88
+ f"| Total Parameters | {self.total_parameters:,} |",
89
+ f"| Parameters (M) | {self.parameters_millions:.2f} |",
90
+ "",
91
+ "## Memory Analysis",
92
+ "",
93
+ "| Component | Size |",
94
+ "|-----------|------|",
95
+ f"| Total Memory | {self.memory_breakdown.total_mb:.2f} MB |",
96
+ f"| Parameter Memory | {self.memory_breakdown.parameter_mb:.2f} MB |",
97
+ f"| Activation Memory | {self.memory_breakdown.activation_mb:.2f} MB |",
98
+ f"| Overhead | {self.memory_breakdown.overhead_bytes / (1024*1024):.2f} MB |",
99
+ "",
100
+ "## FLOPS by Operation Type",
101
+ "",
102
+ "| Operation | FLOPS | Percentage |",
103
+ "|-----------|-------|------------|",
104
+ ]
105
+
106
+ for op_type, flops in list(self.flops_by_op_type.items())[:15]:
107
+ percentage = (
108
+ (flops / self.total_flops * 100) if self.total_flops > 0 else 0
109
+ )
110
+ lines.append(f"| {op_type} | {flops:,} | {percentage:.1f}% |")
111
+
112
+ lines.extend(
113
+ [
114
+ "",
115
+ "## Top 10 Layers by FLOPS",
116
+ "",
117
+ "| Layer | Type | FLOPS | MFLOPS |",
118
+ "|-------|------|-------|--------|",
119
+ ]
120
+ )
121
+
122
+ for layer in self.layer_breakdown[:10]:
123
+ lines.append(
124
+ f"| {layer.name[:40]} | {layer.op_type} | "
125
+ f"{layer.flops:,} | {layer.mflops:.2f} |"
126
+ )
127
+
128
+ return "\n".join(lines)
129
+
130
+ def to_text(self) -> str:
131
+ """Generate a plain text report."""
132
+ separator = "=" * 60
133
+ lines = [
134
+ separator,
135
+ f"Model Complexity Report: {self.model_name}",
136
+ separator,
137
+ f"Generated: {self.generated_at}",
138
+ "",
139
+ "SUMMARY",
140
+ "-" * 40,
141
+ f" Total FLOPS: {self.total_flops:>15,}",
142
+ f" Total GFLOPS: {self.total_gflops:>15.2f}",
143
+ f" Total MAC Ops: {self.total_mac_ops:>15,}",
144
+ f" Parameters: {self.total_parameters:>15,}",
145
+ f" Parameters (M): {self.parameters_millions:>15.2f}",
146
+ "",
147
+ "MEMORY ANALYSIS",
148
+ "-" * 40,
149
+ f" Total Memory: {self.memory_breakdown.total_mb:>12.2f} MB",
150
+ f" Parameters: {self.memory_breakdown.parameter_mb:>12.2f} MB",
151
+ f" Activations: {self.memory_breakdown.activation_mb:>12.2f} MB",
152
+ "",
153
+ "TOP OPERATIONS BY FLOPS",
154
+ "-" * 40,
155
+ ]
156
+
157
+ for op_type, flops in list(self.flops_by_op_type.items())[:10]:
158
+ percentage = (
159
+ (flops / self.total_flops * 100) if self.total_flops > 0 else 0
160
+ )
161
+ lines.append(f" {op_type:<20} {flops:>12,} ({percentage:>5.1f}%)")
162
+
163
+ lines.extend(["", separator])
164
+
165
+ return "\n".join(lines)
166
+
167
+
168
+ def generate_report(model, model_name: Optional[str] = None) -> ComputeCostReport:
169
+ """
170
+ Generate a comprehensive compute cost report for a Core ML model.
171
+
172
+ Parameters
173
+ ----------
174
+ model : MLModel or str
175
+ A loaded MLModel instance or path to a .mlmodel/.mlpackage file.
176
+ model_name : str, optional
177
+ Name to use in the report. Defaults to "Unnamed Model".
178
+
179
+ Returns
180
+ -------
181
+ ComputeCostReport
182
+ Complete report with FLOPS, memory, and layer breakdown.
183
+
184
+ Examples
185
+ --------
186
+ >>> import coremltools as ct
187
+ >>> from coreml_complexity_analyzer import generate_report
188
+ >>>
189
+ >>> model = ct.models.MLModel("my_model.mlpackage")
190
+ >>> report = generate_report(model, "MyModel")
191
+ >>> print(report.to_markdown())
192
+ >>>
193
+ >>> print(f"Total GFLOPS: {report.total_gflops:.2f}")
194
+ >>> print(f"Memory: {report.memory_breakdown.total_mb:.2f} MB")
195
+ """
196
+ if model_name is None:
197
+ model_name = "Unnamed Model"
198
+
199
+ flops_analyzer = FLOPSAnalyzer(model)
200
+ memory_estimator = MemoryEstimator(model)
201
+
202
+ layer_breakdown = flops_analyzer.analyze()
203
+ flops_by_op_type = flops_analyzer.get_flops_by_op_type()
204
+ memory_breakdown = memory_estimator.estimate()
205
+
206
+ return ComputeCostReport(
207
+ model_name=model_name,
208
+ total_flops=flops_analyzer.get_total_flops(),
209
+ total_mac_ops=flops_analyzer.get_total_mac_ops(),
210
+ total_parameters=memory_estimator.get_parameter_count(),
211
+ memory_breakdown=memory_breakdown,
212
+ layer_breakdown=layer_breakdown,
213
+ flops_by_op_type=flops_by_op_type,
214
+ )