Hardware Multithreading: پنهان کردن تأخیر با جابه‌جایی بین وظایف

Hardware Multithreading: پنهان کردن تأخیر با جابه‌جایی بین وظایف

Hardware MultithreadingSimultaneous Multithreadingموازی‌سازی سطح رشته

~3 دقیقه مطالعه · آخرین به‌روزرسانی ۱۵ شهریور ۱۴۰۵

مسئله: زمان بی‌کاری در انتظار عملیات‌های کند

حتی با پایپ‌لاینینگ و موازی‌سازی سطح دستور، که هر دو پیش‌تر در این مجموعه بحث شدند، یک هسته پردازنده مکرراً متوقف می‌شود در حالی که منتظر تکمیل یک عملیات کند است، مانند یک cache miss که نیازمند واکشی داده از حافظه اصلی است. در طول این توقف‌ها، سخت‌افزار اجرایی که در غیر این صورت می‌توانست کار مفیدی انجام دهد بی‌کار می‌ماند.

ایده اصلی: چند رشته که یک هسته را به اشتراک می‌گذارند

Hardware Multithreading اجازه می‌دهد یک هسته پردازنده فیزیکی واحد، وضعیت چند Thread مستقل (جریان‌های جداگانه دستورات) را به‌طور هم‌زمان نگه دارد، و بین آن‌ها جابه‌جا شود تا سخت‌افزار اجرایی را حتی وقتی یک رشته منتظر یک عملیات حافظه کند است، مشغول نگه دارد.

Fine-Grained Multithreading

Fine-Grained Multithreading بین رشته‌ها در هر سیکل ساعت جابه‌جا می‌شود، و به‌صورت round-robin در رشته‌های موجود چرخش می‌کند. این رویکرد می‌تواند به‌طور مؤثری تأخیر ناشی از توقف‌های کوتاه را پنهان کند، چون دستور یک رشته دیگر می‌تواند در همان سیکل بعدی صادر شود، اما سرعت اجرای هر رشته منفرد در حال اجرای مجزا را کمی کاهش می‌دهد، چون آن رشته فقط کسری از سیکل‌ها را دریافت می‌کند.

Coarse-Grained Multithreading

Coarse-Grained Multithreading رشته‌ها را فقط زمانی جابه‌جا می‌کند که رشته در حال اجرای فعلی با یک توقف پرهزینه مواجه شود، مانند یک cache miss که نیازمند دسترسی به حافظه اصلی است. این کار از سربار کوچک هر-سیکل جابه‌جایی هر سیکل اجتناب می‌کند، اما به توقف‌های کوتاه‌تر کندتر واکنش نشان می‌دهد، چون یک تأخیر کوتاه ممکن است ارزش هزینه یک جابه‌جایی کامل رشته را نداشته باشد.

Simultaneous Multithreading: صدور از چند رشته به‌طور هم‌زمان

Simultaneous Multithreading (SMT)، ترکیب‌شده با سخت‌افزار سوپراسکالر و صدور چندگانه که پیش‌تر در این مجموعه بحث شد، فراتر می‌رود با صادر کردن دستورات از چند رشته مختلف درون همان سیکل ساعت، و پر کردن اسلات‌های صدور در غیر این صورت استفاده‌نشده‌ای که یک رشته به‌تنهایی نمی‌توانست به‌طور کامل اشغال کند.

بدون SMT (یک رشته):
سیکل 1: 2 از 4 اسلات صدور استفاده‌شده، 2 بی‌کار

با SMT (دو رشته که هسته را به اشتراک می‌گذارند):
سیکل 1: رشته A از 2 اسلات استفاده می‌کند،
         رشته B از 2 اسلات در غیر این صورت-بی‌کار استفاده می‌کند

چرا این با افزودن هسته‌های بیشتر متفاوت است

Hardware multithreading همان رویکرد چندهسته‌ای که پیش‌تر در این مجموعه بحث شد نیست. Multithreading همان منابع اجرایی فیزیکی، مانند ALU ها، را بین چند رشته درون یک هسته واحد به اشتراک می‌گذارد، در حالی که طرح‌های چندهسته‌ای کل هسته‌ها را تکرار می‌کنند. Multithreading معمولاً از نظر مساحت تراشه ارزان‌تر است اما بهبود کارایی متوسط‌تری فراهم می‌کند، چون رشته‌های روی همان هسته همچنان برای منابع مشترکی مانند فضای کش رقابت می‌کنند.

چرا این تکنیک برای پردازنده‌های امروزی اهمیت دارد

Hardware multithreading به‌طور گسترده در پردازنده‌های تجاری پیاده‌سازی می‌شود به‌طور خاص چون بارهای کاری دنیای واقعی مکرراً روی دسترسی حافظه توقف می‌کنند، که پیش‌تر در این مجموعه درباره سلسله‌مراتب حافظه بحث شد، و multithreading راهی نسبتاً کم‌هزینه برای بازیابی بخش معناداری از آن ظرفیت اجرایی در غیر این صورت هدررفته فراهم می‌کند.

نوشته و پژوهش‌شده توسط دکتر شاهین صیامی

مقالات مرتبط

چرا برنامه‌نویسی موازی سخت است و سیستم‌های موازی چگونه دسته‌بندی می‌شوند

نوشتن نرم‌افزاری که به‌درستی و کارآمد از چند پردازنده استفاده کند، اساساً سخت‌تر از نوشتن کد پی‌درپی است. این مقاله توضیح می‌دهد چرا برنامه‌نویسی موازی چالش‌های منحصربه‌فردی درباره هماهنگی و بازده کاهشی معرفی می‌کند، سپس طبقه‌بندی کلاسیک فلین را پوشش می‌دهد که سخت‌افزار موازی را به SISD، MIMD، SIMD، و مدل‌های مرتبط دسته‌بندی می‌کند.

ادامه

<h2>Real Stuff: Memory Hierarchies in Commercial Processors</h2> <p>Real processors implement the caching and memory concepts covered throughout this chapter with specific, carefully chosen parameters. Both the <code>ARM Cortex-A53</code> and <code>Intel Core i7</code>, discussed earlier in this series regarding pipeline design, also differ meaningfully in their memory hierarchies: mobile-oriented designs like the Cortex-A53 typically use smaller cache sizes at each level to conserve power and die area, while performance-oriented designs like the Core i7 use larger, multi-level caches, often three levels deep, to minimize average memory access time at the cost of additional power and chip area.</p> <h2>Applying Cache Concepts: Cache Blocking for Matrix Multiply</h2> <p>Matrix multiplication, discussed earlier in this series regarding subword parallelism and instruction-level parallelism, can also be optimized specifically for the memory hierarchy using a technique called <code>Cache Blocking</code> (also called <code>Tiling</code>). Rather than processing an entire large matrix row by row, which can repeatedly evict useful cached data due to capacity misses discussed earlier in this series, the matrix is divided into smaller sub-blocks sized specifically to fit within the cache.</p> <pre class="code-block"><code>Without blocking: Large matrix accessed row-by-row, repeatedly evicting data still needed later, causing many capacity misses With blocking: Matrix divided into smaller sub-blocks that fit entirely within the cache, each sub-block fully processed before moving to the next</code></pre><br> <p>By ensuring each sub-block's data remains in the cache throughout its processing, cache blocking significantly reduces the number of capacity misses, directly applying the locality principles introduced earlier in this series to a real, widely used computational workload.</p> <h2>Common Fallacies About Memory Hierarchies</h2> <ul> <li>Assuming a larger cache is always better — as discussed earlier regarding cache performance tradeoffs, a larger cache increases hit time and cost even as it reduces capacity misses.</li> <li>Assuming virtual memory and caching are unrelated systems — as shown earlier in the unified framework covering block placement, identification, replacement, and write policy, they answer the exact same underlying questions.</li> <li>Assuming a cache miss always costs the same amount of time — as discussed earlier regarding the three types of misses, the actual cost depends heavily on which level of the memory hierarchy must ultimately satisfy the request.</li> </ul> <h2>Common Pitfalls in Memory-Sensitive Code</h2> <ul> <li>Writing code with poor spatial locality, such as accessing array elements in a non-sequential pattern, which defeats the benefit of the block-based caching discussed earlier in this series.</li> <li>Ignoring the load-use hazard discussed earlier in this series when reasoning about why memory-heavy code sometimes performs worse than expected despite a seemingly efficient algorithm.</li> <li>Overlooking multicore cache coherence overhead, discussed earlier in this series, when writing parallel code that frequently modifies shared data across cores.</li> </ul> <h2>Chapter Summary: The Full Memory Hierarchy Picture</h2> <p>This chapter traced the path from the smallest and fastest storage to the largest and slowest: SRAM-based caches exploiting locality of reference, virtual memory providing both illusion of abundant memory and process isolation, dependable memory techniques protecting against silent data corruption, cache coherence keeping multicore systems consistent, and RAID protecting persistent storage against physical disk failure. Every one of these mechanisms exists because no single memory technology can be simultaneously fast, large, cheap, and reliable — a theme first introduced at the very start of this chapter and echoed in every technique built on top of it.</p>

مفاهیم نظری کش و حافظه در پردازنده‌های تجاری واقعی با چند سطح کش و اندازه‌های به‌دقت تنظیم‌شده شکل مشخصی به خود می‌گیرند. این مقاله سلسله‌مراتب حافظه واقعی در پردازنده‌های ARM و Intel را مقایسه می‌کند، نشان می‌دهد Cache Blocking چگونه ضرب ماتریس را در عمل تسریع می‌کند، و فصل سلسله‌مراتب حافظه را با پرداختن به تصورات غلط رایج به پایان می‌رساند.

ادامه

RAID: محافظت از داده با پخش آن روی چند دیسک

یک درایو ذخیره‌سازی واحد می‌تواند در هر لحظه خراب شود، و به‌طور بالقوه داده ارزشمند را بدون هیچ هشداری نابود کند. این مقاله توضیح می‌دهد RAID چگونه چند دیسک را ترکیب می‌کند تا قابلیت اطمینان، کارایی، یا هر دو را بهبود بخشد، و مبادلات بین رویکردهای mirroring، striping، و مبتنی بر پریتی را پوشش می‌دهد.

ادامه

انسجام کش: هماهنگ نگه‌داشتن چند هسته درباره حافظه

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

ادامه

کنترل یک کش با یک ماشین حالت متناهی

یک کش صرفاً به‌طور غیرفعال داده ذخیره نمی‌کند؛ منطق کنترلی سخت‌افزار باید چند گام مجزا را برای مدیریت درست یک miss طی کند. این مقاله توضیح می‌دهد یک ماشین حالت متناهی چگونه این منطق کنترلی را مدل می‌کند، حالت‌های درگیر در مدیریت یک cache hit و یک cache miss را مرور می‌کند، و نشان می‌دهد چرا این مدل رسمی طراحی کنترل‌کننده کش را برای استدلال درباره‌اش راحت‌تر می‌کند.

ادامه

یک چارچوب یکپارچه برای درک هر سطح سلسله‌مراتب حافظه

کش‌ها و حافظه مجازی در نگاه اول سیستم‌های بسیار متفاوتی به‌نظر می‌رسند، اما هر دو دقیقاً به همان چهار پرسش بنیادین پاسخ می‌دهند. این مقاله نشان می‌دهد این چهار پرسش چگونه جای‌گذاری بلوک، شناسایی بلوک، جایگزینی بلوک، و مدیریت نوشتن را در سراسر هر سطح سلسله‌مراتب حافظه، از کش‌های کوچک تا حافظه مجازی پشتیبانی‌شده با دیسک، یکپارچه می‌کنند.

ادامه