huggingface / huggingface/diffusers
[mps] training / inference dtype issues
- Dominant language
- Python
- Stars
- 34.5k
- Forks
- 7.3k
- Avg merge
- 3d 3h
- Merged PRs (30d)
- 91
Description
when training on Diffusers without attention slicing, we see:
```
/AppleInternal/Library/BuildRoots/ce725a5f-c761-11ee-a4ec-b6ef2fd8d87b/Library/Caches/com.apple.xbs/Sources/MetalPerformanceShaders/MPSCore/Types/MPSNDArray.mm:788: failed assertion `[MPSNDArray initWithDevice:descriptor:] Error: total bytes of NDArray > 2**32'
```
but with attention slicing, this error disappears.
```py
# Base components to prepare
if torch.backends.mps.is_available():
accelerator.native_amp = False
results = accelerator.prepare(unet, lr_scheduler, optimizer, *train_dataloaders)
unet = results[0]
if torch.backends.mps.is_available():
unet.set_attention_slice()
```
however, once this issue is resolved, there is a new problem:
```
return F.conv2d(input, weight, bias, self.stride,
RuntimeError: Input type (float) and bias type (c10::BFloat16) should be the same
```
this is caused by the following logic:
```py
# Check that all trainable models are in full precision
low_precision_error_string = (
"Please make sure to always have all model weights in full float32 precision when starting training - even if"
" doing mixed precision training. copy of the weights should still be float32."
)
if accelerator.unwrap_model(unet).dtype != torch.float32:
raise ValueError(
f"Unet loaded as datatype {accelerator.unwrap_model(unet).dtype}. {low_precision_error_string}"
)
if (
args.train_text_encoder
and accelerator.unwrap_model(text_encoder).dtype != torch.float32
):
raise ValueError(
f"Text encoder loaded as datatype {accelerator.unwrap_model(text_encoder).dtype}."
f" {low_precision_error_string}"
)
```
which is done because the AdamW optimiser doesn't work with bf16 weights. however, thanks to @AmericanPresidentJimmyCarter we are now able to use the adamw_bfloat16 package to benefit from an optimizer that can handle pure bf16 training.
once that is the case, we can comment out the low precision warning code, and:
```py
unet = UNet2DConditionModel.from_pretrained(
args.pretrained_model_name_or_path, subfolder="unet", revision=args.revision
).to(weight_dtype)
```
load the unet directly in the target precision level.
_Originally posted by @bghira in https://github.com/huggingface/diffusers/issues/7530#issuecomment-2032234598_
Contributor guide
Assessment
This issue has not been assessed yet.