انتقل إلى المحتوى الرئيسي

الوحدة 9 — كلفة الحساب وتحسين الذاكرة

بعد ثمانِ وحدات من التوليد، لاحظنا: SDXL على 8 غيغا VRAM يرمي CUDA out of memory، كلّ صورة تحتاج 12 ثانية على RTX 4070 و2.5 دقيقة على GTX 1660، ومحاولة تشغيل ControlNet + Refiner معًا يُقفل الجهاز. هذه الوحدة تُعطي أدوات ملموسة لجعل Stable Diffusion يعمل على جهازك أيًّا كان، وحسابات دقيقة لتقدير كلفة الإنتاج.

أين تذهب الذاكرة

VRAM المُستهلَك في توليد SDXL نموذجيّ يتوزّع تقريبًا:

المكوّنfp32fp16
U-Net (2.6B معلمة)10.4 غيغا5.2 غيغا
مرمّزات النصّ (CLIP + OpenCLIP)2.6 غيغا1.3 غيغا
VAE0.7 غيغا0.35 غيغا
Latent + قيم انتباه (1024×1024)4-6 غيغا2-3 غيغا
إجماليّ نموذجيّ~18 غيغا~9 غيغا

الرقم الأخير يُفسّر لماذا SDXL في fp32 لا يعمل على أيّ بطاقة استهلاكيّة، ولماذا fp16 هو الافتراضيّ عمليًّا.

نصف الدقّة (fp16)

أرخص وأهمّ تحسين. بدل تخزين كلّ وزن في 32 بت (float32)، نخزّنه في 16 بت (float16). النتيجة:

  • نصف الذاكرة.
  • تسريع 30-50% على GPU حديثة (RTX 30xx وأعلى، A100)، بلا فرق ملموس على أقدم.
  • بلا خسارة بصريّة في 99% من الحالات.

في diffusers:

pipe = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
torch_dtype=torch.float16,
variant="fp16", # يحمّل الوزن المحفوظ أصلًا في fp16
).to("cuda")

variant="fp16" يحمّل ملفّات وزن أصغر ويوفّر ذاكرة النظام أيضًا.

xFormers: انتباه فعّال

بعض عمليّات U-Net الأكثر استهلاكًا للذاكرة هي «self-attention» و«cross-attention». مكتبة xFormers من Meta تعيد كتابتهما بطريقة أوفر ذاكرة (memory-efficient attention). التوفير: 30-40% إضافيّة على fp16.

pipe.enable_xformers_memory_efficient_attention()

قيود: تحتاج تثبيتًا صحيحًا (pip install xformers بنسخة متوافقة مع PyTorch وCUDA). على PyTorch 2.0+ التطبيق الأصليّ (Scaled Dot-Product Attention) يعطي نفس المكاسب تلقائيًّا، فـxFormers أقلّ ضرورة اليوم.

تقطيع الانتباه (attention slicing)

بدل حساب الانتباه على كامل المصفوفة دفعة واحدة، نُقطّعها إلى شرائح. توفير ذاكرة كبير، مقابل تباطؤ 10-20%. مفيد على GPU متواضعة:

pipe.enable_attention_slicing()

الجمع بين هذا وfp16 يُنزل SDXL إلى 6 غيغا VRAM بدل 9، مقابل تباطؤ محدود.

VAE tiling

لتوليد بدقّة عالية (1536×1536 وأعلى)، مرحلة VAE النهائيّة (فكّ latent إلى بكسل) تحتاج ذاكرة مفاجئة (10+ غيغا). VAE tiling يُقطّع هذا إلى مربّعات:

pipe.enable_vae_tiling()

بلا هذا، ستنفجر الذاكرة عند آخر خطوة توليد، بعد أن تكون قد أتمّت 30 خطوة U-Net. مؤلم جدًّا.

تفريغ CPU (CPU offload)

الحلّ الأقصى لـGPU صغيرة (4-6 غيغا). كلّ مكوّن (مرمّز النصّ، U-Net، VAE) يُنقَل إلى GPU حين يُستعمَل ثمّ يعود إلى RAM:

pipe.enable_model_cpu_offload()

يُنزل الحاجة إلى 4-5 غيغا VRAM لـSDXL، مقابل تباطؤ 3-5 أضعاف بسبب النقل. مقبول للاستكشاف، غير مقبول للإنتاج المستمرّ.

بديل أقصى: pipe.enable_sequential_cpu_offload() ينقل حتّى داخل U-Net، ينزل إلى 2-3 غيغا مقابل تباطؤ ×10.

الوصفة حسب VRAM المتاح

VRAMاستراتيجيّةزمن تقريبيّ (1024×1024، 30 خطوة)
4 غيغاSD 1.5 + fp16 + attention slicing + CPU offload60-120 ثانية
6 غيغاSDXL + fp16 + attention slicing + VAE tiling25-45 ثانية
8 غيغاSDXL + fp16 + attention slicing15-25 ثانية
12 غيغاSDXL + fp16 (كلّ شيء نشط، ControlNet ممكن)8-15 ثانية
24 غيغاSDXL + fp16 (Refiner + 2× ControlNet + LoRA معًا)6-12 ثانية

قياس الكلفة الاقتصاديّة

للإنتاج التجاريّ، كلفة الصورة الواحدة تُقاس بوقت GPU:

  • GPU سحابيّ (A100 40GB): حوالي 2 USD/ساعة. صورة SDXL بـ8 ثوانٍ = 0.0044 USD. مئة صورة = 0.44 USD.
  • GPU محلّيّ (RTX 4070، 200 W): 0.2 kWh/ساعة × 0.20 USD/kWh = 0.04 USD/ساعة تشغيل. مئة صورة بـ12 ثانية = 0.013 USD كهرباء (بدون احتساب استهلاك البطاقة).
  • خدمة API (Replicate, Stability API): 0.02-0.05 USD للصورة. بلا صداع تشغيل، لكن أغلى بترتيب من مقدار.

للكتالوج (200-500 صورة/شهر): GPU محلّيّ يستحقّ. للنماذج التجريبيّة القليلة: API يوفّر وقت الإعداد.

الخيط الأحمر: تحسين الأنبوب الإنتاجيّ

بعد الوحدة 7، أنبوب علامة الأثاث يُنتج صورة كلّ 15 ثانية على GPU 12 غيغا. تحسينات هذه الوحدة تُنزل الوقت إلى 8 ثوانٍ (fp16 + xFormers + torch.compile)، فيصير إنتاج 100 صورة كتالوج في 13 دقيقة بدل 25، وكلفة الكهرباء تحت السنت الواحد.

torch.compile (تسريع إضافيّ)

PyTorch 2.0+ يوفّر torch.compile() الذي يُترجم النموذج إلى نسخة مُحسَّنة عند أوّل استدعاء:

pipe.unet = torch.compile(pipe.unet, mode="reduce-overhead")

الاستدعاء الأوّل يستغرق دقيقة (تجميع)، الاستدعاءات التالية أسرع بـ20-30%. مثاليّ لخادم إنتاج يبقى مشتغلًا؛ لا يستحقّ لاستدعاء يوميّ واحد.

عدم الاستقرار

xFormers وtorch.compile يُدخلان أحيانًا تباينًا بصريًّا صغيرًا في النتيجة مقابل نفس البذرة، بسبب فروقات دقّة عائمة. للاختبار A/B الصارم للتعليمة، عطّلهما مؤقّتًا لضمان حتميّة كاملة.

الخلاصة

  • fp16 أرخص وأهمّ تحسين: نصف الذاكرة، بلا فقد بصريّ ملموس.
  • xFormers أو SDPA أصليّ يوفّران 30% إضافيّة على الانتباه.
  • attention slicing وVAE tiling وCPU offload أدوات متدرّجة لآلات محدودة الذاكرة.
  • الكلفة الفعليّة تحت السنت للصورة على GPU سحابيّ، وتحت الفلس على GPU محلّيّ إنتاجيّ.