191 lines
6.0 KiB
Markdown
191 lines
6.0 KiB
Markdown
|
# Отчёт по лабораторной работе №5
|
|||
|
|
|||
|
Выполнила: студентка гр. ИСЭбд-41 Халитова А.М.
|
|||
|
|
|||
|
## Создание приложения
|
|||
|
|
|||
|
В приложении были созданы следующие методы:
|
|||
|
|
|||
|
- Заполнение матрицы рандомными значениями:
|
|||
|
```
|
|||
|
private static int[][] GenerateRandomMatrix(int rows, int cols)
|
|||
|
{
|
|||
|
int[][] matrix = new int[rows][];
|
|||
|
|
|||
|
Random rand = new Random();
|
|||
|
|
|||
|
for (int i = 0; i < rows; i++)
|
|||
|
{
|
|||
|
matrix[i] = new int[cols];
|
|||
|
for (int j = 0; j < cols; j++)
|
|||
|
{
|
|||
|
matrix[i][j] = rand.Next(1, 10);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return matrix;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
- Перемножение матриц обычным алгоритмом:
|
|||
|
```
|
|||
|
public static int[][] MultiplySequential(int[][] matrixA, int[][] matrixB)
|
|||
|
{
|
|||
|
int rowsA = matrixA.Length;
|
|||
|
int colsA = matrixA[0].Length;
|
|||
|
int colsB = matrixB[0].Length;
|
|||
|
|
|||
|
int[][] result = new int[rowsA][];
|
|||
|
|
|||
|
for (int i = 0; i < rowsA; i++)
|
|||
|
{
|
|||
|
result[i] = new int[colsB];
|
|||
|
|
|||
|
for (int j = 0; j < colsB; j++)
|
|||
|
{
|
|||
|
for (int k = 0; k < colsA; k++)
|
|||
|
{
|
|||
|
result[i][j] += matrixA[i][k] * matrixB[k][j];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
- Перемножение матриц параллельным алгоритмом:
|
|||
|
```
|
|||
|
public static int[][] MultiplyParallel(int[][] matrixA, int[][] matrixB, int numThreads)
|
|||
|
{
|
|||
|
int rowsA = matrixA.Length;
|
|||
|
int colsA = matrixA[0].Length;
|
|||
|
int colsB = matrixB[0].Length;
|
|||
|
|
|||
|
int[][] result = new int[rowsA][];
|
|||
|
|
|||
|
Parallel.For(0, rowsA, new ParallelOptions { MaxDegreeOfParallelism = numThreads }, i =>
|
|||
|
{
|
|||
|
result[i] = new int[colsB];
|
|||
|
|
|||
|
for (int j = 0; j < colsB; j++)
|
|||
|
{
|
|||
|
for (int k = 0; k < colsA; k++)
|
|||
|
{
|
|||
|
result[i][j] += matrixA[i][k] * matrixB[k][j];
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
- Создание матриц различных размеров и с различным количеством потоков для параллельного алгоритма:
|
|||
|
```
|
|||
|
[Benchmark]
|
|||
|
public void MultiplySequential_100x100()
|
|||
|
{
|
|||
|
int[][] matrixA = GenerateRandomMatrix(100, 100);
|
|||
|
int[][] matrixB = GenerateRandomMatrix(100, 100);
|
|||
|
MultiplySequential(matrixA, matrixB);
|
|||
|
}
|
|||
|
|
|||
|
[Benchmark]
|
|||
|
public void MultiplyParallel_100x100_4TH()
|
|||
|
{
|
|||
|
int[][] matrixA = GenerateRandomMatrix(100, 100);
|
|||
|
int[][] matrixB = GenerateRandomMatrix(100, 100);
|
|||
|
MultiplyParallel(matrixA, matrixB, 4);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void MultiplyParallel_100x100_8TH()
|
|||
|
{
|
|||
|
int[][] matrixA = GenerateRandomMatrix(100, 100);
|
|||
|
int[][] matrixB = GenerateRandomMatrix(100, 100);
|
|||
|
MultiplyParallel(matrixA, matrixB, 8);
|
|||
|
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void MultiplyParallel_100x100_16TH()
|
|||
|
{
|
|||
|
int[][] matrixA = GenerateRandomMatrix(100, 100);
|
|||
|
int[][] matrixB = GenerateRandomMatrix(100, 100);
|
|||
|
MultiplyParallel(matrixA, matrixB, 16);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
[Benchmark]
|
|||
|
public void MultiplySequential_300x300()
|
|||
|
{
|
|||
|
int[][] matrixA = GenerateRandomMatrix(300, 300);
|
|||
|
int[][] matrixB = GenerateRandomMatrix(300, 300);
|
|||
|
MultiplySequential(matrixA, matrixB);
|
|||
|
}
|
|||
|
|
|||
|
[Benchmark]
|
|||
|
public void MultiplyParallel_300x300_4TH()
|
|||
|
{
|
|||
|
int[][] matrixA = GenerateRandomMatrix(300, 300);
|
|||
|
int[][] matrixB = GenerateRandomMatrix(300, 300);
|
|||
|
MultiplyParallel(matrixA, matrixB, 4);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void MultiplyParallel_300x300_8TH()
|
|||
|
{
|
|||
|
int[][] matrixA = GenerateRandomMatrix(300, 300);
|
|||
|
int[][] matrixB = GenerateRandomMatrix(300, 300);
|
|||
|
MultiplyParallel(matrixA, matrixB, 8);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void MultiplyParallel_300x300_16TH()
|
|||
|
{
|
|||
|
int[][] matrixA = GenerateRandomMatrix(300, 300);
|
|||
|
int[][] matrixB = GenerateRandomMatrix(300, 300);
|
|||
|
MultiplyParallel(matrixA, matrixB, 16);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void MultiplySequential_500x500()
|
|||
|
{
|
|||
|
int[][] matrixA = GenerateRandomMatrix(500, 500);
|
|||
|
int[][] matrixB = GenerateRandomMatrix(500, 500);
|
|||
|
MultiplySequential(matrixA, matrixB);
|
|||
|
}
|
|||
|
|
|||
|
[Benchmark]
|
|||
|
public void MultiplyParallel_500x500_4TH()
|
|||
|
{
|
|||
|
int[][] matrixA = GenerateRandomMatrix(500, 500);
|
|||
|
int[][] matrixB = GenerateRandomMatrix(500, 500);
|
|||
|
MultiplyParallel(matrixA, matrixB, 4);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void MultiplyParallel_500x500_8TH()
|
|||
|
{
|
|||
|
int[][] matrixA = GenerateRandomMatrix(500, 500);
|
|||
|
int[][] matrixB = GenerateRandomMatrix(500, 500);
|
|||
|
MultiplyParallel(matrixA, matrixB, 8);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void MultiplyParallel_500x500_16TH()
|
|||
|
{
|
|||
|
int[][] matrixA = GenerateRandomMatrix(500, 500);
|
|||
|
int[][] matrixB = GenerateRandomMatrix(500, 500);
|
|||
|
MultiplyParallel(matrixA, matrixB, 16);
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
- Запуск приложения:
|
|||
|
```
|
|||
|
static void Main(string[] args)
|
|||
|
{
|
|||
|
var summary = BenchmarkRunner.Run<MatrixMultiplication>();
|
|||
|
Console.ReadLine();
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## Результаты работы приложения
|
|||
|
|
|||
|
![](shot1.png)
|
|||
|
|
|||
|
По результатам работы: для матриц небольших размеров большое количество потоков не ускоряет (а в некоторых случаях замедляет) работу алгоритма, за счет излишнего переключения процессора. Для больших матриц увеличение количества потоков увеличивает скорость работы алгоритма. В сравнении с однопоточным алгоритмом, работа параллельного в несколько раз быстрее.
|