حافظه پنهان قربانی

حافظه پنهان قربانی (Victim cache) یک حافظه نهان (کَش) کوچک و معمولاً با تداعی کامل (fully associative) است که در مسیر بازآوری (refill path) یک حافظه پنهان پردازنده قرار می‌گیرد. این حافظه تمام بلوک‌هایی را که از آن سطح از حافظه پنهان بیرون انداخته (evicted) شده‌اند در خود ذخیره می‌کند و در اصل در سال ۱۹۹۰ پیشنهاد شد. در معماری‌های نوین، این وظیفه معمولاً توسط حافظه‌های پنهان سطح ۳ (L3) یا سطح ۴ (L4) انجام می‌شود.

 نمای کلی 
استفاده از حافظه پنهان قربانی یک تکنیک سخت‌افزاری برای بهبود عملکرد حافظه‌های پنهان است که توسط نورمن جوپی (Norman Jouppi) پیشنهاد شد. همان‌طور که در مقاله او ذکر شده است:«کَش کردن خطاها (Miss caching) یک حافظه پنهان با تداعی کامل را بین کَش اصلی و مسیر بازآوری آن قرار می‌دهد. خطاهایی در کَش که در “کَشِ خطا” (miss cache) پیدا می‌شوند، تنها یک چرخه (cycle) جریمه دارند، در حالی که بدون کَش خطا، جریمه این خطا شامل چرخه‌های متعددی می‌شود. حافظه پنهان قربانی در واقع بهبودی بر روش کش کردن خطاها است که این حافظه پنهانِ کوچک با تداعی کامل را، به جای خط کَش درخواست‌شده، با “قربانیِ” یک خطا (یعنی بلوک بیرون‌انداخته‌شده) پر می‌کند.»حافظه پنهان قربانی یک کَش سخت‌افزاری است که برای کاهش خطاهای تداخلی (conflict misses) و بهبود تأخیر در حافظه‌های پنهان با نگاشت مستقیم (direct-mapped caches) طراحی شده است. این کَش در مسیر بازآوری یک حافظه پنهان سطح ۱ (L1) استفاده می‌شود، جایی که هر خطِ کش (cache-line) که از کش اصلی بیرون انداخته می‌شود، در حافظه پنهان قربانی ذخیره می‌گردد. در نتیجه، حافظه پنهان قربانی تنها زمانی پر می‌شود که داده‌ها از حافظه پنهان سطح ۱ بیرون انداخته شوند. هنگامی که در کش سطح ۱ خطایی (miss) رخ می‌دهد، داده مورد نظر در حافظه پنهان قربانی بررسی می‌شود. اگر داده در آنجا یافت شود (hit)، محتویات خطِ کش سطح ۱ و خطِ کش قربانی مربوطه با یکدیگر جابه‌جا (swap) می‌شوند.

اگرچه این روش در ابتدا توسط جوپی برای بهبود عملکرد کَش سطح ۱ با نگاشت مستقیم پیشنهاد شد، اما ریزپردازنده‌های امروزی با سلسله‌مراتب کَش چندسطحی، از کش سطح ۳ یا سطح ۴ استفاده می‌کنند تا به عنوان حافظه پنهان قربانی برای کَشِ سطح بالاترِ خود در سلسله مراتب حافظه عمل کنند. معماری کریستال ول (Crystal Well) اینتل در پردازنده‌های هسول (Haswell) یک کَش سطح ۴ (روی پردازنده) معرفی کرد که به عنوان حافظه پنهان قربانی برای کش سطح ۳ عمل می‌کند. همچنین در ریزپردازنده‌های POWER5 (محصول IBM)، یک کش سطح ۳ با ظرفیت ۴ تا ۱۲ مگابایت به عنوان حافظه پنهان قربانی استفاده می‌شود.

 پیش‌ زمینه 
با پیشرفت فناوری و معماری سخت‌افزار، عملکرد و فرکانس پردازنده‌ها با سرعت بسیار بیشتری نسبت به زمان چرخه حافظه (Memory cycle times) افزایش یافت که منجر به ایجاد یک شکاف عملکردی قابل‌توجه شد. چالش افزایش تأخیر حافظه در مقایسه با سرعت پردازنده، با استفاده از حافظه پنهان (کش) پرسرعت برطرف شده است.

حافظه‌های پنهان با نگاشت مستقیم (Direct-mapped) نسبت به حافظه‌های پنهان مجموعه‌ای-تداعی‌گر (Set-associative) زمان دسترسی سریع‌تری دارند. با این حال، در کش‌های نگاشت مستقیم، هنگامی که چندین بلوک کش در حافظه به یک خط کش (Cache line) یکسان نگاشت می‌شوند، هر بار که به یکی از آن‌ها دسترسی پیدا می‌شود، یکدیگر را از کش بیرون می‌اندازند. این مسئله که با عنوان مشکل تداخل کش (Cache-conflict) شناخته می‌شود، به دلیل تداعی (Associativity) محدود حافظه پنهان به وجود می‌آید. افزایش میزان تداعی کش می‌تواند این مشکل را کاهش دهد، اما پیچیدگی‌های پیاده‌سازی و محدودیت‌هایی برای میزان افزایش این تداعی وجود دارد. برای رفع مشکل تداخل در شرایطی که با محدودیت تداعی حافظه پنهان مواجه هستیم، اغلب از حافظه پنهان قربانی (Victim cache) استفاده می‌شود.

 پیاده‌ سازی 
رفتار حافظه پنهان قربانی در تعامل با سطح متناظر آن در حافظه پنهان، در ادامه آورده شده است:

 اصابت به حافظه پنهان (Cache Hit): هیچ اقدامی صورت نمی‌گیرد.
 نقصان در حافظه پنهان، اصابت به حافظه پنهان قربانی (Cache Miss, Victim Hit): بلوک موجود در حافظه پنهان قربانی و بلوک موجود در حافظه پنهان اصلی با یکدیگر جابه‌جا (Replace) می‌شوند. این ورودی جدید در حافظه پنهان قربانی، به عنوان جدیدترین بلوک استفاده‌شده (Most Recently Used) در نظر گرفته می‌شود.
 نقصان در حافظه پنهان، نقصان در حافظه پنهان قربانی (Cache Miss, Victim Miss): بلوک از سطح بعدیِ حافظه به حافظه پنهان آورده می‌شود. بلوک اخراج‌شده از حافظه پنهان اصلی، در حافظه پنهان قربانی ذخیره می‌گردد.

 مثال 
بندانگشتی|مثال پیاده‌سازی
یک حافظه پنهان سطح ۱ (L1) با نگاشت مستقیم (Direct-mapped) را در نظر بگیرید که در آن بلوک‌های A و B به یک مجموعه (Set) یکسان اشاره می‌کنند. این حافظه پنهان به یک حافظه پنهان قربانیِ تماماً انجمنی (Fully associative) با ۲ ورودی متصل است که حاوی بلوک‌های C و D می‌باشد.

دنباله دسترسی‌ها به این صورت است: A, B, A, B…

همان‌طور که در نمودار مشاهده می‌شود، در صورت اصابت به حافظه پنهان قربانی (VC hit)، بلوک‌های A و B با یکدیگر جابه‌جا می‌شوند. بلوکی که در حافظه پنهان قربانی دارای کمترین استفاده اخیر (Least Recently Used) بوده است، به همان حالت باقی می‌ماند. بنابراین، این امر توهمی از وجود ویژگی انجمنی (Associativity) را برای حافظه پنهان L1 با نگاشت مستقیم ایجاد می‌کند که به نوبه خود باعث کاهش نقصان‌های ناشی از تداخل (Conflict misses) می‌شود.

در حالتی که دو حافظه پنهان L1 و L2 با سیاست حافظه پنهان انحصاری (Exclusive cache policy) وجود داشته باشند (L2 مکان‌های حافظه یکسانی با L1 را کَش نمی‌کند)، حافظه پنهان L2 به عنوان حافظه پنهان قربانی برای L1 عمل می‌کند.

 پیامدهای کارایی 
در هنگام اندازه‌گیریِ میزان بهبودِ کارایی حاصل از به‌کارگیری حافظه پنهان قربانی، نورمن جوپی (Jouppi) یک حافظه پنهان سطح ۱ با نگاشت مستقیم (Direct-mapped) را در نظر گرفت که با یک حافظه پنهانِ تماماً انجمنی (Fully associative) تقویت شده بود. برای مجموعه آزمایشی که وی استفاده کرد، مشخص شد که به‌طور میانگین ۳۹ درصد از نقصان‌های حافظه پنهانِ داده (Data cache misses) در سطح ۱ از نوع نقصان‌های تداخلی (Conflict misses) هستند، در حالی که این رقم برای نقصان‌های دستورالعمل (Instruction misses) در سطح ۱ به‌طور میانگین ۲۹ درصد است.از آنجا که نقصان‌های تداخلی درصد بالایی از کل نقصان‌ها را تشکیل می‌دهند، بنابراین فراهم کردنِ ویژگیِ انجمنیِ (Associativity) بیشتر از طریقِ تقویت حافظه پنهان سطح ۱ با یک حافظه پنهان قربانی، به‌طور قطع نرخ نقصان (Miss rate) کل را به‌طور قابل‌توجهی بهبود می‌بخشد.

نتایج تجربی با در نظر گرفتن یک حافظه پنهان ۳۲ کیلوبایتی (در حالت‌های نگاشت مستقیم، ۲-راهه و تماماً انجمنی) که با یک حافظه پنهان قربانیِ ۲۵۶ بلوکی (۸ کیلوبایتی) تقویت شده و با اجرای ۸ بنچمارک SPEC95 که به‌طور تصادفی انتخاب‌شده بودند، به دست آمده‌اند. اگرچه این نتایج را نمی‌توان به تمامی بنچمارک‌ها تعمیم داد، اما افزودن یک حافظه پنهان قربانی، باعث کاهش نرخ نقصان بین ۱۰٪ تا ۱۰۰٪ برای تمامی پیکربندی‌های حافظه پنهان می‌شود. با این حال، به نظر می‌رسد میزان این بازدهی پس از رسیدنِ اندازه حافظه پنهان قربانی به ۵۰ بلوک، ثابت می‌شود (Level off) و به این ترتیب، مشاهدات جوپیمبنی بر اینکه مزایای حافظه پنهان قربانی پس از چند بلوکِ نخستِ آن به یک حد ثابت (Plateau) می‌رسد را اثبات می‌کند.

مشخص شده است که میزان کاهشِ نرخِ نقصان برای حافظه پنهانی با اندازه ۶۴ کیلوبایت به مراتب کمتر است، که این امر ثابت می‌کند استفاده از حافظه پنهان قربانی به‌طور نامحدود مقیاس‌پذیر (Scalable) نیست.

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

 منابع