مرا به خاطر بسپار

افزونه های مدرن تک-دستور، چند-داده (SIMD Extensions)

بازدید: 1889 آخرین به‌روزرسانی: 28 شهریور 1402

در این مقاله ابتدا مفهوم SIMD و افزونه‌های آن بیان شده و سپس به تکامل استفاده از SIMD در طی زمان در پردازنده‌های مختلف و جزئیات بیشتر در مورد دستورالعمل‌های آن اشاره می‌شود. همچنین کاربرد این افزونه‌ها در برنامه‌های کاربردی و برنامه نویسی موازی توضیح داده می‌شود.


مقدمه

پردازنده‌ها در واقع یک پیاده‌سازی از یک مدل انتزاعیِ مشخص هستند. به این مدل، معماریِ مجموعه دستورالعمل (ISA [1] ) و به پیاده‌سازیِ آن ریزمعماری گفته می‌شود. ISA در واقع توصیف‌کننده مجموعه دستورالعملهای پشتیبانی شده، نوع داده‌ها، رجیسترها، نحوه پشتیبانی سخت افزاری برای مدیریت حافظه اصلی و ... است. سرعت پردازنده‌ها وابسته به هر دوی این موارد است؛ یعنی هم نحوه پیاده‌سازی شرکت سازنده و هم دستورالعمل‌هایی که پردازنده از آن پشتیبانی می‌کند در کارایی نهایی پردازنده مؤثرند. تاکنون ISA‌های مختلفی برای کاربردهای گوناگون ارائه شده‌اند که متداول‌ترین آن‌ها x86 است که در رایانه‌های شخصی و سرورها استفاده می‌شود. همچنین arm64 در تلفن‌های همراه استفاده می‌شود. در گذر زمان و با تغییر کاربرد پردازنده‌ها و ایجاد نیازمندی‌های جدید کاربران، ISA‌ها نیز برای برآورده کردن هر چه بهتر نیازمندی‌ها تغییر می‌کنند که برخی از این تغییرات در قالب افزونه‌هایی به ISA اضافه می‌شوند. این افزونه‌ها در زمینه‌های مختلف مانند عملیات ریاضی، رمزگذاری، مجازی‌سازی و امنیت برنامه‌ها ارائه می‌شوند. یکی از زمینه‌هایی که ISA‌ها در آن در حال توسعه هستند مدل تک-دستور چند-داده (SIMD [2] ) است که در پردازش موازی داده‌ها استفاده می‌شود. در ادامه به معرفی بیشتر این مدل و جزئیات این افزونه‌ها پرداخته می‌شود.

مدل تک-دستور، چند-داده

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



همان طور که در مثال فوق بیان شد، SIMD می‌تواند در کاربردهایی که قرار است یک عملیات یکسان بر روی مجموعه‌ای از داده‌ها انجام شود باعث تسریع عملکرد پردازنده شود. این دسته از عملیات‌ها در بسیار از کاربردهای امروزی مانند پردازش صدا و تصویر، فشرده‌سازی و بازی‌های رایانه‌ای وجود دارند. اما در گذشته این دسته از کاربردها کمتر بود و در ISA‌های ابتدایی پشتیبانی از این نوع از عملیات وجود نداشت [3] . البته دلیل دیگر محدودیت‌های فناوری سخت‌افزار و وجود چالش‌های ساخت ریزمعماری که این عملیات را انجام دهد، بوده است. افزونه‌های متعددی برای اضافه کردن این قابلیت به ISA‌ها ارائه شده و به مرور زمان در معماری‌های مختلف به طور بهینه پیاده‌سازی شده‌اند.

شرکت اینتل که از گذشته سهم عمده‌‌ای در تولید پردازنده‌ها داشته است، اولین نسخه از سری افزونه‌های مدرن SIMD را در سال 1999 با نام SSE [4] ارائه کرد. در سال بعد SSE2 و بعد از آن در سال 2004 افزونه‌ی SSE3 و متمّم آن با نام Supplemental SSE3 در سال 2006 ارائه شد. این روال سالیانه با معرفی SSE4 در سال 2007 و AVX [5] در سال 2008 ادامه یافت. در سال 2013 دو افزونه‌ی AVX2 و AVX512 ارائه شدند و بعد از آن تا زمان ویرایش این گزارش، یعنی نیمه‌ی اول سال 2021، هیچ افزونه‌ی SIMD دیگری توسط اینتل یا شرکت رقیب آن AMD ارائه نشده است. این افزونه‌ها به طور کلی در دو زمینه سعی در توسعه و بهبود ISA دارند:

1. اندازه‌ی محل ذخیره: پردازنده‌ها برای انجام عملیات، داده‌ها را درون واحد‌های حافظه داخل خود با نام ثَبات (رجیستر) نگه‌داری می‌کنند. افزایش اندازه و تعداد این ثبات‌ها باعث می‌شود پردازنده بتواند داده‌های بیشتری را درون خود نگه داشته و عملیات روی آن‌ها انجام دهد؛ در نتیجه افزونه‌های SIMD مدام در حال افزایش این مقادیر بوده‌اند. به طور مثال در SSE 8 ثبات و هر کدام با اندازه‌ی 128 بیت وجود دارد در حالی که در AVX 16 ثبات 256 بیتی و در AVX512 32 ثبات 512 بیتی در نظر گرفته شده است.
2. عملیات‌: در ISA عملیات‌های قابل انجام در کنار اندازه‌ی عملوندهای آن‌ها تعریف می‌شوند. با پیچیده‌تر شدن کاربردها، نیاز به عملیات پیچیده‌تر و متنوع‌تری بوجود می‌آید و این موضوع در افزونه‌های ISA در نظر گرفته می‎‌شود. به طور مثال در SSE3 امکان ضرب داخلی دو بردار و در SSE4 امکان جست‌وجوی یک رشته کاراکتر داخل یک رشته‌ی متنی دیگر وجود دارد. همچنین در AVX2 امکان خواندن داده‌ها از چندین آدرس غیر مجاور و در AVX512 امکان تعریف و اِعمال یک تابع منطقی و تشخیص داده‌های تکراری در یک بردار و بسیاری دیگر از عملیات‌ پیچیده فراهم شده است.

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

چالش دیگر آن است که افزایش اندازه‌ی ثبات‌ها منجر به پیچیده و بزرگتر شدن مدار‌های مربوط به اجرای این دستورالعمل‌ها داخل پردازنده می‌شود. در نتیجه استفاده از آن‌ها گرمای بیشتری تولید می‌کند. در شکل زیر نمودار کارایی این افزونه‌ها به همراه توان مصرفی و فرکانس کاری پردازنده هنگام استفاده از آن‌ها آورده شده است. همان طور که در این شکل نیز مشاهده می‌شود، در این حالت مجبور به کاهش فرکانس هسته‌ی پردازنده می‌شویم. شاید یکی از دلایلی که بعد از گذشت 8 سال از ارائه‌ی AVX512، هنوز افزونه‌ی دیگری با اندازه‌ی بزرگتر داده‌ها ارائه نشده است و همچنین شرکت AMD هنوز AVX512 را در ریزمعماری‌های خود پیاده‌سازی نکرده است، همین امر باشد.



کاربرد

برای استفاده از قابلیت‌های SIMD یک پردازنده، برنامه‌ی اجرایی باید دستورالعمل‌های آن را استفاده کند؛ این بدان معناست که توسعه‌دهندگان یک برنامه باید در مورد استفاده از این دستورالعمل‌ها تصمیم گرفته و سازگاری برنامه خود را در نظر داشته باشند. به همین دلیل استفاده از این افزونه‌ها در برنامه‌ها تا چندین سال بعد از ارائه شدن آن به تأخیر می‌افتد. در گذشته SIMD بیشتر در حوزه‌های علمی و محاسباتی استفاده می‌شد، امّا امروزه در کنار آن، بسیاری از برنامه‌های کاربردی مانند پخش و ویرایش محتوای چندرسانه‌ای، شبیه‌سازها، نرم‌افزارهای مهندسی و بازی‌های رایانه‌ای نیازمند این افزونه‌ها برای اجرای سریع هستند و کاربرانی که پردازنده‌ی آن‌ها افزونه‌ی مورد استفاده را نداشته باشد قادر به اجرای این برنامه‌ها با کیفیت مناسب نخواهند بود؛ به همین دلیل افزونه‌هایی که یک پردازنده پشتیبانی می‌کند یکی از معیارهای انتخاب خریداران شده است.

توسعه‌دهندگان نیز می‌توانند برای بهبود کارایی برنامه‌ی خود از این افزونه‌ها استفاده کنند. بدین منظور لازم است ابتدا برنامه‌ی خود را بررسی کرده و تطابق‌پذیری آن با مدل SIMD را مشخص کنند. به طور دقیق‌تر باید به دنبال قسمت‌هایی از برنامه باشند که عملیات یکسان روی داده‌های زیادی انجام می‌شود. برای استفاده از این افزونه‌ها در پلتفرم‌های مختلف، روش‌های متفاوتی وجود دارد:

1. کامپایلر: در فرآیند بهینه‌سازی، کامپایلر هر جا مناسب ببیند از دستورات SIMD می‌تواند استفاده کند. این روش ساده است؛ زیرا برنامه‌نویس نیاز نیست صریحاً کاری انجام دهد امّا وابسته به تشخیص کامپایلر است.
2. توابع ذاتی: این توابع که در زبان‌های برنامه‌نویسی سطح پایین مانند C وجود دارند، به طور مستقیم به دستورالعمل‌های SIMD تبدیل می‌شوند. استفاده از آن‌ها در برنامه‌های پیچیده دشوار است و به دانش برنامه‌نویس وابسته است.
3. واسط برنامه‌نویسی: در واسط‌های برنامه‌نویسی موازی کاربردی مانند OpenMP که به طور کلی برای برنامه‌نویسی موازی و چندنخی به وجود آمده‌اند، دستورات خاصی برای مشخص کردن بخش‌هایی از برنامه و یا توابعی که می‌توانند به صورت SIMD اجرا شوند وجود دارد. بدین ترتیب برنامه‌نویس تشخیص می‌دهد کدام قسمت‌ها باید به صورت SIMD اجرا شوند و کامپایلر مابقی کار را انجام می‌دهد.
4. کتابخانه‌ها: در زبان‌های برنامه نویسی و پلتفرم‌های مختلف، کتابخانه‌هایی برای استفاده از SIMD در پیاده‌سازی فراهم شده است. به طور مثال در نسخه‌های اخیر تمام مرورگرها، کتابخانه‌ی wasm_simd امکان اجرای دستورات SIMD با استفاده از WebAssembly روی این مرورگرها را فراهم می‌کند.
5. مفسرها: نسخه‌های خاصی از مفسر‌ها (مانند Python) و ماشین‌های مجازی (مانند JVM) وجود دارند که به طور خودکار و یا استفاده‌ی صریح برنامه‌نویس، امکان اجرای دستورات SIMD را فراهم می‌کنند.

افزونه‌های SIMD تبدیل به بخش جدایی‌ناپذیر نرم‌افزارهای پرکاربرد سریع شده‌اند. امروزه حتی در برنامه‌های کنفرانس آنلاین نیز برای کدگذاری و کدگشایی تصویر و صدا از این افزونه‌ها استفاده می‌شود. با توجه به فراهم بودن این افزونه‌ها در اغلب پردازنده‌های امروزی، انتظار می‌رود پتانسیل موجود در استفاده از SIMD توسط توسعه‌دهندگان و کاربران در آینده بیشتر از پیش در عمل بکار گرفته شود.

برای اطلاعات بیشتر و مثالهای کاربردی می‌توانید به مراجع زیر مراجعه کنید.

[i] www.cs.uu.nl/docs/vakken/magr/2017-2018/files/SIMD Tutorial.pdf
[ii] https://www.intel.com/content/www/us/en/architecture-and-technology/avx-512-overview.html

  1. Instruction Set Architecture
  2. Single Instruction Multiple Data
  3. با این وجود برای انجام چنین عملیاتی در صورت نیاز از کمک پردازنده‌های برداری استفاده می‌شد.
  4. Streaming SIMD Extensions
  5. Advance Vector Extension
تا چه حد این مطلب برای شما مفید بود؟
بر اساس رای 5 نفر

اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.

ثبت نظر

نظر دادن