مدل‌های زبانی بزرگ محلی در ابتدا بسیار سریع به نظر می‌رسند. یک مدل ۷ میلیاردی یا ۱۳ میلیاردی را بارگذاری می‌کنید، یک پرامپت کوتاه می‌فرستید و توکن‌ها با سرعتی مطلوب روی صفحه جاری می‌شوند. سپس یک بلوک کد طولانی را می‌چسبانید، یا تاریخچه چت شما در طول ده‌ها مرحله طولانی می‌شود، و مدل شروع به کند شدن می‌کند. این کندی به ندرت تدریجی است؛ بلکه مانند یک پرتگاه است. یک لحظه GPU در حال تولید توکن است و لحظه بعد، مانیتور سیستم شما نشان می‌دهد که فشار حافظه در حال افزایش است و تولید توکن با لرزش و کندی همراه می‌شود. شما نمی‌توانید دقیقاً با یک فرمول منظم پیش‌بینی کنید که این اتفاق چه زمانی رخ می‌دهد. تنها راهنمای قابل اعتماد شما، خودِ سخت‌افزار است.

هزینه پنهان زمینه (Context)

هر توکنی که تولید می‌کنید، وضعیت (state) جدیدی به KV cache اضافه می‌کند. این حافظه میان‌گیر، کلیدها و مقادیری را که در مراحل prefill و تولید محاسبه شده‌اند، ذخیره می‌کند و در کنار وزن‌های مدل، بافرهای attention و سربار زمان اجرا در حافظه قرار دارد. در یک GPU معمولی مصرف‌کننده با ۱۲ یا ۱۶ گیگابایت VRAM، در نهایت KV cache برای فضای مورد نیاز با بقیه موارد رقابت می‌کند. وقتی حافظه اختصاصی ویدئویی پر می‌شود، سیستم‌عامل خطا نمی‌دهد و متوقف نمی‌شود؛ بلکه بی‌صدا مازاد را به حافظه مشترک (shared memory) منتقل می‌کند و داده‌ها را از طریق گذرگاه PCIe بین GPU و RAM سیستم جابه‌جا می‌کند. آن گذرگاه برای انتقال فایل سریع است، اما در مقایسه با پهنای باند حافظه داخل یک کارت گرافیک، بسیار کند است. نتیجه، یک افت جزئی در عملکرد نیست، بلکه یک فروپاشی کامل است.

سه نشانه از رسیدن به پرتگاه

هنگام اجرای مدل، مانیتورهای سخت‌افزاری خود را زیر نظر داشته باشید. به محض اینکه عملکرد به پرتگاه رسید، سه نشانه واضح خواهید دید.

  • افزایش Shared VRAM. این حافظه‌ای است که درایور GPU از VRAM اختصاصی به مخزنی که توسط سیستم‌عامل میزبان مدیریت می‌شود، منتقل کرده است. لحظه‌ای که این معیار از صفر بالاتر می‌رود، یعنی از خط قرمز عبور کرده‌اید.
  • افزایش مصرف System RAM. داده‌های مازاد باید جایی فرود بیایند و آن مقصد، حافظه اصلی شماست. اگر مصرف RAM شما در حین تولید توکن‌ها توسط مدل افزایش می‌یابد، یعنی داده‌ها در حال تخلیه از GPU هستند.
  • کاهش سرعت Eval به نصف یا بیشتر. یک کندی ۱۰ درصدی ممکن است به معنای thermal throttling یا فرآیندهای پس‌زمینه باشد. اما افت ۵۰ درصدی یا بیشتر، به این معناست که گلوگاه از هسته‌های tensor cores به پهنای باند حافظه و تأخیر PCIe تغییر کرده است. وقتی می‌بینید سرعت تولید از دو رقم به یک رقم کاهش می‌یابد، یعنی از پرتگاه سقوط کرده‌اید.

چرا بنچمارک سریع شما احتمالاً در حال دروغ گفتن است

یک تست سریع (smoke test) به شما اعتماد به نفس کاذب می‌دهد. اگر مدل را با یک پرامپت صد توکنی بنچمارک کنید، نرخ خروجی خوبی ببینید و کار را تمام شده بدانید، در واقع مرحله «ماه عسل» را اندازه‌گیری کرده‌اید. در این حالت KV cache تقریباً خالی است و لایه‌ها تحت فشار یک prefill طولانی قرار نگرفته‌اند. ردپای واقعی حافظه تنها زمانی خود را نشان می‌دهد که مدل یک پرامپت قابل توجه را پردازش کرده و حافظه میان‌گیر به اندازه کاری واقعی خود پر شده باشد. شما باید با prefill عمیق و اجراهای طولانی تولید، تست انجام دهید. اجازه دهید زمینه (context) واقعاً انباشته شود. تنها در این صورت است که فشار حافظه تثبیت شده و محدودیت واقعی را به شما نشان می‌دهد.

یافتن محدودیت خود با llama.cpp

اگر مدل‌ها را از طریق llama.cpp اجرا می‌کنید، می‌توانید با یک محاسبات ساده و یک تست صبورانه، مرز خود را پیدا کنید.

۱. استفاده از حافظه مشترک را اندازه‌گیری کنید.
میزان VRAM اختصاصی پایه خود را با یک پرامپت حداقلی ثبت کنید، سپس یک وظیفه با زمینه طولانی (long-context) اجرا کرده و اوج مصرف را یادداشت کنید. مقدار پایه را از اوج کم کنید. تفاوت حاصل، همان مقداری است که از GPU شما به حافظه مشترک سیستم نشت کرده است.

۲. تغییرات (Delta) RAM خود را محاسبه کنید.
همین تفریق را برای System RAM انجام دهید. مقدار RAM پایه را از مقدار RAM در اوج مصرف طی اجرای طولانی کم کنید. این عدد دقیقاً به شما می‌گوید چه مقدار داده از کارت گرافیک به حافظه اصلی شما منتقل شده است. این عدد میزان نشت داده از طریق گذرگاه را کمی می‌کند.

۳. زمان فروپاشی سرعت Eval را مشخص کنید.
نرخ توکن در ثانیه پایه خود را با نرخ پس از اینکه مدل یک سند طولانی را پردازش کرد، مقایسه کنید. ممکن است ببینید وقتی زمینه تازه است، مدل با سرعت هفده توکن در ثانیه حرکت می‌کند، اما پس از متورم شدن حافظه میان‌گیر، تنها دو توکن در ثانیه ارائه می‌دهد. آن افت پانزده توکنی، اولین هشدار خطر برای شماست.

تعیین نقطه شکست با روش مثلث‌سازی

برای ترسیم دقیق منحنی، به یک نقطه داده‌ی تنها بسنده نکنید. سه آزمایش مجزا در ۱۶,۰۰۰ توکن، ۳۲,۰۰۰ توکن و ۶۵,۰۰۰ توکن انجام دهید. دو نقطه ممکن است نشان‌دهنده‌ی یک خط باشند، اما دو نقطه صرفاً یک حدس هستند. نقطه سوم ثابت می‌کند که آیا با نویز اندازه‌گیری روبرو هستید یا با یک دیوار حافظه (memory wall) واقعی. نتایج بین اجراها را از هم کم کنید تا محاسبه کنید هر هزار توکن اضافی، در ترکیب خاص شما از مدل، لایه‌ی کوانتیزاسیون (quantization layer) و GPU، چقدر حافظه اضافی مصرف می‌کند.

وقتی آن شیب را به دست آوردید، می‌توانید پیش‌بینی کنید. هزینه هر توکن را بردارید، آن را در طول کانتکست (context length) هدف ضرب کنید، برای تبدیل واحدها بر ۱۰۲۴ تقسیم کنید و نتیجه را به بار VRAM مدل پایه خود اضافه کنید. معادله به این صورت است:

بار VRAM مدل + (تعداد توکن‌ها × حافظه به ازای هر توکن ÷ ۱۰۲۴) = میزان استفاده تئوری از VRAM

این پیش‌بینی، پیشگویی نیست؛ بلکه راهنمایی است که از رفتار واقعی مدل استخراج شده است. از آن برای تخمین سقف توانایی خود، پیش از شروع یک اجرای کامل در محیط عملیاتی (production) استفاده کنید.

چرا فرمول‌های تئوری شکست می‌خورند و کوانتیزاسیون چه چیزی را می‌تواند اصلاح کند

فرمول‌های کتاب درسی، واقعیت‌های پیچیده‌ی استنتاج محلی (local inference) را نادیده می‌گیرند. معماری‌های مختلف، بافرهای توجه (attention buffers) را به شکل متفاوتی تخصیص می‌دهند. سیستم‌عامل شما مقداری از VRAM را برای درایور نمایشگر، کامپوزیتور (compositor) و کانتکست CUDA رزرو می‌کند. نسخه‌های مختلف درایور، میزان استفاده‌ی تهاجمی از حافظه مشترک (shared memory) را تغییر می‌دهند. یک معادله‌ی تئوری نمی‌تواند بداند در ساعت ۲ بعد از ظهر، در حالی که مرورگر شما پر از تب‌های باز است، چقدر VRAM واقعاً روی دستگاه شما آزاد است. شما باید مدل را روی سخت‌افزار خاص خود اجرا کنید و نشانگرها را زیر نظر بگیرید.

کوانتیزاسیون تسکینی نسبی ارائه می‌دهد. انتقال KV cache از f16 به q8_0، ردپای حافظه‌ی آن را نصف می‌کند، در حالی که دقت را برای تقریباً تمام وظایف کاربردی در سطح بالایی نگه می‌دارد. این تغییر به شما ظرفیت اضافی (headroom) می‌دهد، اما مصونیت ایجاد نمی‌کند. حافظه پنهان (cache) همچنان با هر توکنی که وارد می‌کنید، به صورت خطی رشد می‌کند. در نهایت، حتی با وجود اندازه‌ی کاهش‌یافته، حجم آن بر حافظه‌ی اختصاصی در دسترس شما غلبه کرده و سرریز به RAM سیستم آغاز می‌شود. فشار تنها زمانی متوقف می‌شود که پنجره‌ی کانتکست (context window) محدود شود یا جابجایی داده‌ها متوقف گردد.

نکته‌ی اصلی

به اسلایدهای بازاریابی، تعداد پارامترها یا محاسبات سرانگشتی اعتماد نکنید. مدل را بارگذاری کنید. مانیتور سیستم خود را باز کنید. یک رشته (thread) ۶۵,۰۰۰ توکنی اجرا کنید، بالا رفتن RAM را تماشا کنید و تعداد توکن‌ها در ثانیه را بشمارید. اعدادی که روی صفحه‌ی نمایش خاص شما و روی GPU خاص شما ظاهر می‌شوند، تنها اعدادی هستند که اهمیت دارند. کانتکست همیشه پیروز است. وظیفه‌ی شما این است که دقیقاً بدانید چه زمانی روی دستگاه شما پیروز می‌شود.