2604
Browse files- 1.png +3 -0
- README.md +11 -0
- media/123456789.jpg +3 -0
- media/123456789.png +3 -0
- media/girl.jpg +2 -2
- media/result_grid.jpg +2 -2
- pipeline_sdxs.py +0 -1
- samples/unet_384x704_0.jpg +2 -2
- samples/unet_416x704_0.jpg +2 -2
- samples/unet_448x704_0.jpg +2 -2
- samples/unet_480x704_0.jpg +2 -2
- samples/unet_512x704_0.jpg +2 -2
- samples/unet_544x704_0.jpg +2 -2
- samples/unet_576x704_0.jpg +2 -2
- samples/unet_608x704_0.jpg +2 -2
- samples/unet_640x704_0.jpg +2 -2
- samples/unet_672x704_0.jpg +2 -2
- samples/unet_704x384_0.jpg +2 -2
- samples/unet_704x416_0.jpg +2 -2
- samples/unet_704x448_0.jpg +2 -2
- samples/unet_704x480_0.jpg +2 -2
- samples/unet_704x512_0.jpg +2 -2
- samples/unet_704x544_0.jpg +2 -2
- samples/unet_704x576_0.jpg +2 -2
- samples/unet_704x608_0.jpg +2 -2
- samples/unet_704x640_0.jpg +2 -2
- samples/unet_704x672_0.jpg +2 -2
- samples/unet_704x704_0.jpg +2 -2
- test.ipynb +2 -2
- train.py +105 -99
- unet/diffusion_pytorch_model.safetensors +1 -1
1.png
ADDED
|
Git LFS Details
|
README.md
CHANGED
|
@@ -79,6 +79,13 @@ image.show()
|
|
| 79 |
upscaled = pipe.image_upscale("media/girl.jpg")
|
| 80 |
```
|
| 81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
### Prompt refine
|
| 83 |
```
|
| 84 |
refined = pipe.refine_prompts("girl")
|
|
@@ -214,6 +221,10 @@ nohup accelerate launch train.py &
|
|
| 214 |
- Rubles: [For users from Russia](https://www.tbank.ru/cf/90ensBQqpJj)
|
| 215 |
- DOGE: DEw2DR8C7BnF8GgcrfTzUjSnGkuMeJhg83
|
| 216 |
- BTC: 3JHv9Hb8kEW8zMAccdgCdZGfrHeMhH1rpN
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
|
| 218 |
## Contacts
|
| 219 |
Please contact with us if you may provide some GPU's or money on training
|
|
|
|
| 79 |
upscaled = pipe.image_upscale("media/girl.jpg")
|
| 80 |
```
|
| 81 |
|
| 82 |
+
```markdown
|
| 83 |
+
| | |
|
| 84 |
+
|:---:|:---:|
|
| 85 |
+
| <img src="media/123456789.jpg" height="512"/> | <img src="media/123456789.png" height="512"/> |
|
| 86 |
+
| original | 2xupscale |
|
| 87 |
+
```
|
| 88 |
+
|
| 89 |
### Prompt refine
|
| 90 |
```
|
| 91 |
refined = pipe.refine_prompts("girl")
|
|
|
|
| 221 |
- Rubles: [For users from Russia](https://www.tbank.ru/cf/90ensBQqpJj)
|
| 222 |
- DOGE: DEw2DR8C7BnF8GgcrfTzUjSnGkuMeJhg83
|
| 223 |
- BTC: 3JHv9Hb8kEW8zMAccdgCdZGfrHeMhH1rpN
|
| 224 |
+
USTD
|
| 225 |
+
- Ethereum / Polygon / BNB SmartChain: 0xD4388B6698dFaE1460E72099D4F208aaCA4f6E6C
|
| 226 |
+
- Tron: TD7ey4h9igPGdcrcBcnZaz56R5tNgRZNvV
|
| 227 |
+
- Solana: MMYFJeYEtYHrSNFHChytJDHbEDniXrnAxPNLhJ1LbkB
|
| 228 |
|
| 229 |
## Contacts
|
| 230 |
Please contact with us if you may provide some GPU's or money on training
|
media/123456789.jpg
ADDED
|
Git LFS Details
|
media/123456789.png
ADDED
|
Git LFS Details
|
media/girl.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
media/result_grid.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
pipeline_sdxs.py
CHANGED
|
@@ -248,7 +248,6 @@ class SdxsPipeline(DiffusionPipeline):
|
|
| 248 |
|
| 249 |
# Encode -> Decode (using mean for deterministic upscale)
|
| 250 |
latents = self.vae.encode(tensors).latent_dist.mean
|
| 251 |
-
latents = latents * self.vae_latents_std.to(latents) + self.vae_latents_mean.to(latents)
|
| 252 |
decoded = self.vae.decode(latents.to(self.vae.dtype))[0]
|
| 253 |
|
| 254 |
# 4. Post-process: Denormalize and Crop
|
|
|
|
| 248 |
|
| 249 |
# Encode -> Decode (using mean for deterministic upscale)
|
| 250 |
latents = self.vae.encode(tensors).latent_dist.mean
|
|
|
|
| 251 |
decoded = self.vae.decode(latents.to(self.vae.dtype))[0]
|
| 252 |
|
| 253 |
# 4. Post-process: Denormalize and Crop
|
samples/unet_384x704_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_416x704_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_448x704_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_480x704_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_512x704_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_544x704_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_576x704_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_608x704_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_640x704_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_672x704_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_704x384_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_704x416_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_704x448_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_704x480_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_704x512_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_704x544_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_704x576_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_704x608_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_704x640_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_704x672_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
samples/unet_704x704_0.jpg
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
test.ipynb
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bd0d1f7f30e064d8fb03320c204b7d67fd5c7df87da6919af818d6e2f60ee1a2
|
| 3 |
+
size 12104053
|
train.py
CHANGED
|
@@ -10,6 +10,7 @@ import bitsandbytes as bnb
|
|
| 10 |
import torch.nn.functional as F
|
| 11 |
import argparse
|
| 12 |
|
|
|
|
| 13 |
from diffusers import UNet2DConditionModel, AsymmetricAutoencoderKL, FlowMatchEulerDiscreteScheduler
|
| 14 |
from transformers import Qwen3_5Tokenizer, Qwen3_5ForConditionalGeneration
|
| 15 |
from torch.utils.data import DataLoader, Sampler
|
|
@@ -21,7 +22,7 @@ from tqdm import tqdm
|
|
| 21 |
from PIL import Image, ImageOps
|
| 22 |
from torch.utils.checkpoint import checkpoint
|
| 23 |
from diffusers.models.attention_processor import AttnProcessor2_0
|
| 24 |
-
from
|
| 25 |
|
| 26 |
# Muon not tested! pip install git+https://github.com/recoilme/muon_adamw8bit.git
|
| 27 |
from muon_adamw8bit import MuonAdamW8bit
|
|
@@ -470,12 +471,14 @@ else:
|
|
| 470 |
return min_learning_rate + 0.5 * (base_learning_rate - min_learning_rate) * \
|
| 471 |
(1 + math.cos(math.pi * decay_ratio))
|
| 472 |
lr_scheduler = LambdaLR(optimizer, lambda step: lr_schedule(step) / base_learning_rate)
|
| 473 |
-
unet, optimizer, lr_scheduler = accelerator.prepare(unet, optimizer, lr_scheduler)
|
| 474 |
|
| 475 |
if torch_compile:
|
| 476 |
-
print("
|
| 477 |
unet = torch.compile(unet)
|
| 478 |
-
print("
|
|
|
|
|
|
|
|
|
|
| 479 |
|
| 480 |
# Фиксированные семплы
|
| 481 |
fixed_samples = get_fixed_samples_by_resolution(dataset)
|
|
@@ -702,105 +705,108 @@ for epoch in range(start_epoch, start_epoch + num_epochs):
|
|
| 702 |
unet.train()
|
| 703 |
|
| 704 |
for step, (latents, embeddings, attention_mask) in enumerate(dataloader):
|
| 705 |
-
|
| 706 |
-
|
| 707 |
-
|
| 708 |
-
|
| 709 |
-
|
| 710 |
-
# шум
|
| 711 |
-
noise = torch.randn_like(latents, dtype=latents.dtype)
|
| 712 |
-
|
| 713 |
-
# 3. Время t (сэмплим, как и раньше, но чуть сжимаем края)
|
| 714 |
-
u = torch.rand(latents.shape[0], device=latents.device, dtype=latents.dtype)
|
| 715 |
-
t = u * (1 - 2 * 1e-5) + 1e-5 # Теперь t строго в (0.00001 ... 0.99999)
|
| 716 |
-
# интерполяция между x0 и шумом
|
| 717 |
-
noisy_latents = (1.0 - t.view(-1, 1, 1, 1)) * latents + t.view(-1, 1, 1, 1) * noise
|
| 718 |
-
# делаем integer timesteps для UNet
|
| 719 |
-
timesteps = t.to(torch.float32).mul(999.0)
|
| 720 |
-
timesteps = timesteps.clamp(0, scheduler.config.num_train_timesteps - 1)
|
| 721 |
-
|
| 722 |
-
# --- Вызов UNet с маской ---
|
| 723 |
-
model_pred = unet(
|
| 724 |
-
noisy_latents,
|
| 725 |
-
timesteps,
|
| 726 |
-
encoder_hidden_states=embeddings,
|
| 727 |
-
encoder_attention_mask=attention_mask,
|
| 728 |
-
).sample
|
| 729 |
-
|
| 730 |
-
target = noise - latents
|
| 731 |
-
|
| 732 |
-
mse_loss = F.mse_loss(model_pred.float(), target.float())
|
| 733 |
-
batch_losses.append(mse_loss.detach().item())
|
| 734 |
-
|
| 735 |
-
if (global_step % 100 == 0) or (global_step % sink_interval == 0):
|
| 736 |
-
accelerator.wait_for_everyone()
|
| 737 |
-
|
| 738 |
-
losses_dict = {}
|
| 739 |
-
losses_dict["mse"] = mse_loss
|
| 740 |
-
|
| 741 |
-
if (global_step % 100 == 0) or (global_step % sink_interval == 0):
|
| 742 |
-
accelerator.wait_for_everyone()
|
| 743 |
-
|
| 744 |
-
accelerator.backward(mse_loss)
|
| 745 |
|
| 746 |
-
|
| 747 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 748 |
|
| 749 |
-
|
| 750 |
-
|
| 751 |
-
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
|
| 755 |
-
|
| 756 |
-
|
| 757 |
-
|
| 758 |
-
|
| 759 |
-
global_step += 1
|
| 760 |
-
progress_bar.update(1)
|
| 761 |
-
if accelerator.is_main_process:
|
| 762 |
-
if fbp:
|
| 763 |
-
current_lr = base_learning_rate
|
| 764 |
-
else:
|
| 765 |
-
current_lr = lr_scheduler.get_last_lr()[0]
|
| 766 |
-
batch_grads.append(grad)
|
| 767 |
|
| 768 |
-
|
| 769 |
-
|
| 770 |
-
|
| 771 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 772 |
if accelerator.sync_gradients:
|
| 773 |
-
|
| 774 |
-
|
| 775 |
-
|
| 776 |
-
|
| 777 |
-
|
| 778 |
-
|
| 779 |
-
|
| 780 |
-
|
| 781 |
-
|
| 782 |
-
|
| 783 |
-
|
| 784 |
-
|
| 785 |
-
|
| 786 |
-
|
| 787 |
-
|
| 788 |
-
|
| 789 |
-
|
| 790 |
-
|
| 791 |
-
|
| 792 |
-
|
| 793 |
-
|
| 794 |
-
|
| 795 |
-
|
| 796 |
-
|
| 797 |
-
|
| 798 |
-
|
| 799 |
-
|
| 800 |
-
|
| 801 |
-
|
| 802 |
-
|
| 803 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 804 |
|
| 805 |
if accelerator.is_main_process:
|
| 806 |
avg_epoch_loss = np.mean(batch_losses) if len(batch_losses) > 0 else 0.0
|
|
|
|
| 10 |
import torch.nn.functional as F
|
| 11 |
import argparse
|
| 12 |
|
| 13 |
+
from datetime import datetime
|
| 14 |
from diffusers import UNet2DConditionModel, AsymmetricAutoencoderKL, FlowMatchEulerDiscreteScheduler
|
| 15 |
from transformers import Qwen3_5Tokenizer, Qwen3_5ForConditionalGeneration
|
| 16 |
from torch.utils.data import DataLoader, Sampler
|
|
|
|
| 22 |
from PIL import Image, ImageOps
|
| 23 |
from torch.utils.checkpoint import checkpoint
|
| 24 |
from diffusers.models.attention_processor import AttnProcessor2_0
|
| 25 |
+
from contextlib import nullcontext
|
| 26 |
|
| 27 |
# Muon not tested! pip install git+https://github.com/recoilme/muon_adamw8bit.git
|
| 28 |
from muon_adamw8bit import MuonAdamW8bit
|
|
|
|
| 471 |
return min_learning_rate + 0.5 * (base_learning_rate - min_learning_rate) * \
|
| 472 |
(1 + math.cos(math.pi * decay_ratio))
|
| 473 |
lr_scheduler = LambdaLR(optimizer, lambda step: lr_schedule(step) / base_learning_rate)
|
|
|
|
| 474 |
|
| 475 |
if torch_compile:
|
| 476 |
+
print("Compiling UNet... Это займет несколько минут, не прерывайте!")
|
| 477 |
unet = torch.compile(unet)
|
| 478 |
+
print("Compiling - ok")
|
| 479 |
+
|
| 480 |
+
if not fbp:
|
| 481 |
+
unet, optimizer, lr_scheduler = accelerator.prepare(unet, optimizer, lr_scheduler)
|
| 482 |
|
| 483 |
# Фиксированные семплы
|
| 484 |
fixed_samples = get_fixed_samples_by_resolution(dataset)
|
|
|
|
| 705 |
unet.train()
|
| 706 |
|
| 707 |
for step, (latents, embeddings, attention_mask) in enumerate(dataloader):
|
| 708 |
+
|
| 709 |
+
if save_model == False and epoch == 0 and step == 5 :
|
| 710 |
+
used_gb = torch.cuda.max_memory_allocated() / 1024**3
|
| 711 |
+
print(f"Шаг {step}: {used_gb:.2f} GB")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 712 |
|
| 713 |
+
amp_context = accelerator.autocast() if torch_compile else nullcontext()
|
| 714 |
+
with accelerator.accumulate(unet):
|
| 715 |
+
with amp_context:
|
| 716 |
+
# шум
|
| 717 |
+
noise = torch.randn_like(latents, dtype=latents.dtype)
|
| 718 |
+
|
| 719 |
+
# 3. Время t (сэмплим, как и раньше, но чуть сжимаем края)
|
| 720 |
+
u = torch.rand(latents.shape[0], device=latents.device, dtype=latents.dtype)
|
| 721 |
+
t = u * (1 - 2 * 1e-5) + 1e-5 # Теперь t строго в (0.00001 ... 0.99999)
|
| 722 |
+
# интерполяция между x0 и шумом
|
| 723 |
+
noisy_latents = (1.0 - t.view(-1, 1, 1, 1)) * latents + t.view(-1, 1, 1, 1) * noise
|
| 724 |
+
# делаем integer timesteps для UNet
|
| 725 |
+
timesteps = t.to(torch.float32).mul(999.0)
|
| 726 |
+
timesteps = timesteps.clamp(0, scheduler.config.num_train_timesteps - 1)
|
| 727 |
+
|
| 728 |
+
# --- Вызов UNet с маской ---
|
| 729 |
+
model_pred = unet(
|
| 730 |
+
noisy_latents,
|
| 731 |
+
timesteps,
|
| 732 |
+
encoder_hidden_states=embeddings,
|
| 733 |
+
encoder_attention_mask=attention_mask,
|
| 734 |
+
).sample
|
| 735 |
|
| 736 |
+
target = noise - latents
|
| 737 |
+
|
| 738 |
+
mse_loss = F.mse_loss(model_pred.float(), target.float())
|
| 739 |
+
batch_losses.append(mse_loss.detach().item())
|
| 740 |
+
|
| 741 |
+
if (global_step % 100 == 0) or (global_step % sink_interval == 0):
|
| 742 |
+
accelerator.wait_for_everyone()
|
| 743 |
+
|
| 744 |
+
losses_dict = {}
|
| 745 |
+
losses_dict["mse"] = mse_loss
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 746 |
|
| 747 |
+
if (global_step % 100 == 0) or (global_step % sink_interval == 0):
|
| 748 |
+
accelerator.wait_for_everyone()
|
| 749 |
+
|
| 750 |
+
accelerator.backward(mse_loss)
|
| 751 |
+
|
| 752 |
+
if (global_step % 100 == 0) or (global_step % sink_interval == 0):
|
| 753 |
+
accelerator.wait_for_everyone()
|
| 754 |
+
|
| 755 |
+
grad = 0.0
|
| 756 |
+
if not fbp:
|
| 757 |
if accelerator.sync_gradients:
|
| 758 |
+
grad_val = accelerator.clip_grad_norm_(unet.parameters(), clip_grad_norm)
|
| 759 |
+
grad = grad_val.float().item() if torch.is_tensor(grad_val) else float(grad_val)
|
| 760 |
+
optimizer.step()
|
| 761 |
+
lr_scheduler.step()
|
| 762 |
+
optimizer.zero_grad(set_to_none=True)
|
| 763 |
+
|
| 764 |
+
if accelerator.sync_gradients:
|
| 765 |
+
global_step += 1
|
| 766 |
+
progress_bar.update(1)
|
| 767 |
+
if accelerator.is_main_process:
|
| 768 |
+
if fbp:
|
| 769 |
+
current_lr = base_learning_rate
|
| 770 |
+
else:
|
| 771 |
+
current_lr = lr_scheduler.get_last_lr()[0]
|
| 772 |
+
batch_grads.append(grad)
|
| 773 |
+
|
| 774 |
+
log_data = {}
|
| 775 |
+
log_data["loss_mse"] = mse_loss.detach().item()
|
| 776 |
+
log_data["lr"] = current_lr
|
| 777 |
+
log_data["grad"] = grad
|
| 778 |
+
if accelerator.sync_gradients:
|
| 779 |
+
if use_wandb:
|
| 780 |
+
wandb.log(log_data, step=global_step)
|
| 781 |
+
if use_comet_ml:
|
| 782 |
+
comet_experiment.log_metrics(log_data, step=global_step)
|
| 783 |
+
|
| 784 |
+
current_time = time.time()
|
| 785 |
+
is_time_to_sample = (current_time - last_sample_time) >= sample_interval_seconds
|
| 786 |
+
if is_time_to_sample or global_step == 50:
|
| 787 |
+
# Передаем tuple (emb, mask) для негатива
|
| 788 |
+
if save_model:
|
| 789 |
+
generate_and_save_samples(fixed_samples, (uncond_emb, uncond_mask), global_step)
|
| 790 |
+
elif epoch % 10 == 0:
|
| 791 |
+
generate_and_save_samples(fixed_samples, (uncond_emb, uncond_mask), global_step)
|
| 792 |
+
last_n = sink_interval
|
| 793 |
+
|
| 794 |
+
if save_model:
|
| 795 |
+
has_losses = len(batch_losses) > 0
|
| 796 |
+
avg_sample_loss = np.mean(batch_losses[-sink_interval:]) if has_losses else 0.0
|
| 797 |
+
last_loss = batch_losses[-1] if has_losses else 0.0
|
| 798 |
+
max_loss = max(avg_sample_loss, last_loss)
|
| 799 |
+
should_save = max_loss < min_loss * save_barrier
|
| 800 |
+
print(
|
| 801 |
+
f"Saving: {should_save} | Max: {max_loss:.4f} | "
|
| 802 |
+
f"Last: {last_loss:.4f} | Avg: {avg_sample_loss:.4f}"
|
| 803 |
+
)
|
| 804 |
+
# 6. Сохранение и обновление
|
| 805 |
+
if should_save:
|
| 806 |
+
min_loss = max_loss
|
| 807 |
+
save_checkpoint(unet)
|
| 808 |
+
last_sample_time = current_time
|
| 809 |
+
unet.train()
|
| 810 |
|
| 811 |
if accelerator.is_main_process:
|
| 812 |
avg_epoch_loss = np.mean(batch_losses) if len(batch_losses) > 0 else 0.0
|
unet/diffusion_pytorch_model.safetensors
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
size 3210307232
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9b2e01643382012adcffc091502a64e908d85a394504a92cf8bb8aa8cec080b9
|
| 3 |
size 3210307232
|