199 lines
6.6 KiB
Markdown
199 lines
6.6 KiB
Markdown
|
# Отчёт по лабораторной работе №6
|
|||
|
|
|||
|
Выполнила: студентка гр. ИСЭбд-41 Халитова А.М.
|
|||
|
|
|||
|
## Создание приложения
|
|||
|
|
|||
|
В приложении были созданы следующие методы:
|
|||
|
|
|||
|
- Заполнение матрицы рандомными значениями:
|
|||
|
```
|
|||
|
public static double[][] GenerateRandomMatrix(int rows, int cols)
|
|||
|
{
|
|||
|
double[][] matrix = new double[rows][];
|
|||
|
|
|||
|
Random rand = new Random();
|
|||
|
|
|||
|
for (int i = 0; i < rows; i++)
|
|||
|
{
|
|||
|
matrix[i] = new double[cols];
|
|||
|
for (int j = 0; j < cols; j++)
|
|||
|
{
|
|||
|
matrix[i][j] = rand.Next(1, 10);
|
|||
|
}
|
|||
|
}
|
|||
|
return matrix;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
- Метод создания подматрицы для удаления строки и столбца в вычислении определителя:
|
|||
|
```
|
|||
|
private static double[][] GetSubMatrix(double[][] matrix, int rowToRemove, int colToRemove)
|
|||
|
{
|
|||
|
int size = matrix.Length;
|
|||
|
double[][] subMatrix = new double[size - 1][];
|
|||
|
|
|||
|
for (int i = 0, newRow = 0; i < size; i++)
|
|||
|
{
|
|||
|
if (i != rowToRemove)
|
|||
|
{
|
|||
|
subMatrix[newRow] = new double[size - 1];
|
|||
|
for (int j = 0, newCol = 0; j < size; j++)
|
|||
|
{
|
|||
|
if (j != colToRemove)
|
|||
|
{
|
|||
|
subMatrix[newRow][newCol] = matrix[i][j];
|
|||
|
newCol++;
|
|||
|
}
|
|||
|
}
|
|||
|
newRow++;
|
|||
|
}
|
|||
|
}
|
|||
|
return subMatrix;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
- Метод вычисления детерминанта обычным алгоритмом:
|
|||
|
```
|
|||
|
public static double DeterminantSequential(double[][] matrix)
|
|||
|
{
|
|||
|
int size = matrix.Length;
|
|||
|
|
|||
|
if (size == 1)
|
|||
|
{
|
|||
|
return matrix[0][0];
|
|||
|
}
|
|||
|
|
|||
|
if (size == 2)
|
|||
|
{
|
|||
|
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
|
|||
|
}
|
|||
|
|
|||
|
double determinant = 0;
|
|||
|
|
|||
|
for (int i = 0; i < size; i++)
|
|||
|
{
|
|||
|
double sign = (i % 2 == 0) ? 1 : -1;
|
|||
|
double cofactor = sign * matrix[0][i] * DeterminantSequential(GetSubMatrix(matrix, 0, i));
|
|||
|
determinant += cofactor;
|
|||
|
}
|
|||
|
return determinant;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
- Метод вычисления детерминанта параллельным алгоритмом:
|
|||
|
```
|
|||
|
public static double DeterminantParallel(double[][] matrix, int numThreads)
|
|||
|
{
|
|||
|
int size = matrix.Length;
|
|||
|
|
|||
|
if (size == 1)
|
|||
|
{
|
|||
|
return matrix[0][0];
|
|||
|
}
|
|||
|
|
|||
|
if (size == 2)
|
|||
|
{
|
|||
|
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
|
|||
|
}
|
|||
|
|
|||
|
double determinant = 0;
|
|||
|
|
|||
|
Parallel.For(0, size, new ParallelOptions { MaxDegreeOfParallelism = numThreads }, i =>
|
|||
|
{
|
|||
|
double sign = (i % 2 == 0) ? 1 : -1;
|
|||
|
double cofactor = sign * matrix[0][i] * DeterminantSequential(GetSubMatrix(matrix, 0, i));
|
|||
|
determinant += cofactor;
|
|||
|
});
|
|||
|
return determinant;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
- Методы генерации матриц различных размеров и с различным числом потоков. Поскольку ресурсы машины не позволяют вычислить детерминанту для больших матриц (процесс занимает большое количество времени и памяти, происходит зависание), вычислять будем для матриц меньших размеров (2, 4, 8):
|
|||
|
```
|
|||
|
|
|||
|
[Benchmark]
|
|||
|
public void DeterminantSequential_2x2()
|
|||
|
{
|
|||
|
double[][] matrix = GenerateRandomMatrix(2, 2);
|
|||
|
DeterminantSequential(matrix);
|
|||
|
}
|
|||
|
|
|||
|
[Benchmark]
|
|||
|
public void DeterminantParallel_2x2_4TH()
|
|||
|
{
|
|||
|
double[][] matrix = GenerateRandomMatrix(2, 2);
|
|||
|
DeterminantParallel(matrix, 4);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void DeterminantParallel_2x2_8TH()
|
|||
|
{
|
|||
|
double[][] matrix = GenerateRandomMatrix(2, 2);
|
|||
|
DeterminantParallel(matrix, 8);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void DeterminantParallel_2x2_16TH()
|
|||
|
{
|
|||
|
double[][] matrix = GenerateRandomMatrix(2, 2);
|
|||
|
DeterminantParallel(matrix, 16);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void DeterminantSequential_4x4()
|
|||
|
{
|
|||
|
double[][] matrix = GenerateRandomMatrix(4, 4);
|
|||
|
DeterminantSequential(matrix);
|
|||
|
}
|
|||
|
|
|||
|
[Benchmark]
|
|||
|
public void DeterminantParallel_4x4_4TH()
|
|||
|
{
|
|||
|
double[][] matrix = GenerateRandomMatrix(4, 4);
|
|||
|
DeterminantParallel(matrix, 4);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void DeterminantParallel_4x4_8TH()
|
|||
|
{
|
|||
|
double[][] matrix = GenerateRandomMatrix(4, 4);
|
|||
|
DeterminantParallel(matrix, 8);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void DeterminantParallel_4x4_16TH()
|
|||
|
{
|
|||
|
double[][] matrix = GenerateRandomMatrix(4, 4);
|
|||
|
DeterminantParallel(matrix, 16);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void DeterminantSequential_8x8()
|
|||
|
{
|
|||
|
double[][] matrix = GenerateRandomMatrix(8, 8);
|
|||
|
DeterminantSequential(matrix);
|
|||
|
}
|
|||
|
|
|||
|
[Benchmark]
|
|||
|
public void DeterminantParallel_8x8_4TH()
|
|||
|
{
|
|||
|
double[][] matrix = GenerateRandomMatrix(8, 8);
|
|||
|
DeterminantParallel(matrix, 4);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void DeterminantParallel_8x8_8TH()
|
|||
|
{
|
|||
|
double[][] matrix = GenerateRandomMatrix(8, 8);
|
|||
|
DeterminantParallel(matrix, 8);
|
|||
|
}
|
|||
|
[Benchmark]
|
|||
|
public void DeterminantParallel_8x8_16TH()
|
|||
|
{
|
|||
|
double[][] matrix = GenerateRandomMatrix(8, 8);
|
|||
|
DeterminantParallel(matrix, 16);
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Запуск приложения происходит с помощью строки `var summary = BenchmarkRunner.Run<MatrixDeterminant>();`.
|
|||
|
|
|||
|
|
|||
|
## Результаты работы приложения
|
|||
|
|
|||
|
![](shot.PNG)
|
|||
|
|
|||
|
Вывод: по результатам работы, для малых матриц парралельный алгоритм не дает прироста в скорости работы. Для матрицы 8 на 8 дает прирост только распараллеливание на малое число потоков. Для вычисления детерминанта больших матриц (больше, чем 8 на 8) не хватает вычислительной мощности моего процессора, но можно предположить что в этом случае увеличение числа потоков приводило бы к увеличению скорости работы.
|