2013-03-06 3 views
8

मैं सी # समानांतर का उपयोग कर रहा हूं। डेटा के हजार से अधिक सबसेट को संसाधित करने के लिए। सेट के आकार के आधार पर, एक सेट को प्रक्रिया में 5-30 मिनट लगते हैं। मेरे कंप्यूटर मेंसी # समांतर फोरैच समान रूप से परिष्कृत कार्य

ParallelOptions po = new ParallelOptions(); 
po.MaxDegreeOfParallelism = Environment.ProcessorCount 

मुझे 8 समांतर प्रक्रियाएं मिलेंगी। जैसा कि मैंने समझा, प्रक्रियाओं को समांतर कार्यों के बीच समान रूप से विभाजित किया गया है (उदाहरण के लिए पहला कार्य नौकरियां संख्या 1,9,17 आदि प्राप्त होता है, दूसरा 2,10,18 आदि प्राप्त होता है); इसलिए, एक कार्य दूसरों की तुलना में जल्द ही अपनी नौकरी खत्म कर सकता है। क्योंकि डेटा के उन सेटों ने दूसरों की तुलना में कम समय लिया।

समस्या यह है कि चार समांतर कार्य 24 घंटे के भीतर अपनी नौकरी खत्म करते हैं, लेकिन अंतिम 48 घंटों में खत्म होता है। क्या समांतरता को व्यवस्थित करने का कोई मौका है ताकि सभी समांतर कार्य समान रूप से खत्म हो रहे हों? इसका मतलब है कि सभी समांतर कार्य तब तक काम करना जारी रखते हैं जब तक कि सभी नौकरियां नहीं की जातीं?

+0

सबसे लंबा कार्य कब तक करता है? – dasblinkenlight

+0

सबसे लंबा एकल लूप 30 मिनट तक है और सबसे लंबे समय तक समानांतर कार्य के लिए कुल प्रोसेसिंग 48 घंटे लगती है। – Allan

उत्तर

4

चूंकि नौकरियां बराबर नहीं हैं, इसलिए आप प्रोसेसर के बीच नौकरियों की संख्या को विभाजित नहीं कर सकते हैं और उन्हें एक ही समय में समाप्त कर सकते हैं। मुझे लगता है कि आपको यहां क्या चाहिए 8 कार्यकर्ता थ्रेड जो अगली नौकरी को लाइन में पुनः प्राप्त करते हैं। अगली नौकरी पाने के लिए आपको फ़ंक्शन पर लॉक का उपयोग करना होगा।

किसी ने मुझे ठीक कर लें मैं गलत हूँ, लेकिन मेरे सिर के ऊपर से ... एक कार्यकर्ता धागा इस तरह एक समारोह में दिया जा सकता है: होगा अगले नौकरी पाने के लिए

public void ProcessJob() 
{ 
    for (Job myJob = GetNextJob(); myJob != null; myJob = GetNextJob()) 
    { 
     // process job 
    } 
} 

और समारोह इस तरह दिखें:

private List<Job> jobs; 
private int currentJob = 0; 

private Job GetNextJob() 
{ 
    lock (jobs) 
    { 
     Job job = null; 
     if (currentJob < jobs.Count) 
     { 
      job = jobs[currentJob]; 
      currentJob++; 
     } 
     return job; 
    } 
} 
+1

+1 मुझे यकीन नहीं है कि कोड सही है, लेकिन मजदूरों को मुक्त करने के रूप में कतार से नौकरियां लेने का विचार निश्चित रूप से सही है। – dasblinkenlight

1

ऐसा लगता है कि कोई उपयोग करने के लिए उपयोग समाधान नहीं है और इसे बनाना होगा।

मेरे पिछले कोड था:

var ListOfSets = (from x in Database 
      group x by x.SetID into z 
      select new { ID = z.Key}).ToList(); 

ParallelOptions po = new ParallelOptions(); 
po.MaxDegreeOfParallelism = Environment.ProcessorCount; 

Parallel.ForEach(ListOfSets, po, SingleSet=> 
{ 
    AnalyzeSet(SingleSet.ID); 
}); 

सभी सीपीयू रों ​​बीच समान रूप से काम साझा करने के लिए, मैं अभी भी Parallel का उपयोग काम करने के लिए, लेकिन ForEach के बजाय मैं For और मैट से एक विचार का उपयोग करें। नया कोड है:

Parallel.For(0, Environment.ProcessorCount, i=> 
{ 
    while(ListOfSets.Count() > 0) 
    { 
     double SetID = 0; 
     lock (ListOfSets) 
     { 
      SetID = ListOfSets[0].ID; 
      ListOfSets.RemoveAt(0); 
     } 
    AnalyzeSet(SetID); 
    } 
}); 

तो, आपकी सलाह के लिए धन्यवाद।

+0

अपना समाधान साझा करने के लिए धन्यवाद। मैं बहुत बहु थ्रेडेड प्रोग्रामिंग नहीं करता हूं, लेकिन अगली बार जब मैं करता हूं तो मैं निश्चित रूप से समांतर की जांच करूँगा। के लिए। –

+0

समाधान के लिए धन्यवाद। नोट: आपके द्वारा बनाए गए समय के बीच। गणना() और जब आप कोई अन्य थ्रेड लॉक करते हैं तो बहु थ्रेडिंग के कारण अंतिम सूची आइटम ले सकता है। यदि आपकी सूची में अभी भी कुछ है और यदि बाहर नहीं है तो आपको अपने लॉक पर दोबारा जांच करनी चाहिए। – BlouBlou

1

एक विकल्प, जैसा कि दूसरों द्वारा सुझाया गया है, अपने निर्माता उपभोक्ता कतार का प्रबंधन करना है। मुझे यह ध्यान रखना है कि BlockingCollection का उपयोग करके यह बहुत आसान बनाता है।

BlockingCollection<JobData> queue = new BlockingCollection<JobData>(); 

//add data to queue; if it can be done quickly, just do it inline. 
//If it's expensive, start a new task/thread just to add items to the queue. 
foreach (JobData job in data) 
    queue.Add(job); 

queue.CompleteAdding(); 

for (int i = 0; i < Environment.ProcessorCount; i++) 
{ 
    Task.Factory.StartNew(() => 
    { 
     foreach (var job in queue.GetConsumingEnumerable()) 
     { 
      ProcessJob(job); 
     } 
    }, TaskCreationOptions.LongRunning); 
} 
संबंधित मुद्दे