C# WPF并行计算两个矩阵

    技术2026-02-20  13

    并行计算两个矩阵

    要求: 编写一个WPF应用程序,利用数据并行计算两个矩阵(M×N和N×P)的乘积,得到一个M×P的矩阵。 (1)在代码中用多任务通过调用某方法实现矩阵并行运算,在调用的参数中分别传递M、N、P的大小。 (2)程序中至少要测试3次有代表性的不同大小的矩阵运算,并显示其并行运行用时。

    1.初始化矩阵,用100以内的随机数填充

    private double[,] Init(int row, int col) { double[,] data = new double[row, col]; Random r = new Random(); for(int i = 0; i < row; i++) { for(int j = 0; j < col; j++) { data[i, j] = r.Next(100); } } return data; }

    2.串行算法

    private void Compute(double[,] a, double[,] b, double[,] result) { int aRows = a.GetLength(0); int aCols = a.GetLength(1); int bCols = b.GetLength(1); for(int i = 0;i < aRows; i++) { for (int j = 0; j < bCols; j++) { double temp = 0; for (int k = 0; k < aCols; k++) { temp += a[i, k] * b[k, j]; } result[i, j] = temp; } } }

    3.并行算法,仅将最外层换为Parallel.For

    private void ParallelCompute(double[,] a, double[,] b, double[,] result) { int aRows = a.GetLength(0); int aCols = a.GetLength(1); int bCols = b.GetLength(1); Action<int> action = (i) => { for (int j = 0; j < bCols; j++) { double temp = 0; for (int k = 0; k < aCols; k++) { temp += a[i, k] * b[k, j]; } result[i, j] = temp; } }; Parallel.For(0, aRows, action); }

    4.定义时钟,并为防止运行时界面卡顿使用异步编程

    Stopwatch stopwatch = new Stopwatch(); public MainWindow() { InitializeComponent(); } private async void button_Click(object sender, RoutedEventArgs e) { textblock.Text = ""; long[] t1 = await Task.Run(() => Multiply(325,18,66)); textblock.Text = string.Format("测试1(矩阵1:325×18,矩阵2:18×66),非并行用时:{0}毫秒,并行用时:{1}毫秒", t1[0], t1[1]); long[] t2 = await Task.Run(() => Multiply(3250, 180, 660)); textblock.Text += string.Format("\n测试2(矩阵2:3250×180,矩阵2:180×660),非并行用时:{0}毫秒,并行用时:{1}毫秒", t2[0], t2[1]); long[] t3 = await Task.Run(() => Multiply(32500, 200, 900)); textblock.Text += string.Format("\n测试3(矩阵3:32500×200,矩阵2:200×900),非并行用时:{0}毫秒,并行用时:{1}毫秒", t3[0], t3[1]); }

    5.初始化矩阵后计算,同时计时,结束后返回时钟数组

    private long[] Multiply(int m, int n, int p) { long[] timeElapsed = new long[2]; double[,] m1 = Init(m, n); double[,] m2 = Init(n, p); double[,] result = new double[m, p]; //串行 stopwatch.Restart(); result = new double[m, p]; Compute(m1, m2, result); stopwatch.Stop(); timeElapsed[0] = stopwatch.ElapsedMilliseconds; //并行 stopwatch.Restart(); result = new double[m, p]; ParallelCompute(m1, m2, result); stopwatch.Stop(); timeElapsed[1] = stopwatch.ElapsedMilliseconds; return timeElapsed; }

    结果: 问题讨论: 1.结果只出现一行,没有用+=。输出未换行,字符串添加\n。 2.初始化时,System.IndexOutOfRangeException:“索引超出了数组界限。”原因:i,j出现写反的错误。 3.仅将最外层的for改为Parallel.For更优。 4.出现数过大,等待时间过久的问题

    Processed: 0.038, SQL: 9