[英]Multithreading matrix multiplication in C#
我有一個任務-寫多線程矩陣乘法。 每個向量乘積必須在新線程中計算(如果矩陣n乘m,m乘k,則必須n乘k線程)。 我還必須顯示結果矩陣元素的計算順序。 我寫了代碼,結果很奇怪-計算順序幾乎是順序的。 但是我要計算新線程中的每個元素,因此必須對結果矩陣的元素進行隨機的計算。 怎么了? 這是我的代碼。
using System;
using System.Threading;
using System.Collections.Generic;
namespace MatrixMultiplication
{
class Matrix
{
public int Row{get; set;}
public int Column { get; set;}
double[,] arr;
Matrix() { }
public Matrix(int row,int column)
{
Row = row;
Column = column;
arr = new double[row, column];
}
public double[] GetColumn(int i)
{
double[] res=new double[Row];
for (int j = 0; j < Row; j++)
res[j] = arr[j, i];
return res;
}
public double[] GetRow(int i)
{
double[] res = new double[Column];
for (int j = 0; j < Column; j++)
res[j] = arr[i, j];
return res;
}
public double this[int i,int j]
{
get { return arr[i, j]; }
set { arr[i, j] = value; }
}
public Matrix RandomValues()
{
Random rnd=new Random();
for (int i = 0; i < Row; i++)
for (int j = 0; j < Column; j++)
arr[i, j] =rnd.Next(10);
return this;
}
public void Print()
{
for(int i=0;i<Row;i++){
for (int j = 0; j < Column; j++)
Console.Write(arr[i,j]+" ");
Console.WriteLine();
}
}
public static Matrix operator*(Matrix a, Matrix b)
{
Matrix result=new Matrix(a.Row,b.Column);
List<Thread> threads = new List<Thread>();
for (int i = 0; i <a.Row*b.Column;i++ )
{
int tempi = i;
Thread thread = new Thread(()=>VectorMult(tempi, a, b, result));
thread.Start();
threads.Add(thread);
}
foreach (Thread t in threads)
t.Join();
return result;
}
public static void VectorMult(int tmp, Matrix a, Matrix b,Matrix result){
int i = tmp / b.Column;
int j = tmp % b.Column;
double[] x = a.GetRow(i);
double[] y = b.GetColumn(j);
for (int k = 0; k < x.Length; k++)
result[i, j] += x[k] * y[k];
Console.WriteLine("Calculate element{0}{1}", i, j);
}
}
class Program
{
static void Main(string[] args)
{
int n = int.Parse(Console.ReadLine());
int m = int.Parse(Console.ReadLine());
int k = int.Parse(Console.ReadLine());
Matrix A = new Matrix(n,m).RandomValues();
Matrix B = new Matrix(m,k).RandomValues();
A.Print();
Console.WriteLine(new String('-',20));
B.Print();
Console.WriteLine(new String('-', 20));
Matrix C = A * B;
C.Print();
}
}
}
您所描述的是正常的-請參閱今天早些時候的這篇帖子 , 該帖子演示了獨立線程中的進程如何不總是按預期的順序運行。 他們可能會在大部分時間或大部分時間內這樣做,但是隨后您會得到一些意外的行為。
計算是否需要按照特定的順序進行,還是只需要能夠看到計算的順序?
如果要啟動新線程,則無法控制順序。 (您已經看到了。)您也無法捕獲它們的完成順序,因為完成計算並記錄結果(控制台或任何其他輸出)不是原子操作。
這可能發生:
當操作必須按特定順序進行時,多線程並不是很好。
您可以在完成計算后將計算結果插入ConcurrentQueue
中,並且順序基本上是正確的。
首先,您應該使代碼盡可能簡單明了。 而不是計算i < a.Row * b.Column
您應該使s 為 2:
for (int i = 0; i < a.Row; i++)
for (int j = 0; j < b.Column; j++)
{
int tempi = i;
int tempj = j;
Thread thread = new Thread(() => VectorMult(tempi, tempj, a, b, result));
thread.Start();
threads.Add(thread);
}
然后,在VectorMult(int tmpi, int tmpj, Matrix a, Matrix b, Matrix result)
函數中,代替計算j = tempi % b.Column
東西,而將其作為參數tempj 。 有了i和j,它變成:
int i = tmpi;
int j = tmpj;
double[] x = a.GetRow(i);
double[] y = b.GetColumn(j);
for (int k = 0; k < x.Length; k++)
result[i, j] += x[k] * y[k];
最后,不要忘記,在使用共享資源和線程時,事情可能會變得很瘋狂。 確保使用互斥對象。
這是我的全部代碼,
using System;
using System.Threading;
using System.Collections.Generic;
namespace MatrixMultiplication
{
class Matrix
{
public int Row { get; set; }
public int Column { get; set; }
double[,] arr;
public static Mutex mutex = new Mutex();
Matrix() { }
public Matrix(int row, int column)
{
Row = row;
Column = column;
arr = new double[row, column];
}
public double[] GetColumn(int i)
{
double[] res = new double[Row];
for (int j = 0; j < Row; j++)
res[j] = arr[j, i];
return res;
}
public double[] GetRow(int i)
{
double[] res = new double[Column];
for (int j = 0; j < Column; j++)
res[j] = arr[i, j];
return res;
}
public double this[int i, int j]
{
get { return arr[i, j]; }
set { arr[i, j] = value; }
}
public Matrix RandomValues()
{
Random rnd = new Random();
for (int i = 0; i < Row; i++)
for (int j = 0; j < Column; j++)
arr[i, j] = rnd.Next(10);
return this;
}
public void Print()
{
for (int i = 0; i < Row; i++)
{
for (int j = 0; j < Column; j++)
Console.Write(arr[i, j] + " ");
Console.WriteLine();
}
}
public static Matrix operator *(Matrix a, Matrix b)
{
Matrix result = new Matrix(a.Row, b.Column);
List<Thread> threads = new List<Thread>();
for (int i = 0; i < a.Row; i++)
for (int j = 0; j < b.Column; j++)
{
int tempi = i;
int tempj = j;
Thread thread = new Thread(() => VectorMult(tempi, tempj, a, b, result));
thread.Start();
threads.Add(thread);
}
foreach (Thread t in threads)
t.Join();
return result;
}
public static void VectorMult(int tmpi, int tmpj, Matrix a, Matrix b, Matrix result)
{
mutex.WaitOne();
int i = tmpi;
int j = tmpj;
double[] x = a.GetRow(i);
double[] y = b.GetColumn(j);
for (int k = 0; k < x.Length; k++)
result[i, j] += x[k] * y[k];
mutex.ReleaseMutex();
}
}
class Program
{
static void Main(string[] args)
{
Console.Write("n=");
int n = int.Parse(Console.ReadLine());
Console.Write("m=");
int m = int.Parse(Console.ReadLine());
Console.Write("k=");
int k = int.Parse(Console.ReadLine());
Matrix A = new Matrix(n, m).RandomValues();
Matrix B = new Matrix(m, k).RandomValues();
A.Print();
Console.WriteLine(new String('-', 20));
B.Print();
Console.WriteLine(new String('-', 20));
Matrix C = A * B;
C.Print();
Console.ReadLine();
}
}
}
祝你一切順利! :)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.