احسان میرسعیدی
احسان میرسعیدی
خواندن ۲ دقیقه·۷ سال پیش

موازی سازی حلقه های for و foreach

با اینکه عصر ما عصر پردازنده های چند هسته ای است، اما ما عموما به همان سبک و سیاق سابق و با فرض تک پردازنده ای بودن سیستم، به توسعه برنامه ها می پردازیم. اگرچه در گذشته بهره گیری از پردازنده ها و توسعه برنامه های multi thread در گذشته کاری دشوار، زمانگیر و حساس بود. اما در دات نت 4 با معرفی کتابخانه TPL دیگر بهانه ای برای عدم توسعه برنامه های چند نخی وجود ندارد.

در همه برنامه ها ما از حلقه های for و یا foreach استفاده می کنیم. گاه درون این حلقه ها:
1. عملیات پیچیده و زمانگیری انجام می شود.
2. هر بار چرخش حلقه مستقل از چرخش های قبلی و بعدی می باشد. یعنی چرخه ها از لحاظِ "داده ای" دارای استقلال هستند.

در اینگونه موارد آیا بهتر نیست که به جای استفاده از حلقه های معمولی، کار را بین همه پردازنده ها تقسیم کنیم؟ بهتر نیست کار را به طور موازی انجام دهیم تا از همه ظرفیت سیستم استفاده شود و زود تر به زمان برسیم؟

خبر خوب این است که با استفاده از کلاس Parallel و متد های For و ForEach این کار به راحتی هر چه تمام تر انجام می گیرد. این دستورات به طور خودکار با توجه به تعداد پردازنده ها و هسته های موجود، تعداد Thread های مناسبی را به کار خواهند گرفت، کار را ما بین Thread ها تقسیم کرده و موازی سازی را انجام می دهند. در تصویر زیر مثال ساده ای را خواهیم داشت:

این ساده ترین حالت به کار گیری از متد For می باشد. آرگومان اول، بیانگر مقدار آغازین، آرگومان دوم بیانگر مقدار نهایی حلقه می باشد. آرگومان سوم یک متد (یا دقیق تر بگوییم یک delegate) می باشد. ورودی این متد index حلقه می باشد.
کار به این ترتیب است که متد For ابتدا تعداد Thread های مناسبی را (با توجه به سخت افزار موجود) در اختیار می گیرد. سپس هر Thread مسئولیت اجرای یک بار چرخش حلقه را به عهده می گیرد. در هر بار چرخش هر Thread متدی که مشخص کرده ایم را اجرا می کند. پس از اتمام اجرای متد، چرخش دیگری به Thread محول می شود و الی آخر....
در این روش، برخلاف حلقه های معمولی، طبیعتا نباید انتظار داشته باشیم که حلقه به صورت سریالی اجرا شود و هیچ ترتیب مشخصی در چرخش ها وجود نخواهد داشت.

نکته ای که باید در استفاده از این متد ها رعایت شود آن است که اگر کار پردازشی انجام شده درون حلقه سبک و ساده باشد، عموما روش ساده بهتر از روش Parallel.For عمل می کند. چرا که روش چند نخی هزینه هایی را اعم از مدیریت Thread ها، Context Switch و صدا زدن delegate تحمیل می کند که ممکن است در حلقه های ساده، سربار بیشتری ایجاد کنند و کار در مدت زمان بیشتری تمام شود.

مثال کاربردی تر :
https://msdn.microsoft.com/en-us/library/dd460703(v=vs.110).aspx

توضیحات کامل تر:
https://msdn.microsoft.com/library/ff963552.aspx

irandotnetcsharpasynctpl
شاید از این پست‌ها خوشتان بیاید