memset0 commited on
Commit
ee38fef
·
verified ·
1 Parent(s): d0388d3

Add distill-math239k-coldstart-forward-kl-260430-172233/epoch_3_step_179601 (weights + config + modeling)

Browse files
distill-math239k-coldstart-forward-kl-260430-172233/config.json ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "DFlashDraftModel"
4
+ ],
5
+ "attention_bias": false,
6
+ "attention_dropout": 0.0,
7
+ "auto_map": {
8
+ "AutoModel": "dflash.DFlashDraftModel"
9
+ },
10
+ "block_size": 16,
11
+ "bos_token_id": 151643,
12
+ "dflash_config": {
13
+ "causal_head": true,
14
+ "mask_token_id": 151669,
15
+ "target_layer_ids": [
16
+ 1,
17
+ 9,
18
+ 17,
19
+ 25,
20
+ 33
21
+ ]
22
+ },
23
+ "dtype": "bfloat16",
24
+ "eos_token_id": 151645,
25
+ "head_dim": 128,
26
+ "hidden_act": "silu",
27
+ "hidden_size": 4096,
28
+ "initializer_range": 0.02,
29
+ "intermediate_size": 12288,
30
+ "layer_types": [
31
+ "full_attention",
32
+ "full_attention",
33
+ "full_attention",
34
+ "full_attention",
35
+ "full_attention"
36
+ ],
37
+ "max_position_embeddings": 40960,
38
+ "max_window_layers": 5,
39
+ "model_type": "qwen3",
40
+ "num_attention_heads": 32,
41
+ "num_hidden_layers": 5,
42
+ "num_key_value_heads": 8,
43
+ "num_target_layers": 36,
44
+ "rms_norm_eps": 1e-06,
45
+ "rope_scaling": null,
46
+ "rope_theta": 1000000,
47
+ "sliding_window": null,
48
+ "tie_word_embeddings": false,
49
+ "transformers_version": "4.57.1",
50
+ "use_cache": true,
51
+ "use_sliding_window": false,
52
+ "vocab_size": 151936
53
+ }
distill-math239k-coldstart-forward-kl-260430-172233/dflash.py ADDED
@@ -0,0 +1,449 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Callable, Optional
2
+
3
+ import torch
4
+ from torch import nn
5
+ from transformers import DynamicCache
6
+ from transformers.cache_utils import Cache
7
+ from transformers.modeling_outputs import CausalLMOutputWithPast
8
+ from transformers.models.qwen3.modeling_qwen3 import (
9
+ ALL_ATTENTION_FUNCTIONS,
10
+ FlashAttentionKwargs,
11
+ GradientCheckpointingLayer,
12
+ Qwen3Config,
13
+ Qwen3MLP,
14
+ Qwen3PreTrainedModel,
15
+ Qwen3RMSNorm,
16
+ Qwen3RotaryEmbedding,
17
+ eager_attention_forward,
18
+ rotate_half,
19
+ )
20
+ from typing_extensions import Tuple, Unpack
21
+
22
+
23
+ def sample(logits: torch.Tensor, temperature: float = 0.0) -> torch.Tensor:
24
+ if temperature < 1e-5:
25
+ return torch.argmax(logits, dim=-1)
26
+ bsz, seq_len, vocab_size = logits.shape
27
+ logits = logits.view(-1, vocab_size)
28
+ logits = logits / temperature
29
+ probs = torch.softmax(logits, dim=-1)
30
+ return torch.multinomial(probs, num_samples=1).view(bsz, seq_len)
31
+
32
+
33
+ def apply_rotary_pos_emb(q, k, cos, sin, position_ids=None, unsqueeze_dim=1):
34
+ cos = cos.unsqueeze(unsqueeze_dim)
35
+ sin = sin.unsqueeze(unsqueeze_dim)
36
+ q_len = q.size(-2)
37
+ q_embed = (q * cos[..., -q_len:, :]) + (rotate_half(q) * sin[..., -q_len:, :])
38
+ k_embed = (k * cos) + (rotate_half(k) * sin)
39
+ return q_embed, k_embed
40
+
41
+
42
+ def _to_additive_attention_mask(
43
+ attention_mask: torch.Tensor,
44
+ *,
45
+ query_dtype: torch.dtype,
46
+ device: torch.device,
47
+ key_len: int,
48
+ ) -> torch.Tensor:
49
+ if attention_mask.ndim == 4:
50
+ attention_mask = attention_mask[:, :, :, :key_len]
51
+ if attention_mask.dtype == torch.bool:
52
+ additive_mask = torch.zeros_like(attention_mask, dtype=query_dtype, device=device)
53
+ return additive_mask.masked_fill(
54
+ attention_mask.logical_not().to(device=device),
55
+ torch.finfo(query_dtype).min,
56
+ )
57
+ return attention_mask.to(device=device, dtype=query_dtype)
58
+
59
+
60
+ def _build_dflash_causal_attention_mask(
61
+ *,
62
+ query: torch.Tensor,
63
+ key: torch.Tensor,
64
+ cached_kv_len: int,
65
+ ctx_len: int,
66
+ ) -> torch.Tensor:
67
+ q_len = query.shape[-2]
68
+ kv_len = key.shape[-2]
69
+ key_positions = torch.arange(kv_len, device=query.device)
70
+ query_positions = cached_kv_len + ctx_len + torch.arange(q_len, device=query.device)
71
+ can_attend = key_positions.unsqueeze(0) <= query_positions.unsqueeze(1)
72
+ mask = torch.zeros((1, 1, q_len, kv_len), dtype=query.dtype, device=query.device)
73
+ return mask.masked_fill(can_attend.logical_not().unsqueeze(0).unsqueeze(0), torch.finfo(query.dtype).min)
74
+
75
+
76
+ class Qwen3DFlashAttention(nn.Module):
77
+ """Multi-headed attention from 'Attention Is All You Need' paper"""
78
+
79
+ def __init__(self, config: Qwen3Config, layer_idx: int):
80
+ super().__init__()
81
+ self.config = config
82
+ self.layer_idx = layer_idx
83
+ self.head_dim = getattr(
84
+ config, "head_dim", config.hidden_size // config.num_attention_heads
85
+ )
86
+ self.num_key_value_groups = (
87
+ config.num_attention_heads // config.num_key_value_heads
88
+ )
89
+ self.scaling = self.head_dim**-0.5
90
+ self.attention_dropout = config.attention_dropout
91
+ dflash_config = getattr(config, "dflash_config", {}) or {}
92
+ self.is_causal = bool(dflash_config.get("causal_head", False))
93
+ self.q_proj = nn.Linear(
94
+ config.hidden_size,
95
+ config.num_attention_heads * self.head_dim,
96
+ bias=config.attention_bias,
97
+ )
98
+ self.k_proj = nn.Linear(
99
+ config.hidden_size,
100
+ config.num_key_value_heads * self.head_dim,
101
+ bias=config.attention_bias,
102
+ )
103
+ self.v_proj = nn.Linear(
104
+ config.hidden_size,
105
+ config.num_key_value_heads * self.head_dim,
106
+ bias=config.attention_bias,
107
+ )
108
+ self.o_proj = nn.Linear(
109
+ config.num_attention_heads * self.head_dim,
110
+ config.hidden_size,
111
+ bias=config.attention_bias,
112
+ )
113
+ self.q_norm = Qwen3RMSNorm(self.head_dim, eps=config.rms_norm_eps)
114
+ self.k_norm = Qwen3RMSNorm(self.head_dim, eps=config.rms_norm_eps)
115
+ self.sliding_window = (
116
+ config.sliding_window
117
+ if config.layer_types[layer_idx] == "sliding_attention"
118
+ else None
119
+ )
120
+
121
+ def forward(
122
+ self,
123
+ hidden_states: torch.Tensor,
124
+ target_hidden: torch.Tensor,
125
+ position_embeddings: tuple[torch.Tensor, torch.Tensor],
126
+ attention_mask: Optional[torch.Tensor],
127
+ past_key_values: Optional[Cache] = None,
128
+ cache_position: Optional[torch.LongTensor] = None,
129
+ **kwargs: Unpack[FlashAttentionKwargs],
130
+ ) -> tuple[torch.Tensor, Optional[torch.Tensor]]:
131
+ bsz, q_len = hidden_states.shape[:-1]
132
+ ctx_len = target_hidden.shape[1]
133
+ is_causal = kwargs.pop("is_causal", None)
134
+ if is_causal is None:
135
+ is_causal = self.is_causal
136
+ q = self.q_proj(hidden_states)
137
+ q = q.view(bsz, q_len, -1, self.head_dim)
138
+ q = self.q_norm(q).transpose(1, 2)
139
+ k_ctx = self.k_proj(target_hidden)
140
+ k_noise = self.k_proj(hidden_states)
141
+ v_ctx = self.v_proj(target_hidden)
142
+ v_noise = self.v_proj(hidden_states)
143
+ k = torch.cat([k_ctx, k_noise], dim=1).view(
144
+ bsz, ctx_len + q_len, -1, self.head_dim
145
+ )
146
+ v = torch.cat([v_ctx, v_noise], dim=1).view(
147
+ bsz, ctx_len + q_len, -1, self.head_dim
148
+ )
149
+ k = self.k_norm(k).transpose(1, 2)
150
+ v = v.transpose(1, 2)
151
+ cos, sin = position_embeddings
152
+ q, k = apply_rotary_pos_emb(q, k, cos, sin)
153
+ cached_kv_len = past_key_values.get_seq_length() if past_key_values is not None else 0
154
+ if past_key_values is not None:
155
+ cache_kwargs = {"sin": sin, "cos": cos, "cache_position": cache_position}
156
+ k, v = past_key_values.update(k, v, self.layer_idx, cache_kwargs)
157
+
158
+ attn_backend = self.config._attn_implementation
159
+ use_explicit_dflash_causal_mask = bool(is_causal) and attn_backend in {"eager", "sdpa"}
160
+ if use_explicit_dflash_causal_mask:
161
+ dflash_causal_mask = _build_dflash_causal_attention_mask(
162
+ query=q, key=k, cached_kv_len=cached_kv_len, ctx_len=ctx_len,
163
+ )
164
+ if attention_mask is not None:
165
+ dflash_causal_mask = dflash_causal_mask + _to_additive_attention_mask(
166
+ attention_mask, query_dtype=q.dtype, device=q.device, key_len=k.shape[-2],
167
+ )
168
+ attention_mask = dflash_causal_mask
169
+ is_causal = False
170
+
171
+ kwargs["is_causal"] = is_causal
172
+
173
+ attn_fn: Callable = eager_attention_forward
174
+ if self.config._attn_implementation != "eager":
175
+ attn_fn = ALL_ATTENTION_FUNCTIONS[self.config._attn_implementation]
176
+ attn_output, attn_weights = attn_fn(
177
+ self,
178
+ q,
179
+ k,
180
+ v,
181
+ attention_mask,
182
+ dropout=0.0 if not self.training else self.attention_dropout,
183
+ scaling=self.scaling,
184
+ sliding_window=self.sliding_window,
185
+ **kwargs,
186
+ )
187
+ attn_output = attn_output.reshape(bsz, q_len, -1)
188
+ attn_output = self.o_proj(attn_output)
189
+ return attn_output, attn_weights
190
+
191
+
192
+ class Qwen3DFlashDecoderLayer(GradientCheckpointingLayer):
193
+ def __init__(self, config: Qwen3Config, layer_idx: int):
194
+ super().__init__()
195
+ self.hidden_size = config.hidden_size
196
+ self.self_attn = Qwen3DFlashAttention(config=config, layer_idx=layer_idx)
197
+ self.mlp = Qwen3MLP(config)
198
+ self.input_layernorm = Qwen3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
199
+ self.post_attention_layernorm = Qwen3RMSNorm(
200
+ config.hidden_size, eps=config.rms_norm_eps
201
+ )
202
+
203
+ def forward(
204
+ self,
205
+ target_hidden: Optional[torch.Tensor] = None,
206
+ hidden_states: Optional[torch.Tensor] = None,
207
+ attention_mask: Optional[torch.Tensor] = None,
208
+ position_ids: Optional[torch.LongTensor] = None,
209
+ past_key_value: Optional[Cache] = None,
210
+ output_attentions: Optional[bool] = False,
211
+ use_cache: Optional[bool] = False,
212
+ cache_position: Optional[torch.LongTensor] = None,
213
+ position_embeddings: Optional[
214
+ Tuple[torch.Tensor, torch.Tensor]
215
+ ] = None, # necessary, but kept here for BC
216
+ **kwargs: Unpack[FlashAttentionKwargs],
217
+ ) -> Tuple[
218
+ torch.FloatTensor, Optional[Tuple[torch.FloatTensor, torch.FloatTensor]]
219
+ ]:
220
+ residual = hidden_states
221
+ hidden_states = self.input_layernorm(hidden_states)
222
+ hidden_states = self.self_attn(
223
+ hidden_states=hidden_states,
224
+ target_hidden=target_hidden,
225
+ attention_mask=attention_mask,
226
+ position_ids=position_ids,
227
+ past_key_values=past_key_value,
228
+ output_attentions=output_attentions,
229
+ use_cache=use_cache,
230
+ cache_position=cache_position,
231
+ position_embeddings=position_embeddings,
232
+ **kwargs,
233
+ )[0]
234
+ hidden_states = residual + hidden_states
235
+ residual = hidden_states
236
+ hidden_states = self.post_attention_layernorm(hidden_states)
237
+ hidden_states = self.mlp(hidden_states)
238
+ hidden_states = residual + hidden_states
239
+ return hidden_states
240
+
241
+
242
+ def build_target_layer_ids(num_target_layers: int, num_draft_layers: int):
243
+ if num_draft_layers == 1:
244
+ return [(num_target_layers // 2)]
245
+ start = 1
246
+ end = num_target_layers - 3
247
+ span = end - start
248
+ target_layer_ids = [
249
+ int(round(start + (i * span) / (num_draft_layers - 1)))
250
+ for i in range(num_draft_layers)
251
+ ]
252
+ return target_layer_ids
253
+
254
+
255
+ def extract_context_feature(
256
+ hidden_states: list[torch.Tensor],
257
+ layer_ids: Optional[list[int]],
258
+ ) -> torch.Tensor:
259
+ offset = 1
260
+ selected_states = []
261
+ for layer_id in layer_ids:
262
+ selected_states.append(hidden_states[layer_id + offset])
263
+ target_hidden = torch.cat(selected_states, dim=-1)
264
+ return target_hidden
265
+
266
+
267
+ class DFlashDraftModel(Qwen3PreTrainedModel):
268
+ config_class = Qwen3Config
269
+ _no_split_modules = ["Qwen3DFlashDecoderLayer"]
270
+
271
+ def __init__(self, config) -> None:
272
+ super().__init__(config)
273
+ self.config = config
274
+ if not hasattr(self.config, "dflash_config") or self.config.dflash_config is None:
275
+ self.config.dflash_config = {}
276
+ self.causal_head = bool(self.config.dflash_config.get("causal_head", False))
277
+ self.layers = nn.ModuleList(
278
+ [
279
+ Qwen3DFlashDecoderLayer(config, layer_idx)
280
+ for layer_idx in range(config.num_hidden_layers)
281
+ ]
282
+ )
283
+ dflash_config = getattr(config, "dflash_config", {}) or {}
284
+ self.target_layer_ids = dflash_config.get(
285
+ "target_layer_ids",
286
+ build_target_layer_ids(config.num_target_layers, config.num_hidden_layers),
287
+ )
288
+ self.norm = Qwen3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
289
+ self.rotary_emb = Qwen3RotaryEmbedding(config)
290
+ self.fc = nn.Linear(
291
+ len(self.target_layer_ids) * config.hidden_size,
292
+ config.hidden_size,
293
+ bias=False,
294
+ )
295
+ self.hidden_norm = Qwen3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
296
+ self.block_size = config.block_size
297
+ self.mask_token_id = dflash_config.get("mask_token_id", None)
298
+ self.post_init()
299
+
300
+ def resolve_causal_head(self, head_type: str = "auto") -> bool:
301
+ if head_type == "auto":
302
+ return bool(self.causal_head)
303
+ if head_type == "bidirectional":
304
+ return False
305
+ if head_type == "causal":
306
+ return True
307
+ raise ValueError(
308
+ f"Unsupported head_type={head_type!r}. Expected one of: auto, bidirectional, causal."
309
+ )
310
+
311
+ def forward(
312
+ self,
313
+ position_ids: torch.LongTensor,
314
+ attention_mask: Optional[torch.Tensor] = None,
315
+ noise_embedding: Optional[torch.Tensor] = None,
316
+ target_hidden: Optional[torch.Tensor] = None,
317
+ past_key_values: Optional[Cache] = None,
318
+ use_cache: bool = False,
319
+ **kwargs,
320
+ ) -> CausalLMOutputWithPast:
321
+ hidden_states = noise_embedding
322
+ target_hidden = self.hidden_norm(self.fc(target_hidden))
323
+ position_embeddings = self.rotary_emb(hidden_states, position_ids)
324
+ for layer in self.layers:
325
+ hidden_states = layer(
326
+ hidden_states=hidden_states,
327
+ target_hidden=target_hidden,
328
+ attention_mask=attention_mask,
329
+ position_ids=position_ids,
330
+ past_key_value=past_key_values,
331
+ use_cache=use_cache,
332
+ position_embeddings=position_embeddings,
333
+ **kwargs,
334
+ )
335
+ return self.norm(hidden_states)
336
+
337
+ @torch.inference_mode()
338
+ def spec_generate(
339
+ self,
340
+ target: nn.Module,
341
+ input_ids: torch.LongTensor,
342
+ max_new_tokens: int,
343
+ stop_token_ids: list[int],
344
+ temperature: float,
345
+ ):
346
+ self.eval()
347
+ num_input_tokens = input_ids.shape[1]
348
+ max_length = num_input_tokens + max_new_tokens
349
+
350
+ block_size = self.block_size
351
+ output_ids = torch.full(
352
+ (1, max_length + block_size),
353
+ self.mask_token_id,
354
+ dtype=torch.long,
355
+ device=target.device,
356
+ )
357
+ position_ids = torch.arange(
358
+ output_ids.shape[1], device=target.device
359
+ ).unsqueeze(0)
360
+
361
+ past_key_values_target = DynamicCache()
362
+ past_key_values_draft = DynamicCache()
363
+
364
+ # Prefill stage
365
+ output = target(
366
+ input_ids,
367
+ position_ids=position_ids[:, :num_input_tokens],
368
+ past_key_values=past_key_values_target,
369
+ use_cache=True,
370
+ logits_to_keep=1,
371
+ output_hidden_states=True,
372
+ )
373
+
374
+ output_ids[:, :num_input_tokens] = input_ids
375
+ output_ids[:, num_input_tokens : num_input_tokens + 1] = sample(
376
+ output.logits, temperature
377
+ )
378
+ target_hidden = extract_context_feature(
379
+ output.hidden_states, self.target_layer_ids
380
+ )
381
+
382
+ # Decode stage
383
+ acceptance_lengths = []
384
+ start = input_ids.shape[1]
385
+ while start < max_length:
386
+ block_output_ids = output_ids[:, start : start + block_size].clone()
387
+ block_position_ids = position_ids[:, start : start + block_size]
388
+ noise_embedding = target.model.embed_tokens(block_output_ids)
389
+ draft_logits = target.lm_head(
390
+ self(
391
+ target_hidden=target_hidden,
392
+ noise_embedding=noise_embedding,
393
+ position_ids=position_ids[
394
+ :, past_key_values_draft.get_seq_length() : start + block_size
395
+ ],
396
+ past_key_values=past_key_values_draft,
397
+ use_cache=True,
398
+ is_causal=False,
399
+ )[:, -block_size + 1 :, :]
400
+ )
401
+ past_key_values_draft.crop(start)
402
+ block_output_ids[:, 1:] = sample(draft_logits)
403
+ output_ids[:, start + 1 : start + block_size] = block_output_ids[:, 1:]
404
+
405
+ output = target(
406
+ block_output_ids,
407
+ position_ids=block_position_ids,
408
+ past_key_values=past_key_values_target,
409
+ use_cache=True,
410
+ output_hidden_states=True,
411
+ )
412
+
413
+ posterior = sample(output.logits, temperature)
414
+ acceptance_length = (
415
+ (block_output_ids[:, 1:] == posterior[:, :-1])
416
+ .cumprod(dim=1)
417
+ .sum(dim=1)[0]
418
+ .item()
419
+ )
420
+ output_ids[:, start : start + acceptance_length + 1] = block_output_ids[
421
+ :, : acceptance_length + 1
422
+ ]
423
+ output_ids[:, start + acceptance_length + 1] = posterior[
424
+ :, acceptance_length
425
+ ]
426
+ start += acceptance_length + 1
427
+ past_key_values_target.crop(start)
428
+ target_hidden = extract_context_feature(
429
+ output.hidden_states, self.target_layer_ids
430
+ )[:, : acceptance_length + 1, :]
431
+ acceptance_lengths.append(acceptance_length + 1)
432
+ if stop_token_ids is not None and any(
433
+ stop_token_id in output_ids[:, num_input_tokens:]
434
+ for stop_token_id in stop_token_ids
435
+ ):
436
+ break
437
+ output_ids = output_ids[:, :max_length]
438
+ output_ids = output_ids[:, output_ids[0] != self.mask_token_id]
439
+ if stop_token_ids is not None:
440
+ stop_token_ids = torch.tensor(stop_token_ids, device=output_ids.device)
441
+ stop_token_indices = torch.isin(
442
+ output_ids[0][num_input_tokens:], stop_token_ids
443
+ ).nonzero(as_tuple=True)[0]
444
+ if stop_token_indices.numel() > 0:
445
+ output_ids = output_ids[
446
+ :, : num_input_tokens + stop_token_indices[0] + 1
447
+ ]
448
+
449
+ return output_ids
distill-math239k-coldstart-forward-kl-260430-172233/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:47d993f0ff478e54bc0053025f0e82d2aaca023bf120d39d0edbb95404bc0296
3
+ size 2097259104