وبلاگ نت‌آرامآموزش، تجربه و راهکارهای زیرساخت

NUMA چیست و چرا دسترسی حافظه سرور چندپردازنده‌ای کند می‌شود؟

آموزش بررسی گره‌های NUMA، پردازش و حافظه محلی و آزمایش سنجیده سیاست numactl در سرور اختصاصی.

انتشار:
توسط تیم فنی نت‌آرام
۶ دقیقه زمان مطالعه
۰ دیدگاه
محتوای تخصصی، ساده و کاربردی
هماهنگ با هویت حرفه‌ای نت‌آرام
بازگشت به لیست مقالات
تصویر شاخص مقاله NUMA چیست و چرا دسترسی حافظه سرور چندپردازنده‌ای کند می‌شود؟ در وبلاگ نت‌آرام
محتوای آموزشی وبلاگ نت‌آرام
یک برنامه روی سرور اختصاصی ایران با چند پردازنده اجرا می‌شود، اما با وجود CPU و RAM کافی، تأخیر آن بالا است. یکی از علت‌های ممکن، محل استفاده از حافظه در معماری NUMA است. در این معماری هر پردازنده یا مجموعه‌ای از هسته‌ها به بخشی از حافظه نزدیک‌تر است. دسترسی به حافظه متصل به گره دیگر می‌تواند هزینه بیشتری داشته باشد.
NUMA همیشه مشکل نیست و پراکندگی حافظه روی چند گره هم به‌تنهایی خطا محسوب نمی‌شود. برنامه‌های چندرشته‌ای و داده‌های بزرگ ممکن است از چند گره بهره ببرند. هدف این راهنما اندازه‌گیری و مقایسه در شرایط مشابه است، نه مجبورکردن همه برنامه‌ها به استفاده از یک گره.

۱. قبل از تغییر، نوع سرور و بار را مشخص کنید

در ترمینال لینوکس اجرا کنید:
کد / دستورlscpu numactl --hardware
دستور اول تعداد CPUها و اطلاعات معماری را نشان می‌دهد؛ دومی گره‌های NUMA، CPUهای هر گره، حافظه و فاصله نسبی گره‌ها را فهرست می‌کند. اگر numactl نصب نیست، بسته معتبر همان توزیع را با هماهنگی نصب کنید. در بعضی سرورها فقط یک node دیده می‌شود؛ در این صورت این مقایسه چندگره‌ای کاربرد ندارد. در محیط مجازی، توپولوژی مهمان ممکن است با میزبان فیزیکی فرق کند و محدودیت‌های مجازی‌ساز مهم‌اند.
برنامه، حجم کار، تعداد درخواست هم‌زمان و زمان پاسخ در دوره عادی و دوره کند را ثبت کنید. تأخیر دیسک، شبکه، قفل نرم‌افزار و محدودیت CPU هم می‌توانند همان علامت را بسازند. مقایسه بدون کنترل این عوامل ممکن است علت اشتباهی را نشان دهد.

۲. ببینید برنامه روی کدام CPUها کار می‌کند

PID نمونه را با شناسه واقعی برنامه جایگزین کنید:
کد / دستورps -L -p 1234 -o pid,tid,psr,comm taskset -cp 1234
دستور اول threadها و CPU ثبت‌شده برای هرکدام را در همان لحظه نشان می‌دهد؛ psr تاریخچه کامل اجرا نیست و thread می‌تواند جابه‌جا شود. دستور دوم مجموعه CPUهای مجاز پردازش را نشان می‌دهد، نه اینکه تمام زمان روی آن‌ها اجرا شده باشد. با فهرست CPUهای هر node در خروجی numactl --hardware مقایسه کنید. اگر برنامه چند thread دارد، محدودیت هر thread و cgroup یا تنظیم‌های خود برنامه را نیز در نظر بگیرید.
برای دیدن گروه کنترلی پردازش، cat /proc/1234/cgroup را با PID واقعی اجرا کنید. تنظیم cpuset یا مجازی‌ساز ممکن است تعداد CPU و گره حافظه قابل استفاده را محدود کند. تغییر affinity بدون توجه به آن‌ها می‌تواند نتیجه آزمون را مخدوش یا اجرای برنامه را ناممکن کند.

۳. توزیع حافظه را با گره‌های CPU مقایسه کنید

کد / دستورnumastat -p 1234 numastat
دستور اول حافظه منتسب به پردازش را به تفکیک node نشان می‌دهد. دستور دوم شمارنده‌های کل سیستم را نمایش می‌دهد. حافظه موجود روی node ۱ به‌تنهایی ثابت نمی‌کند thread همیشه از حافظه دور استفاده کرده است؛ محل اجرا و حافظه می‌توانند در طول زمان تغییر کنند و برخی صفحه‌ها مشترک باشند. چند نمونه در دوره کندی بگیرید و با زمان پاسخ برنامه و محل threadها کنار هم بگذارید.
شمارنده‌های numa_hit و numa_miss درباره موفقیت تخصیص نسبت به گره ترجیحی‌اند؛ local_node و other_node به محل تخصیص در مقایسه با CPU مربوط می‌شوند. این شمارنده‌ها آمار کل هستند و جای اندازه‌گیری مستقیم تأخیر برنامه را نمی‌گیرند. مستند کرنل درباره شمارنده‌های NUMA تعریف دقیق آن‌ها را توضیح می‌دهد.

۴. اگر شواهد به محل حافظه اشاره دارند، آزمایش مقایسه‌ای بسازید

روی محیط آزمایشی با داده غیرحساس و منابع مشابه، یک کار واقعی قابل تکرار را انتخاب کنید. ابتدا بدون سیاست اضافی چند بار آن را اجرا و زمان، throughput، خطا و مصرف حافظه هر node را ثبت کنید. سپس فقط اگر node صفر CPU و حافظه کافی و مجاز دارد، می‌توانید نسخه آزمایشی همان برنامه را با سیاست محدود اجرا کنید:
کد / دستورnumactl --cpunodebind=0 --membind=0 /path/to/test-program
مسیر و پارامترهای برنامه آزمایشی خودتان را جایگزین کنید؛ مثال، فرمان آماده برای سرویس تولیدی نیست. cpunodebind اجرای پردازش را به CPUهای node مشخص محدود می‌کند و membind تخصیص حافظه را به آن node محدود می‌کند. طبق راهنمای numactl، اگر حافظه کافی در node انتخاب‌شده نباشد، تخصیص می‌تواند شکست بخورد حتی اگر node دیگر فضای آزاد داشته باشد. این سیاست در زمان اجرای فرمان آزمایشی اعمال می‌شود و جابه‌جایی خودکار همه حافظه یک پردازش از قبل اجراشده را تضمین نمی‌کند.
کار آزمایشی باید داده، تعداد درخواست و مدت یکسانی با آزمون قبلی داشته باشد. هر دو حالت را چند بار اجرا کنید و میانگین، صدک تأخیر و خطاها را مقایسه کنید. اگر محدودکردن به یک node سرعت را کاهش داد یا حافظه تمام شد، همان نتیجه نشان می‌دهد این سیاست برای آن بار مناسب نیست.

۵. راهکار را متناسب با برنامه انتخاب کنید

اگر برنامه از تنظیم داخلی NUMA، workerهای جدا یا استقرار چند نمونه پشتیبانی می‌کند، ابتدا راهنمای همان برنامه را بخوانید. ممکن است اجرای نمونه‌های جدا با CPU و حافظه متناسب هر گره بهتر باشد؛ ممکن است نیز به‌خاطر نیاز زیاد حافظه یا ارتباط بین threadها بدتر عمل کند. سیاست interleave یا ترجیح محلی نیز گزینه‌هایی با رفتار متفاوت‌اند و باید در بار واقعی آزموده شوند.
چیدمان فیزیکی ماژول‌های RAM طبق راهنمای سازنده سرور نیز مهم است. حافظه نامتوازن، ماژول خراب یا تنظیم firmware می‌تواند ظرفیت هر node را تغییر دهد. برای تغییر سخت‌افزار از مسئول دیتاسنتر بخواهید مدل، چیدمان مجاز و وضعیت سلامت را بررسی کند؛ از جابه‌جایی ماژول روی سرور روشن بدون پشتیبانی سازنده خودداری کنید.
اگر NUMA عامل اصلی نبود، به زمان انتظار دیسک، قفل برنامه، فشار حافظه و شبکه برگردید. برای تشخیص محدودیت یک سرویس systemd، راهنمای MemoryMax یک علت متفاوت را بررسی می‌کند.

۶. اعمال تولیدی و بازگشت

فقط پس از نتیجه قابل تکرار در آزمایش، تغییر را با مالک سرویس در پنجره مناسب، به روش پشتیبانی‌شده برنامه یا واحد systemd برنامه‌ریزی کنید. تنظیم قبلی و روش بازگشت را ثبت کنید. محدودکردن CPU یا حافظه می‌تواند روی سایر بارهای سرور و زمان راه‌اندازی اثر بگذارد؛ آن را به همه سرویس‌ها تعمیم ندهید.
پس از اعمال، همان شاخص‌های برنامه و توزیع حافظه را زیر بار واقعی ببینید. اگر خطا، کمبود حافظه یا تأخیر بدتر شد، سیاست قبلی را در زمان مجاز بازگردانید و دوباره آزمایش کنید. هدف، بهبود قابل اندازه‌گیری سرویس است، نه صرفاً تغییر یک عدد NUMA.
اشتراک‌گذاری:
لینکدینتلگرامایکس

دیدگاه‌ها (۰)

دیدگاه‌های تاییدشده و پاسخ‌های تیم نت‌آرام