多线程并没有改善性能,但使其更慢

问题描述:

我有一个多线程应用程序,比较两个List o1和o2中的CompareRow,并获得相似度,然后在列表中存储o1.CompareRow,o2.CompareRow和Similarity ,因为getSimilarity过程非常耗时,而且数据通常超过1000,所以使用多线程应该帮助,但事实上,它不是,请 帮助指出的是,几件事情我已经考虑的是多线程并没有改善性能,但使其更慢

1. Database shouldnot be a problem, cause i already load the data into 
two List<> 
2. There is no shared writable data to complete 
3. the order of the records is not a problem 

请求帮助,这是紧急的,截止日期是接近的....

public class OriginalRecord 
{ 
    public int PrimaryKey; 
    public string CompareRow; 
} 
=============================================== 
public class Record 
{ 
    // public ManualResetEvent _doneEvent; 
    public string r1 { get; set; } 
    public string r2 { get; set; } 
    public float similarity { get; set; } 
    public CountdownEvent CountDown; 
    public Record(string r1, string r2, ref CountdownEvent _countdown) 
    { 
     this.r1 = r1; 
     this.r2 = r2; 
     //similarity = GetSimilarity(r1, r2); 
     CountDown = _countdown; 
    } 

    public void ThreadPoolCallback(Object threadContext) 
    { 
     int threadIndex = (int)threadContext; 
     similarity = GetSimilarity(r1, r2); 
     CountDown.Signal(); 
    } 


    private float GetSimilarity(object obj1, object obj2) 
    { 
     //Very time-consuming 
     ComparisionLibrary.MatchsMaker match 
    = new ComparisionLibrary.MatchsMaker (obj1.ToString(), obj2.ToString()); 
     return match.Score; 
    } 
} 



    ================================================================ 
public partial class FormMain : Form 
{ 
public FormMain() 
    { 
     InitializeComponent(); 

     List<OriginalRecord> oList1=... //get loaded from database 
     List<OriginalRecord> oList2 =... //get loaded from database 


     int recordNum = oList1.Count * oList2.Count; 
     CountdownEvent _countdown = new CountdownEvent(recordNum); 

     Record[] rArray = new Record[recordNum]; 
     int num = 0; 
     for (int i = 0; i <oList1.Count; i++) 
     { 
      for (int j = 0; j < oList2.Count; j++) 
      { 
      //Create a record instance 
      Record r 
      =new Record(oList1[i].CompareRow,oList2[j].CompareRow,ref _countdown); 
       rArray[num]=r; 
      //here use threadpool 
      ThreadPool.QueueUserWorkItem(r.ThreadPoolCallback, num); 

      num++; 
      } 
     } 
     _countdown.Wait(); 

     List<Record> rList = rArray.ToList(); 
     PopulateGridView(rList); 
    } 

这里是我在调试模式下拍摄的照片 引起我注意的两件事是 1.只有4个线程创建工作,但我设置线程池中的minthreads是10 2.正如你所看到的,甚至4个线程创建的,但只有一个线程在任何时间工作, 更糟糕的是,有时没有线程是由方式工作 ,该ComparisionLibrary是我下载做繁重的工作

我不能交库照片,你会请给我一封电子邮件或者我可以把照片发给你,谢谢。

+0

我认为这是建议使用PLINQ http://msdn.microsoft.com/en-us/library/dd997425.aspx而不是线程池。你可以轻松地做到这一点。 – 2012-03-21 07:43:39

+0

我试过了,但并不是真的平行。ForEach(oList1,(o1,state,i)=> {Parallel.ForEach(oList2,(o2,state1,i1)=> {记录r =新记录(o1.CompareRow,o2.CompareRow); rList.Add(r );});}); rList是concurrentBag – 2012-03-21 07:48:53

+0

我也推荐使用plinq(parallel for)。另外你应该注意的是,如果你的处理器没有足够的物理内核(超线程并不总是像广告所说的那样工作),那么在多线程中运行一个程序实际上会减慢一切。 – linkerro 2012-03-21 07:56:42

嗨,我的假设:

1)如果您的计算机有1个CPU比你不会获得任何性能改进。事实上,由于Context Switch,你会失去表现。

2)尝试设置ThreadPool类的最大线程值。

ThreadPool.SetMaxThreads(x); 

3)尝试使用PLINQ。

+0

我的CPU是四核的,我把线程设置为100,并且我可以看到超过100个线程在运行,并且CPU使用率接近80%到90%,但仍然使用比单线程更多的时间,所以很伤心~~~ – 2012-03-21 07:59:33

+0

其实,我想过之前的上下文切换,但没有证明这是问题,此外,上下文切换似乎可以避免,没有我可以做... – 2012-03-21 08:02:56

这样的猜测,尝试使用TPL,而不是简单的线程池,如:

int nums = new int[1]; 
nums[0] = num; 
    Task t = null; 
    t = new Task(() => 
    { 
     r.ThreadPoolCallback(nums[0]); 
    }); 
    t.Start(); 

编辑 你试图比较:
通过这样的事情更换

ThreadPool.QueueUserWorkItem(r.ThreadPoolCallback, num); 

两个list1,list2,每个项目都在独立的线程池中,这就是list1.Count*list2.Count线程池的调用,这个我觉得很喜欢平顺化(这可能会导致许多上下文切换)。

尝试将所有比较任务分成几个组(例如4-8),并在单独的线程中启动每个比较任务。也许这可能有帮助。但是,这只是一个假设。

+0

对不起,只是试过,没有运气,没有任何区别,但谢谢反正 – 2012-03-21 08:14:18

+0

我在想,如果上下文切换是问题,如果我使用控制台而不是窗口形式,会有帮助吗? – 2012-03-21 08:21:25

+0

它不会帮助,我认为 – 2012-03-21 09:11:27

如果您想将大任务分解为几个小任务,请注意,只有小任务在运行时间方面不会太短,并行化才有效。如果您将2秒的运行时作业减少到100.000 0.02毫秒的作业,那么将作业分配给工作人员的开销会非常大,以至于平行过程的运行速度会非常慢,那么通常会这样做。只有并行化开销远小于其中一个小任务的平均运行时间时,您才会看到性能提升。尽量减少大块的问题。

+0

另请参阅http://stackoverflow.com/questions/9808495/multicore-with-plyr-mc的一些信息,虽然在不使用C# – 2012-03-21 16:49:04