0

آشنایی با فناوری پردازش‌های ناهمگام (Async Compute)

 
samsam
samsam
کاربر طلایی1
تاریخ عضویت : بهمن 1387 
تعداد پست ها : 50672
محل سکونت : یزد

آشنایی با فناوری پردازش‌های ناهمگام (Async Compute)

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

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

تراشه‌های شتاب‌دهنده گرافیکی به منظور تحت اختیار گرفتن توانایی‌های پردازشی محاسباتی خود مستقیماً به قابلیت Pipelining تعبیه شده در آن‌ها وابسته می‌باشند. اصطلاح Pipelining یا خطوط لوله در زبان فارسی به انبوه تعداد المان‌های محاسباتی پردازشی قرارگرفته در یک تراشه گرافیکی اطلاق می‌شود که در قالب چندین سری به یکدیگر متصل شده و خروجی یک المان ورودی المان دیگر می‌باشد. المان‌های موجود در یک خط لوله معمولاً در حالت موازی یا به صورت چندین قطعه در واحد زمان پردازش می‌شوند. همان‌طور که پیشتر گفته شد تراشه‌های شتاب‌دهنده گرافیکی مستقیماً به قابلیت نامبرده به منظور دستیابی به کارایی مطلوب خود نیازمند بوده و خروجی یک المان در فناوری نامبرده ورودی المان دیگر و متصل به آن می‌باشد، بنابراین وجود گلوگاه در یک مرحله به بروز مشکل و در دسترس قرار نگرفتن مراحل آتی منتهی می‌شود. مراحل نامبرده قابلیت‌هایی از جمله پردازش فرامین مختلف، پردازش هندسی، تبدیل تصاویر به پیکسل‌های تشکیل‌دهنده صفحات نمایشگر، سایه زنی و عملیات شطرنجی را در بر می‌گیرند. هرکدام از مراحل موجود در خطوط لوله قرارگرفته در دل تراشه‌های شتاب‌دهنده گرافیکی توانایی استفاده از قابلیت پردازش‌های موازی در مقیاس بسیار عظیمی را دارا می‌باشند، اما توان عملیاتی هر مرحله نیز مستقیماً به مراحل قرارگرفته در پیشرو یا پیشتر از مرحله فعلی وابسته می‌باشد. برنامه‌های اجرایی بار پردازشی خود را در قالب لیست یا بافری از دستورات که تشکیل شده از زنجیره‌هایی از اطلاعات پردازشی مختلف می‌باشند را به تراشه شتاب‌دهنده گرافیکی ارسال می‌کنند. هر کدام از بافرهای ارسالی در حالت کلی با عملیات پردازشی به خصوصی نظیر نگاشت سایه‌های موجود، نورپردازی، شبیه‌سازی فیزیکی و … مرتبط می‌باشند. تراشه شتاب‌دهنده گرافیکی در حالت ایدئال باید از توانایی‌های لازمه به منظور محاسبه و پردازش تعداد چندین عملیات به صورت همزمان را دارا باشد. دستیابی به اصل فوق به معنای بهبود فریم‌های پردازشی در یک ثانیه و کاهش مدت زمان تأخیر بدون نیاز به قدرت محاسباتی بیشتر می‌باشد. اما ذکر این نکته ضروری است که مشکلات پیشروی توسعه‌دهندگان جهت سرانجام رسانی استراتژی فوق چالش برانگیز می‌باشند.

graphic-rendering-pipeline

تراشه شتاب‌دهنده گرافیکی به منظور پردازش انبوه دستورات موجود در خطوط لوله پردازشی خود باید از قابلیت مرتب‌سازی دستورات برخوردار باشد، اما قابلیت نامبرده به خودی خود قابلیت اجرایی نداشته و تراشه شتاب‌دهنده گرافیکی به منظور تحقق آن نیازمند اطلاعاتی در خصوص پردازش همگام و ناهمگام بارهای ارسالی می‌باشد. اطلاعات مورد نیاز تراشه‌های شتاب‌دهنده گرافیکی به منظور مرتب‌سازی دستورات و پردازش آن‌ها به کمک رابط‌های برنامه‌نویسی گرافیکی تهیه و ارسال شده یا به‌عبارتی‌دیگر توسعه‌دهندگان عناوین مختلف به کمک رابط‌های برنامه‌نویسی نامبرده قابلیت در اختیار گرفتن سخت‌افزار و هدایت آن بوسیله مهیا سازی اطلاعات مورد نیاز را دارا می‌باشند. رابط‌های برنامه‌نویسی کنونی نظیر نسخه یازدهم رابط برنامه‌نویسی DirectX و OpenGL همان‌طور که مستحضر هستید در دسته رابط‌های برنامه‌نویسی سطح بالا قرارگرفته و بر خلاف رابط‌های برنامه‌نویسی سطح پایین مورد استفاده در کنسول‌های بازی از قابلیت‌های لازمه به منظور فراهم‌سازی اطلاعات در خصوص پردازش‌های ناهمگام برخوردار نمی‌باشند، اما یکی از مهم‌ترین ویژگی‌های افزوده شده به رابط‌های برنامه‌نویسی نسل بعد نظیر DirectX 12 و Vulkan فراهم آوردن بسترهای مورد نیاز و ضروری برای توسعه‌دهندگان عناوین مختلف به منظور ارائه اطلاعات مذکور و ارسال آن‌ها به تراشه شتاب‌دهنده گرافیکی می‌باشد. نرم افزارها و برنامه‌های مبتنی بر رابط برنامه‌نویسی DirectX12 بارهای پردازشی خود به تعداد صفوف قرارگرفته در دل تراشه شتاب‌دهنده گرافیکی (Queue) ارسال می‌کنند. رابط برنامه‌نویسی نامبرده قابلیت پشتیبانی از سه تعداد نوع صف را دارا می‌باشد.

صفوف گرافیکی که مستقیماً به پردازش‌های گرافیکی اصلی اختصاص یافته‌اند.

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

صفوف پشتیبانی از قابلیت رونوشت که به منظور انتقال داده‌های ساده حاضر می‌باشند.

لیست یا بافر دستورات موجود در یک صف باید به صورت همگام پردازش شوند، درحالی‌که دستورات قرارگرفته در صفوف دیگر به صورت ناهمگام یا به‌عبارتی‌دیگر همزمان (موازی) با دیگر صفوف موجود قابل پردازش می‌باشند. تداخل پردازشی اطلاعات قرارگرفته در تعداد صفوف مختلف در افزایش پتانسیل تراشه شتاب‌دهنده گرافیکی و بهبود کارایی نقش به سزایی را ایفا می‌کند. توسعه‌دهندگان عناوین کنسولی همان‌طور که پیشتر گفته با قابلیت پردازش‌های ناهمگام و تعداد صفوف قرارگرفته در بطن تراشه‌های شتاب‌دهنده گرافیکی آشنایی داشته و به توسعه محصولات خود بر پایه فناوری موجود اقدام ورزیده‌اند. یکی از مهم‌ترین دلایل برتری کنسول ها و دست‌یابی به کیفیت بصری بهتر عناوین موجود در مقایسه با رایانه‌های شخصی که از قدرت سخت‌افزاری مشابه بهره می‌برند استفاده از قابلیت معرفی شده توسط توسعه‌دهندگان می‌باشد. رابط‌های برنامه‌نویسی سطح پایین و نسل بعد نظیر DirectX 12 و Vulkan سرانجام بسترهای لازمه به منظور کنترل سخت‌افزار در ابعاد بسیار گسترده‌تر را در اختیار سازندگان قرار داده و در کاهش فاصله موجود بین کنسول‌ها و پلتفرم معظم PC کارنامه درخشانی را از آن خود کرده‌اند.

graphics-rendering-tasks

 

زمان‌بندی

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

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

single-task-switching-mechanism

الگوریتم فوق در سویچ عملیات پردازشی توسط تراشه شتاب‌دهنده گرافیکی یا به‌عبارتی‌دیگر تغییر بار پردازشی موجود نقش به سزایی را ایفا می‌کند. در ابتدا ارسال ترافیک یا کار مرتبط با ترافیک فعلی باید متوقف شود. پس از متوقف شدن روند ارسال ترافیک‌های مرتبط پردازش تمامی دستورات و اطلاعات موجود در بزرگراه در دستور کار قرار می‌گیرد. پس از پردازش دستورات موجود تمامی اطلاعات زمینه ترافیک فعلی با ترافیکی که در ادامه قصد ورود به بزرگراه را دارد تعویض شده و سپس اجازه ورود ترافیک جدید به بزرگراه صادر می‌شود.

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

یکی دیگر از راه‌حل‌های جایگزین به منظور دست‌یابی به پدیده زمان‌بندی پردازش اطلاعات اختصاص اولویت به بافرهای قرارگرفته در صف‌های حاوی دستورات می‌باشد. دستورات قرارگرفته در صفوف دارای اهمیت بیشتر از اولویت بالاتری در پردازش نیز برخوردار می‌باشند. اصطلاح Pre-emption بدان معنی است که یک عملیات دارای اولویت کمتر به صورت موقتی می‌تواند به حالت تعلیق درآید (تا زمانی که دستورات قرارگرفته در صفوف دارای اولویت بیشتر کاملاً پردازش شوند). دستورات دارای اولویت بالاتر به منزله وسایل نقلیه اضطراری (به‌عنوان‌مثال آمبولانس) نمایان می‌کنند. این خود بدان معنی است که برخی از قوانین راهنمایی و رانندگی نظیر رنگ قرمز چراغ‌ها در روند حرکت آن‌ها تأثیری نداشته و علاوه بر آن حق تقدم در رویایی با تقاطع و چهارراه‌ها نیز از آن ترافیک‌های نامبرده می‌باشند. استراتژی مذکور در کاهش مدت زمان تأخیر پردازش تأثیرگذار می‌باشد اما لزوماً به افزایش میزان بهره‌وری اطلاعات به دلیل جلوگیری از پردازش پیوسته عملیات و اجرای دستورات منتهی نمی‌شود. ذکر این نکته ضروری است که دربرخی از موارد به دلیل عواملی نظیر تعویض سربار چهارچوب‌ها و … ممکن است کاهش میزان راندمان و بهره‌وری را نیز شاهد باشیم.

pre-emption-mechanism

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

Asynchronous- compute

 

طراحی سخت‌افزار

یکی دیگر از مهم‌ترین فاکتورهای مورد نیاز به منظور بهره‌مندی حداکثری از فناوری مورد بحث در مقاله فوق وجود سخت‌افزار مناسب می‌باشد. یک تراشه شتاب‌دهنده گرافیکی در حالت ایدئال باید پردازش‌های گرافیکی را به صورت چند رشته‌ای به‌صورت همزمان اداره و پردازش کند، به‌عبارتی‌دیگر عملیات گرافیکی به چندین رشته قرار گرفته در دل تراشه شتاب‌دهنده گرافیکی واگذار شده و سپس منابع محاسباتی موجود بین تمامی آن‌ها به اشتراک گذاشته می‌شوند. معماری GCN کمپانی قدرتمند AMD ضوابط و معیارهای فوق را کاملاً رعایت کرده و به‌گونه‌ای طراحی و توسعه یافته است تا توانایی پردازش چندین رشته از دستورات به صورت همزمان یا موازی را دارا باشد. قابلیت نامبرده به لطف تعبیه تعداد چندین واحد پردازشی ناهمگام تحت عنوان واحدهای ACE محقق شده و همانطور که پیشتر گفته پردازش همزمان تعداد چندین رشته از دستورات مختلف را فراهم ساخته‌اند. هر کدام از واحدهای پردازشی ناهمگام قرار گرفته در بطن تراشه‌های شتاب‌دهنده گرافیکی توانایی دریافت، تجزیه و ارسال دستورات را به صورت کاملاً مستقل از دیگر واحدهای پردازشی موجود دارا می‌باشند. معماری قدرتمند GCN قابلیت پشتیبانی از تعداد هشت واحد پردازشی ناهمگام را دارا بوده و هر کدام از واحدهای نامبرده نیز دارای تعداد هشت صف اطلاعاتی کاملاً مستقل از یکدیگر می‌باشند. اطلاعات ارسالی و ذخیره شده در صفوف به منظور پردازش پیوسته به واحد پردازشی ارسال شده و واحدهای دیگر نیز به صورت کاملاً مستقل به فعالیت خود ادامه می‌دهند. واحدهای پردازشی ناهمگام قرار گرفته در بطن تراشه‌های شتاب‌دهنده گرافیکی توانایی کارکرد همزمان یا به‌عبارتی‌دیگر موازی با واحدهای دیگر نظیر تعداد دو واحد DMA و واحد مسئول پردازش‌های گرافیکی را دارا می‌باشند. واحد پردازشگر دستورات گرافیکی مسئولیت رسیدگی و هدایت صفوف گرافیکی، واحدهای پردازشی ناهمگام یا به‌عبارتی‌دیگر واحدهای ACE مسئولیت هدایت صفوف حاوی دستورات محاسباتی و واحدهای DMA نیز مسئولیت هدایت صفوف رونوشتی را برعهده دارند. هرکدام از صفوف اطلاعاتی نامبرده توانایی ارسال المان‌های قرار گرفته در دل خود را بدون نیاز به انتظار جهت به اتمام رسیدن عملیات‌های دیگر دارا می‌باشند که این خود به پردازش مستقل ترافیک‌های ارسالی و اجرای پیوسته دستورات منتهی می‌شود.

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

gcn-architecture-block-diagram

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

سه شنبه 10 فروردین 1395  6:48 PM
تشکرات از این پست
دسترسی سریع به انجمن ها