जवाबों:
नहीं, यह 1000 थ्रेड शुरू नहीं करेगा - हाँ, यह सीमित करेगा कि कितने थ्रेड का उपयोग किया जाता है। समानांतर एक्सटेंशन उचित संख्या में कोर का उपयोग करता है, जो इस आधार पर करता है कि आपके पास कितने भौतिक हैं और कितने पहले से ही व्यस्त हैं। यह प्रत्येक कोर के लिए काम आवंटित करता है और फिर एक तकनीक का उपयोग करता है जिसे काम चोरी कहा जाता है ताकि प्रत्येक थ्रेड प्रक्रिया को कुशलता से अपनी कतार बनाने के लिए और केवल किसी भी महंगी क्रॉस-थ्रेड पहुंच की आवश्यकता होती है जब इसे वास्तव में करने की आवश्यकता होती है।
यह कैसे काम आवंटित करता है और अन्य सभी विषयों के बारे में जानकारी के भार के लिए PFX टीम ब्लॉग पर एक नज़र है ।
ध्यान दें कि कुछ मामलों में आप जो समानता चाहते हैं, उसकी डिग्री भी निर्दिष्ट कर सकते हैं।
एक ही कोर मशीन पर ... संग्रह के समानांतर फ़ॉरचैट विभाजन (चंक्स) जो कई थ्रेड्स के बीच काम कर रहा है, लेकिन उस संख्या की गणना एक एल्गोरिथ्म के आधार पर की जाती है जो खाते में लेता है और लगातार किए गए कार्य की निगरानी करता है। धागे यह ForEach को आवंटित कर रहा है। इसलिए यदि ForEach का मुख्य भाग लंबे समय तक चलने वाले IO- बाउंड / ब्लॉकिंग फ़ंक्शन को कॉल करता है जो थ्रेड को प्रतीक्षा में छोड़ देता है, तो एल्गोरिथ्म अधिक थ्रेड्स को स्पॉन करेगा और उनके बीच संग्रह को पुन: उत्पन्न करेगा । यदि थ्रेड जल्दी से पूर्ण हो जाते हैं और उदाहरण के लिए IO थ्रेड पर ब्लॉक नहीं करते हैं, जैसे कि बस कुछ संख्याओं की गणना करना,एल्गोरिथ्म एक बिंदु तक थ्रेड्स की संख्या (या वास्तव में नीचे) तक पहुंच जाएगा जहां एल्गोरिथ्म थ्रूपुट (प्रत्येक पुनरावृत्ति का औसत पूरा होने का समय) के लिए इष्टतम मानता है ।
मूल रूप से सभी विभिन्न समानांतर लाइब्रेरी फ़ंक्शंस के पीछे थ्रेड पूल, उपयोग करने के लिए अधिकतम संख्या में थ्रेड्स का काम करेगा। भौतिक प्रोसेसर कोर की संख्या समीकरण का केवल एक हिस्सा है। कोर की संख्या और थ्रेड की संख्या के बीच एक से एक संबंध नहीं है।
मुझे रद्द करने और थ्रेड को सिंक्रोनाइज़ करने में सहायक बहुत उपयोगी नहीं है। उम्मीद है कि MS MSDN में बेहतर उदाहरणों की आपूर्ति कर सकता है।
मत भूलो, शरीर कोड को कई थ्रेड पर चलाने के लिए लिखा जाना चाहिए, साथ ही सभी सामान्य थ्रेड सुरक्षा कारणों के साथ, फ्रेमवर्क उस कारक को सार नहीं करता है ... अभी तक।
यह प्रोसेसर / कोर की संख्या के आधार पर एक इष्टतम संख्या में थ्रेड्स का काम करता है। वे सभी एक ही बार में नहीं जाएंगे।
क्या देखें समानांतर। इसके लिए प्रति कार्य एक कार्य का उपयोग किया जाता है? उपयोग करने के लिए एक "मानसिक मॉडल" के विचार के लिए। हालांकि लेखक यह बताता है कि "दिन के अंत में, यह याद रखना महत्वपूर्ण है कि कार्यान्वयन विवरण किसी भी समय बदल सकता है।"
बड़ा सवाल है। आपके उदाहरण में, क्वाड कोर प्रोसेसर पर भी समानांतर का स्तर बहुत कम है, लेकिन कुछ प्रतीक्षा के साथ समानांतरकरण का स्तर काफी अधिक हो सकता है।
// Max concurrency: 5
[Test]
public void Memory_Operations()
{
ConcurrentBag<int> monitor = new ConcurrentBag<int>();
ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
var arrayStrings = new string[1000];
Parallel.ForEach<string>(arrayStrings, someString =>
{
monitor.Add(monitor.Count);
monitor.TryTake(out int result);
monitorOut.Add(result);
});
Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}
अब देखें कि क्या होता है जब एक HTTP अनुरोध को अनुकरण करने के लिए एक प्रतीक्षा ऑपरेशन जोड़ा जाता है।
// Max concurrency: 34
[Test]
public void Waiting_Operations()
{
ConcurrentBag<int> monitor = new ConcurrentBag<int>();
ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
var arrayStrings = new string[1000];
Parallel.ForEach<string>(arrayStrings, someString =>
{
monitor.Add(monitor.Count);
System.Threading.Thread.Sleep(1000);
monitor.TryTake(out int result);
monitorOut.Add(result);
});
Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}
मैंने अभी तक कोई बदलाव नहीं किया है और समवर्ती / समानांतरकरण के स्तर में नाटकीय रूप से उछाल आया है। संगामिति के साथ इसकी सीमा बढ़ सकती है ParallelOptions.MaxDegreeOfParallelism
।
// Max concurrency: 43
[Test]
public void Test()
{
ConcurrentBag<int> monitor = new ConcurrentBag<int>();
ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
var arrayStrings = new string[1000];
var options = new ParallelOptions {MaxDegreeOfParallelism = int.MaxValue};
Parallel.ForEach<string>(arrayStrings, options, someString =>
{
monitor.Add(monitor.Count);
System.Threading.Thread.Sleep(1000);
monitor.TryTake(out int result);
monitorOut.Add(result);
});
Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}
// Max concurrency: 391
[Test]
public void Test()
{
ConcurrentBag<int> monitor = new ConcurrentBag<int>();
ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
var arrayStrings = new string[1000];
var options = new ParallelOptions {MaxDegreeOfParallelism = int.MaxValue};
Parallel.ForEach<string>(arrayStrings, options, someString =>
{
monitor.Add(monitor.Count);
System.Threading.Thread.Sleep(100000);
monitor.TryTake(out int result);
monitorOut.Add(result);
});
Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}
मैं सेटिंग को फिर से शुरू करता हूं ParallelOptions.MaxDegreeOfParallelism
। यह आवश्यक रूप से उपयोग में धागे की संख्या में वृद्धि नहीं करेगा, लेकिन यह सुनिश्चित करेगा कि आप केवल एक थ्रेड की संख्या शुरू करें, जो आपकी चिंता का विषय है।
अंत में अपने प्रश्न का उत्तर देने के लिए, नहीं, आपको एक बार में शुरू करने के लिए सभी सूत्र नहीं मिलेंगे। यदि आप समानांतर दौड़ में पूरी तरह से दौड़ना चाहते हैं, तो Parallel.Invoke का उपयोग करें।
// 636462943623363344
// 636462943623363344
// 636462943623363344
// 636462943623363344
// 636462943623363344
// 636462943623368346
// 636462943623368346
// 636462943623373351
// 636462943623393364
// 636462943623393364
[Test]
public void Test()
{
ConcurrentBag<string> monitor = new ConcurrentBag<string>();
ConcurrentBag<string> monitorOut = new ConcurrentBag<string>();
var arrayStrings = new string[1000];
var options = new ParallelOptions {MaxDegreeOfParallelism = int.MaxValue};
Parallel.ForEach<string>(arrayStrings, options, someString =>
{
monitor.Add(DateTime.UtcNow.Ticks.ToString());
monitor.TryTake(out string result);
monitorOut.Add(result);
});
var startTimes = monitorOut.OrderBy(x => x.ToString()).ToList();
Console.WriteLine(string.Join(Environment.NewLine, startTimes.Take(10)));
}