多线程不会提高性能,但会使速度更慢

时间:2012-03-21 07:37:13

标签: c# multithreading

我有一个多线程应用程序,在两个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是我下载的图书馆来做繁重的工作

我无法发布照片,请你给我发电子邮件或者我可以把照片发给你,谢谢。

3 个答案:

答案 0 :(得分:1)

如果要将大型任务拆分为几个小任务,请注意并行化仅在小任务在运行时方面不太短时才有效。如果将2秒的运行时作业切换为100.000 0.02 ms作业,则将作业分配给工作人员的开销可能非常大,以至于进程运行速度比通常情况下要慢得多。只有当并行化的开销远小于其中一个小任务的平均运行时间时,您才会看到性能提升。尝试用更大的块来解决你的问题。

答案 1 :(得分:0)

嗨,我的假设:

1)如果您的计算机有1个CPU,那么您将无法获得任何性能提升。实际上,由于Context Switch,你将失去表现。

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

ThreadPool.SetMaxThreads(x);

3)尝试使用PLINQ。

答案 2 :(得分:0)

作为猜测,尝试使用TPL而不是普通的ThreadPool,例如: 替换

ThreadPool.QueueUserWorkItem(r.ThreadPoolCallback, num);

通过这样的事情:

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

修改 你试图比较两个list1,list2,来自池的单独线程中的每个项目,这是list1.Count*list2.Count线程池调用,它寻找我喜欢很多的paralelization(这可能会导致许多上下文切换)。

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