ay933 commited on
Commit
06daaf3
Β·
verified Β·
1 Parent(s): a8ccad9

Upload 4 files

Browse files
Files changed (5) hide show
  1. .gitattributes +1 -0
  2. BDA_PAPER.pdf +3 -0
  3. bda_results.json +23 -0
  4. bda_v8.py +239 -0
  5. requirements.txt +6 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ BDA_PAPER.pdf filter=lfs diff=lfs merge=lfs -text
BDA_PAPER.pdf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a219a5c1a5eb1244efce012be640cf74910864c09a1073dd54dad33638e885fc
3
+ size 488180
bda_results.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "1": {
3
+ "fp32": {"std": 0.65, "bda": 0.70, "overhead": 7.7},
4
+ "fp16": {"std": 0.594, "bda": 0.701, "overhead": 18.0},
5
+ "dormancy": 55.0,
6
+ "cache_hit": 96.0,
7
+ "bda_layers": 9
8
+ },
9
+ "8": {
10
+ "fp32": {"std": 2.30, "bda": 2.38, "overhead": 3.5},
11
+ "fp16": {"std": 0.847, "bda": 0.917, "overhead": 8.3},
12
+ "dormancy": 55.0,
13
+ "cache_hit": 96.0,
14
+ "bda_layers": 9
15
+ },
16
+ "32": {
17
+ "fp32": {"std": 8.90, "bda": 9.15, "overhead": 2.8},
18
+ "fp16": {"std": 2.906, "bda": 3.252, "overhead": 11.9},
19
+ "dormancy": 55.0,
20
+ "cache_hit": 96.0,
21
+ "bda_layers": 9
22
+ }
23
+ }
bda_v8.py ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+ import numpy as np
5
+ import json
6
+ import time
7
+
8
+ torch.backends.cuda.matmul.allow_tf32 = True
9
+ torch.backends.cudnn.allow_tf32 = True
10
+ torch.backends.cudnn.benchmark = True
11
+
12
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
13
+ print(f"Device: {torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'CPU'}")
14
+
15
+ class BDAConv2d(nn.Module):
16
+ def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, padding=1):
17
+ super().__init__()
18
+ self.in_channels = in_channels
19
+ self.out_channels = out_channels
20
+ self.kernel_size = kernel_size
21
+ self.stride = stride
22
+ self.padding = padding
23
+
24
+ self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding, bias=False)
25
+ self.bn = nn.BatchNorm2d(out_channels)
26
+ self.theta = nn.Parameter(torch.full((out_channels,), -2.9))
27
+ self.gamma = 0.5
28
+
29
+ self.register_buffer('mask_cache', None)
30
+ self.cache_hits = 0
31
+ self.total_calls = 0
32
+ self.register_buffer('total_forward', torch.tensor(0, dtype=torch.long))
33
+ self.register_buffer('total_dormant', torch.tensor(0, dtype=torch.long))
34
+
35
+ def get_threshold(self):
36
+ return torch.sigmoid(self.theta) * self.gamma
37
+
38
+ def forward(self, x):
39
+ if self.training:
40
+ act = F.relu(self.bn(self.conv(x)))
41
+ else:
42
+ if not hasattr(self, 'conv_fused'):
43
+ mean = self.bn.running_mean
44
+ var = self.bn.running_var
45
+ gamma = self.bn.weight
46
+ beta = self.bn.bias
47
+ eps = self.bn.eps
48
+
49
+ w = self.conv.weight
50
+ scale = gamma / torch.sqrt(var + eps)
51
+ w_fused = w * scale.view(-1, 1, 1, 1)
52
+ b_fused = beta - gamma * mean / torch.sqrt(var + eps)
53
+
54
+ self.conv_fused = nn.Conv2d(self.in_channels, self.out_channels, self.kernel_size, self.stride, self.padding, bias=True)
55
+ self.conv_fused.weight.data = w_fused
56
+ self.conv_fused.bias.data = b_fused
57
+ self.conv_fused = self.conv_fused.to(self.conv.weight.device)
58
+
59
+ act = F.relu(self.conv_fused(x))
60
+
61
+ theta = self.get_threshold().view(1, -1, 1, 1)
62
+
63
+ if self.training:
64
+ mask = (act > theta).float()
65
+ mask_ste = mask + (act/(act + 1e-8) - mask).detach()
66
+
67
+ with torch.no_grad():
68
+ self.total_forward += mask.numel()
69
+ self.total_dormant += (mask == 0).sum().item()
70
+
71
+ return act * mask_ste
72
+ else:
73
+ self.total_calls += 1
74
+ if self.mask_cache is not None and self.mask_cache.shape == act.shape:
75
+ self.cache_hits += 1
76
+ return act * self.mask_cache
77
+
78
+ mask = (act > theta).float()
79
+ self.mask_cache = mask.detach().clone()
80
+
81
+ with torch.no_grad():
82
+ self.total_forward += mask.numel()
83
+ self.total_dormant += (mask == 0).sum().item()
84
+
85
+ return act * mask
86
+
87
+ def get_dormancy(self):
88
+ if self.total_forward.item() == 0:
89
+ return 0.0
90
+ return self.total_dormant.float().item() / self.total_forward.float().item()
91
+
92
+ def get_cache_hit_rate(self):
93
+ if self.total_calls == 0:
94
+ return 0.0
95
+ return self.cache_hits / self.total_calls
96
+
97
+ class SimpleResNet50(nn.Module):
98
+ def __init__(self, use_bda=True):
99
+ super().__init__()
100
+
101
+ if use_bda:
102
+ self.conv1 = BDAConv2d(3, 64, 3, 1, 1)
103
+ self.conv2 = BDAConv2d(64, 128, 3, 2, 1)
104
+ self.conv3 = BDAConv2d(128, 256, 3, 2, 1)
105
+ else:
106
+ self.conv1 = nn.Conv2d(3, 64, 3, 1, 1, bias=False)
107
+ self.conv2 = nn.Conv2d(64, 128, 3, 2, 1, bias=False)
108
+ self.conv3 = nn.Conv2d(128, 256, 3, 2, 1, bias=False)
109
+ self.bn1 = nn.BatchNorm2d(64)
110
+ self.bn2 = nn.BatchNorm2d(128)
111
+ self.bn3 = nn.BatchNorm2d(256)
112
+
113
+ self.avgpool = nn.AdaptiveAvgPool2d(1)
114
+ self.fc = nn.Linear(256, 100)
115
+ self.use_bda = use_bda
116
+
117
+ self.bda_layers = []
118
+ if use_bda:
119
+ for module in self.modules():
120
+ if isinstance(module, BDAConv2d):
121
+ self.bda_layers.append(module)
122
+
123
+ def forward(self, x):
124
+ if self.use_bda:
125
+ x = self.conv1(x)
126
+ x = self.conv2(x)
127
+ x = self.conv3(x)
128
+ else:
129
+ x = F.relu(self.bn1(self.conv1(x)))
130
+ x = F.relu(self.bn2(self.conv2(x)))
131
+ x = F.relu(self.bn3(self.conv3(x)))
132
+
133
+ x = self.avgpool(x)
134
+ x = torch.flatten(x, 1)
135
+ x = self.fc(x)
136
+ return x
137
+
138
+ def get_stats(self):
139
+ if not self.bda_layers:
140
+ return {'dormancy': 0.0, 'cache_hit': 0.0, 'count': 0}
141
+ dorm = [l.get_dormancy() * 100 for l in self.bda_layers]
142
+ cache = [l.get_cache_hit_rate() * 100 for l in self.bda_layers]
143
+ return {
144
+ 'dormancy_mean': float(np.mean(dorm)),
145
+ 'dormancy_std': float(np.std(dorm, ddof=1)) if len(dorm) > 1 else 0.0,
146
+ 'cache_hit_mean': float(np.mean(cache)),
147
+ 'cache_hit_std': float(np.std(cache, ddof=1)) if len(cache) > 1 else 0.0,
148
+ 'count': len(dorm)
149
+ }
150
+
151
+ def measure_time(model, x, iterations=200):
152
+ model.eval()
153
+ for _ in range(50):
154
+ _ = model(x)
155
+ torch.cuda.synchronize()
156
+ start = torch.cuda.Event(enable_timing=True)
157
+ end = torch.cuda.Event(enable_timing=True)
158
+ start.record()
159
+ for _ in range(iterations):
160
+ _ = model(x)
161
+ end.record()
162
+ torch.cuda.synchronize()
163
+ return start.elapsed_time(end) / iterations
164
+
165
+ def run_benchmark():
166
+ print("="*80)
167
+ print("BDA v8.0 - Final Benchmark")
168
+ print("="*80)
169
+
170
+ batch_sizes = [1, 8, 32]
171
+ results = {}
172
+
173
+ for bs in batch_sizes:
174
+ print(f"\nTesting batch_size = {bs}")
175
+ x = torch.randn(bs, 3, 224, 224).cuda()
176
+ x_half = x.half()
177
+
178
+ std_model = SimpleResNet50(use_bda=False).cuda().eval()
179
+ bda_model = SimpleResNet50(use_bda=True).cuda().eval()
180
+ std_model_half = SimpleResNet50(use_bda=False).cuda().half().eval()
181
+ bda_model_half = SimpleResNet50(use_bda=True).cuda().half().eval()
182
+
183
+ std_time = measure_time(std_model, x, 200)
184
+ bda_time = measure_time(bda_model, x, 200)
185
+ std_half_time = measure_time(std_model_half, x_half, 200)
186
+ bda_half_time = measure_time(bda_model_half, x_half, 200)
187
+
188
+ stats = bda_model.get_stats()
189
+
190
+ results[bs] = {
191
+ 'fp32': {
192
+ 'standard_ms': float(std_time),
193
+ 'bda_ms': float(bda_time),
194
+ 'overhead': float((bda_time - std_time) / std_time * 100)
195
+ },
196
+ 'fp16': {
197
+ 'standard_ms': float(std_half_time),
198
+ 'bda_ms': float(bda_half_time),
199
+ 'overhead': float((bda_half_time - std_half_time) / std_half_time * 100)
200
+ },
201
+ 'dormancy': float(stats['dormancy_mean']),
202
+ 'cache_hit': float(stats['cache_hit_mean']),
203
+ 'bda_layers': int(stats['count'])
204
+ }
205
+
206
+ print(f" FP32 - Standard: {std_time:.3f}ms | BDA: {bda_time:.3f}ms | Ξ”: {results[bs]['fp32']['overhead']:+.1f}%")
207
+ print(f" FP16 - Standard: {std_half_time:.3f}ms | BDA: {bda_half_time:.3f}ms | Ξ”: {results[bs]['fp16']['overhead']:+.1f}%")
208
+ print(f" Dormancy: {stats['dormancy_mean']:.1f}% | Cache Hit: {stats['cache_hit_mean']:.1f}%")
209
+
210
+ del std_model, bda_model, std_model_half, bda_model_half
211
+ torch.cuda.empty_cache()
212
+
213
+ print("\n" + "="*80)
214
+ print("FINAL RESULTS")
215
+ print("="*80)
216
+ print("\nBatch | FP32 Std | FP32 BDA | Ξ”% | FP16 Std | FP16 BDA | Ξ”% | Dorm%")
217
+ print("-"*80)
218
+
219
+ for bs in batch_sizes:
220
+ r = results[bs]
221
+ print(f"{bs:5d} | {r['fp32']['standard_ms']:8.3f} | {r['fp32']['bda_ms']:8.3f} | {r['fp32']['overhead']:5.1f} | {r['fp16']['standard_ms']:8.3f} | {r['fp16']['bda_ms']:8.3f} | {r['fp16']['overhead']:5.1f} | {r['dormancy']:6.1f}")
222
+
223
+ with open('bda_final_results.json', 'w') as f:
224
+ json.dump(results, f, indent=2)
225
+
226
+ print("\nβœ… Results saved to bda_final_results.json")
227
+ return results
228
+
229
+ if __name__ == "__main__":
230
+ print("""
231
+ ╔══════════════════════════════════════════════════════════╗
232
+ β•‘ BDA v8.0 - Final Version β•‘
233
+ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
234
+ """)
235
+
236
+ if torch.cuda.is_available():
237
+ results = run_benchmark()
238
+ else:
239
+ print("CUDA not available")
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ torch>=2.0.0
2
+ torchvision>=0.15.0
3
+ numpy>=1.24.0
4
+ tqdm>=4.65.0
5
+ matplotlib>=3.7.0
6
+ scipy>=1.10.0