آیا مطمئن هستید که تمام توکنهای مدل محلی شما روی GPU پردازش میشوند؟ بسیاری از این مدلها رازی تاریک دارند: سختافزار ممکن است بدون هیچ اطلاعی به کاربر، بار پردازشی را رها کرده و به CPU بسپارد.
Picchio، ابزار تشخیص جدیدی است که با تحلیل همزمان لاگهای نرمافزاری و تلهمتری سختافزاری سیستمعامل، این پدیده را که «پسنشینی خاموش CPU» (Silent CPU Fallback) نامیده میشود، شناسایی میکند. طبق گزارش نویسنده، این ابزار زمانی متولد شد که شکافی عظیم بین سرعت خام llama.cpp (۳۶ توکن در ثانیه) و سرعت در سطح اپلیکیشن (۱۱.۵ توکن در ثانیه) مشاهده شد. نویسنده با اجرای یک ماتریس ۳۲-سلولی (۳۲ حالت مختلف) شامل ترکیبات CPU و GPU و حالتهای «سرد» (Cold) و «گرم» (Warm)، دریافت که عدد ۳۶ توکن در ثانیه در هیچیک از سلولها تکرار نمیشود؛ او متوجه شد که آن عدد در واقع مربوط به یک «باند» یا مسیر پردازشی دیگر بود که به اشتباه به عنوان سرعت تولید متن در یاد گرفته شده بود.
اندازهگیری استنتاج (Inference) — که شبیه لحظهٔ خودِ آشپزی است و نه دورهی آموزش آشپز — در محیطهای محلی بهشدت نادقیق است. اکثر کاربران تنها به عدد «توکن در ثانیه» (tok/s) بسنده میکنند، اما این معیار اغلب شکستهای بحرانی در سرعت پیشپر کردن یا مشکلات پنهان انتقال داده را میپوشاند. همانطور که در تحلیلهای پیشین ما دربارهی بهینهسازی مدلهای بازمتن اشاره کردیم، گذار به استکهای تولیدی محلی نیازمند ابزارهای نظارتی دقیق است. Picchio برای این منظور، عملکرد را به جای یک عدد واحد، به یک سیستم سه بانهای تقسیم میکند:
- پیشپر کردن (Prefill / Prompt Processing): سرعت خواندن پرامپت اولیه توسط مدل. این پارامتر زمان رسیدن به اولین توکن (Time to First Token) را در پرامپتهای طولانی تعیین میکند. اگر در اسکرینشاتهای مک عددی مثل ۵۰۰ توکن در ثانیه میبینید، تقریباً همیشه مربوط به این بخش است، نه تولید متن.
- رمزگشایی (Decode / tg or eval): سرعت واقعی نوشتن پاسخ توسط مدل.
- ساعت دیواری (Wallclock): مجموع توکنهای تولید شده تقسیم بر کل زمان، شامل زمان بارگذاری و گرم شدن.
این سه مسیر بهطور مجزا شکست میخورند. برای مثال، طبق مستندات Picchio، از دست دادن دسترسی به GPU میتواند هزینهٔ پیشپر کردن را ۲۲ برابر افزایش دهد، در حالی که هزینهٔ رمزگشایی در همان فایل مدل، کمتر از ۲ برابر شود.
برای شکار این اختلالات، Picchio در یک رشته (Thread) پسزمینه، نمایشگر GPU سیستمعامل را رصد میکند. در macOS از دستور ioreg با فرکانس ۴ هرتز و شمارندههای انرژی powermetrics (بدون نیاز به دسترسی sudo) استفاده میکند و در لینوکسهای NVIDIA، از درایور NVML بهره میگیرد. ابزار بر اساس این تلهمتری، یکی از سه حکم زیر را صادر میکند:
۱. شواهد متناقض (CONFLICTING EVIDENCE / exit 5): مدل ادعای انتقال کامل (Full Offload) به GPU را دارد، اما تلهمتری سیستم نشان میدهد که نمودار GPU کاملاً تخت مانده و فعالیتی نداشته است.
۲. پسنشینی خاموش (SILENT CPU FALLBACK / exit 4): بیلد مدل هیچ شواهدی از حضور GPU در لاگها چاپ نمیکند، در حالی که نمایشگر سیستم نشان میدهد GPU در حالت بیکار (Idle) است.
۳. سالم (HEALTHY / exit 0): هیچ شواهدی از شکست در انتقال یا پردازش یافت نشد.
علاوه بر سختافزار، Picchio برچسبهای کوانتش (Quantization) — که شبیه فشردهسازی یک فایل عکس برای اشغال فضای کمتر است اما با حفظ جزئیات — را به چالش میکشد. این ابزار با پیمایش جدول تنسورهای GGUF و قیمتگذاری هر تنسور بر اساس نوع ggml آن، دقت این برچسبها را میسنجد. نویسنده دریافت که چهار نسخه مختلف از مدل Qwen3.5-9B که همگی برچسب «Q4_K_M» داشتند، در واقع در ۴۲۷ تنسور مشترک، مقادیر ۵.۰۲، ۵.۰۲، ۵.۰۷ و ۵.۲۷ بیت بهازای هر وزن مصرف میکردند.
این یعنی برچسب «۴ بیتی» اغلب مصرف واقعی حافظه را کمتر از حد واقعی نشان میدهد. یک نمونه specific از Q4_K_M حدود ۵.۰۷ بیت بهازای هر وزن مصرف میکرد که ۲۷٪ بیشتر از برچسبش بود و شامل ترکیبی از پنج نوع تنسور با محدوده ۴.۵۰ تا ۳۲.۰۰ بیت میشد. ابزار Picchio پیش از چاپ نتایج، تأیید میکند که آفستهای بایتی در هدر با مجموع نهایی مطابقت داشته باشند.
همچنین برچسبها در توصیف مجموعه تنسورها شکست میخورند. ممکن است یک کوانتایزر، یک سر MTP با ۲۴۳ میلیون پارامتر (با نوع q8_0) را در فایل اصلی قرار دهد، در حالی که کوانتایزر دیگر آن را در یک مخزن جداگانه ارسال کند. در مدلهای ترکیب خبرهها (MoE)، Picchio تعداد خبرههای فعال در هر توکن را گزارش میدهد؛ مثلاً در یک تست با فایل id-35b.txt، مشاهده شد که تنها ۸ خبره از ۲۵۶ خبره فعال بودند که یعنی حدود ۳.۵ میلیارد پارامتر از ۳۴.۷ میلیارد پارامتر در هر توکن به کار گرفته شدند. چنین بهینهسازیهایی در مدیریت حافظه و پارامترها، یادآور تلاشهایی چون پروژهی Colibrì برای اجرای مدلهای غولپیکر ۷۴۴ میلیارد پارامتری با رم بسیار محدود است تا بهرهوری سختافزاری به حداکثر برسد.
نصب این ابزار با یک دستور ساده curl انجام میشود:curl -fsSLO https://raw.githubusercontent.com/logxio/picchio/main/picchio.pypython3 picchio.py
در صورت عدم ارائه آرگومان، ابزار بهطور خودکار مدلها را در تگهای ollama، پوشههای جاری و کشهای HF یا LM Studio مییابد. این برنامه سه پاس (Pass) را با یک پرامپت ثابت اجرا میکند که پاس اول همیشه «سرد» (Cold) است. هر اجرا حدود یک دقیقه با GPU و چندین دقیقه با CPU زمان میبرد و نتایج را در یک فایل کش در مسیر ~/.cache/picchio مینویسد.
برخی از قابلیتهای کلیدی و دستورات این ابزار عبارتند از:
picchio model.gguf: تشخیص کامل llama.cpp شامل سه پاس تست، بررسی جایگاه حافظه، تجزیه و تحلیل استارت سرد و حکم نهایی.picchio qwen3.5:9b: اجرای پاسها از طریق یک سرور محلی ollama. جایگاه حافظه از روی تقسیم حافظه گزارش شده استخراج میشود.picchio http://127.0.0.1:8080: اندازهگیری یک llama-server که از قبل در حال اجراست؛ این دستور فقط ردیفهای «گرم» را میسنجد و چیزی را لانچ نمیکند.picchio guard -- <command>: پوشش دادن هر دستوری و هشدار فوری در صورت خروج لایهها از GPU، بدون اینکه پروسه را متوقف کند.picchio id MODEL: تجزیه برچسب کوانت برای گزارش بیتهای مؤثر بهازای هر وزن، ترکیب انواع تنسور و نوع داده KV.picchio plan [MODEL]: استفاده از هدر GGUF برای پیشبینی اینکه آیا مدل در حافظه جای میگیرد یا خیر. تخمین رمزگشایی پس از اولین اجرای اندازهگیری اضافه میشود.picchio compare A.txt B.txt: مقایسه دو بلوک ذخیرهشده؛ در این حالت، اولین تفاوت در پیکربندی به عنوان دلیل تفاوت عملکرد معرفی میشود.picchio verify FILE: بررسی اینکه آیا یک بلوک متنی کپی شده، حاوی اعدادی است که با هم تناقض دارند یا خیر.picchio watch [PID]: متصل کردن نمایشگر GPU سیستمعامل به یک پروسه خاص یا کل GPU (مخصوص macOS و بدون تحلیل لاگهای موتور).picchio model.gguf --ctx-sweep: اندازهگیری مجدد مسیرها در چندین عمق مختلف کانتکست برای گزارش شیب کاهش سرعت.
برای دقت بیشتر، Picchio پرچمهای (Flags) متعددی دارد:
--passes N: تنظیم تعداد پاسهای اندازهگیری (پیشفرض ۳).--keep-logs DIR: ذخیره خروجی خام موتور و منحنی GPU در فایلtelemetry.json(برای macOS و لینوکس NVIDIA).--no-telemetry: نادیده گرفتن نمونهبرداری از GPU سیستمعامل و اتکای حکم نهایی تنها به موتور و زمانبندی.--json: خروجی اندازهگیریها به صورت ماشینخوان.--bin PATH: امکان تعیین یک فایل باینری سفارشی برای llama.cpp.--selftest: بازپخش لاگهای خام از مسیرexamples/raw/برای تأیید بلوکهای حکم صادر شده.
در اسکریپتنویسی، ابزار از کدهای خروج خاصی استفاده میکند: ۰ برای سالم، ۲ برای عدم اجرای موفق، ۳ برای انتقال جزئی (Partial Offload)، ۴ برای پسنشینی خاموش و ۵ برای شواهد متناقض. دستور guard کد خروج دستورِ پیچیده شده را پاس میدهد (۱۲۸ + سیگنال).
در بنچمارکهای مقایسهای روی یک Apple M5 (با ۳۲ گیگابایت رم، macOS 26.5.1) با استفاده از llama.cpp build 9430 و ollama 0.31.1، با حدود ۷۳۰ توکن پرامپت و ۱۲۸ توکن تولید شده در هر پاس (پروتکل mp1)، نتایج زیر حاصل شد:
| دستگاه | مدل | موتور | پیشپر کردن | رمزگشایی | ساعت دیواری | حکم |
|---|---|---|---|---|---|---|
| Apple M5 | Qwen3.5-9B Q4_K_M | llama.cpp | 588.0 | 21.1 | 15.5 | HEALTHY |
| Apple M5 | همان، اجبار به CPU | llama.cpp | 26.8 | 12.2 | 3.0 | SILENT CPU FALLBACK |
| Apple M5 | qwen3.5:9b | ollama | 833.8 | 21.3 | 18.1 | HEALTHY |
| Apple M5 | Qwen3.6-35B-A3B | llama.cpp | 787.3 | 34.4 | 19.1 | HEALTHY |
| Apple M5 | qwen3.6:35b-a3b | ollama | 1191.8 | 33.4 | 27.6 | HEALTHY |
| RTX 4090 | Qwen3.5-9B Q4_K_M | llama.cpp | 6763.3 | 138.0 | 25.2 | HEALTHY |
نکته قابل توجه این است که مدل MoE با ۳۵ میلیارد پارامتر، ۱.۶ برابر سریعتر از مدل ۹ میلیارد پارامتری متراکم (Dense) رمزگشایی کرد. با این حال، این مدل از مشکلات زمان بارگذاری رنج میبرد: ۱۳ ثانیه از ۱۹ ثانیه اولین پاس، صرف خواندن ۲۰.۶ گیگابایت وزنها شد.
برای توسعهدهندگان، برچسب روی فایل GGUF دیگر منبع قابل اعتمادی نیست. تفاوت در نحوه مدیریت انواع تنسورها توسط کوانتایزرهای مختلف باعث میشود دو فایل با نام یکسان، نیازهای حافظهای متفاوتی داشته باشند. این چالشهای سطح پایین در مدیریت حافظه و سختافزار، اهمیت درک عمیق از نحوه تعامل مدل با GPU را دوچندان میکند؛ همانطور که در بررسی ساخت یک مدل GPT-2 از صفر با زبان C و CUDA دیدیم، مدیریت دستی منابع تنها راه رسیدن به بهینهترین عملکرد است. این موضوع هنگام مقایسه llama-bench با Picchio مشهود است؛ llama-bench سقوط ۲۱ برابری سرعت پرامپت در CPU را نشان میدهد اما هیچ اطلاعاتی درباره زمان بارگذاری، تفکیک سرد/گرم یا حکم نهایی ارائه نمیدهد.
این ابزار، بنچمارکهای مدلهای محلی را از «ادعاهای حداکثری» به «حسابرسی فنی» تبدیل میکند. با افشای پسنشینیهای خاموش، Picchio گفتگوهای صادقانهتری را درباره اینکه آیا «انتقال کامل به GPU» واقعاً اتفاق میافتد یا خیر، ایجاد میکند. اگر در حال استقرار مدلهای محلی هستید، اتکا به لاگهای موتور به تنهایی یک ریسک است. تطبیق این لاگها با تلهمتری سختافزاری، تنها راه تضمین این است که کاربران با گلوگاه CPU مواجه نشوند.
گام بعدی شما
- اگر مدلهای محلی را روی سختافزارهای مختلف مستقر میکنید، Picchio را برای تأیید واقعی Full GPU Offload اجرا کنید.
- برچسبهای 4-bit را به صورت مطلق قبول نکنید و با دستور
picchio idمقدار واقعی بیتها را بسنجید. - از قابلیت
guardبرای مانیتور کردن لایههای مدل در حین توسعه اپلیکیشن استفاده کنید تا از افت ناگهانی سرعت مطلع شوید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو