اکثرا توسعه دهندگان Net. با LINQ آشنا میباشند،تکنولوژی ای که طرح و نقشه برنامه نویسی عملی
(functional programming ) را به محیط شی گرایی میآورد. Parallel LINQ یا PLINQ, با اضافه کردن قابلیت های موازی بصری بر روی یک فریمورک قدرتمند، LINQ را یک مرحله بالا میبرد .
PLINQ یک موتور اجرای پرس و جو (query) است ،هر پرس و جوی LINQ-to-Objects یا LINQ-to-XML را میپذیرد و بصورت خودکار از چندین پردازشگر یا هسته که برای اجرا در دسترس هستند ، استفاده میکند .
استفاده از PLINQ دقیقا همانند استفاده از LINQ-to-Objects و LINQ-to-XML است . شما از تمام Operatorهایی که در 3.0 #C یا کلاس System.Linq.Enumerable ، شاملOrderBy, Join, Select,Where هستند ، میتوانید استفاده کنید .
کوئری های LINQ-to-SQL و LINQ-to-Entities بوسیله پایگاه داده های خاص و query providerها ، قابل اجرا خواهند بود . بنابراین ، PLINQ راهی برای توازی این دسته از کوئری ها پیشنهاد نمیدهد .
استفاده از متد AsParallel :
متد AsParallel ، درگاهی است به PLINQ .رشته ای از داده ها را به ParallelQuery تبدیل میکند . موتور LINQ استفاده از ParallelQuery در queryها را تشخیص میدهد و بصورت خودکار آن را به PLINQ تبدیل میکند . شما در هر بار استفاده از PLINQ به احتمال زیاد باید از متد AsParallel هم استفاده کنید .
Sequential LINQ execution :
var customers = new[] { new Customer { ID = 1, FirstName = "Sandeep" , LastName = "Ramani" }, new Customer { ID = 2, FirstName = "Dharmik" , LastName = "Chotaliya" }, new Customer { ID = 3, FirstName = "Nisar" , LastName = "Kalia" } , new Customer { ID = 4, FirstName = "Ravi" , LastName = "Mapara" } , new Customer { ID = 5, FirstName = "Hardik" , LastName = "Mistry" } new Customer { ID = 6, FirstName = "Sandy" , LastName = "Ramani" }, new Customer { ID = 7, FirstName = "Jigar" , LastName = "Shah" }, new Customer { ID = 8, FirstName = "Kaushal" , LastName = "Parik" } , new Customer { ID = 9, FirstName = "Abhishek" , LastName = "Swarnker" } , new Customer { ID = 10, FirstName = "Sanket" , LastName = "Patel" } new Customer { ID = 11, FirstName = "Dinesh" , LastName = "Prajapati" }, new Customer { ID = 12, FirstName = "Jayesh" , LastName = "Patel" }, new Customer { ID = 13, FirstName = "Nimesh" , LastName = "Mishra" } , new Customer { ID = 14, FirstName = "Shiva" , LastName = "Reddy" } , new Customer { ID = 15, FirstName = "Jasmin" , LastName = "Malviya" } new Customer { ID = 16, FirstName = "Haresh" , LastName = "Bhanderi" }, new Customer { ID = 17, FirstName = "Ankit" , LastName = "Ramani" }, new Customer { ID = 18, FirstName = "Sanket" , LastName = "Shah" } , new Customer { ID = 19, FirstName = "Amit" , LastName = "Shah" } , new Customer { ID = 20, FirstName = "Nilesh" , LastName = "Soni" } }; var results = from c in customers where c.FirstName.StartsWith("San") select c;
Parallel LINQ execution :
var customers = new[] { new Customer { ID = 1, FirstName = "Sandeep" , LastName = "Ramani" }, new Customer { ID = 2, FirstName = "Dharmik" , LastName = "Chotaliya" }, new Customer { ID = 3, FirstName = "Nisar" , LastName = "Kalia" } , new Customer { ID = 4, FirstName = "Ravi" , LastName = "Mapara" } , new Customer { ID = 5, FirstName = "Hardik" , LastName = "Mistry" } new Customer { ID = 6, FirstName = "Sandy" , LastName = "Ramani" }, new Customer { ID = 7, FirstName = "Jigar" , LastName = "Shah" }, new Customer { ID = 8, FirstName = "Kaushal" , LastName = "Parik" } , new Customer { ID = 9, FirstName = "Abhishek" , LastName = "Swarnker" } , new Customer { ID = 10, FirstName = "Sanket" , LastName = "Patel" } new Customer { ID = 11, FirstName = "Dinesh" , LastName = "Prajapati" }, new Customer { ID = 12, FirstName = "Jayesh" , LastName = "Patel" }, new Customer { ID = 13, FirstName = "Nimesh" , LastName = "Mishra" } , new Customer { ID = 14, FirstName = "Shiva" , LastName = "Reddy" } , new Customer { ID = 15, FirstName = "Jasmin" , LastName = "Malviya" } new Customer { ID = 16, FirstName = "Haresh" , LastName = "Bhanderi" }, new Customer { ID = 17, FirstName = "Ankit" , LastName = "Ramani" }, new Customer { ID = 18, FirstName = "Sanket" , LastName = "Shah" } , new Customer { ID = 19, FirstName = "Amit" , LastName = "Shah" } , new Customer { ID = 20, FirstName = "Nilesh" , LastName = "Soni" } }; var results = from c in customers.AsParallel() where c.FirstName.StartsWith("San") select c;
با اضافه کردن متد ()AsParallel ،زمان اجرای Net. توازی (parallelize ) عملیات ها در سراسر هسته های چندگانه به طور خودکار انجام میشود . در حقیقت ، PLINQ مسئولیت قسمت بندی کردن داده ها، برای اینکه قادر به پردازش آنها بصورت موازی باشد را ، تماما بر عهده میگیرد .
با اضافه کردن متد ()AsParallel ،زمان اجرای Net. توازی (parallelize ) عملیات ها در سراسر هسته های چندگانه به طور خودکار انجام میشود . در حقیقت ، PLINQ مسئولیت قسمت بندی کردن داده ها، برای اینکه قادر به پردازش آنها بصورت موازی باشد را ، تماما بر عهده میگیرد .
زمانی که شما کوئری های ساده بالا را اجرا میکنید ،خروجی یکسانی دریافت خواهید کرد اما احتمالا در جهت های مختلف . تکه کد اول یک مثال از Sequential LINQ execution ، و تکه کد دوم یک مثال از Parallel LINQ execution میباشد .
محدودیت ها :
1. PLINQ فقط بر روی مجموعه های local کار میکند . این بدان معناست که اگر شما از LINQ Providerهایی ، همانند LINQ to SQL یا ADO.NET Entity Framework استفاده میکنید ، شما شانسی در این زمینه برای استفاده از این نسخه ندارید .
2. زمانی که داده هارا قسمت بندی میکنید و آنها را بصورت موازی اجرا میکنید ، خروجیِ شما دقیقا همانند خروجی اجرای کدها بصورت سریالی نمیشود .
اگرچه ، شما قادر به استفاده از آن با استفاده از متد ()AsOrdered در کوئری های خود خواهید بود ، که دستورِ خاصی را بصورت اجباری بر روی نتیجه شما اعمال میکند، به یاد داشته باشید که ، متد ()AsOrdered برای مجموعه های بزرگ روی کارایی تاثیر دارد .
حفظ نظم نتایج جستجوی کوئری PLINQ با استفاده از متد AsOdered :
var results = from c in customers.AsParallel().AsOrdered() where c.FirstName.StartsWith("San") select c;
کنترل توازی :
1. اجبار اجرای موازی :
در اینگونه موارد ، PLINQ ممکن است تصمیم بگیرد که با کوئری شما بهتر است بصورت ترتیبی رفتار شود . شما این را میتوانید با استفاده از متد WithExecutionMode کنترل کنید ، که به نوع ParallelQuery اعمال میشود . متد
WithExecutionMode یک مقدار از ParallelExecutionMode enumeration دریافت میکند . در اینجا دو نوع مقدار وجود دارد : defualt (اجازه میدهد PLINQ برای اینکه چه کاری انجام شود تصمیم بگیرد ) و ForceParallelism .
در زیر تکه کدی وجود دارد که استفاده از متد را نمایش میدهد :
var results = from c in customers.AsParallel().WithExecutionMode (ParallelExecutionMode.ForceParallelism) where c.FirstName.StartsWith("San") select c;
2. محدود کردن درجه توازی :
شما میتوانید با استفاده از متد WithDegreeofParallelism که روی ParallelQuery کار میکند ، درخواست دهید که PLINQ تعداد قسمت هایی که قرار است با هم پردازش شوند را محدود کند . این متد ، یک مقدار int دریافت میکند که نشان دهنده ماکزیمم تعداد قسمت بندی هایی است که با ید با هم پردازش شوند . این را تحت عنوان درجه توازی میشناسند . تنظیم درجه توازی PLINQ را مجبور به استفاده از آن نمیکند . فقط سقف درجه توازی را تعیین میکند . ممکن است PLINQ تصمیم به استفاده از مقدار کمتری از آن چه شما مشخص کرده اید ، بگیرد . اگر شما از متد WithExecutionMode استفاده نمیکنید ، ممکن است تصمیم به اجرای queryها بصورت ترتیبی بکنید .
در زیر تکه کدی آمده است که استفاده از این متد را نمایش میدهد :
var results = from c in customers.AsParallel().WithDegreeOfParallelism(2) where c.FirstName.StartsWith("San") select c;
3. تولید و استفاده از توالی موازی (Parallel Sequence) :
IEnumerable<int> evens = ((ParallelQuery<int>) ParallelEnumerable.Range(0, 50000)) .Where(i => i % 2 == 0) .Select(i => i);
کد بالا از متد Range برای ایجاد 50000 عدد integer که از 0 شروع میشود ، استفاده کرده است . اولین آرگومان دریافتی اندیس آغازین آن است و دومین آرگومان تعداد مقادیری که شما نیاز دارید . توجه داشته باشید که ما مقدار را از متد Range به Cast ، ParallelQuery کردیم . اگر این کار را نکنیم ، LINQ پشتیبانی از توالی بصورت موازی را تشخیص نمیدهد و کوئری ها را به صورت متوالی اجرا خواهد کرد .
4. تولید و استفاده از تکرار توالی (Repeating Sequnce) :
int sum = ParallelEnumerable.Repeat(1, 50000) .Select(i => i) .Sum();
متد Static Repeat یک شئ و یک مقدار را دریافت میکند و توالی ای را ایجاد میکند که در آن اشیا به تعداد مقداری که متد دریافت کرده است تکرار میشوند .
تلگرام : @ayhan_dev
اینستاگرام: Instagram.com/ayha.n_1380