تقریبا تمام پردازندهها از پردازندههای کممصرف و کمتوانی مانند Cortex-A5 آرم تا پردازندههای قدرتمندی همچون Core i7 اینتل همگی از حافظهی پرسرعتی به نام کش (Cache) بهره میبرند. حتی میکروکنترلرهای رده بالا نیز عموما کَشِ کوچکی دارند. با وجود اینکه در طراحی آنها مصرف انرژی اهمیت زیادی دارد و کش نیز انرژی مصرف میکند، اما مزیتهای حافظهی کش آنقدر مهم هستند که استفاده از کش را توجیه میکند.
کشینگ و استفاده از کش اختراع شد تا یک مشکل جدی را حل کند. در دهههای اولیهی ظهور کامپیوتر، حافظهی اصلی به شدت کند و بسیار گران بود و از طرفی پردازندهها نیز چندان سریع نبودند. در دههی ۱۹۸۰ اختلاف سرعت بین حافظه و پردازنده افزایش یافت و سرعت کلاکِ میکروپروسسورها مدام در حال افزایش بود. در این شرایط همچنان حافظهها کند بودند و در واقع نمیتوانستند پا به پای پردازندهها دسترسی به اطلاعات را فراهم کنند. اینجا بود که لزوم ساخت حافظههای سریعتر حس شد. در نمودار زیر میتوانید رشد سرعت حافظههای DRAM و CPU ها را طی سالهای ۱۹۸۰ تا ۲۰۰۰ مشاهده کنید:
در سال ۱۹۸۰ کش در میکروپروسسورها وجود نداشت. در سال ۱۹۹۵ استفاده از سطح دوم کش رواج یافت.
کش چطور کار میکند؟
کشِ CPU، حافظهی کوچکی است که اطلاعات مورد نیاز پردازنده در آن ذخیره میشود تا پردازنده در نیازِ بعدی خود به این اطلاعات، به سرعت به آنها دسترسی داشته باشد. اینکه چه اطلاعاتی باید در حافظه ذخیره شود، به الگوریتمهای پیچیده و فرضیات مشخصی از کدهای نرمافزار مربوط است. هدف اصلی در استفاده از کش آن است که مطمئن شویم بیت بعدی از اطلاعات که CPU به آنها نیاز دارد، در کش ذخیره شده باشند تا با حداکثر سرعت و حداقل تاخیر در اختیار پردازنده قرار گیرند. به این فرایند Cache Hit نیز گفته میشود یعنی بیت بعدی که پردازنده به آنها نیاز دارد، در کش آماده باشد.
از سوی دیگر، موضوعی با عنوان Cache Miss وجود دارد و به معنی آن است که اطلاعاتی که پردازنده به آنها نیاز دارد در کش وجود ندارد و برای یافتن آنها باید به حافظههای دیگر مراجعه کند. این همان جایی است که L2 Cache یا سطح دوم حافظهی کش وارد بازی میشود. هرچند حافظهی L2 به اندازهی L1 سریع نیست، اما ظرفیت آن بیشتر است. برخی از پردازندهها از طراحی پوششی بهره میبرند و این بدین معنی است که اطلاعاتی که در L1 ذخیره میشود همزمان در L2 نیز کپی میشود. اما طراحی دیگری نیز وجود دارد که در آن هیچ وقت اطلاعات موجود در L1 و L2 یکسان نخواهند بود. اگر پردازنده اطلاعات مورد نیاز خود را در L2 پیدا نکند آنوقت به سطح سوم کش یا L3 مراجعه میکند به همین ترتیب در صورت پیدا نشدن اطلاعات در L3 پردازنده به L4 سر میزند و اگر اطلاعات مورد نیاز پردازنده در این سطح از حافظه نبود آنوقت ناگزیر به مراجعه به رم (DRAM) میشود. توجه داشته باشید که تمام پردازندههای از هر چهار سطح حافظهی کش پشتیبانی نمیکنند و برخی از پردازندههای قدیمی تنها سه یا دو سطح از حافظهی کش را در اختیار دارند.
سطح دوم از حافظهی کش، ارزانترو بزرگتر از L1 است و علاوه بر آن مصرف انرژی کمتری نیز دارد. اما با این حال بسیاری از پردازندههای مدرن امروزی ۹۵ درصد از درخواستهای خود را از همان L1 پاسخ میگیرند و کمتر نیاز به مراجعه به حافظهی سطح دوم پیدا میکنند.
چرا ظرفیت حافظهی کش CPU مدام در حال افزایش است؟
دلیل اینکه مدام ظرفیت حافظهی کش افزایش مییابد آن است که با افزایش حافظهی کش، شانس دسترسی به اطلاعات در این حافظه بیشتر شده و نیاز به رم کمتر میشود و این موضوع به معنی افزایش بازده سیستم خواهد بود.
در نمودار بالا که از بررسی انندتک تهیه شده است میتوانید تاثیر اضافه شدن حافظهی ۱۲۸ مگابایتی L4 Cache را در کاهش تاخیر در هر کلاک مشاهده کنید. خط قرمز مربوط به پردازندهای است که حافظهی L4 دارد. دقت داشته باشید که برای فایلهای سنگین، سرعت آن تقریبا دو برابر دیگر پردازندههای اینتل است.
طراحی کش چه تاثیری بر روی بازده دارد؟
تاثیر اضافه شدن کش به CPU ارتباط مستقیم به نرخ مراجعات موفق پردازنده به کش دارد. هر چه دفعات مراجعهی CPU کمتر با شکست روبرو شود، بازده پردازنده افزایش مییابد. در ادامه چند مثال برای این موضوع ارائه میکنیم تا دید بهتری نسبت به آن داشته باشید.
تصویر کنید که یک CPU مجبور باشد اطلاعات مشخصی را ۱۰۰ بار پشت سر هم از L1 بخواند. حافظهی L1 تاخیر یک نانوثانیه دارد و هر ۱۰۰ بار نیز حافظه با موفقیت اطلاعات را میخواند. به این ترتیب پردازنده ۱۰۰ نانوثانیه برای انجام این عملیات زمان صرف میکند.
حال تصور کنید که همان CPU با نرخ ۹۹ درصد اطلاعات را از L1 بخواند و صدمین مراجعهی آن به L1 بدون پاسخ بماند و مجبور باشد به L2 مراجعه کنید. تاخیر L2 ده سیکل یا ۱۰ نانوثانیه است به این ترتیب پردازنده ۹۹ نانوثانیه برای کسب اطلاعات از L1 و ۱۰ نانوثانیه برای کسب اطلاعات از L2 صرف میکند. این بدین معنی است که اگر یک درصد از مراجعات پردازنده به حافظهی L1 بدون پاسخ بماند ۱۰ درصد سرعت پردازنده کاهش مییابد.
در دنیای واقعی حافظهی L1 بین ۹۵ تا ۹۷ درصد مراجعات پردازنده را پاسخ میدهد، اما همان دو درصد اختلاف میتواند تاثیر محسوسی در سرعت پردازش امور داشته باشد. تازه این برای زمانی است که مطمئن باشیم اطلاعاتی که در L1 یافت نشده است حتما در L2 وجود دارد. اما در دنیای واقعی بعضی اوقات اطلاعات مورد نیاز پردازنده حتی در L3 و L4 نیز وجود ندارد و پردازنده مجبور به مراجعه به رم است. اگر پردازنده مجبور به کسب اطلاعات از رم باشد آنوقت سیکل پاسخدهی به ۸۰ تا ۱۲۰ نانوثانیه افزایش مییابد.
وقتی پردازندههای سری بولدوزر AMD را با رقبای اینتلی آن مقایسه کنیم، مبحث طراحی کش و تاثیر آن بر روی بازده، به یک عامل بسیار مهم تبدیل میشود؛ عاملی که معادلات بازی را بر هم میزند. بسیاری از کارشناسان، یکی از دلایل مهم عقب ماندن AMD از Intel در قدرت و بازدهی پردازندهها را در طراحی کش میدانند. پردازندههای سری بولدوزر AMD از مشکل Cache Contention رنج میبرند. این مشکل زمانی رخ میدهد که دو رشته یا Thread متفاوت اطلاعات را بر روی یک سکتور از کش ذخیره کنند. این مشکل تاثیر بسیار منفی بر روی بازده هر دو Thread دارد. تصور کنید که یک هسته برای کسب اطلاعات مورد نظر خود به کش مراجعه میکند، اما هستهای دیگر اطلاعات مورد نظر خود را بر روی همان بخش از حافظه کپی کرده است. در این صورت هسته مجبور است یک بار تمام سطوح کش را چک کرده و سپس به رم مراجعه کرده و مجددا اطلاعات مورد نظر خود را در سطح اول کش بنویسد. این مشکل حتی در پردازندههای مجهز به معماری Streamroller ایامدی نیز وجود دارد و حتی تلاش این شرکت برای اختصاص ۹۶ کیلوبایت به L1 Code Cache هم موثر نبوده است. از طرفی حتی استفاده از فناوری HSA یا معماری ناهمگن نیز در این باره چندان موثر نبوده است.
به هر حال، کش مبحث فوقالعاده پیچیدهای است که در سرعت پردازش دستورات نقش مهمی را ایفا میکند و به نظر میرسد مدیریت بهتر آن در پردازندههای اینتل یکی از مهمترین دلایل برتری محصولات این شرکت در رقابت با پردازندههای AMD است.