带线程矩阵乘法 [英] Matrix Multiplication with threads

查看:96
本文介绍了带线程矩阵乘法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要乘法矩阵.当我使用Parallel.For时,单线程比多线程慢.但是当我使用两个线程时,单线程比两个线程快. 我想用两个线程相乘矩阵.我的错误是什么?我不明白谢谢您的回答.

I want to multiplication matrix.When I use Parallel.For,single thread is slower than multi thread.But when I use two threads, single thread is faster than two threads. I want to multiplication matrix with use two threads. What is my error ? I don't understand. Thank you for your answers..

 class carp
 {
     double[,] a = new double[300, 300];
     double[,] b = new double[300, 300];
     double[,] c = new double[300, 300];
     int indis = 0;

     public carp(double[,] a, double[,] b, double[,] c,int i)
     {
         this.a = a;
         this.b = b;
         this.c = c;
         indis = i;
     }
     public void matrixloop()
     {
         Thread t1;
         Thread t2;
         ThreadStart starter;
         ThreadStart starter2;
         int s = a.GetLength(0);
         for (int i = 0; i < s; i++)
         {
             for (int j = 0; j < s; j++)
             {

                starter = () => carpı(i,s,j);
                 starter2 = () => carpı(i, s, j+1);

               t1=new Thread(starter);
                 t2 = new Thread(starter);                        
                 t1.Start();
                 t2.Start();
                 t1.Join();
                 t2.Join();
                 j = j + 1;                     

             }
         }            
     }

     private void carpı(int i, int s, int j)
     {
         //multiplication operation
         double v = 0;

         for (int k = 0; k < s; k++)
         {
             v += a[i, k] * b[k, j];
         }

         c[i, j] = v + 1;            
     }        
 }

推荐答案

这使用两个BackgroundWorker对象完成您想要的

This does what you want using two BackgroundWorker objects

public class MatrixCalc
{
    readonly double[,] a, b, c;
    readonly int a_rows, a_cols, b_rows, b_cols, c_rows, c_cols;
    bool result_ok;
    int thread_count;
    BackgroundWorker bw1, bw2;
    AutoResetEvent re;

    public MatrixCalc(double[,] a, double[,] b, double[,] c)
    {
        a_rows=a.GetLength(0);
        a_cols=a.GetLength(1);
        b_rows=b.GetLength(0);
        b_cols=b.GetLength(1);
        c_rows=c.GetLength(0);
        c_cols=c.GetLength(1);
        // keep references of arrays
        this.a=a;
        this.b=b;
        this.c=c;
    }

    public void Multiply()
    {
        result_ok=false;
        this.bw1=new BackgroundWorker();
        this.bw2=new BackgroundWorker();
        this.re=new AutoResetEvent(false);
        bw1.WorkerSupportsCancellation=true;
        bw1.DoWork+=new DoWorkEventHandler(bw_DoWork);            
        bw1.RunWorkerCompleted+=new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        bw1.RunWorkerAsync(0);
        bw2.WorkerSupportsCancellation=true;
        bw2.DoWork+=new DoWorkEventHandler(bw_DoWork);
        bw2.RunWorkerCompleted+=new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        bw2.RunWorkerAsync(1);
        re.WaitOne();
        re.WaitOne();
    }
    public bool OK { get { return result_ok; } }
    public void Cancel()
    {
        bw1.CancelAsync();
        bw2.CancelAsync();
        re.WaitOne();
        re.WaitOne();
    }

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        thread_count--;
        this.result_ok=(!e.Cancelled)&&(thread_count==0);
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        thread_count++;
        if(!e.Cancel)
        {
            var offset=(int)e.Argument;
            for(int i=0; i<a_rows; ++i)
            {
                // This is the trick. Start from column 0 or 1
                // and skip over one column.
                //
                // Thread 1 Columns : 0,2,4,6,...
                // Thread 2 Columns:  1,3,5,7,...
                //
                for(int j=offset; j<b_cols; ++j, ++j)
                {
                    var sum =InnerLoop(i, j);
                    lock(c)
                    {
                        c[i, j]=sum;
                    }
                    // Debug.WriteLine("C[{0},{1}]={2}", i, j, sum);
                }
            }
        }
        re.Set();
    }

    public double InnerLoop(int a_row, int b_col)
    {
        double sum=0;
        for(int i=0; i<a_cols; i++)
        {
            sum+=a[a_row, i]*b[i, b_col];
        }
        return sum;
    }
}

class Program
{
    static void Main(string[] args)
    {
        const int N=5;
        double[,] a = new double[N,N], b=new double[N,N], c=new double[N,N];
        MatrixCalc calc=new MatrixCalc(a, b, c);
        // Fill in some values into arrays
        for(int i=0; i<N; i++)
        {
            a[i, i]=1;
            b[i, i]=1;
            if(i>0)
            {
                b[i, 0]=-i;
                a[0, i]=i;
            }
        }

        calc.Multiply();

        // Debug.WriteLine("Result: {0}", calc.OK);
    }
}

这篇关于带线程矩阵乘法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆