সমান্তরাল.ফোর্চ প্রতিটি বনাম টাস্ক.ফ্যাক্টরি.স্টার্টনিউ


267

নীচের কোড স্নিপেটগুলির মধ্যে পার্থক্য কী? উভয়ই থ্রেডপুলের থ্রেড ব্যবহার করবে না?

উদাহরণস্বরূপ, যদি আমি একটি সংগ্রহে প্রতিটি আইটেমের জন্য একটি ফাংশন কল করতে চান,

Parallel.ForEach<Item>(items, item => DoSomething(item));

vs

foreach(var item in items)
{
  Task.Factory.StartNew(() => DoSomething(item));
}

উত্তর:


302

প্রথমটি একটি আরও ভাল বিকল্প।

সমান্তরাল.ফরআচ প্রতিটি অভ্যন্তরীণভাবে Partitioner<T>আপনার সংগ্রহকে কাজের আইটেমগুলিতে বিতরণ করতে একটি ব্যবহার করে । এটি আইটেম প্রতি এক কাজ করবে না, বরং জড়িত ওভারহেড কম করার জন্য এটি ব্যাচ করবে।

দ্বিতীয় বিকল্পটি Taskআপনার সংগ্রহে আইটেম প্রতি একক সময় নির্ধারণ করবে । ফলাফলগুলি প্রায় (প্রায়) একই রকম হবে, এটি প্রয়োজনীয়তার চেয়ে অনেক বেশি ওভারহেড প্রবর্তন করবে, বিশেষত বৃহত সংগ্রহের জন্য এবং সামগ্রিক রানটাইমকে ধীর করে দেবে।

অবগতির জন্য - পার্টিশনকারী উপযুক্ত ব্যবহারের মাধ্যমে নিয়ন্ত্রণ করা যায় ব্যবহৃত Parallel.ForEach করার overloads , যদি তাই হয় পছন্দসই। বিশদর জন্য , এমএসডিএন-এ কাস্টম পার্টিশনস দেখুন ।

মূল পার্থক্য, রানটাইম এ, দ্বিতীয়টি অ্যাসিঙ্ক্রোনাস কাজ করবে। এটি সমান্তরাল ব্যবহার করে সদৃশ করা যেতে পারে For

Task.Factory.StartNew( () => Parallel.ForEach<Item>(items, item => DoSomething(item)));

এটি করার দ্বারা, আপনি এখনও পার্টিশনকারীদের সুবিধা গ্রহণ করুন, তবে অপারেশন সম্পূর্ণ না হওয়া পর্যন্ত অবরুদ্ধ করবেন না।


8
আইআইআরসি, সমান্তরাল দ্বারা ডিফল্ট পার্টিশন করা হয়েছে For মাইক্রোসফ্টের সমান্তরাল প্রোগ্রামিং নিবন্ধের প্যাটার্নগুলি দেখুন ; এটি এতে এই সমস্ত জিনিসটির দুর্দান্ত ব্যাখ্যা পেয়েছে।
মাল রস

2
@ মাল: বাছাই করুন ... এটি আসলে পার্টিশনার নয়, বরং টাস্কশেল্ডারের কাজ। টাস্কশেজুলার, ডিফল্টরূপে নতুন থ্রেডপুল ব্যবহার করে, যা এটি এখন খুব ভালভাবে পরিচালনা করে।
রিড কোপসি

ধন্যবাদ। আমি জানতাম আমার "আমি কোনও বিশেষজ্ঞ নই, তবে ..." ক্যাভেটে রেখে যাওয়া উচিত। :)
মল রস

@ রিডকপসি: সমান্তরাল মাধ্যমে শুরু করা কাজগুলি কীভাবে সংযুক্ত করবেন? মোড়ক টাস্পের জন্য প্রতিটি? সুতরাং যখন আপনি কল করবেন। একটি মোড়ক টাস্কে অপেক্ষা করুন () সমান্তরালভাবে চলমান কাজগুলি শেষ না হওয়া পর্যন্ত এটি স্তব্ধ হয়ে যায়?
কনস্ট্যান্টিন তারকাস

1
@ টারকাস আপনি যদি একাধিক অনুরোধ করে থাকেন তবে প্রতিটি কাজের আইটেমটিতে (আপনার সমান্তরাল লুপে) কেবলমাত্র HTTPClient.GetString ব্যবহার করা ভাল। ইতিমধ্যে সমবর্তী লুপটির ভিতরে একটি অ্যাসিঙ্ক বিকল্প রাখার কোনও কারণ নেই, সাধারণত ...
রিড কোপসি

89

আমি "সমান্তরাল.ফরফ" এবং একটি "টাস্ক" অবজেক্টের সাথে "1,000,000,000 (এক বিলিয়ন)" একটি পদ্ধতি চালানোর জন্য একটি ছোট পরীক্ষা করেছি experiment

আমি প্রসেসরের সময়টি পরিমাপ করেছি এবং সমান্তরাল আরও কার্যকর পেয়েছি। সমান্তরাল.ফোর্স আপনার কাজটিকে ছোট কাজের আইটেমগুলিতে ভাগ করে দেয় এবং এগুলি সর্বোত্তম উপায়ে সমান্তরালভাবে সমস্ত কোরে সম্পাদন করে। প্রচুর টাস্ক অবজেক্ট তৈরি করার সময় (এফওয়াইআই টিপিএল অভ্যন্তরীণভাবে থ্রেড পুলিং ব্যবহার করবে) প্রতিটি কার্য সম্পাদনে বাক্সে আরও চাপ তৈরি করবে যা নীচের পরীক্ষায় প্রমাণিত।

আমি একটি ছোট ভিডিওও তৈরি করেছি যা বেসিক টিপিএলকে ব্যাখ্যা করে এবং এটিও দেখিয়েছি যে কীভাবে প্যারালাল For ফোর্সগুলি আপনার কার্যকে আরও কার্যকরভাবে ব্যবহার করে http://www.youtube.com/watch?v=No7QqSc5cl8 স্বাভাবিক কর্ম এবং থ্রেডের তুলনায়।

পরীক্ষা-নিরীক্ষা ঘ

Parallel.For(0, 1000000000, x => Method1());

পরীক্ষা 2

for (int i = 0; i < 1000000000; i++)
{
    Task o = new Task(Method1);
    o.Start();
}

প্রসেসরের সময়ের তুলনা


এটি আরও দক্ষ হবে এবং থ্রেড তৈরি করা ব্যয়বহুল পরীক্ষা 2 এর পিছনে কারণটি খুব খারাপ অভ্যাস।
টিম

@ জর্জি - এটি খারাপের বিষয়ে আরও কথা বলার জন্য দয়া করে দয়া করে।
শিবপ্রসাদ কৈরালা

3
আমি দুঃখিত, আমার ভুল, আমার স্পষ্ট করা উচিত ছিল। আমার অর্থ 1000000000 এ লুপে টাস্ক তৈরি করা The ওভারহেডটি অভাবনীয়। সমান্তরাল একবারে 63৩ টিরও বেশি টাস্ক তৈরি করতে পারে না তা উল্লেখ করার দরকার নেই, যা এটি ক্ষেত্রে আরও বেশি অনুকূলিত করে তোলে।
জর্জি-এটি

এটি 1000000000 কাজের জন্য সত্য। তবে আমি যখন কোনও চিত্র প্রক্রিয়া করি (বারবার, ফ্র্যাক্টাল জুম করে) এবং সমান্তরাল করি lines এটি দ্রুত করার জন্য আমি 64৪ টি কাজের প্যাকেজে ডেটা নিজেই বিভক্ত করেছি এবং এর জন্য কার্য তৈরি করেছি। (তারপরে টাস্ক.ওয়েটএল সমাপ্তির জন্য অপেক্ষা করতে হবে)) নিষ্ক্রিয় থ্রেডগুলি তাদের (সমান্তরাল.ফোর্স) নির্ধারিত অংশটি শেষ করার জন্য 1-2 থ্রেড অপেক্ষা না করে কাজ শেষ করতে সহায়তা করার জন্য একটি কার্য প্যাকেজ বেছে নেওয়ার ধারণা।
টেড হানসেন

1
Mehthod1()এই উদাহরণে কি করে ?
জাপানোলিকিকা

17

সমান্তরাল.ফর প্রতিটি অপ্টিমাইজ করে (এমনকি নতুন থ্রেড শুরুও করতে পারে না) এবং লুপ শেষ না হওয়া অবধি ব্লক করে দেবে এবং টাস্ক.ফ্যাক্টরি স্পষ্টভাবে প্রতিটি আইটেমের জন্য একটি নতুন টাস্ক ইনস্ট্যান্স তৈরি করবে এবং সেগুলি শেষ হওয়ার আগেই ফিরে আসবে (অ্যাসিনক্রোনাস টাস্ক)। সমান্তরাল.ফোর্যাচ অনেক বেশি দক্ষ।


11

আমার দৃষ্টিতে সর্বাধিক বাস্তব পরিস্থিতি হল যখন কাজগুলি শেষ করার জন্য একটি ভারী অপারেশন হয়। শিবপ্রসাদের দৃষ্টিভঙ্গি নিজেই কম্পিউটিংয়ের চেয়ে অবজেক্ট তৈরি / স্মৃতি বরাদ্দের দিকে বেশি মনোনিবেশ করে। নিম্নলিখিত পদ্ধতিটিকে কল করে আমি একটি গবেষণা করেছি:

public static double SumRootN(int root)
{
    double result = 0;
    for (int i = 1; i < 10000000; i++)
        {
            result += Math.Exp(Math.Log(i) / root);
        }
        return result; 
}

এই পদ্ধতিটি কার্যকর করতে প্রায় 0.5 0.5 সেকেন্ড লাগে।

আমি সমান্তরাল ব্যবহার করে এটি 200 বার কল করেছি:

Parallel.For(0, 200, (int i) =>
{
    SumRootN(10);
});

তারপরে আমি এটিকে 200 বার পুরানো ফ্যাশন ব্যবহার করে কল করেছি:

List<Task> tasks = new List<Task>() ;
for (int i = 0; i < loopCounter; i++)
{
    Task t = new Task(() => SumRootN(10));
    t.Start();
    tasks.Add(t);
}

Task.WaitAll(tasks.ToArray()); 

প্রথম কেস 26656 মিমিতে সম্পন্ন হয়েছে, দ্বিতীয়টি 24478 মিলিমিটারে। আমি অনেক বার পুনরাবৃত্তি। প্রতিটি সময় দ্বিতীয় পদ্ধতির প্রান্তিক দ্রুত।


প্যারালাল.ওফর ব্যবহার করা পুরানো ধাঁচের উপায়। অভিন্ন নয় এমন কাজের ইউনিটগুলির জন্য টাস্ক ব্যবহার করার পরামর্শ দেওয়া হচ্ছে। মাইক্রোসফ্ট এমভিপি এবং টিপিএলের ডিজাইনাররা আরও উল্লেখ করেছেন যে টাস্কগুলি ব্যবহার করে থ্রেডগুলি আরও দক্ষতার সাথে ব্যবহার করা হবে, অন্যান্য ইউনিটগুলি সম্পূর্ণ হওয়ার অপেক্ষায় অনেকগুলি আইয়নট ব্লক করবে।
সানক্যাট 2000 2000
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.