Skip to content

SD1.x models with a Tiny U-Net #745

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions docs/tiny_U-Nets_in_SD1x.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Running SD1.x models with tiny U-Nets

### Preface

Tiny SD 1.x models have a very small U-Net part. Unlike other 1.x models they consist of only 6 U-Net blocks, resulting in relatively small checkpoint files (approximately 1 GB). Running these models saves almost 50% of the time. For more details, refer to the paper: https://arxiv.org/pdf/2305.15798.pdf .

There are only a few Tiny SD 1.x models available online, such as:

* https://huggingface.co/segmind/tiny-sd
* https://huggingface.co/segmind/portrait-finetuned
* https://huggingface.co/nota-ai/bk-sdm-tiny

To create a checkpoint file, follow these steps:

### Download model from Hugging Face

Download the model using Python on your computer, for example this way:

```python
import torch
from diffusers import StableDiffusionPipeline
pipe = StableDiffusionPipeline.from_pretrained("segmind/tiny-sd")
unet=pipe.unet
for param in unet.parameters():
param.data = param.data.contiguous() # <- important here
pipe.save_pretrained("segmindtiny-sd", safe_serialization=True)
```

### Convert that to a ckpt file

To convert the downloaded model to a checkpoint file, you need another Python script. Download the conversion script from here:

* https://raw.githubusercontent.com/huggingface/diffusers/refs/heads/main/scripts/convert_diffusers_to_original_stable_diffusion.py


### Run convert script

Now, run that conversion script:

```bash
python convert_diffusers_to_original_stable_diffusion.py \
--model_path ./segmindtiny-sd \
--checkpoint_path ./segmind_tiny-sd.ckpt --half
```

The file **segmind_tiny-sd.ckpt** will be generated and is now ready to use with sd.cpp

You can follow a similar process for other models mentioned above from Hugging Face.


### Another ckpt file on the net

There is another model file available online:

* https://huggingface.co/ClashSAN/small-sd/resolve/main/tinySDdistilled.ckpt

If you want to use that, you have to adjust some **non-contiguous tensors** first:

```python
import torch
ckpt = torch.load("tinySDdistilled.ckpt", map_location=torch.device('cpu'))
for key, value in ckpt['state_dict'].items():
if isinstance(value, torch.Tensor):
ckpt['state_dict'][key] = value.contiguous()
torch.save(ckpt, "tinySDdistilled_fixed.ckpt")
```

8 changes: 8 additions & 0 deletions model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1644,8 +1644,13 @@ SDVersion ModelLoader::get_sd_version() {
bool is_xl = false;
bool is_flux = false;

bool maybe_unet_is_tiny = false;

#define found_family (is_xl || is_flux)
for (auto& tensor_storage : tensor_storages) {
if (tensor_storage.name == "model.diffusion_model.up_blocks.0.attentions.1.transformer_blocks.0.norm2.bias") {
maybe_unet_is_tiny = true;
}
if (!found_family) {
if (tensor_storage.name.find("model.diffusion_model.double_blocks.") != std::string::npos) {
is_flux = true;
Expand Down Expand Up @@ -1722,6 +1727,9 @@ SDVersion ModelLoader::get_sd_version() {
if (is_ip2p) {
return VERSION_SD1_PIX2PIX;
}
if (maybe_unet_is_tiny && tensor_storages.size() > 800 && tensor_storages.size() < 805) {
return VERSION_SD1_TINY_UNET;
}
return VERSION_SD1;
} else if (token_embedding_weight.ne[0] == 1024) {
if (is_inpaint) {
Expand Down
3 changes: 2 additions & 1 deletion model.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ enum SDVersion {
VERSION_SD1,
VERSION_SD1_INPAINT,
VERSION_SD1_PIX2PIX,
VERSION_SD1_TINY_UNET,
VERSION_SD2,
VERSION_SD2_INPAINT,
VERSION_SDXL,
Expand Down Expand Up @@ -49,7 +50,7 @@ static inline bool sd_version_is_sd3(SDVersion version) {
}

static inline bool sd_version_is_sd1(SDVersion version) {
if (version == VERSION_SD1 || version == VERSION_SD1_INPAINT || version == VERSION_SD1_PIX2PIX) {
if (version == VERSION_SD1 || version == VERSION_SD1_INPAINT || version == VERSION_SD1_PIX2PIX || version == VERSION_SD1_TINY_UNET) {
return true;
}
return false;
Expand Down
1 change: 1 addition & 0 deletions stable-diffusion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const char* model_version_to_str[] = {
"SD 1.x",
"SD 1.x Inpaint",
"Instruct-Pix2Pix",
"SD 1.x tiny UNet",
"SD 2.x",
"SD 2.x Inpaint",
"SDXL",
Expand Down
Loading