El equipo de investigación de Screen Art ha sometido a prueba el modelo de edición de imágenes de Qwen en todas sus configuraciones posibles sobre hardware consumer. Tres métodos fallaron. El cuarto funcionó — y encontramos comportamientos que no están en la documentación oficial.

Hardware principal
RTX 3090 Ti · 24 GB VRAM · 94 GB RAM
Hardware secundario
RTX 3060 · 12 GB VRAM
Entorno
diffusers 0.37 · NF4 pre-cuantizado · FastAPI

Cuando Qwen lanzó Qwen-Image-Edit-2511 en noviembre de 2025, la promesa era clara: edición semántica de imagen sin necesidad de máscaras, controlada únicamente mediante texto. El problema también era inmediato: el modelo pesa 55 GB en bf16, muy por encima de lo que cabe en cualquier GPU de consumo.

Lo que sigue documenta tres meses de pruebas: los tres callejones sin salida, el setup que finalmente funcionó, y varios descubrimientos que no aparecen en el README oficial del modelo.

🔬Grupo de investigación: Pruebas realizadas por el equipo de Screen Art sobre hardware propio. Los resultados pueden variar según configuración de sistema y carga concurrente de GPU.
55 GB
Modelo bf16 original
14.3s
Tiempo final/imagen
17.5 GB
VRAM pico producción
4 steps
Con Lightning LoRA
01

El modelo: tres componentes con necesidades de VRAM muy distintas

Qwen-Image-Edit-2511 es un MMDiT (Multimodal Diffusion Transformer) de Alibaba/Qwen. No es un LLM: es un modelo de edición de imágenes con tres piezas bien diferenciadas. Entender qué hace cada una y con qué frecuencia se ejecuta es clave para gestionar la VRAM correctamente.

Componente Tamaño bf16 Función Ejecuciones por imagen
Transformer (DiT) 39 GB Motor principal de denoising 4–40 iteraciones en bucle
Text Encoder (Qwen2.5-VL) 16 GB Procesa el prompt de texto 1 vez únicamente
VAE 243 MB Encode/decode píxeles ↔ latentes 1 vez al final

La clave: el transformer es el cuello de botella real — se ejecuta en bucle en cada step de denoising. El text encoder solo se ejecuta una vez por imagen, lo que lo convierte en el candidato idóneo para moverlo fuera de la GPU principal sin impacto grave en velocidad.

02

Los métodos que no funcionan: tres callejones documentados

bitsandbytes INT4 dinámico

El primer intento fue cuantizar el modelo en runtime con bitsandbytes. El resultado fue inmediato y definitivo:

UserWarning: "no linear modules were found in the model"
# bitsandbytes busca capas nn.Linear estándar.
# El DiT de Qwen usa arquitectura custom — no las expone.
# El modelo carga en bf16 completo ignorando la cuantización.

Con 55 GB de modelo y 24 GB de GPU, diffusers cargó los primeros 17 GB en VRAM y el resto quedó en RAM del sistema. Durante la inferencia los pesos no se movían correctamente entre RAM y GPU — las imágenes generadas eran ruido puro.

torchao FP8/INT4

Incompatible con torch 2.5 (torch.int1 no existe). Con torch 2.6 aparecen conflictos con diffusers 0.37. Callejón sin salida independientemente de la versión de partida.

DiffSynth-Studio

Bug en preparing_device: recibe un dtype en lugar de un device. El text encoder bf16 (16 GB) llenaba la GPU solo al intentar cargarlo — sin llegar a la inferencia.

03

La solución: NF4 pre-cuantizado con estrategia por zonas

El repo ovedrive/Qwen-Image-Edit-2511-4bit resuelve el problema con una cuantización selectiva que no trata todas las capas por igual:

# Cuantización selectiva por zonas del transformer
Capas 0–29      (entrada):  bf16 completo   → preserva calidad perceptual
Capas 30–N-30   (centro):   NF4 4-bit       → máxima compresión
Capas N-30–N    (salida):   bf16 completo   → preserva reconstrucción

Resultado: transformer 39 GB bf16  →  ~12 GB NF4 en VRAM

NF4 (Normal Float 4-bit) es superior a INT4 uniforme: sus 16 valores posibles siguen una distribución normal, que coincide con la distribución real de los pesos en redes neuronales. El error de cuantización se minimiza donde más afecta a la calidad de salida.

Por qué bitsandbytes dinámico no sirve aquí

Los pesos ya están convertidos a NF4 en disco. Se cargan directamente sin que bitsandbytes necesite detectar ni cuantizar nada — por eso funciona con arquitecturas DiT custom donde el cuantizador dinámico falla.

04

Gestión de VRAM: el text encoder fuera de la GPU principal

Con el modelo NF4 funcionando en una sola GPU, el consumo en reposo era de 18.1 GB — demasiado para convivir con otros modelos en producción. El siguiente paso: mover el text encoder (4.5 GB) fuera de la 3090 Ti.

Intento 1: text encoder en CPU

enable_model_cpu_offload() mueve todos los componentes a RAM del sistema y los sube a GPU solo cuando se necesitan. Libera mucha VRAM — pero a un coste de velocidad demasiado alto:

Modo VRAM reposo VRAM pico Tiempo/img
Todo en GPU 18.1 GB 22.6 GB 15.7s
CPU offload completo 0 GB 14.6 GB 23.0s (+7.3s)

La penalización de 7.3 segundos viene del movimiento CPU↔GPU de todos los componentes en cada step. El transformer sube, procesa y baja — igual que el text encoder. Inviable para producción.

Intento 2: text encoder en la RTX 3060 (misma placa base)

La RTX 3060 está conectada en la misma placa por PCIe. La transferencia de embeddings entre GPUs es órdenes de magnitud más rápida que desde CPU RAM. Los embeddings de texto son apenas unos pocos MB — la transferencia tarda menos de 50ms.

Modo 3090 reposo 3090 pico 3060 Tiempo
Todo en 3090 18.1 GB 22.6 GB 15.7s
Text enc. en CPU 0 GB 14.6 GB 23.0s
✓ Text enc. en 3060 13.0 GB 17.5 GB 5.15 GB 16.7s (+1s)

Solo 1 segundo de penalización a cambio de liberar 5 GB en la 3090 Ti. Con 11 GB libres en reposo, otros modelos conviven sin problema. Este es el sweet spot.

diffusers asume que todos los componentes están en el mismo device. Para que funcione con multi-GPU se necesita un patch que redirige el routing de embeddings:

# Distribuir componentes entre GPUs
pipe.transformer  = pipe.transformer.to("cuda:0")   # RTX 3090 Ti
pipe.vae          = pipe.vae.to("cuda:0")
pipe.text_encoder = pipe.text_encoder.to("cuda:1")  # RTX 3060

# Patch: execution device siempre cuda:0
QwenImageEditPipeline._execution_device = property(
    lambda self: torch.device("cuda:0")
)

# Patch: routing de embeddings cuda:1 → cuda:0
_orig = pipe._get_qwen_prompt_embeds
def _patched(prompt, image=None, device=None, dtype=None):
    e, m = _orig(prompt, image=image, device=torch.device("cuda:1"), dtype=dtype)
    return e.to("cuda:0"), m.to("cuda:0") if m is not None else m
pipe._get_qwen_prompt_embeds = _patched
05

Lightning LoRA: 4 steps con una regla que no se puede ignorar

El repo lightx2v/Qwen-Image-Edit-2511-Lightning incluye una LoRA de destilación que reduce la inferencia de 40 a 4 steps — una ganancia de ~10× en velocidad.

⚠ Regla crítica — leer antes de usar

Lightning está diseñado para true_cfg_scale=1.0 sin negative_prompt. Con cfg alto y negative_prompt a resoluciones ≥1024px los colores se rompen: tonos de piel rojos y metálicos, ropa con reflejos amarillos. Con solo 4 steps el modelo no puede reconciliar la doble pasada positivo/negativo.

# ✓ Configuración correcta con Lightning
output = pipe(
    image=input_image,
    prompt="change background to sunset beach",
    num_inference_steps=4,
    true_cfg_scale=1.0,      # Sin double-pass CFG
    guidance_scale=None,     # Ignorado con Lightning
    # NO usar negative_prompt — rompe colores a ≥1024px
)

# Para cambios difíciles (pelo, barba) — desactivar Lightning
output = pipe(
    image=img,
    prompt="change beard and hair to completely black",
    negative_prompt="white hair, gray hair, blurry",
    num_inference_steps=20,
    true_cfg_scale=12.0,    # ~120s, VRAM pico 21.5 GB
)
06

Benchmarks: velocidad, VRAM y el efecto torch.compile

GANADORMulti-GPU + compile
 
14.3s
Multi-GPU sin compile
 
16.7s
Todo en 3090 Ti
 
15.7s
CPU offload completo
 
23.0s
20 steps sin Lightning
 
~120s
Configuración Tiempo 3090 reposo 3090 pico 3060
Todo en 3090 Ti 15.7s 18.1 GB 22.6 GB
Multi-GPU + torch.compile ✓ 14.3s 13.0 GB 17.5 GB 5.15 GB
Multi-GPU sin compile 16.7s 13.0 GB 17.5 GB 5.15 GB
CPU offload completo 23.0s 0 GB 14.6 GB
20 steps cfg=12 sin Lightning ~120s 18.1 GB 21.5 GB
Nota sobre torch.compile en producción

torch.compile añade ~6.7 GB extra en VRAM para cachear los kernels compilados (19.7 GB vs 13 GB sin compile). En entornos multi-modelo puede ser preferible operar sin compile (16.7s) para tener más margen. La ganancia de 2.5s no siempre justifica el coste en VRAM.

🔬 Descubrimiento

La resolución no afecta al tiempo de generación

Generando a 512×512, 1024×1024 o 1920×1080, el tiempo es prácticamente idéntico (~14–16s). El transformer opera sobre un espacio latente de tamaño fijo gracias al VAE que comprime la imagen antes de la difusión. El VAE encode/decode sí escala con la resolución, pero es irrelevante frente al transformer.

Conclusión práctica: genera siempre a la resolución final deseada, sin penalización. 1024×1024 es gratis frente a 512×512.

Resolución Tiempo VRAM pico
512×512 14.3s 17.46 GB
1024×1024 14.3s 17.46 GB
1280×720 14.2s 17.49 GB
1080×1080 14.3s 17.46 GB
1920×1080 15.7s 22.60 GB
07

Casos de uso: edición semántica, qué funciona y qué no

Qwen-Image-Edit es un modelo de edición semántica, no de generación desde cero. Necesita una imagen de entrada y modifica partes de ella según el prompt. Su caso de uso natural es "cambia el fondo a París" — no "pon esta cara en París".

✓ Funciona · Lightning 4-step (~14–16s)
  • Cambio de fondo y escenario
  • Cambio de color de ropa
  • Conversión de estilo artístico
  • Fusión de sujeto con nuevo entorno
  • Vista 360° con LoRA Multiple-Angles
  • Boceto → objeto o arquitectura
✗ Requiere 20 steps sin Lightning (~2 min)
  • Cambio color pelo y barba (cfg=12)
  • Edición de texto en carteles
  • Boceto → persona u animal orgánico
  • Cambios de identidad muy específicos
08

LoRA Multiple-Angles: vista 360° desde una sola fotografía

La LoRA de fal/Qwen-Image-Edit-2511-Multiple-Angles-LoRA define 96 posiciones de cámara mediante tokens especiales: 4 elevaciones × 8 azimuths × 3 distancias.

# Formato:  [azimuth] [elevation] [distancia]
" front view eye-level shot medium shot"
" right side view eye-level shot medium shot"
" back view eye-level shot medium shot"
" high-angle shot front view medium shot"

# Combinar Lightning + Angles (mejor que Angles solo con 20 steps)
pipe.set_adapters(["angles", "lightning"], adapter_weights=[0.9, 1.0])

La combinación Lightning + Angles produce mejor calidad que Angles solo con 20 steps. Con 4 steps el modelo hace cambios conservadores que no generan anatomía errónea. Una vuelta completa de 360° (8 azimuths + 3 elevaciones = 11 imágenes) se completa en menos de 3 minutos.

09

Boceto a imagen: seguimiento geométrico sin ControlNet

🔬 Comportamiento no documentado oficialmente

El modelo respeta la geometría del boceto como guía estructural

Al pasar un boceto simple como imagen de entrada, el modelo lo interpreta simultáneamente como contenido a transformar y como guía de composición — sin ControlNet como componente separado, sin VRAM adicional, sin configuración especial.

El tejado, ventanas y puerta de un boceto de casa aparecen en la misma posición y proporciones en todas las variantes generadas. Es un comportamiento emergente del entrenamiento del MMDiT: el modelo fue entrenado para preservar la estructura de la imagen de entrada, y eso incluye bocetos simples. Esto no está documentado en el README oficial del modelo.

  Qwen-Edit boceto ControlNet Canny
Mecanismo Implícito en el MMDiT Componente separado
VRAM extra 0 GB ~2–4 GB
Modelo adicional No
Geometría / arquitectura Excelente Excelente
Personas y animales orgánicos Limitado Excelente
Tiempo (Lightning, 1024px) ~14s ~10–20s
10

Stack recomendado para producción en 24 GB VRAM

Caso de uso Configuración Tiempo VRAM 3090 Notas
Edición semántica NF4 + Lightning + Multi-GPU 14–17s 17.5 GB pico Permanente en memoria entre requests
Vista 360° Lightning + Angles LoRA ~16s/vista 17.5 GB pico 11 vistas en <3 min
Boceto → objeto Lightning 4-step ~14s 17.5 GB pico Sin ControlNet necesario
Cambio de pelo/barba 20 steps cfg=12 ~120s 21.5 GB pico Incompatible con otros modelos activos
¿Tiene imagen de entrada?
├── SÍ
│   ├── Editar fondo / ropa / estilo       → Lightning 4-step  (~14s)
│   ├── Cambiar ángulo de cámara           → Lightning + Angles (~16s)
│   ├── Boceto → objeto / arquitectura     → Lightning 4-step  (~14s)
│   └── Cambio color pelo / barba          → 20 steps cfg=12   (~120s)
└── NO
    ├── Generar desde prompt                → Flux Schnell / RealVisXL
    └── Boceto → persona / animal           → RealVisXL + ControlNet Canny
11

Qwen-Image-2.0: el sucesor que cambia la ecuación de hardware

Mientras realizábamos estos benchmarks, Alibaba lanzó el 10 de febrero de 2026 Qwen-Image-2.0 — un modelo que unifica generación y edición en una sola arquitectura de 7B parámetros, frente a los 20B del modelo que hemos estado usando en este benchmark. El cambio de escala es dramático.

  Qwen-Image-Edit-2511 Qwen-Image-2.0
Parámetros ~20B 7B
Tamaño estimado bf16 ~55 GB ~14–16 GB
VRAM mínima estimada 16 GB con offload 8–12 GB sin cuantizar
Generación T2I (texto a imagen) No
Edición I2I (imagen a imagen)
Resolución nativa 1024px 2048px (2K nativo)
Pesos descargables Sí — Apache 2.0 No publicados aún
🔜 Próximo benchmark · En cuanto salgan los pesos

Estamos deseando probarlo y hacer la comparativa

Un modelo de 7B que unifica generación y edición debería caber sin cuantizar en una GPU de 12 GB — algo completamente fuera del alcance con el modelo actual. Si las estimaciones se confirman, todo el trabajo documentado en este artículo (el NF4, el patch multi-GPU, el routing del text encoder) dejará de ser necesario para la mayoría de casos de uso.

Las LoRAs existentes — Multiple-Angles y Lightning — deberán ser reentrenadas sobre la nueva arquitectura por sus creadores. Es la condición inevitable de cualquier cambio de modelo base. Esperamos verlo de la comunidad en las semanas posteriores al lanzamiento de los pesos.

En cuanto estén disponibles haremos la comparativa directa sobre el mismo hardware: ¿cuánto mejora la calidad a 2K nativo? ¿Es Lightning necesario con 7B o el modelo ya es suficientemente rápido? ¿Cabe en una 3060 de 12 GB sin cuantizar? Tenemos muchas ganas de comprobarlo.

11b

Recursos: dónde descargar cada pieza

Todos los checkpoints usados en este benchmark son Apache 2.0 y están disponibles en HuggingFace. El orden de descarga importa: el modelo base primero, las LoRAs después.

Modelo base NF4 — transformer + text_encoder + VAE

Creado por Abhishek Dujari (ovedrive/Qwen-Image-Edit-2511-4bit). Cuantizado desde el modelo oficial Qwen/Qwen-Image-Edit-2511. Ocupa ~17 GB en disco frente a los 55 GB del original.

huggingface-cli download ovedrive/Qwen-Image-Edit-2511-4bit \
    --local-dir /workspace/qwen-image-edit/model-4bit

LoRA Lightning — 4-step y 8-step

De ModelTC / lightx2v/Qwen-Image-Edit-2511-Lightning. El repo incluye también un split FP8 de 19 GB que no hemos usado — se puede ignorar descargando solo los .safetensors sueltos:

# Descarga completa del repo (incluye el split FP8 de 19 GB — no necesario)
huggingface-cli download lightx2v/Qwen-Image-Edit-2511-Lightning \
    --local-dir /workspace/qwen-image-edit/lora-lightning

# Recomendado: solo el 4-step bf16 (811 MB)
huggingface-cli download lightx2v/Qwen-Image-Edit-2511-Lightning \
    --include "Qwen-Image-Edit-2511-Lightning-4steps-V1.0-bf16.safetensors" \
    --local-dir /workspace/qwen-image-edit/lora-lightning
Por qué descartar el split FP8

El split FP8 es un formato alternativo para hardware con soporte nativo FP8 (H100, RTX 4090 con driver reciente). En una RTX 3090 Ti no aporta nada y ocupa 19 GB adicionales. Para el pipeline con diffusers + NF4, el bf16.safetensors de 811 MB es suficiente.

Resumen de archivos en disco

Archivo / directorio Tamaño Repo HuggingFace Autor
model-4bit/ ~17 GB ovedrive/Qwen-Image-Edit-2511-4bit Abhishek Dujari · JustLab.ai
lora-lightning/
*-4steps-V1.0-bf16.safetensors
811 MB lightx2v/Qwen-Image-Edit-2511-Lightning ModelTC / lightx2v
lora-lightning/
*-8steps-V1.0-bf16.safetensors
811 MB lightx2v/Qwen-Image-Edit-2511-Lightning ModelTC / lightx2v
split FP8 (19 GB) 19 GB mismo repo No descargar — no necesario
13

Los hallazgos clave: lo que no encontrarás documentado en ningún otro sitio

01
NF4 pre-cuantizado es el único camino viable. bitsandbytes dinámico, torchao y DiffSynth-Studio fallan por tres razones distintas e independientes. El modelo requiere pesos ya convertidos en disco — no cuantización en runtime.
02
El text encoder en la segunda GPU cuesta 1 segundo, no 7. CPU offload penaliza 7.3s porque mueve todos los componentes. Mover solo el text encoder a la RTX 3060 por PCIe cuesta 1s y libera 5 GB en la GPU principal.
03
La resolución no afecta al tiempo. 512×512 y 1024×1024 tardan exactamente lo mismo (~14.3s). El transformer opera en espacio latente fijo. No hay razón para generar a baja resolución.
04
Lightning + negative_prompt a ≥1024px rompe los colores. El modelo hace double-pass CFG que no puede reconciliar en 4 steps. La solución es true_cfg_scale=1.0 sin negative_prompt. Los resultados son completamente diferentes.
05
El modelo respeta la geometría de bocetos sin ControlNet. Comportamiento emergente del entrenamiento MMDiT — no documentado en el README oficial. Funciona para arquitectura y objetos geométricos; no para personas u orgánicos complejos.
06
Lightning + Angles LoRA combinados supera a Angles solo con 20 steps. Con 4 steps el modelo hace cambios conservadores que no generan anatomía errónea. Una vuelta 360° de 11 imágenes se completa en menos de 3 minutos.

Investigación realizada por Screen Art S.L. sobre hardware propio. Todos los benchmarks son mediciones reales, no estimaciones. Hardware: RTX 3090 Ti (24 GB) + RTX 3060 (12 GB) + 94 GB RAM. Marzo 2026.