PDA

View Full Version : سوال: پیشنهاد یک راه حل موازی برای یک مساله ؟؟؟



Moharram
یک شنبه 12 آبان 1387, 11:41 صبح
سلام

من باید یه سری دیتا رو بصورت پیوسته دریافت کنم و بین چند Core پردازشی پخش کنم، چه راه حلی پیشنهاد میکنید؟

سیستم کامپیوتری هم خیلی خوبه با این مشخصات:


2 پردازنده QuadCore 3.6GHz
MainBoard : SuperMicro
RAM : 3GB

خودم این راه حل به ذهنم رسید که یک Thread برای یک CPU تعریف کنم و Thread مدام دیتاهای موجود رو به الگوریتم بده، اما یه مشکلی وجود داره و اون اینه که Thread تمام CPU رو مشغول نمیکنه. مثلا 80% پردازنده پر میشه. این بقیه CPU چی شده و آیا صرف IO میشه؟

یه سوال دیگه این که چطور میشه این Thread رو دوتا یا بیشتر کرد. منظورم همزمانی بین Thread هاست و اینکه مثلا دو تا Thread سر وقت یک دیتا نروند.

Nima_NF
یک شنبه 12 آبان 1387, 15:26 عصر
اگر می خواهید برنامه برای یک cpu بنویسید که 4 هسته دارد باید الگوریتم خود را به 4 قسمت تقسیم کنید و برنامه را با چهار thread بنویسید تا نهایت استفاده و سرعت از پردازنده انجام شود.

شاید IO الگوریتم شما بالا باشد و CPU نتواند در آن زمان به آن برسد ممکن هست همان 20% کم بیاید،(با توجه به سرعت Ram و هارددیسک) اما اگر فکر می کنید که این طور نیست می توانید از اولویت ها استفاده کنید، با API ی SetThreadPriority می توانید به thread خود اولیت high بدهید اما آگاه باشید که این کار خطرناکی محسوب می شود و ممکن است سیستم نتواند به کار اصلی خود به خوبی ادامه دهد.

در مورد همزمان سازی ها هم که قبلا توضیحات و مثال هایی برایتان زده بودم،( مانند lock و mutex و ...)

Moharram
چهارشنبه 15 آبان 1387, 16:11 عصر
یه کم دیگه توضیح میدم:

دیتا داره تو یه آرایه پر میشه و یک اشاره گر داره به آخرین عضو اون اشاره میکنه. از طرف دیگه یه اشاره گر هم برای پردازش وجود داره و Thread اون رو چک میکنه تا اگه دیتایی وجود داشته باشه پردازش بکنه


while(true)
{
if(processNum != Counter)
{
execute(processNum);
processNum++;
}
}


حالا اگه بخواهیم یک Thread پردازشگر دیگه داشته باشیم، چطوری باید با هم همزمان بشن. مثلا موقع دیباگ میبینم که وسط تابع Execute ، دومین Thread دوباره همون دیتای اولی رو برداشته و شروع کرده به پردازش.

یه سوال دیگه اینکه این ThreadPool به چه معناست؟
فکر کنم اینجور باشه که چند تا Thread داشته باشیم که با Flag اجرا بشن. اونوقت یک چیزی (مثلا یه Thread ای) وظایف رو بین اونها تقسیم کنه. مساله ای که پیش میاد اینه که خروجیها چطور Sort بشن. چون ممکنه که پردازش پکت اول زیاد طول بکشه و در این مدت پکت دوم و سوم پردازش بشوند...

Nima_NF
پنج شنبه 16 آبان 1387, 00:20 صبح
همیشه راحت ترین راه برای اینکه دردسر کمتری در همزمان سازی ها داشته باشیم این هست که روشی پیدا کنیم که الگوریتم ما برای هر thread مجزا شود، به این شکل دیگر نیاز نیست چندان از روش های همزمان سازی استفاده کنیم.

مثلا متغیر های متفاوتی داشته باشیم که در هر thread جداگانه پردازش شوند، یا مشخص کنیم کدام بخش توسط کدام thread پردازش شود.

مثلا در نمونه شما اگر آرایه و حجم داده های ورودی شما زیاد هست، آرایه می تواند به بخش های 10KB تقسیم شود، و هر 10 کیلو بایت به یک thread اختصاص داده شود تا پردازش شود (یا هر مقدار دیگری که با تست کردن خواهید فهمید چه مقداری سرعت را افزایش می دهد و تاخیر ها نیز کمتر می شود). 10KB اول به Thread1 و 10KB بعدی به Thread2 و ...در هر مرحله نیز آن ها می توانند با متغیر های مشترک به همدیگر اطلاع می دهند که مثلا در حال پردازش چندمین خانه است یا چندمین 10KB .
پس دقت کنید که سرعت پردازندها بالاست و نیاز نیست به فکر این باشید که فقط 1 بایت آرایه توسط یک thread در یک ثانیه پردازش شود، به فکر پردازش دسته ای از بایت ها باشید.

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

ThreadPoolها هم دردسرها خود را دارند و فکر نمی کنم برای کارهای ساده چندان نیاز باشد به سراغ callback ها و اتومات سازی برویم.

Moharram
دوشنبه 27 آبان 1387, 09:44 صبح
وقتی الگوریتم بدون Thread اجرا میشه مشکلی پیش نمی یاد، ولی وقتی تو Thread میره یک error زیاد پیش می یاد، بشکل زیر:


Windows has triggered a breakpoint in a.exe. this may be du to a corruption of the heap, which indicates a bug in a.exe or any of DLLs it has loaded.
this may also be du to the user pressing F12 while a.exe has focus.
the output window may have more diagnostic information.

با سه تا کلید Break، Continue، ignore

در واقع نمی فهمم که از کجای برنامه این Error درست شده...

vcldeveloper
دوشنبه 27 آبان 1387, 17:55 عصر
در همچین مواردی کاری که روی داده ها انجام میشه ثابت هست، فقط حجم داده ها هست که موجب کندی میشه، در نتیجه از Threadهای مختلف برای تقسیم پردازش روی داده ها استفاده میشه. حالت دیگه مثلا این بود که پردازش سنگینی باید انجام میشد، در اون صورت باید الگوریتم به چندین بخش مستق کوچکتر شکسته می شد، و هر بخش آن توسط یک Thread بصورت همزمان اجرا می شد.

برای کار شما که مربوط به حالت اول میشه، میشه از Thread-Pool استفاده کرد. یک Thread-Pool شامل یک کنترل کننده، و تعدادی Worker-Thread هست. کنترل کننده به میزان مورد نیاز Worker-Threadها را میسازه، و وظیفه که به آن تحویل داده شده را بین آنها تقسیم میکنه. اگر Threadایی زودتر از دیگران وظیفه اش را انجام داد، کنترل کننده آن را حذف نمیکنه، بلکه یا آن را برای وظایف بعدی منتظر نگه میداره، یا بخشی از وظایف باقی مانده را به آن محول میکنه، به اصطلاح Load-Balancing میکنه تا فشار کار روی همه Threadها بطور یکسان تقسیم بشه.
پیاده سازی یک Thread-Pool هر چند ایده آن ساده است، دارای پیچیدگی ها و ریزه کاری های زیادی هست. افراد و شرکت های مختلف Thread-Poolهای مختلفی را طراحی و پیاده سازی کردند که شما می توانید بجای پیاده سازی خودتان، از آنها استفاده کنید. یکی از مزیت های Thread-Pool آن هست که تا حد زیادی وظیفه همزمان سازی Threadها را خودش بر عهده می گیرد، و در صورت تقسیم مناسب وظیفه، می توان با تغییر یک متغیر تعداد Worker-Threadها را کم یا زیاد کرد، تا برنامه روی سیستم های مختلف از حداکثر توان موجود استفاده کنه؛ یعنی Scalability برنامه به میزان زیادی افزایش پیدا میکنه. نکته ایی که مهم است این هست که بتوانید داده ها را به شکل مناسب و بطوری که پردازش هر گروه از داده ها بر سایر داده ها تاثیر نگذارد، تقسیم کنید. اگر این کار به درستی انجام نشه، Thread-Pool به خودی خود نمی تواند برای شما معجزه کند!

در کنار مطلب بالا، شرکت های مختلف کتابخانه هایی برای Parallel Programming عرضه می کنند. معمولا در این کتابخانه ها برنامه نویس فقط با تقسیم پردازش مربوطه درگیر می شود، و مستقیما با پیاده سازی Threadها، Lockها، یا چگونگی همزمام سازی Threadها درگیر نمی شود. تمامی این امور (حتی تعداد Threadهای استفاده شده) توسط کتابخانه کنترل می شود. حتی برخی از این کتابخانه ها ساختارهای زبانی جدیدی در اختیار برنامه نویس قرار می دهند، مثل حلقه های for موازی، یا Futures. گرایش به این نوع کتابخانه ها در سال های اخیر افزایش زیادی پیدا کرده.
شرکت های سازنده CPU، مثل اینتل، هم کتابخانه و کامپایلرهایی برای استفاده بهتر از قابلیت های موازی سازی محصولات خودشان ارائه می کنند. ممکن هست در کتابخانه های اینتل نمونه هایی از Thread-Pool یا سایر ابزارهای موازی سازی وجود داشته باشه. کامپایلرهای مربوطه هم که سعی می کنند تا حد امکان، بدون نیاز به تغییر کد، اجرای پردازش را به شاخه های مختلف برای اجرا شدن روی هسته های مختلف، تقسیم کنند. البته این کامپایلرها هم در این زمینه قابلیت محدودی دارند، و نمیشه از آنها انتظار داشت که یک برنامه Single-Thread را با یک کامپایل تبدیل به Multi-threaded کنند!

Moharram
یک شنبه 10 آذر 1387, 08:47 صبح
با تشکر از نظرات دوستان

یه مشکلی دیگه ای هم که پیش اومده اینه:

در هر Thread باید یک Function از یک dll رو صدا بزنم، وقتی فقط یک Thread دارم مشکلی نیست ولی تا دو تا Thread میشه Error های نامشخص از تابع dll میده و چون سورس dll در اختیار نیست، نمی دونم مشکل از کجاست... ؟

ممکنه مشکل بخاطر همزمان run شدن یک تابع از dll باشه ... !!! ؟؟؟

Nima_NF
یک شنبه 10 آذر 1387, 14:53 عصر
بستگی دارد که چه dll باشد و چه تابعی باشد،

- ممکن است تابعی مقدار کنونی بخشی از سیستم را دریافت کند و تابعی دیگر مقدار کنونی سیستم را set کند، اجرای همزمان این دو تابع احتمال بروز خطای پیش بینی نشده دارد و باید از همزمان سازی ها استفاده کرد.

- در مورارد نادری نیز اگر dll دینامیک لود می شود، ممکن هست dll در قسمت DllMain خود پس از فراخوانی LoadLibrary نیازمند مقداردهی های اولیه باشد که فقط در یک thread شما انجام می شود و درنتیجه برای سایر thread ها مشکل ایجاد کند. برای این موارد اگر dll نوشته خودتان هست می توانید از Thread Local Storage استفاده کنید و جلوی برخی از موارد را بگیرید. (با توجه به DLL_THREAD_ATTACH)


در حالت معمولی که فراخوانی مجدد ربطی به هم ندارد مشکل جای دیگری است.
ضمنا همیشه سعی کنید بخشی از خطا را هنگام سوال خود قرار دهید، در غیر این صورت حدس زدن هم بیهوده است!

Moharram
چهارشنبه 20 آذر 1387, 19:02 عصر
- ممکن است تابعی مقدار کنونی بخشی از سیستم را دریافت کند و تابعی دیگر مقدار کنونی سیستم را set کند، اجرای همزمان این دو تابع احتمال بروز خطای پیش بینی نشده دارد و باید از همزمان سازی ها استفاده کرد.



با تشکر از جناب Nima_NF

من dll رو استاتیک Load میکردم، ولی یک کپی ازش ساختم (یعنی به ازای هر Thread یک کپی از فایل درست کردم) و بصورت دینامیک بهش متصل شدم و مشکل ظاهرا حل شده....

از توابع LoadLibrary و GetProcAddress استفاده کردم...

Moharram
چهارشنبه 20 آذر 1387, 19:08 عصر
یک مقدار با دیباگ کردن برنامه تو VS2008 مشکل دارم...

همه چیز ظاهرا درسته ولی وقتی exe برنامه رو run میکنم، صفحه Debug میاد و به فایل dbghook.c اشاره میکنه:



__declspace(noinline)
void __cdecl _CRT_DEBUGGER_HOOK(int _Reserved)
{
/*assign 0 to _debugger_hook_dummy so that the function is not folded in retail*/
(_Reserver)
_debugger_hook_dummy=0;
}


آیا باید Setting ای، چیزی تو Option برنامه ست بشه...

در ضمن برنامه بصورت Release و با FULL Optimization ساخته شده...

ممنون