Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Homework1.Tests/Homework1.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Homework1\Homework1.csproj" />
</ItemGroup>
</Project>
68 changes: 68 additions & 0 deletions Homework1.Tests/MatrixTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
namespace Homework1.Tests;

public class Tests
{
Matrix matrix1;
Matrix matrix2;
Comment on lines +5 to +6
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Matrix matrix1;
Matrix matrix2;
private Matrix matrix1;
private Matrix matrix2;

В .NET по традиции всегда явно пишут модификаторы видимости, даже если умолчания устраивают


[SetUp]
public void Setup()
{
matrix1 = new(new int[2, 3] { { 1, 2, 3 }, { 3, 5, 6 } }, 2, 3);
matrix2 = new(new int[3, 2] { { 1, 2 }, { 3, 5 }, { 3, 0 } }, 3, 2);
}

[Test]
public void ExceptionsTest()
{
Assert.Throws<ArgumentNullException>(() => new Matrix(null));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут nullability-анализ ругается, если хотите null, напишите null!. Надо, чтобы компилировалось без предупреждений.

Assert.Throws<ArgumentNullException>(() => Matrix.MultiThreadedMultiplyingMatrixes(null, matrix1));
Assert.Throws<ArgumentNullException>(() => Matrix.MultiThreadedMultiplyingMatrixes(matrix1, null));
Assert.Throws<ArgumentException>(() => Matrix.MultiThreadedMultiplyingMatrixes(matrix1, matrix1));
Assert.Throws<ArgumentNullException>(() => Matrix.SequentialMultiplyingMatrixes(null, matrix1));
Assert.Throws<ArgumentNullException>(() => Matrix.SequentialMultiplyingMatrixes(matrix1, null));
Assert.Throws<ArgumentException>(() => Matrix.SequentialMultiplyingMatrixes(matrix1, matrix1));
}

[Test]
public void EqualCalculationTest()
{
Matrix matrix3 = Matrix.SequentialMultiplyingMatrixes(matrix1, matrix2);
Matrix matrix4 = Matrix.MultiThreadedMultiplyingMatrixes(matrix1, matrix2);

Assert.Multiple(() =>
{
Assert.That(matrix4.Height, Is.EqualTo(matrix3.Height));
Assert.That(matrix4.Width, Is.EqualTo(matrix3.Width));
});

for (int i = 0; i < matrix4.Height; i++)
{
for (int j = 0; j < matrix3.Width; j++)
{
Assert.That(matrix4.MatrixOfNumbers[i, j], Is.EqualTo(matrix3.MatrixOfNumbers[i, j]));
}
}
}

[Test]
public void RightCalculationTest()
{
var matrix3 = Matrix.SequentialMultiplyingMatrixes(matrix1, matrix2);
Matrix matrix4 = new(new int[2, 2] { { 16, 12 }, { 36, 31 } }, 2, 2);

Assert.Multiple(() =>
{
Assert.That(matrix4.Height, Is.EqualTo(matrix3.Height));
Assert.That(matrix4.Width, Is.EqualTo(matrix3.Width));
});

for (int i = 0; i < matrix4.Height; i++)
{
for (int j = 0; j < matrix3.Width; j++)
{
Assert.That(matrix4.MatrixOfNumbers[i, j], Is.EqualTo(matrix3.MatrixOfNumbers[i, j]));
}
}
}
}
1 change: 1 addition & 0 deletions Homework1.Tests/Usings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using NUnit.Framework;
65 changes: 65 additions & 0 deletions Homework1/ComparisonMatrixCountingSpeeds.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
namespace Homework1;

using System.Diagnostics;

public static class ComparisonMatrixCountingSpeeds
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Надо комментарии ко всем типам и всем public-членам

{
public static (double, double)[] Experiments(int sizeOfData, int amountOfTestsInSample) //size of data, mathematical expectation, dispersion
{
List<long> timeByThreads = new();
List<long> timeSequential = new();
for (int testNumber = 0; testNumber < amountOfTestsInSample; testNumber++)
{
int[,] numbersInMatrix1 = CreateSquareArrayWithRandomValues(sizeOfData);
int[,] numbersInMatrix2 = CreateSquareArrayWithRandomValues(sizeOfData);
Matrix matrix1 = new(numbersInMatrix1, sizeOfData, sizeOfData);
Matrix matrix2 = new(numbersInMatrix2, sizeOfData, sizeOfData);
timeByThreads.Add(TimeOfMultiThreadedMultiplying(matrix1, matrix2));
timeSequential.Add(TimeOfSequentialMultiplying(matrix1, matrix2));
}
double? mathematicalExpectationByThreads = timeByThreads.Average();
double? mathematicalExpectationSequential = timeSequential.Average();
double dispersionByThreads = DispersionCalculator(timeByThreads, mathematicalExpectationByThreads.Value);
double dispersionSequential = DispersionCalculator(timeSequential, mathematicalExpectationSequential.Value);
return new (double, double)[] { (mathematicalExpectationByThreads.Value, dispersionByThreads), (mathematicalExpectationSequential.Value, dispersionSequential) };
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вместо массива кортежей, где всегда должно быть два элемента, сделали бы специальный struct. Явные именованные поля лучше соглашений

}

private static double DispersionCalculator(List<long> time, double mathematicalExpectation)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Методы должны называться глаголами в повелительной форме

{
var sumOfSquareDifference = Enumerable.Range(0, time.Count).Sum(i => (time[i] - mathematicalExpectation) * (time[i] - mathematicalExpectation));
return sumOfSquareDifference / time.Count;
}

private static int[,] CreateSquareArrayWithRandomValues(int size)
{
var random = new Random();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Random в принципе должен быть на систему один (во-первых потому, что больше одного не нужно, во-вторых, потому что он инициализируется временем, так что если два объекта Random создать одновременно, они просто одинаковые значения будут выдавать, в-третьих, сборщику мусора их ещё удалять). Так что сделайте его статическим полем.

var array = new int[size, size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
array[i, j] = random.Next();
}
}
return array;
}

private static long TimeOfMultiThreadedMultiplying(Matrix matrix1, Matrix matrix2)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
Matrix.MultiThreadedMultiplyingMatrixes(matrix1, matrix2);
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}

private static long TimeOfSequentialMultiplying(Matrix matrix1, Matrix matrix2)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
Matrix.SequentialMultiplyingMatrixes(matrix1, matrix2);
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
}

10 changes: 10 additions & 0 deletions Homework1/Homework1.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
31 changes: 31 additions & 0 deletions Homework1/Homework1.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 25.0.1706.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Homework1", "Homework1.csproj", "{14F8B15D-5607-477A-A472-19A069798644}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Homework1.Tests", "..\Homework1.Tests\Homework1.Tests.csproj", "{79329A91-4C97-4EBF-A9CA-034DF6F6322E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{14F8B15D-5607-477A-A472-19A069798644}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14F8B15D-5607-477A-A472-19A069798644}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14F8B15D-5607-477A-A472-19A069798644}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14F8B15D-5607-477A-A472-19A069798644}.Release|Any CPU.Build.0 = Release|Any CPU
{79329A91-4C97-4EBF-A9CA-034DF6F6322E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{79329A91-4C97-4EBF-A9CA-034DF6F6322E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{79329A91-4C97-4EBF-A9CA-034DF6F6322E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{79329A91-4C97-4EBF-A9CA-034DF6F6322E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {00E31478-F7C2-44B2-A7A6-52E93083F34F}
EndGlobalSection
EndGlobal
180 changes: 180 additions & 0 deletions Homework1/Matrix.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
namespace Homework1;

/// <summary>
/// The matrix class implements methods:
/// matrix representation as a row, matrix multiplication by threads and sequential.
/// </summary>
public class Matrix
{
public int[,] MatrixOfNumbers { get; private set; }
public int Height { get; private set; } = 0;
public int Width { get; private set; } = 0;

/// <summary>
/// Creates new instance of Matrix class by file content.
/// </summary>
public Matrix(string filePath)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

лучше передавать в конструктор сразу ширину, высоту и данные. Так положено по правилам инкапсуляции. Вдруг пользователь захочет вводить из консоли?

{
if (filePath == null)
{
throw new ArgumentNullException(nameof(filePath));
}
string[] matrixInLines = File.ReadAllLines(filePath);
Height = matrixInLines.Length;
if (Height < 1)
{
throw new ArgumentException("There is no numbers in file");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new ArgumentException("There is no numbers in file");
throw new ArgumentException("There are no numbers in file");

}
string[] parsedFirstLine = matrixInLines[0].Split(" ", StringSplitOptions.RemoveEmptyEntries);
Width = parsedFirstLine.Length;
if (Width < 1)
{
throw new ArgumentException("There is no numbers in file");
}
MatrixOfNumbers = new int[Height, Width];
for (int i = 0; i < Height; i++)
{
string line = matrixInLines[i];
string[] stringOfNumbers = line.Split(" ", StringSplitOptions.RemoveEmptyEntries);
if (stringOfNumbers.Length != Width)
{
throw new ArgumentException("Amount of numbers in line isn't equal");
}
if (i == 0)
{
Width = stringOfNumbers.Length;
}
for (int j = 0; j < Width; j++)
{
if (int.TryParse(stringOfNumbers[j], out int currentValue))
{
MatrixOfNumbers[i, j] = currentValue;
}
else
{
throw new ArgumentException("Not inly numbers in file");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new ArgumentException("Not inly numbers in file");
throw new ArgumentException("Not only numbers in file");

}
}
}
}

/// <summary>
/// Creates new instance of Matrix class.
/// </summary>
/// <param name="matrix"> matrix in array</param>
/// <param name="height">matrix height</param>
/// <param name="width">matrix width</param>
public Matrix(int[,] matrix, int height, int width)
{
MatrixOfNumbers = matrix;
Height = height;
Width = width;
}

/// <summary>
/// return matrix in string
/// </summary>
public string PrintedMatrix()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public string PrintedMatrix()
public string ToString()

{
string matrixInString = "";
for (int i = 0; i < Height; i++)
{
for (int j = 0; j < Width; j++)
{
matrixInString += Convert.ToString(MatrixOfNumbers[i, j]) + ' ';
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Никогда не конкатенируйте строки в цикле, это же постоянное копирование строк и аллокации. Используйте StringBuilder

}
matrixInString += '\n';
}
return matrixInString;
}

/// <summary>
/// Multiplies matrixes sequential.
/// </summary>
public static Matrix SequentialMultiplyingMatrixes(Matrix matrix1, Matrix matrix2)
{
if (matrix1 == null)
{
throw new ArgumentNullException(nameof(matrix1));
}
Comment on lines +96 to +99
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (matrix1 == null)
{
throw new ArgumentNullException(nameof(matrix1));
}
ArgumentNullException.ThrowIfNull(matrix1);


if (matrix2 == null)
{
throw new ArgumentNullException(nameof(matrix2));
}

if (matrix1.Width != matrix2.Height)
{
throw new ArgumentException("Matrix sizes are inconsistent");
}
var matrix3Numbers = new int[matrix1.Height, matrix2.Width];
for (int i = 0; i < matrix1.Height; i++)
{
for (int j = 0; j < matrix2.Width; j++)
{
matrix3Numbers[i, j] = 0;
for (int k = 0; k < matrix1.Width; k++)
{
matrix3Numbers[i, j] += matrix1.MatrixOfNumbers[i, k] * matrix2.MatrixOfNumbers[k, j];
}
}
}

return new Matrix(matrix3Numbers, matrix1.Height, matrix2.Width);
}

/// <summary>
/// Multiplies matrixes by threads.
/// </summary>
public static Matrix MultiThreadedMultiplyingMatrixes(Matrix matrix1, Matrix matrix2)
{
if (matrix1 == null)
{
throw new ArgumentNullException(nameof(matrix1));
}

if (matrix2 == null)
{
throw new ArgumentNullException(nameof(matrix2));
}

if (matrix1.Width != matrix2.Height)
{
throw new ArgumentException("Matrix sizes are inconsistent");
}
var matrix3Numbers = new int[matrix1.Height, matrix2.Width];

int amountOfThreads = Environment.ProcessorCount;
var matrixMyltiplyingThreads = new Thread[amountOfThreads];
Comment on lines +147 to +148
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Так может получиться больше потоков, чем нужно. В матрице может быть меньше Environment.ProcessorCount строк


for (int i = 0; i < matrixMyltiplyingThreads.Length; i++)
{
int threadFirstLine = i;
uint amountOfElementsInMatrix = (uint)matrix1.Height * (uint)matrix2.Width;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uint -- тоже слишком низкоуровнево. Не стоит заморачиваться такими вещами, пиши var amountOfElementsInMatrix = ... и всё

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Всё так, хотя и некритично. Лишние аннотации типов в целом не мешают

matrixMyltiplyingThreads[i] = new Thread(() =>
{
int currentLine = threadFirstLine;
while (currentLine < matrix1.Height)
{
for (int currentColumn = 0; currentColumn < matrix2.Width; ++currentColumn)
{
matrix3Numbers[currentLine, currentColumn] = Enumerable.Range(0, matrix1.Width).Sum(multiplyingIndex => matrix1.MatrixOfNumbers[currentLine, multiplyingIndex] * matrix2.MatrixOfNumbers[multiplyingIndex, currentColumn]);
}
currentLine += amountOfThreads;
}
});
}

foreach (var thread in matrixMyltiplyingThreads)
{
thread.Start();
}
foreach (var thread in matrixMyltiplyingThreads)
{
thread.Join();
}
return new Matrix(matrix3Numbers, matrix1.Height, matrix2.Width);
}
}


Loading