نرمافزار Matlab به عنوان ابزاری شناختهشده برای انجام محاسبات علمی، طراحیها و شبیهسازیهای فنی و مهندسی و به عنوان یک محیط ساده، اما منعطف برای انجام محاسبات ریاضی، کاربرد وسیعی در محیطهای دانشگاهی و صنعتی یافته و جایگاه خود را به عنوان یک محیط عملیاتی و اسکریپتنویسی ساده اما قدرتمند در محافل علمی به خوبی باز کرده است. این نرمافزار در طی مدت مدیدی، از دهه 1970 در دانشگاه نیومکزیکو تاکنون که توسط Mathworks در کالیفرنیا عرضه ميشود، مراحل مختلف پیشرفت و تکامل را پیموده است و نسخههای نهایی این نرمافزار که امروزه با قیمت پایه 1500 دلار با شش Toolbox پایه عرضه ميشود (البته نسخه کامل آن حداکثر 5 دلار هزینه در بر دارد)، امکانات بسیار پیشرفتهای را در اختیار كاربر ميگذارد. مهمترین ویژگی این نرمافزار، امکان تهيه و استفاده از ماجولهایی تحت عنوان Toolbox است که به صورت جدا قابلسفارش و خریداری است. یکی از این جعبه افزارها، Distributed Computing Toolbox است (در نسخههای جدید، عنوان این ابزار به Parallel Computing Toolbox تغییر یافته است) که امکاناتی برای انجام محاسبات در Matlab را به صورت موازی و توزیع شده در اختیار كاربر ميگذارد. در این مقاله، امکانات و چند برنامه نمونه در این محیط را بررسي خواهيم كرد.
موتور پردازش توزیع یافته Matlab
ابـــــزار مــحاسبـــــات مـــوازی نـــــرمافــــزار Matlab (Matlab Parallel Computing Toolbox) و نــــــــــرمافـــــــــزارMatlab Distributed Computing Server امکان تقسیم اجرای کدهای نيازمند زمانِ اجرای بالا روی مجموعهای از کامپیوترهای مختلف، کامپیوترهای چند پردازندهاي یا پردازندههای چند هستهای را فراهم ميسازد. این مجموعه ابزارها با استفاده از امکاناتی چون حلقههای For موازی، آرایههای توزیع یافته، الگوریتمهای عددی موازی و توابع مبادله پیام، محیطی ساده اما قدرتمند را برای انجام محاسبات علمی به صورت موازی و بدون نیاز به شناخت عمیق از رشتههای پردازشی (thread)، مبادلات دادهای و برنامه نویسیهای پیچیده موازی به ارمغان آورده است. در این مجموعه، عملیات بزرگ و سنگین محاسباتی به عنوان Job شناخته ميشوند که خود از زیر دستوراتی با نام Task تشکیل شدهاند.
در این مجموعه، ماشینی که در آن Jobها و Taskها تعریف شده و مورد استفاده قرار ميگیرند، Matlab Client نامیده ميشود. در بيشتر موارد، ماشین کلاینت همان ماشینی است که کاربر در آن به برنامهنویسی (در اصل، اسکریپت نویسی) با دستورات Matlab ميپردازد. این ماشین، با استفاده از Matlab Parallel Computing Toolbox به تعریف و برقراری رابطه با Jobها و Taskها ميپردازد. در این میان، ماجول MATLAB Distributed Computing Server وظیفه اجرای وظایف و انجام عملیات تبادل داده بین آنها و ماشین کلاینت را برعهده داشته و در هسته نسخههای اخیر Matlab موجود است. قسمتی از موتور پردازش توزیع یافته Matlab که Job Manager نام دارد، وظیفه کلی ایجاد هماهنگی بین وظایف و مبادلات دادهای مربوطه و مقادیر بازگردانده شده آنها را بر عهده دارد. اما وظیفه اصلی این ماجول، ارسال وظایف به ماشینهای در حال اجرای Matlab (این ماشینها، ماشینهای کارگر یا Matlab Worker خوانده ميشوند) و بازگرداندن نتایج از آنها است.
در این مجموعه کاربر ميتواند از Job Manager اصلی شرکت Mathworks موجود در نرمافزار Matlab استفاده کرده یا سیستمهایی نظیر Microsoft Windows HPC Server یا Platform LSF را به کار گیرد. شكلهاي 1، 2 و 3 دیاگرام معماری سیستم پردازش موازی Matlab و انواع ترکیبهای آن را نشان ميدهند.تنظیمات موتور پردازش موازی نرمافزار Matlab در این سیستم، تعیینکننده معماری موجود سیستم و نحوه ارسال وظایف از کلاینت به Job Manager و از آنجا به ماشینهای کارگر است. این تنظیمات در صورتی که موتور پردازش موازی و Toolbox پردازش موازی در نرمافزار Matlab نصب شده باشد، از طریق منوی اصلی Distributed و گزینه Manage Configurations قابل دسترسی است (شكل 4).
شکل 1- سادهترین ترکیب Client، Job Manager و Worker در محیط پردازش موازی Matlab
شکل 2- ترکیب چندگانه کلاینتها با یک Job Manager و چندین Worker در محیط پردازش موازی Matlab
شکل 3- ترکیب پیچیده چندگانه کلاینتها، Job Managerها و Workerها در یک شبکه بزرگ در محیط پردازش موازی Matlab
شکل 4- مدیریت تنظیمات موتور پردازش موازی نرمافزار Matlab
در صورتی که از نرمافزار Matlab روی یک كامپيوتر مجهز به پردازنده چند هستهای یا یک كامپيوتر چند پردازندهای استفاده شود، ميتوان از تنظیمات local که به صورت پیش فرض در سیستم موجود است، استفاده كرد. در این حالت، Job Manager به تعداد هستههای سیستم (حداکثر هشت عدد)، Worker ایجاد کرده و آنها را آماده انجام محاسبات ميكند. در صورت نیاز ميتوان تنظیمات جدیدی در سیستم تعریف كرد. در هر نرمافزار Matlab روی هر كامپيوتر ميتوان تعداد زیادی از تنظیمات را ذخیره کرد که یکی از آنها باید به عنوان پیش فرض تعیین شود. به عنوان مثال، مطابق شكل 5 ميتوان یک Job Manager جدید در كامپيوتر تعریف كرد. هر Job Manager تنظیمات اختصاصی خود را دارد که در شكل 6 نمونهای از آنها را مشاهده ميكنيد. همانطور که در شكل 6 ميبینید، گزینههای مختلفی از جمله نام سرور، حداکثر تعداد Job ها، فایلهای مورد نیاز همراه برنامه برای ارسال به اعضای کلاستر و خصوصیات سفارشی برای توابع جهت تنظیم درJob Manager وجود دارد.
شکل 5- روش تعریف یک Job Manager جدید در Matlab
شکل 6- تنظیمات Job Manager
حلقه for موازی
با توجه به نیازهای امروز، در نرمافزار Matlab امکاناتی برای استفاده از حلقههای For موازی برای اسکریپتنویسی وجود دارد. حلقههای For موازی حلقههایی هستند که قسمتی از آنها روی ماشین کلاینت Matlab اجرا شده و قسمتی از آنها به صورت موازی به مجموعه ماشینهای Matlab Workers ارسال ميشود (شكل 7). دادههای مورد نیاز ماشینهای کارگر از کلاینت به آنها ارسال شده و پس از انجام محاسبات، نتایج به کلاینت بازگردانده خواهد شد. نکته قابل توجه اين که هر اجرای حلقه For موازی در یک ماشین کارگر یک Iteration بوده و هر کدام از آنها از یکدیگر مستقل بوده و تضمینی برای همگامی اجرای آنها وجود ندارد. بنابراين، تنها حلقههایی که محاسبات و دادههای آنها امکان اجرا به صورت جداگانه را داشته باشند، با حلقه For موازی قابل پیاده سازی هستند.
شکل 7
برای استفاده از حلقههای موازی For باید مجموعه موتور پردازش موازی نرمافزار را فعال كرد. برای این کار، باید با استفاده از تابع Matlabpool، Scheduler را فعال کرده و سپس تعداد خاصی از ماشینهای کارگر را رزرو كنيم. با توجه به تنظیمات پیش فرض در Scheduler ماشینهای کارگر انتخابی ميتوانند ماشینهای فیزیکی بوده که در یک کلاستر قرار دارند یا اینکه مفهومی مجازی روی ماشین کلاینت Matlab باشند.در بخش قبل با سفارشیسازی تنظیمات Scheduler آشنا شدهاید. برای آغاز یک Session با ماشینهای کارگر بر اساس تنظیمات پیش فرض Scheduler، باید عبارتMatlabpool را در خط فرمان نرمافزار وارد كنيد. این تابع، در صورت وجود تنظیمات مناسب ماشینهای کارگر راه دور را برای انجام محاسبات موازی آماده کار خواهد کرد. در صورتی که این تنظیمات را تغییر نداده باشید و تنها گزینه موجود برای Scheduler گزینه local باشد، تابع مذکور به ازای هر هسته پردازنده سیستم، یک کارگر روی ماشین محلی ایجاد خواهد کرد. حداکثر تعداد این کارگرها، هشت عدد خواهد بود.
توجه کنید که در صورتی که از تابع Matlabpool برای ایجاد Session استفاده نكنيد، حلقههای Parfor به صورت سریال اجرا خواهند شد. حال، تابعی مطابق آنچه در فهرست یک آمده است تعریف كرده و با عنوان benchmark.m ذخیره ميكنيم. این تابع ساده، یک ماتریس به عنوان ورودی دریافت کرده و عملیاتی روی آن انجام ميدهد. پس از تعریف تابع نمونه، نوبت به نوشتن اسکریپت تولید متغیرها (ماتریس مرجع) و استفاده از تابع بالا ميرسد. برای این منظور، اسکریپتی مطابق فهرست 2 ایجاد ميكنيم.در این اسکریپت، ابتدا ماتریسی از اعداد تصادفی با ابعاد 2 به توان 20 و 16 تولید ميشود. سپس، در صورتی که Matlabpool فعال باشد، آنرا ميبندد و تابع مذکور را فراخوانی ميكند. در این حالت، اجرای حلقه Parfor به صورت سریال اتفاق خواهد افتاد. در ادامهMatlabpool با تعداد کارگرهای دلخواه که در بالای اسکریپت مشخص شدهاند، فراخوانی شده و تابع دوباره فراخوانی ميشود. در این حالت، حلقه به صورت موازی به اجرا در خواهد آمد. در انتها، خروجیهای به دست آمده نمایش داده شده و میزان افزایش سرعت نیز محاسبه شده و نمایش داده ميشود. پس از اجرای اسکریپت فوق، نتایج به دست آمده مطابق با فهرست 3 خواهد بود.
function [ T ] = benchMark( Ain, E )
% تعریف متغیرها
Msz = size(Ain,1);
a = zeros(Msz,1,›single›);
R = zeros(Msz,1,›single›);
k1 = single(pi/4);
k2 = single(pi/5);
A = single(Ain);
% شروع تایمر
tstart = tic;
% انجام محاسبات سنگین
parfor (e=1:E)
a = A(:,e);
R = k2*a - k1.^2*a.^2 ...
+ k2.^2*a.^3 - k1.^3*a.^4 ...
+ k2.^4*a.^5 - k1.^5*a.^6 ...
+ k2.^7*a.^7 - k1.^8*a.^8 ...
+ k2.^9*a.^9 - k1.^10*a.^10 ...
+ k2.^11*a.^11 - k1.^12*a.^12 ...
+ k2.^13*a.^13 - k1.^14*a.^14 ...
+ k2.^15*a.^15 - k1.^16*a.^16 ...
+ k2.^17*a.^17 - k1.^18*a.^18 ...
+ k2.^19*a.^19 - k1.^20*a.^20;
end
% پایان تایمر
% برگرداندن زمان محاسبه
T = toc(tstart);
end
فهرست 1- تابع نمونه برای انجام محاسبات سنگین
clear all;
% ایجاد متغیرها
NLNcols = 2^20;
E = 16;
% تعیین تعداد کارگرها
noWorkers = 2;
%تولید ماتریس رفرنس
Aref = rand(NLNcols,E);
%% محاسبات با یک ماشین کارگر
%==========================================================================
if matlabpool(‹size›) > 0
matlabpool close force;
end
% دریافت ماتریس ورودی
A = Aref;
T_single_CPU = benchMark( A, E );
%% محاسبات با چند ماشین کارگر
%==========================================================================
isOpenCorr = matlabpool(‹size›) == noWorkers;
if ~isOpenCorr,
matlabpool close force
matlabpool(noWorkers)
end
% دریافت ماتریس ورودی
A = Aref;
T_multi_CPU = benchMark( A, E );
%% PRINT DATA
fprintf(‹=============================================\n›);
strCPU1 = ‹# Workers: %d -> CPU Time [s]: %8.3f\n›;
fprintf(strCPU1, 1, T_single_CPU);
strCPU1 = ‹# Workers: %d -> CPU Time [s]: %8.3f\n›;
fprintf(strCPU1, noWorkers, T_multi_CPU);
fprintf(‹=============================================\n›);
str = ‹Speed-up; 1-CPU / M-CPU [-]: %8.3f\n›;
fprintf(str, T_single_CPU/T_multi_CPU);
فهرست 2- اسکریپت استفاده کننده از تابع نمونه
=============================================
# Workers: 1 -> CPU Time [s]: 58.992
# Workers: 2 -> CPU Time [s]: 30.837
=============================================
Speed-up; 1-CPU / M-CPU [-]: 1.913
فهرست 3- افزایش سرعت محاسبات با استفاده از Parfor به میزان 1,92 برابر برای 2 کارگر (هسته)
همان طور که مشاهده ميكنيد، با انجام محاسبات به صورت موازی به افزایش سرعتی مطابق با 92,1 برابر دست یافتهایم. ميتوان با افزایش متغیر noWorkers به مقادیر بالاتر روی پردازندههای قدرتمندتر و چند هستهای افزایش سرعت را برای تعداد هستهها و کارگرهای بیشتر نیز محاسبه كرد.
یک برنامه، چندین داده
یکی دیگر از امکاناتی که توسط ابزار محاسبات موازی Matlab در اختیار کاربران قرار گرفته ، امکان توسعه یک کد و اجرای آن روی چندین کارگر با دادههای متفاوت است (Single Program, Multiple Data). در این حالت، یک کد به تمام کارگرها ارسال شده و هر کدام ميتوانند دادههای اختصاصی و منحصر به فردی برای اجرا به کد مذکور وارد کرده و نتایج را ارسال كنند. برای استفاده از این قابلیت، ميتوان از کد نمونه فهرست4 استفاده كرد. در کد بالا، متغیر m حداقل تعداد ماشینهای کارگر برای اجرا و متغیرn حداکثر تعداد ماشینهای کارگر را تعیین ميكند. به عنوان مثال، کدی مطابق با فهرست 5 ميتواند به عنوان یک نمونه برای اجرا روی سه lab مورد استفاده قرار گیرد. نکته قابل توجه این است که هر ماشین کارگر یک شاخص منحصر به فرد دارد که با متغیر labindexمشخص ميشود. این متغیر برای سفارشیسازی متغیرهای محلی در هر ماشین کارگر مورد استفاده قرار ميگیرد. فهرست 6 نمونهای از طرز استفاده از labindex را نشان ميدهد. با استفاده از قابلیت شاخص منحصر به فرد برای هر ماشین کارگر، ميتوان به سادگی برای هر ماشین دادههای منحصر به فردی بارگذاری كرد.
spmd (m, n)
<برنامه اجرایی>
end
فهرست 4 - نمونه تعیین کد اجرایی برای ارسال به ماشینهای کارگر با دادههای مختلف
matlabpool
spmd (3)
R = rand(10000,10000);
end
matlabpool close
فهرست 5- یک برنامه نمونه برای استفاده از Spmd
spmd (3)
if labindex==1
R = rand(9,9);
else
R = rand(4,4);
end
end
فهرست 6- روش استفاده از شاخص labindex در Spmd
فهرست 7 نمونهای از این تکنیک را برای بارگذاری فایلهای متنی مختلف به عنوان ورودیهای مختلف هر ماشین کارگرنشان ميدهد. برای دسترسی به مقادیر دادههای ایجاد شده روی هر ماشین کارگر، به سادگی ميتوان از نام متغیر مربوطه استفاده كرد. این متغیر، به صورت یک مجموعه کامپوزیت برگردانده ميشود که هر عضو آن حاوی دادههای مربوط به ماشین کارگر مربوطه است. به عنوان مثال، به فهرست8 توجه كنيد. همانطور که در فهرست 8 نیز مشاهده ميکنید، در Spmd تعیین شده است که در ماشینهای کارگر با اندیس بالاتر از یک، متغیر HH با یک ماتریس 4×4 پر شود. پس از فراخوانی متغیر HH خروجی نشان ميدهد که نخستين عنصر مجموعه خالی و باقی حاوی داده است. یکی دیگر از قابلیتهای سودمند Spmd برای کار با آرایهها، قابلیت توزیع آنها بین labهاست. برای توزیع یک آرایه عددی بین ماشینهای کارگر، ميتوان از تابع Codistributed استفاده كرد. فهرست 9 نمونهای از توزیع یک ماتریس10×3 را بین چهار lab نشان ميدهد. دستور getLocalPart نیز قسمتهای تخصیص داده شده به هر lab را نشان ميدهد.
spmd (3)
labdata = load([‹datafile_› num2str(labindex) ‹.ascii›])
result = MyFunction(labdata)
end
فهرست 7- بارگذاری فایلهای متنی مختلف به عنوان ورودی منحصر به فرد برای هر ماشین کارگر
>>spmd
>> if labindex > 1
>> HH = rand(4);
>> end
>> end
>> HH
%---------- خروجی در کلاینت -----------------
Lab 1: No data
Lab 2: class = double, size = [4 4]
Lab 3: class = double, size = [4 4]
>> HH{2}
%---------- خروجی در کلاینت -----------------
HH{2}
16 2 3
5 11 10
9 7 6
4 14 15
>> Lab 2:
%---------- خروجی در کلاینت -----------------
HH
16 2 3
5 11 10
9 7 6
4 14 15
فهرست 8- دسترسی به متغیرهای ایجاد شده در ماشینهای کارگر
spmd
A = [11:20; 21:30; 31:40];
D = codistributed(A);
getLocalPart(D)
end
LAB 1 LAB 2 LAB 3 LAB 4
| | |
11 12 13 | 14 15 16 | 17 18 | 19 20
21 22 23 | 24 25 26 | 27 28 | 29 30
31 32 33 | 34 35 36 | 37 38 | 39 40
فهرست 9- توزیع یک ماتریس10´3بین چهار lab به همراه خروجی
محاسبات موازی در محیط گرافیکی پس از بررسی ابزارهای سودمند Parfor و Spmd درParallel Computing Toolbox در نرمافزار Matlab، به معرفی و بررسی یک محیط گرافیکی برای اجرای دستورات در محیط پردازش موازی Matlab خواهیم پرداخت. در Parallel Computing Toolbox نرمافزار Matlab یک محیط گرافیکی برای اجرای دستورات و برنامههای موازی تعبیه شده است که امکان مشاهده اجرای دستورات و نمایش متغیرهای خروجی را دارد. این پنجره از طریق واردکردن دستور Pmode با پارامترهای مناسب اجرا ميشود. با وارد کردن دستورات مندرج در فهرست 10 این پنجره چهار lab در سیستم محلی ایجادکرده و ترمینال مربوط به هر کدام را در یک پنجره اما به صورت یکجا نمایش ميدهد (شكل 8). پارامتر دوم در دستور فوق (دراینجا local) نام تنظیمات Matlab Distributed Engine است که در قسمت آغازین این نوشتار به آن پرداختیم. در صورتی که بخواهیم به ماشینهای کارگر واقعی که روی شبکه موجود هستند متصل شویم، باید نام تنظیمات مربوطه را وارد كنيم. در صورتی که این پارامتر خالی گذاشته شود، از تنظیمات پیش فرض استفاده خواهد شد. پارامتر دوم، تعداد ماشینهای کارگر یا labهای مورد نیاز را تعیین ميکند. در صورتی که این پارامتر نیز خالی گذاشته شود، از مقادیر پیش فرض استفاده خواهد شد.
شکل 8- محیط گرافیکی pmode که با اجرای کد فهرست 9 اجرا شده است.
pmode start local 4
فهرست 10- اجرای ابزار گرافیکی pmode با چهار lab به صورت محلی
همان طور که در تصویر ميبینید، این محیط شبیه به وجود چهار ترمینال Matlab است که هر کدام در فضایی مجزا اجرا ميشوند. یک خط فرمان کلی نیز وجود دارد که تمام دستورات به همه labها، از این طریق اعمال ميشوند. روش کار با محیط گرافیکی pmode همانند روش استفاده از Spmd است و Pmode را ميتوان نمونه گرافیکی آن دانست. با توجه به خصوصیات و مشخصات این ابزار گرافیکی، ميتوان آن را وسیلهای برای آزمایش و ارزیابی برنامههای موازی به صورت گرافیکی دانست. هر چند این محیط از لحاظ کارایی با Spmd تفاوت چندانی ندارد، اما بیشتر برای اهداف اشکال زادیی و ارزیابی کد مورد استفاده قرار ميگیرد. حال برای آشنایی بیشتر با محیط گرافیکی موازی Matlab دستورات آورده شده در فهرست 11 را به ترتیب در خط فرمان آن وارد كنيم. خروجی pmode به این دستورات مطابق آنچه در شكلهاي 9 و 10 آمده است خواهد بود. برای بازخوانی دادهها از هر lab به ماشین کلاینت برای انجام محاسبات یا رسم انواع نمودار، باید در ترمینال ماشین کلاینت از پارامتر lab2client به همراه شماره lab مربوطه استفاده كرد. فهرست12 نمونهای از دریافت دادهها از چهار lab مثال بالا را نشان ميدهد. با استفاده از دستورات و تکنیکهای ساده توضیح داده شده در بالا اکنون ميتوانيد با ترکیب آنها در برنامههای پیچیده، حداکثر کارایی را از سیستمهای چند هستهای یا چند پردازندهای به دست آورید.
شکل 9- خروجی کارگرهای مختلف به دستورات وارد شده در رابط pmode
شکل 10
ارزیابی عملکرد سیستم با استفاده از Mpiprofiler
همان طور که مشاهده كرديد، نرمافزار Matlab با یک هسته درونی قوی، ابزاری ساده و کارا برای انجام محاسبات موازی در اختیار کاربران قرار داده است. اما حلقه تکمیل کننده این مجموعه ابزار پیشرفته، ابزاری برای ارزیابی عملکرد ماشینهای کارگر و ارائه گزارشهای مختلف به کاربر از عملکرد واقعی سیستم است. برای این منظور و جهت استفاده از این امکانات، باید هنگام اجرای وظایف، ابزار Mpiprofiler را فعال كرد تا به جمعآوری داده در رابطه با عملیات سیستم بپردازد. برای فعالسازی این ابزار ميتوان از کد آورده شده در فهرست 13 استفاده كرد. دادههایی که این ابزار جمع آوری ميكند، دادههایی از قبیل زمان اجرای هر تابع در هر lab، زمان اجرای هر خط در توابع، شامل حجم دادههای مبادله شده بین lab ها و زمانی که هر lab برای مبادله داده منتظر ميماند، است. به عنوان مثال، با اجرای کد فهرست 14 در پنجره Pmode، ابزار Mpiprofiler نتایجی مشابه شكل 11 ارائه خواهد داد.
شکل 11 - نتایج به دست آمده برای آنالیز اجرای کد فهرست 14 توسط mpiprofiler
شکل 12- نتایج زمان مبادلات دادهای بین labها به صورت نمودار گرافیکی
P>> segment = [1 2; 3 4; 5 6]
P>> segment = segment + 10*labindex
فهرست 11- نمونهای از دستورات برای آزمایش محیط pmode
>> pmode lab2client segment 1
>> segment
segment =
11 12
13 14
15 16
>> pmode lab2client segment 2
>> segment
segment =
21 22
23 24
25 26
>> pmode lab2client segment 3
>> segment
segment =
31 32
33 34
35 36
>> pmode lab2client segment 4
>> segment
segment =
41 42
43 44
45 46
فهرست 12- طریقه دریافت مقادیر از هر lab در ماشین کلاینت برای انجام اموری چون رسم گرافیکی
mpiprofile on
فهرست 13- فعالسازی ابزارMpiprofiler
P>> R1 = rand(16, codistributor())
P>> R2 = rand(16, codistributor())
P>> mpiprofile on
P>> P = R1*R2
P>> mpiprofile off
P>> mpiprofile viewer
فهرست 14- یک برنامه نمونه برای بررسی در mpiprofiler
جمعبندی
در این نوشتار به بررسی اجمالی قابلیتهای محاسبات موازی Matlab پرداختیم و به صورت مختصر، اجزای اصلی تشکیل دهنده آن را مورد بررسی قرار دادیم. به يقين با ترکیب این تکنیكها و ابزارها با کدهای ساده و سریال قدیمی و با نیاز اندک به دستکاری کد و بدون داشتن دانش کافی درباره مسائل و مشکلات مربوط به Threading، به سادگی ميتوان برنامههای خود را روی سخت افزارهای مناسب امروزی به نحو احسن و با کارایی بالا اجرا كرد.
منبع : ماهنامه شبکه