From 9daa23152f2912fbb981c0f31a5c22ee4c0097e6 Mon Sep 17 00:00:00 2001 From: Khusainov Ilas Date: Thu, 11 Sep 2025 10:40:47 +0300 Subject: [PATCH 01/11] add matrix utils --- .gitignore | 4 + HW1/HW1.sln | 22 +++ .../MatrixMultiplication.csproj | 21 +++ HW1/MatrixMultiplication/matrixUtils.cs | 162 ++++++++++++++++++ .../matrixmultiplication.cs | 37 ++++ HW1/MatrixMultiplication/stylecop.json | 9 + .../matrixmultiplication.Test.csproj | 36 ++++ .../matrixmultiplicationTest.cs | 64 +++++++ HW1/matrixmultiplication.Test/stylecop.json | 9 + 9 files changed, 364 insertions(+) create mode 100644 HW1/HW1.sln create mode 100644 HW1/MatrixMultiplication/MatrixMultiplication.csproj create mode 100644 HW1/MatrixMultiplication/matrixUtils.cs create mode 100644 HW1/MatrixMultiplication/matrixmultiplication.cs create mode 100644 HW1/MatrixMultiplication/stylecop.json create mode 100644 HW1/matrixmultiplication.Test/matrixmultiplication.Test.csproj create mode 100644 HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs create mode 100644 HW1/matrixmultiplication.Test/stylecop.json diff --git a/.gitignore b/.gitignore index ce89292..5596d38 100644 --- a/.gitignore +++ b/.gitignore @@ -416,3 +416,7 @@ FodyWeavers.xsd *.msix *.msm *.msp + +# Rider +.idea +.git diff --git a/HW1/HW1.sln b/HW1/HW1.sln new file mode 100644 index 0000000..3ad542c --- /dev/null +++ b/HW1/HW1.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MatrixMultiplication", "MatrixMultiplication\MatrixMultiplication.csproj", "{3C1ACBE6-BD12-4934-A58E-10141C3D6419}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "matrixmultiplication.Test", "matrixmultiplication.Test\matrixmultiplication.Test.csproj", "{93242727-EAF9-411B-AFFD-8FFFF083BE84}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3C1ACBE6-BD12-4934-A58E-10141C3D6419}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3C1ACBE6-BD12-4934-A58E-10141C3D6419}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C1ACBE6-BD12-4934-A58E-10141C3D6419}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3C1ACBE6-BD12-4934-A58E-10141C3D6419}.Release|Any CPU.Build.0 = Release|Any CPU + {93242727-EAF9-411B-AFFD-8FFFF083BE84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93242727-EAF9-411B-AFFD-8FFFF083BE84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93242727-EAF9-411B-AFFD-8FFFF083BE84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93242727-EAF9-411B-AFFD-8FFFF083BE84}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/HW1/MatrixMultiplication/MatrixMultiplication.csproj b/HW1/MatrixMultiplication/MatrixMultiplication.csproj new file mode 100644 index 0000000..52bba11 --- /dev/null +++ b/HW1/MatrixMultiplication/MatrixMultiplication.csproj @@ -0,0 +1,21 @@ + + + + Library + net8.0 + enable + enable + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/HW1/MatrixMultiplication/matrixUtils.cs b/HW1/MatrixMultiplication/matrixUtils.cs new file mode 100644 index 0000000..6adeaa3 --- /dev/null +++ b/HW1/MatrixMultiplication/matrixUtils.cs @@ -0,0 +1,162 @@ +namespace MatrixMultiplication; + +/// +/// Helper static class for working with matrices. +/// Contains functions for generating, checking, and other matrix operations. +/// +public static class MatrixUtils +{ + + /// + /// Printing the matrix to the console. + /// + public static void MatrixOutput(int[,] matrix) + { + var rows = matrix.GetLength(0); + var columns = matrix.GetLength(1); + + for (var i = 0; i < rows; i++) + { + for (var j = 0; j < columns; j++) + { + Console.Write(matrix[i, j].ToString().PadLeft(5)); + } + Console.WriteLine(); + } + } + + /// + /// Generates a random integer matrix of the specified size. + /// + public static int[,] GeneratorRandomMatrix(int rows, int columns, int minValue = -10, int maxValue = 10) + { + var matrix = new int[rows, columns]; + var randomNum = new Random(); + + for (var i = 0; i < rows; i++) + { + for (var j = 0; j < columns; j++) + { + matrix[i, j] = randomNum.Next(minValue, maxValue); + } + } + + return matrix; + } + + /// + /// Multiplies two matrices and returns the result. + /// + /// First matrix. + /// Second matrix. + /// Resulting matrix after multiplication. + public static int[,] MatrixMultiply(int[,] matrix1, int[,] matrix2) + { + var lengthRowMatrix1 = matrix1.GetLength(0); + var lengthColumnMatrix1 = matrix1.GetLength(1); + var lengthRowMatrix2 = matrix2.GetLength(0); + var lengthColumnMatrix2 = matrix2.GetLength(1); + + if (lengthColumnMatrix1 != lengthRowMatrix2) + { + throw new ArgumentException("The number of columns of the first matrix is not equal to the number of rows of the second one!"); + } + + var result = new int[lengthRowMatrix1, lengthColumnMatrix2]; + + for (var i = 0; i < lengthRowMatrix1; i++) + { + for (var j = 0; j < lengthColumnMatrix2; j++) + { + var sum = 0; + for (var k = 0; k < lengthColumnMatrix1; k++) + { + sum += matrix1[i, k] * matrix2[k, j]; + } + result[i, j] = sum; + } + } + return result; + } + + /// + /// Multiplies two matrices in parallel. + /// Each cell of the result matrix is computed in a separate thread. + /// + /// First matrix. + /// Second matrix. + /// Resulting matrix of multiplication. + /// Thrown when dimensions are not compatible for multiplication. + public static int[,] MultiplyMatrixParallel(int[,] matrix1, int[,] matrix2) + { + var lengthRowMatrix1 = matrix1.GetLength(0); + var lengthColumnMatrix1 = matrix1.GetLength(1); + var lengthRowMatrix2 = matrix2.GetLength(0); + var lengthColumnMatrix2 = matrix2.GetLength(1); + + if (lengthColumnMatrix1 != lengthRowMatrix2) + { + throw new ArgumentException("The number of columns of the first matrix is not equal to the number of rows of the second one!"); + } + + var result = new int[lengthRowMatrix1, lengthColumnMatrix2]; + var threads = new Thread[lengthRowMatrix1]; + + for (var i = 0; i < lengthRowMatrix1; i++) + { + var row = i; + threads[row] = new Thread(() => + { + for (var j = 0; j < lengthColumnMatrix2; j++) + { + var sum = 0; + for (var k = 0; k < lengthColumnMatrix1; k++) + { + sum += matrix1[row, k] * matrix2[k, j]; + } + result[row, j] = sum; + } + }); + threads[row].Start(); + } + + for (var i = 0; i < lengthRowMatrix1; i++) + { + threads[i].Join(); + } + + return result; + } + /// + /// Compares two matrices for equality. + /// + /// First matrix. + /// Second matrix. + /// + /// true — if the matrices are the same size and all their elements match. + /// false — if the dimensions are different or at least one element is different. + /// + public static bool MatrixEquals(int[,] matrix1, int[,] matrix2) + { + if (matrix1.GetLength(0) != matrix2.GetLength(0) || + matrix1.GetLength(1) != matrix2.GetLength(1)) + { + return false; + } + + int rows = matrix1.GetLength(0); + int cols = matrix1.GetLength(1); + + for (int i = 0; i < rows; i++) + { + for (int j = 0; j < cols; j++) + { + if (matrix1[i, j] != matrix2[i, j]) + { + return false; + } + } + } + return true; + } +} \ No newline at end of file diff --git a/HW1/MatrixMultiplication/matrixmultiplication.cs b/HW1/MatrixMultiplication/matrixmultiplication.cs new file mode 100644 index 0000000..42f4ff4 --- /dev/null +++ b/HW1/MatrixMultiplication/matrixmultiplication.cs @@ -0,0 +1,37 @@ +// +// Copyright (c) khusainovilas. All rights reserved. +// + +namespace MatrixMultiplication +{ + /// + /// Realization of matrix multiplication of parallel processing. + /// + public static class Matrix + { + public static void RunExample() + { + var matrix1 = new int[,] + { + { 1, 2 }, + { 3, 4 }, + }; + var matrix2 = new int[,] + { + { 2, 0 }, + { 1, 2 }, + }; + + Console.WriteLine("Матрица 1:"); + MatrixUtils.MatrixOutput(matrix1); + + Console.WriteLine("\nМатрица 2:"); + MatrixUtils.MatrixOutput(matrix2); + + var result = MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2); + + Console.WriteLine("\nРезультат умножения:"); + MatrixUtils.MatrixOutput(result); + } + } +} \ No newline at end of file diff --git a/HW1/MatrixMultiplication/stylecop.json b/HW1/MatrixMultiplication/stylecop.json new file mode 100644 index 0000000..76c8e76 --- /dev/null +++ b/HW1/MatrixMultiplication/stylecop.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "khusainovilas", + "copyrightText": "Copyright (c) {companyName}. All rights reserved." + } + } +} \ No newline at end of file diff --git a/HW1/matrixmultiplication.Test/matrixmultiplication.Test.csproj b/HW1/matrixmultiplication.Test/matrixmultiplication.Test.csproj new file mode 100644 index 0000000..6e9eb81 --- /dev/null +++ b/HW1/matrixmultiplication.Test/matrixmultiplication.Test.csproj @@ -0,0 +1,36 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + diff --git a/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs b/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs new file mode 100644 index 0000000..7d1a9d9 --- /dev/null +++ b/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs @@ -0,0 +1,64 @@ +// +// Copyright (c) khusainovilas. All rights reserved. +// + +namespace matrixmultiplication.Test; + +using MatrixMultiplication; + +/// +/// NUnit tests for matrix multiplication functions. +/// Tests both sequential and parallel implementations for correctness. +/// +public class MatrixmultiplicationTest +{ + private int[,] matrix1; + private int[,] matrix2; + private int[,] matrixExpected; + + /// + /// Initializes matrices before each test. + /// + [SetUp] + public void Setup() + { + this.matrix1 = new int[,] + { + { 1, 2 }, + { 3, 4 }, + }; + this.matrix2 = new int[,] + { + { 2, 0 }, + { 1, 2 }, + }; + this.matrixExpected = new int[,] + { + { 4, 4 }, + { 10, 8 }, + }; + } + + /// + /// Tests the sequential matrix multiplication function. + /// Checks that the result matches the expected output. + /// + [Test] + public void MatrixMultiply_ReturnsCorrectResult() + { + var result = MatrixUtils.MatrixMultiply(matrix1, matrix2); + Assert.That(MatrixUtils.MatrixEquals(result, matrixExpected), Is.True); + } + + /// + /// Tests the parallel matrix multiplication function. + /// Ensures that parallel computation produces the correct result. + /// + [Test] + public void ParallelMatrixMultiply_ReturnsCorrectResult() + { + var result = MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2); + Assert.That(MatrixUtils.MatrixEquals(result, matrixExpected), Is.True); + } +} + diff --git a/HW1/matrixmultiplication.Test/stylecop.json b/HW1/matrixmultiplication.Test/stylecop.json new file mode 100644 index 0000000..76c8e76 --- /dev/null +++ b/HW1/matrixmultiplication.Test/stylecop.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "khusainovilas", + "copyrightText": "Copyright (c) {companyName}. All rights reserved." + } + } +} \ No newline at end of file From a6b6b7552eabb65704acf0932100dc31eb4fc5c3 Mon Sep 17 00:00:00 2001 From: Khusainov Ilas Date: Thu, 11 Sep 2025 10:52:19 +0300 Subject: [PATCH 02/11] fix warnings --- HW1/MatrixMultiplication/matrixUtils.cs | 35 +++++++++++-------- .../matrixmultiplicationTest.cs | 2 +- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/HW1/MatrixMultiplication/matrixUtils.cs b/HW1/MatrixMultiplication/matrixUtils.cs index 6adeaa3..588cc54 100644 --- a/HW1/MatrixMultiplication/matrixUtils.cs +++ b/HW1/MatrixMultiplication/matrixUtils.cs @@ -6,10 +6,10 @@ /// public static class MatrixUtils { - /// /// Printing the matrix to the console. /// + /// input matrix. public static void MatrixOutput(int[,] matrix) { var rows = matrix.GetLength(0); @@ -24,10 +24,15 @@ public static void MatrixOutput(int[,] matrix) Console.WriteLine(); } } - + /// - /// Generates a random integer matrix of the specified size. + /// Generates a random integer matrix of the specified size with values in the given range. /// + /// Number of rows in the matrix. + /// Number of columns in the matrix. + /// Minimum value for matrix elements (inclusive). + /// Maximum value for matrix elements (exclusive). + /// A 2D integer array filled with random values. public static int[,] GeneratorRandomMatrix(int rows, int columns, int minValue = -10, int maxValue = 10) { var matrix = new int[rows, columns]; @@ -43,7 +48,7 @@ public static void MatrixOutput(int[,] matrix) return matrix; } - + /// /// Multiplies two matrices and returns the result. /// @@ -61,7 +66,7 @@ public static void MatrixOutput(int[,] matrix) { throw new ArgumentException("The number of columns of the first matrix is not equal to the number of rows of the second one!"); } - + var result = new int[lengthRowMatrix1, lengthColumnMatrix2]; for (var i = 0; i < lengthRowMatrix1; i++) @@ -76,6 +81,7 @@ public static void MatrixOutput(int[,] matrix) result[i, j] = sum; } } + return result; } @@ -98,10 +104,10 @@ public static void MatrixOutput(int[,] matrix) { throw new ArgumentException("The number of columns of the first matrix is not equal to the number of rows of the second one!"); } - + var result = new int[lengthRowMatrix1, lengthColumnMatrix2]; var threads = new Thread[lengthRowMatrix1]; - + for (var i = 0; i < lengthRowMatrix1; i++) { var row = i; @@ -119,14 +125,15 @@ public static void MatrixOutput(int[,] matrix) }); threads[row].Start(); } - + for (var i = 0; i < lengthRowMatrix1; i++) { threads[i].Join(); } - + return result; } + /// /// Compares two matrices for equality. /// @@ -144,12 +151,12 @@ public static bool MatrixEquals(int[,] matrix1, int[,] matrix2) return false; } - int rows = matrix1.GetLength(0); - int cols = matrix1.GetLength(1); - - for (int i = 0; i < rows; i++) + var rows = matrix1.GetLength(0); + var cols = matrix1.GetLength(1); + + for (var i = 0; i < rows; i++) { - for (int j = 0; j < cols; j++) + for (var j = 0; j < cols; j++) { if (matrix1[i, j] != matrix2[i, j]) { diff --git a/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs b/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs index 7d1a9d9..e88f0bd 100644 --- a/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs +++ b/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs @@ -19,7 +19,7 @@ public class MatrixmultiplicationTest /// /// Initializes matrices before each test. /// - [SetUp] + [SetUp] public void Setup() { this.matrix1 = new int[,] From 2f06fd9de9ad046fefd9b5da113b169f09b5cfc3 Mon Sep 17 00:00:00 2001 From: khusainovilas Date: Thu, 11 Sep 2025 11:00:40 +0300 Subject: [PATCH 03/11] test --- HW1/MatrixMultiplication/matrixmultiplication.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HW1/MatrixMultiplication/matrixmultiplication.cs b/HW1/MatrixMultiplication/matrixmultiplication.cs index 42f4ff4..0ac8898 100644 --- a/HW1/MatrixMultiplication/matrixmultiplication.cs +++ b/HW1/MatrixMultiplication/matrixmultiplication.cs @@ -31,7 +31,7 @@ public static void RunExample() var result = MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2); Console.WriteLine("\nРезультат умножения:"); - MatrixUtils.MatrixOutput(result); + MatrixUtils.MatrixOutput(result); } } } \ No newline at end of file From 4b880faca4f902f648d0247ea7315734d3041225 Mon Sep 17 00:00:00 2001 From: khusainovilas Date: Thu, 11 Sep 2025 20:43:20 +0300 Subject: [PATCH 04/11] add --- HW1/MatrixMultiplication/Program.cs | 28 +++++++ HW1/MatrixMultiplication/matrixBench.cs | 16 ++++ HW1/MatrixMultiplication/matrixUtils.cs | 82 +++++++++++++++++-- .../matrixmultiplication.cs | 37 --------- .../matrixmultiplicationTest.cs | 15 ++-- 5 files changed, 127 insertions(+), 51 deletions(-) create mode 100644 HW1/MatrixMultiplication/Program.cs create mode 100644 HW1/MatrixMultiplication/matrixBench.cs delete mode 100644 HW1/MatrixMultiplication/matrixmultiplication.cs diff --git a/HW1/MatrixMultiplication/Program.cs b/HW1/MatrixMultiplication/Program.cs new file mode 100644 index 0000000..cf06921 --- /dev/null +++ b/HW1/MatrixMultiplication/Program.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) khusainovilas. All rights reserved. +// + +using MatrixMultiplication; + +// Write dotnet run -- +// Input files must contain matrices as strings of numbers separated by spaces. +// Each line of the file is a row of the matrix. +// The program checks the correctness of the matrix sizes and creates a new file with the product. +// Example: +// dotnet run -- "TestMatrix/TestFile1.txt" "TestMatrix/TestFile2.txt" "TestMatrix/result.txt" +// +if (args.Length != 3 || string.IsNullOrEmpty(args[0]) || string.IsNullOrEmpty(args[1]) || string.IsNullOrEmpty(args[2])) +{ + Console.WriteLine("Error when passing arguments"); + return; +} + +var matrixPath1 = args[0]; +var matrixPath2 = args[1]; +var resultFile = args[2]; + +var matrix1 = MatrixUtils.ReadMatrixFromFile(matrixPath1); +var matrix2 = MatrixUtils.ReadMatrixFromFile(matrixPath2); +var matrixResult = MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2); + +MatrixUtils.WriteMatrixToFile(resultFile, matrixResult); \ No newline at end of file diff --git a/HW1/MatrixMultiplication/matrixBench.cs b/HW1/MatrixMultiplication/matrixBench.cs new file mode 100644 index 0000000..66d22d8 --- /dev/null +++ b/HW1/MatrixMultiplication/matrixBench.cs @@ -0,0 +1,16 @@ +// +// Copyright (c) khusainovilas. All rights reserved. +// + +namespace MatrixMultiplication; + +using MatrixMultiplication; + +/// +/// Compare the operating speed with the sequential version depending on the matrix sizes. +/// +public class matrixBench +{ + int[] sizeOfMatrix = [100, 500, 1000]; + int repeat = 5; +} \ No newline at end of file diff --git a/HW1/MatrixMultiplication/matrixUtils.cs b/HW1/MatrixMultiplication/matrixUtils.cs index 588cc54..4e0843a 100644 --- a/HW1/MatrixMultiplication/matrixUtils.cs +++ b/HW1/MatrixMultiplication/matrixUtils.cs @@ -1,4 +1,8 @@ -namespace MatrixMultiplication; +// +// Copyright (c) khusainovilas. All rights reserved. +// + +namespace MatrixMultiplication; /// /// Helper static class for working with matrices. @@ -21,6 +25,7 @@ public static void MatrixOutput(int[,] matrix) { Console.Write(matrix[i, j].ToString().PadLeft(5)); } + Console.WriteLine(); } } @@ -36,13 +41,13 @@ public static void MatrixOutput(int[,] matrix) public static int[,] GeneratorRandomMatrix(int rows, int columns, int minValue = -10, int maxValue = 10) { var matrix = new int[rows, columns]; - var randomNum = new Random(); + var randomNumbers = new Random(); for (var i = 0; i < rows; i++) { for (var j = 0; j < columns; j++) { - matrix[i, j] = randomNum.Next(minValue, maxValue); + matrix[i, j] = randomNumbers.Next(minValue, maxValue); } } @@ -78,6 +83,7 @@ public static void MatrixOutput(int[,] matrix) { sum += matrix1[i, k] * matrix2[k, j]; } + result[i, j] = sum; } } @@ -93,7 +99,7 @@ public static void MatrixOutput(int[,] matrix) /// Second matrix. /// Resulting matrix of multiplication. /// Thrown when dimensions are not compatible for multiplication. - public static int[,] MultiplyMatrixParallel(int[,] matrix1, int[,] matrix2) + public static int[,] MultiplyMatrixParallel(int[,] matrix1, int[,] matrix2) { var lengthRowMatrix1 = matrix1.GetLength(0); var lengthColumnMatrix1 = matrix1.GetLength(1); @@ -120,6 +126,7 @@ public static void MatrixOutput(int[,] matrix) { sum += matrix1[row, k] * matrix2[k, j]; } + result[row, j] = sum; } }); @@ -152,11 +159,11 @@ public static bool MatrixEquals(int[,] matrix1, int[,] matrix2) } var rows = matrix1.GetLength(0); - var cols = matrix1.GetLength(1); + var columns = matrix1.GetLength(1); for (var i = 0; i < rows; i++) { - for (var j = 0; j < cols; j++) + for (var j = 0; j < columns; j++) { if (matrix1[i, j] != matrix2[i, j]) { @@ -164,6 +171,69 @@ public static bool MatrixEquals(int[,] matrix1, int[,] matrix2) } } } + return true; } + + /// + /// Reads a matrix of integers from a text file. + /// + /// The path to the file containing the matrix. + /// matrix from file. + public static int[,] ReadMatrixFromFile(string path) + { + var lines = File.ReadAllLines(path); + if (lines.Length == 0) + { + throw new Exception("Matrix file is empty."); + } + + var rows = lines.Length; + var columns = lines[0].Split(' ').Length; + + var matrix = new int[rows, columns]; + + for (var i = 0; i < rows; i++) + { + var nums = lines[i].Split(' ').Select(int.Parse).ToArray(); + + if (nums.Length != columns) + { + throw new Exception("Invalid matrix format: the matrix is not complete"); + } + + for (var j = 0; j < columns; j++) + { + matrix[i, j] = nums[j]; + } + } + + return matrix; + } + + /// + /// Writes a matrix to a text file. + /// + /// The path to the output file. + /// Matrix for writing to file to write. + public static void WriteMatrixToFile(string path, int[,] matrix) + { + var rows = matrix.GetLength(0); + var columns = matrix.GetLength(1); + + using var writer = new StreamWriter(path); + for (var i = 0; i < rows; i++) + { + for (var j = 0; j < columns; j++) + { + writer.Write(matrix[i, j]); + if (j < columns - 1) + { + writer.Write(" "); + } + } + + writer.WriteLine(); + } + } } \ No newline at end of file diff --git a/HW1/MatrixMultiplication/matrixmultiplication.cs b/HW1/MatrixMultiplication/matrixmultiplication.cs deleted file mode 100644 index 0ac8898..0000000 --- a/HW1/MatrixMultiplication/matrixmultiplication.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) khusainovilas. All rights reserved. -// - -namespace MatrixMultiplication -{ - /// - /// Realization of matrix multiplication of parallel processing. - /// - public static class Matrix - { - public static void RunExample() - { - var matrix1 = new int[,] - { - { 1, 2 }, - { 3, 4 }, - }; - var matrix2 = new int[,] - { - { 2, 0 }, - { 1, 2 }, - }; - - Console.WriteLine("Матрица 1:"); - MatrixUtils.MatrixOutput(matrix1); - - Console.WriteLine("\nМатрица 2:"); - MatrixUtils.MatrixOutput(matrix2); - - var result = MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2); - - Console.WriteLine("\nРезультат умножения:"); - MatrixUtils.MatrixOutput(result); - } - } -} \ No newline at end of file diff --git a/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs b/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs index e88f0bd..b146b60 100644 --- a/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs +++ b/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs @@ -2,7 +2,7 @@ // Copyright (c) khusainovilas. All rights reserved. // -namespace matrixmultiplication.Test; +namespace Matrixmultiplication.Test; using MatrixMultiplication; @@ -44,10 +44,10 @@ public void Setup() /// Checks that the result matches the expected output. /// [Test] - public void MatrixMultiply_ReturnsCorrectResult() + public void MatrixUtils_MatrixMultiply_Matrix1_Matrix2() { - var result = MatrixUtils.MatrixMultiply(matrix1, matrix2); - Assert.That(MatrixUtils.MatrixEquals(result, matrixExpected), Is.True); + var result = MatrixUtils.MatrixMultiply(this.matrix1, this.matrix2); + Assert.That(MatrixUtils.MatrixEquals(result, this.matrixExpected), Is.True); } /// @@ -55,10 +55,9 @@ public void MatrixMultiply_ReturnsCorrectResult() /// Ensures that parallel computation produces the correct result. /// [Test] - public void ParallelMatrixMultiply_ReturnsCorrectResult() + public void MatrixUtils_MultiplyMatrixParallel_Matrix1_Matrix2() { - var result = MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2); - Assert.That(MatrixUtils.MatrixEquals(result, matrixExpected), Is.True); + var result = MatrixUtils.MultiplyMatrixParallel(this.matrix1, this.matrix2); + Assert.That(MatrixUtils.MatrixEquals(result, this.matrixExpected), Is.True); } } - From e719a2a4ad914ca92705ea0d8205b0cd0902e437 Mon Sep 17 00:00:00 2001 From: khusainovilas Date: Thu, 11 Sep 2025 22:53:52 +0300 Subject: [PATCH 05/11] add: benchmark statistics --- .../MatrixMultiplication.csproj | 6 +- HW1/MatrixMultiplication/Program.cs | 30 +++++--- HW1/MatrixMultiplication/matrixBench.cs | 76 ++++++++++++++++++- HW1/MatrixMultiplication/matrixUtils.cs | 2 +- HW1/MatrixMultiplication/resultBenchmark.txt | 0 5 files changed, 98 insertions(+), 16 deletions(-) create mode 100644 HW1/MatrixMultiplication/resultBenchmark.txt diff --git a/HW1/MatrixMultiplication/MatrixMultiplication.csproj b/HW1/MatrixMultiplication/MatrixMultiplication.csproj index 52bba11..09c6393 100644 --- a/HW1/MatrixMultiplication/MatrixMultiplication.csproj +++ b/HW1/MatrixMultiplication/MatrixMultiplication.csproj @@ -1,7 +1,7 @@  - Library + Exe net8.0 enable enable @@ -18,4 +18,8 @@ + + + + diff --git a/HW1/MatrixMultiplication/Program.cs b/HW1/MatrixMultiplication/Program.cs index cf06921..086e901 100644 --- a/HW1/MatrixMultiplication/Program.cs +++ b/HW1/MatrixMultiplication/Program.cs @@ -4,6 +4,7 @@ using MatrixMultiplication; +// 1. To multiply matrices from files: // Write dotnet run -- // Input files must contain matrices as strings of numbers separated by spaces. // Each line of the file is a row of the matrix. @@ -11,18 +12,27 @@ // Example: // dotnet run -- "TestMatrix/TestFile1.txt" "TestMatrix/TestFile2.txt" "TestMatrix/result.txt" // -if (args.Length != 3 || string.IsNullOrEmpty(args[0]) || string.IsNullOrEmpty(args[1]) || string.IsNullOrEmpty(args[2])) +// 2. To run the statistics benchmark: +// dotnet run -- benchmark +// +if (args.Length == 1 && args[0].Equals("benchmark", StringComparison.CurrentCultureIgnoreCase)) +{ + MatrixBench.RunBenchmark(); +} +else if (args.Length != 3 || string.IsNullOrEmpty(args[0]) || string.IsNullOrEmpty(args[1]) || + string.IsNullOrEmpty(args[2])) { Console.WriteLine("Error when passing arguments"); - return; } +else +{ + var matrixPath1 = args[0]; + var matrixPath2 = args[1]; + var resultFile = args[2]; -var matrixPath1 = args[0]; -var matrixPath2 = args[1]; -var resultFile = args[2]; - -var matrix1 = MatrixUtils.ReadMatrixFromFile(matrixPath1); -var matrix2 = MatrixUtils.ReadMatrixFromFile(matrixPath2); -var matrixResult = MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2); + var matrix1 = MatrixUtils.ReadMatrixFromFile(matrixPath1); + var matrix2 = MatrixUtils.ReadMatrixFromFile(matrixPath2); + var matrixResult = MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2); -MatrixUtils.WriteMatrixToFile(resultFile, matrixResult); \ No newline at end of file + MatrixUtils.WriteMatrixToFile(resultFile, matrixResult); +} diff --git a/HW1/MatrixMultiplication/matrixBench.cs b/HW1/MatrixMultiplication/matrixBench.cs index 66d22d8..5978c2c 100644 --- a/HW1/MatrixMultiplication/matrixBench.cs +++ b/HW1/MatrixMultiplication/matrixBench.cs @@ -4,13 +4,81 @@ namespace MatrixMultiplication; -using MatrixMultiplication; +using System; +using System.Diagnostics; +using System.Linq; /// /// Compare the operating speed with the sequential version depending on the matrix sizes. /// -public class matrixBench +public class MatrixBench { - int[] sizeOfMatrix = [100, 500, 1000]; - int repeat = 5; + /// + /// Runs the benchmark for multiple matrix sizes and saves the results to a file. + /// + public static void RunBenchmark() + { + int[] sized = [100, 200, 500]; + const string filePath = "resultBenchmark.txt"; + + File.WriteAllText(filePath, "Size\tSeq_Mean\tSeq_Sigma\tPar_Mean\tPar_Sigma\n"); + + foreach (var size in sized) + { + var sequentialResult = BenchmarkMatrixMultiplication(size, false); + var parallelResult = BenchmarkMatrixMultiplication(size, true); + + // {значение, ширина} — задаёт фиксированную ширину колонки + var line = + $"{size,4} {sequentialResult.Mean,10:F4} {sequentialResult.Sigma,10:F4} {parallelResult.Mean,10:F4} {parallelResult.Sigma,10:F4}"; + + File.AppendAllText("resultBenchmark.txt", line + Environment.NewLine); + } + } + + /// + /// Runs a matrix multiplication benchmark and computes mathematical expectation and standard deviation. + /// + /// The number of rows and columns of the square matrix. + /// If true, uses parallel matrix multiplication. + /// Number of measurement repetitions for statistics (default 100). + /// + /// Tuple (Mean, Sigma): + /// Mean — mathematical expectation; + /// Sigma — standard deviation. + private static (double Mean, double Sigma) BenchmarkMatrixMultiplication(int size, bool useParallel, int repeat = 10) + { + var elapsedTimes = new double[10]; + for (var i = 0; i < repeat; i++) + { + elapsedTimes[i] = PerformSingleRun(size, useParallel); + } + + var mean = elapsedTimes.Average(); + var sigma = Math.Sqrt(elapsedTimes.Average(t => Math.Pow(t - mean, 2))); + + return (mean, sigma); + } + + /// + /// Performs a single run of matrix multiplication with randomly generated matrix. + /// + /// The number of rows and columns of the square matrix. + /// If true, uses parallel matrix multiplication. + /// Elapsed time in milliseconds for a single multiplication. + private static long PerformSingleRun(int size, bool useParallel) + { + var matrix1 = MatrixUtils.GeneratorRandomMatrix(size, size); + var matrix2 = MatrixUtils.GeneratorRandomMatrix(size, size); + + var stopwatch = Stopwatch.StartNew(); + + _ = useParallel + ? MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2) + : MatrixUtils.MatrixMultiply(matrix1, matrix2); + + stopwatch.Stop(); + + return stopwatch.ElapsedMilliseconds; + } } \ No newline at end of file diff --git a/HW1/MatrixMultiplication/matrixUtils.cs b/HW1/MatrixMultiplication/matrixUtils.cs index 4e0843a..36497de 100644 --- a/HW1/MatrixMultiplication/matrixUtils.cs +++ b/HW1/MatrixMultiplication/matrixUtils.cs @@ -38,7 +38,7 @@ public static void MatrixOutput(int[,] matrix) /// Minimum value for matrix elements (inclusive). /// Maximum value for matrix elements (exclusive). /// A 2D integer array filled with random values. - public static int[,] GeneratorRandomMatrix(int rows, int columns, int minValue = -10, int maxValue = 10) + public static int[,] GeneratorRandomMatrix(int rows, int columns, int minValue = -100, int maxValue = 100) { var matrix = new int[rows, columns]; var randomNumbers = new Random(); diff --git a/HW1/MatrixMultiplication/resultBenchmark.txt b/HW1/MatrixMultiplication/resultBenchmark.txt new file mode 100644 index 0000000..e69de29 From 2e86e726ce9348a278a2f560e9ea5fdd7d1c3210 Mon Sep 17 00:00:00 2001 From: khusainovilas Date: Fri, 12 Sep 2025 23:42:27 +0300 Subject: [PATCH 06/11] refactor: improve code quality and error handling --- .../MatrixMultiplication.csproj | 2 + HW1/MatrixMultiplication/matrixBench.cs | 39 +++++++++------- HW1/MatrixMultiplication/matrixUtils.cs | 45 +++++++++---------- HW1/MatrixMultiplication/resultBenchmark.txt | 6 +++ 4 files changed, 52 insertions(+), 40 deletions(-) diff --git a/HW1/MatrixMultiplication/MatrixMultiplication.csproj b/HW1/MatrixMultiplication/MatrixMultiplication.csproj index 09c6393..341f08b 100644 --- a/HW1/MatrixMultiplication/MatrixMultiplication.csproj +++ b/HW1/MatrixMultiplication/MatrixMultiplication.csproj @@ -5,6 +5,8 @@ net8.0 enable enable + true + $(NoWarn);1591 diff --git a/HW1/MatrixMultiplication/matrixBench.cs b/HW1/MatrixMultiplication/matrixBench.cs index 5978c2c..774fe07 100644 --- a/HW1/MatrixMultiplication/matrixBench.cs +++ b/HW1/MatrixMultiplication/matrixBench.cs @@ -11,26 +11,25 @@ namespace MatrixMultiplication; /// /// Compare the operating speed with the sequential version depending on the matrix sizes. /// -public class MatrixBench +public static class MatrixBench { /// /// Runs the benchmark for multiple matrix sizes and saves the results to a file. /// public static void RunBenchmark() { - int[] sized = [100, 200, 500]; + int[] sizes = [100, 200, 300, 400, 500]; const string filePath = "resultBenchmark.txt"; - File.WriteAllText(filePath, "Size\tSeq_Mean\tSeq_Sigma\tPar_Mean\tPar_Sigma\n"); + File.WriteAllText(filePath, $"{"Size",4} {"Seq_Exp",10} {"Seq_Dev",10} {"Par_Exp",10} {"Par_Dev",10}\n"); - foreach (var size in sized) + foreach (var size in sizes) { var sequentialResult = BenchmarkMatrixMultiplication(size, false); var parallelResult = BenchmarkMatrixMultiplication(size, true); - // {значение, ширина} — задаёт фиксированную ширину колонки var line = - $"{size,4} {sequentialResult.Mean,10:F4} {sequentialResult.Sigma,10:F4} {parallelResult.Mean,10:F4} {parallelResult.Sigma,10:F4}"; + $"{size,4} {sequentialResult.Expectation,10:F4} {sequentialResult.Deviation,10:F4} {parallelResult.Expectation,10:F4} {parallelResult.Deviation,10:F4}"; File.AppendAllText("resultBenchmark.txt", line + Environment.NewLine); } @@ -43,21 +42,22 @@ public static void RunBenchmark() /// If true, uses parallel matrix multiplication. /// Number of measurement repetitions for statistics (default 100). /// - /// Tuple (Mean, Sigma): - /// Mean — mathematical expectation; - /// Sigma — standard deviation. - private static (double Mean, double Sigma) BenchmarkMatrixMultiplication(int size, bool useParallel, int repeat = 10) + /// Tuple (expectation, deviation):. + /// - Expectation: mathematical expectation time in milliseconds. + /// - Deviation: standard deviation time in milliseconds. + /// + private static (double Expectation, double Deviation) BenchmarkMatrixMultiplication(int size, bool useParallel, int repeat = 10) { - var elapsedTimes = new double[10]; + var elapsedTimes = new double[repeat]; for (var i = 0; i < repeat; i++) { elapsedTimes[i] = PerformSingleRun(size, useParallel); } - var mean = elapsedTimes.Average(); - var sigma = Math.Sqrt(elapsedTimes.Average(t => Math.Pow(t - mean, 2))); + var expectation = elapsedTimes.Average(); + var deviation = Math.Sqrt(elapsedTimes.Average(t => Math.Pow(t - expectation, 2))); - return (mean, sigma); + return (expectation, deviation); } /// @@ -73,9 +73,14 @@ private static long PerformSingleRun(int size, bool useParallel) var stopwatch = Stopwatch.StartNew(); - _ = useParallel - ? MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2) - : MatrixUtils.MatrixMultiply(matrix1, matrix2); + if (useParallel) + { + MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2); + } + else + { + MatrixUtils.MatrixMultiply(matrix1, matrix2); + } stopwatch.Stop(); diff --git a/HW1/MatrixMultiplication/matrixUtils.cs b/HW1/MatrixMultiplication/matrixUtils.cs index 36497de..3599ac5 100644 --- a/HW1/MatrixMultiplication/matrixUtils.cs +++ b/HW1/MatrixMultiplication/matrixUtils.cs @@ -10,26 +10,6 @@ namespace MatrixMultiplication; /// public static class MatrixUtils { - /// - /// Printing the matrix to the console. - /// - /// input matrix. - public static void MatrixOutput(int[,] matrix) - { - var rows = matrix.GetLength(0); - var columns = matrix.GetLength(1); - - for (var i = 0; i < rows; i++) - { - for (var j = 0; j < columns; j++) - { - Console.Write(matrix[i, j].ToString().PadLeft(5)); - } - - Console.WriteLine(); - } - } - /// /// Generates a random integer matrix of the specified size with values in the given range. /// @@ -67,6 +47,7 @@ public static void MatrixOutput(int[,] matrix) var lengthRowMatrix2 = matrix2.GetLength(0); var lengthColumnMatrix2 = matrix2.GetLength(1); + // Checking the compatibility of matrices for multiplication if (lengthColumnMatrix1 != lengthRowMatrix2) { throw new ArgumentException("The number of columns of the first matrix is not equal to the number of rows of the second one!"); @@ -106,9 +87,10 @@ public static void MatrixOutput(int[,] matrix) var lengthRowMatrix2 = matrix2.GetLength(0); var lengthColumnMatrix2 = matrix2.GetLength(1); + // Checking the compatibility of matrices for multiplication if (lengthColumnMatrix1 != lengthRowMatrix2) { - throw new ArgumentException("The number of columns of the first matrix is not equal to the number of rows of the second one!"); + throw new ArgumentException("The number of columns of the first matrix is not equal to the number of rows of the second one."); } var result = new int[lengthRowMatrix1, lengthColumnMatrix2]; @@ -182,21 +164,38 @@ public static bool MatrixEquals(int[,] matrix1, int[,] matrix2) /// matrix from file. public static int[,] ReadMatrixFromFile(string path) { + // Checking the existence of the file + if (!File.Exists(path)) + { + throw new FileNotFoundException("File not found."); + } + var lines = File.ReadAllLines(path); + + // Checking that the file is not empty if (lines.Length == 0) { throw new Exception("Matrix file is empty."); } var rows = lines.Length; - var columns = lines[0].Split(' ').Length; + var columns = lines[0].Split(' ', StringSplitOptions.RemoveEmptyEntries).Length; var matrix = new int[rows, columns]; for (var i = 0; i < rows; i++) { - var nums = lines[i].Split(' ').Select(int.Parse).ToArray(); + // Check that the string contains only numbers, spaces, and minus signs. + if (lines[i].Any(c => !char.IsDigit(c) && c != ' ' && c != '-')) + { + throw new Exception("Invalid character in matrix file: only digits, spaces and minus signs are allowed."); + } + + var nums = lines[i].Split(' ', StringSplitOptions.RemoveEmptyEntries) + .Select(int.Parse) + .ToArray(); + // Checking that all rows and columns in the matrix have the same length if (nums.Length != columns) { throw new Exception("Invalid matrix format: the matrix is not complete"); diff --git a/HW1/MatrixMultiplication/resultBenchmark.txt b/HW1/MatrixMultiplication/resultBenchmark.txt index e69de29..15de6a7 100644 --- a/HW1/MatrixMultiplication/resultBenchmark.txt +++ b/HW1/MatrixMultiplication/resultBenchmark.txt @@ -0,0 +1,6 @@ +Size Seq_Exp Seq_Dev Par_Exp Par_Dev + 100 5,7000 0,9000 24,9000 2,0712 + 200 49,5000 5,1039 52,9000 11,0494 + 300 158,2000 25,7674 67,6000 9,8914 + 400 385,9000 56,2538 123,1000 13,1640 + 500 811,2000 123,2119 313,0000 102,8669 From 85d303a1bcbad5aa85dba860a12b02e69142c8ea Mon Sep 17 00:00:00 2001 From: khusainovilas Date: Tue, 21 Oct 2025 20:27:26 +0300 Subject: [PATCH 07/11] Upgrade project to .NET 9 --- HW1/MatrixMultiplication/MatrixMultiplication.csproj | 2 +- HW1/matrixmultiplication.Test/matrixmultiplication.Test.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HW1/MatrixMultiplication/MatrixMultiplication.csproj b/HW1/MatrixMultiplication/MatrixMultiplication.csproj index 341f08b..917eeb4 100644 --- a/HW1/MatrixMultiplication/MatrixMultiplication.csproj +++ b/HW1/MatrixMultiplication/MatrixMultiplication.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable true diff --git a/HW1/matrixmultiplication.Test/matrixmultiplication.Test.csproj b/HW1/matrixmultiplication.Test/matrixmultiplication.Test.csproj index 6e9eb81..8f34892 100644 --- a/HW1/matrixmultiplication.Test/matrixmultiplication.Test.csproj +++ b/HW1/matrixmultiplication.Test/matrixmultiplication.Test.csproj @@ -1,7 +1,7 @@ - net8.0 + net9.0 enable enable From 70464291f7e12a9e12d5a52c2e15d25dad60a09a Mon Sep 17 00:00:00 2001 From: khusainovilas Date: Wed, 7 Jan 2026 23:15:33 +0300 Subject: [PATCH 08/11] fix remarks --- .../MatrixFormatException.cs | 37 +++++++++++++++++ HW1/MatrixMultiplication/Program.cs | 40 +++++++++++++++---- 2 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 HW1/MatrixMultiplication/MatrixFormatException.cs diff --git a/HW1/MatrixMultiplication/MatrixFormatException.cs b/HW1/MatrixMultiplication/MatrixFormatException.cs new file mode 100644 index 0000000..f0ef9c5 --- /dev/null +++ b/HW1/MatrixMultiplication/MatrixFormatException.cs @@ -0,0 +1,37 @@ +// +// Copyright (c) khusainovilas. All rights reserved. +// + +namespace MatrixMultiplication; + +/// +/// The exception that is thrown when a matrix file has an invalid format. +/// +public class MatrixFormatException : Exception +{ + /// + /// Initializes a new instance of the class. + /// + public MatrixFormatException() + { + } + + /// + /// Initializes a new instance of the class with a message. + /// + /// The error message. + public MatrixFormatException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the class with a message and inner exception. + /// + /// The error message. + /// The inner exception. + public MatrixFormatException(string message, Exception innerException) + : base(message, innerException) + { + } +} \ No newline at end of file diff --git a/HW1/MatrixMultiplication/Program.cs b/HW1/MatrixMultiplication/Program.cs index 086e901..41ffa23 100644 --- a/HW1/MatrixMultiplication/Program.cs +++ b/HW1/MatrixMultiplication/Program.cs @@ -19,10 +19,15 @@ { MatrixBench.RunBenchmark(); } -else if (args.Length != 3 || string.IsNullOrEmpty(args[0]) || string.IsNullOrEmpty(args[1]) || - string.IsNullOrEmpty(args[2])) +else if (args.Length != 3 || string.IsNullOrEmpty(args[0]) || string.IsNullOrEmpty(args[1]) || string.IsNullOrEmpty(args[2])) { - Console.WriteLine("Error when passing arguments"); + Console.WriteLine("Invalid arguments"); + Console.WriteLine( + "Usage:\n" + + "1) Matrix multiplication:\n" + + " dotnet run -- \n" + + "2) Run benchmark:\n" + + " dotnet run -- benchmark"); } else { @@ -30,9 +35,30 @@ var matrixPath2 = args[1]; var resultFile = args[2]; - var matrix1 = MatrixUtils.ReadMatrixFromFile(matrixPath1); - var matrix2 = MatrixUtils.ReadMatrixFromFile(matrixPath2); - var matrixResult = MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2); + try + { + var matrix1 = MatrixUtils.ReadMatrixFromFile(matrixPath1); + var matrix2 = MatrixUtils.ReadMatrixFromFile(matrixPath2); + var matrixResult = MatrixUtils.MultiplyMatrixParallel(matrix1, matrix2); - MatrixUtils.WriteMatrixToFile(resultFile, matrixResult); + MatrixUtils.WriteMatrixToFile(resultFile, matrixResult); + + Console.WriteLine($"Matrix multiplication completed successfully. Result saved in '{resultFile}'."); + } + catch (MatrixFormatException ex) + { + Console.WriteLine($"Matrix error: {ex.Message}"); + } + catch (FileNotFoundException ex) + { + Console.WriteLine($"File error: {ex.Message}"); + } + catch (ArgumentException ex) + { + Console.WriteLine($"Multiplication error: {ex.Message}"); + } + catch (Exception ex) + { + Console.WriteLine($"Unexpected error: {ex.Message}"); + } } From c03977fd34507f5d662a7890276376e0d69a561b Mon Sep 17 00:00:00 2001 From: khusainovilas Date: Wed, 7 Jan 2026 23:18:38 +0300 Subject: [PATCH 09/11] fix remarks --- HW1/MatrixMultiplication/matrixBench.cs | 8 ++-- HW1/MatrixMultiplication/matrixUtils.cs | 42 ++++++++++--------- .../matrixmultiplicationTest.cs | 42 ++++++++++++++++--- 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/HW1/MatrixMultiplication/matrixBench.cs b/HW1/MatrixMultiplication/matrixBench.cs index 774fe07..c37b03b 100644 --- a/HW1/MatrixMultiplication/matrixBench.cs +++ b/HW1/MatrixMultiplication/matrixBench.cs @@ -1,4 +1,4 @@ -// +// // Copyright (c) khusainovilas. All rights reserved. // @@ -68,8 +68,8 @@ private static (double Expectation, double Deviation) BenchmarkMatrixMultiplicat /// Elapsed time in milliseconds for a single multiplication. private static long PerformSingleRun(int size, bool useParallel) { - var matrix1 = MatrixUtils.GeneratorRandomMatrix(size, size); - var matrix2 = MatrixUtils.GeneratorRandomMatrix(size, size); + var matrix1 = MatrixUtils.GenerateRandomMatrix(size, size); + var matrix2 = MatrixUtils.GenerateRandomMatrix(size, size); var stopwatch = Stopwatch.StartNew(); @@ -79,7 +79,7 @@ private static long PerformSingleRun(int size, bool useParallel) } else { - MatrixUtils.MatrixMultiply(matrix1, matrix2); + MatrixUtils.MultiplyMatrix(matrix1, matrix2); } stopwatch.Stop(); diff --git a/HW1/MatrixMultiplication/matrixUtils.cs b/HW1/MatrixMultiplication/matrixUtils.cs index 3599ac5..de08e66 100644 --- a/HW1/MatrixMultiplication/matrixUtils.cs +++ b/HW1/MatrixMultiplication/matrixUtils.cs @@ -1,4 +1,4 @@ -// +// // Copyright (c) khusainovilas. All rights reserved. // @@ -18,7 +18,7 @@ public static class MatrixUtils /// Minimum value for matrix elements (inclusive). /// Maximum value for matrix elements (exclusive). /// A 2D integer array filled with random values. - public static int[,] GeneratorRandomMatrix(int rows, int columns, int minValue = -100, int maxValue = 100) + public static int[,] GenerateRandomMatrix(int rows, int columns, int minValue = -100, int maxValue = 100) { var matrix = new int[rows, columns]; var randomNumbers = new Random(); @@ -40,7 +40,7 @@ public static class MatrixUtils /// First matrix. /// Second matrix. /// Resulting matrix after multiplication. - public static int[,] MatrixMultiply(int[,] matrix1, int[,] matrix2) + public static int[,] MultiplyMatrix(int[,] matrix1, int[,] matrix2) { var lengthRowMatrix1 = matrix1.GetLength(0); var lengthColumnMatrix1 = matrix1.GetLength(1); @@ -94,28 +94,32 @@ public static class MatrixUtils } var result = new int[lengthRowMatrix1, lengthColumnMatrix2]; - var threads = new Thread[lengthRowMatrix1]; + var numThreads = Math.Min(Environment.ProcessorCount, lengthRowMatrix1); + var threads = new Thread[numThreads]; - for (var i = 0; i < lengthRowMatrix1; i++) + for (var t = 0; t < numThreads; t++) { - var row = i; - threads[row] = new Thread(() => + var threadIndex = t; + threads[t] = new Thread(() => { - for (var j = 0; j < lengthColumnMatrix2; j++) + for (var i = threadIndex; i < lengthRowMatrix1; i += numThreads) { - var sum = 0; - for (var k = 0; k < lengthColumnMatrix1; k++) + for (var j = 0; j < lengthColumnMatrix2; j++) { - sum += matrix1[row, k] * matrix2[k, j]; - } + var sum = 0; + for (var k = 0; k < lengthColumnMatrix1; k++) + { + sum += matrix1[i, k] * matrix2[k, j]; + } - result[row, j] = sum; + result[i, j] = sum; + } } }); - threads[row].Start(); + threads[t].Start(); } - for (var i = 0; i < lengthRowMatrix1; i++) + for (var i = 0; i < numThreads; i++) { threads[i].Join(); } @@ -132,7 +136,7 @@ public static class MatrixUtils /// true — if the matrices are the same size and all their elements match. /// false — if the dimensions are different or at least one element is different. /// - public static bool MatrixEquals(int[,] matrix1, int[,] matrix2) + public static bool AreMatrixEqual(int[,] matrix1, int[,] matrix2) { if (matrix1.GetLength(0) != matrix2.GetLength(0) || matrix1.GetLength(1) != matrix2.GetLength(1)) @@ -175,7 +179,7 @@ public static bool MatrixEquals(int[,] matrix1, int[,] matrix2) // Checking that the file is not empty if (lines.Length == 0) { - throw new Exception("Matrix file is empty."); + throw new MatrixFormatException("Matrix file is empty."); } var rows = lines.Length; @@ -188,7 +192,7 @@ public static bool MatrixEquals(int[,] matrix1, int[,] matrix2) // Check that the string contains only numbers, spaces, and minus signs. if (lines[i].Any(c => !char.IsDigit(c) && c != ' ' && c != '-')) { - throw new Exception("Invalid character in matrix file: only digits, spaces and minus signs are allowed."); + throw new MatrixFormatException("Invalid character in matrix file: only digits, spaces and minus signs are allowed."); } var nums = lines[i].Split(' ', StringSplitOptions.RemoveEmptyEntries) @@ -198,7 +202,7 @@ public static bool MatrixEquals(int[,] matrix1, int[,] matrix2) // Checking that all rows and columns in the matrix have the same length if (nums.Length != columns) { - throw new Exception("Invalid matrix format: the matrix is not complete"); + throw new MatrixFormatException("Invalid matrix format: the matrix is not complete."); } for (var j = 0; j < columns; j++) diff --git a/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs b/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs index b146b60..4dbf6cf 100644 --- a/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs +++ b/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs @@ -1,4 +1,4 @@ -// +// // Copyright (c) khusainovilas. All rights reserved. // @@ -41,23 +41,53 @@ public void Setup() /// /// Tests the sequential matrix multiplication function. - /// Checks that the result matches the expected output. /// [Test] public void MatrixUtils_MatrixMultiply_Matrix1_Matrix2() { - var result = MatrixUtils.MatrixMultiply(this.matrix1, this.matrix2); - Assert.That(MatrixUtils.MatrixEquals(result, this.matrixExpected), Is.True); + var result = MatrixUtils.MultiplyMatrix(this.matrix1, this.matrix2); + Assert.That(MatrixUtils.AreMatrixEqual(result, this.matrixExpected), Is.True); } /// /// Tests the parallel matrix multiplication function. - /// Ensures that parallel computation produces the correct result. /// [Test] public void MatrixUtils_MultiplyMatrixParallel_Matrix1_Matrix2() { var result = MatrixUtils.MultiplyMatrixParallel(this.matrix1, this.matrix2); - Assert.That(MatrixUtils.MatrixEquals(result, this.matrixExpected), Is.True); + Assert.That(MatrixUtils.AreMatrixEqual(result, this.matrixExpected), Is.True); + } + + /// + /// Tests multiplication with 1x1 matrices. + /// + [Test] + public void MultiplyMatrix_OneByOneMatrices_ReturnsCorrectValue() + { + int[,] a = { { 5 } }; + int[,] b = { { 3 } }; + int[,] expected = { { 15 } }; + + var resultSeq = MatrixUtils.MultiplyMatrix(a, b); + var resultPar = MatrixUtils.MultiplyMatrixParallel(a, b); + + Assert.Multiple(() => + { + Assert.That(MatrixUtils.AreMatrixEqual(resultSeq, expected), Is.True); + Assert.That(MatrixUtils.AreMatrixEqual(resultPar, expected), Is.True); + }); + } + + /// + /// Tests multiplication with empty matrices. + /// + [Test] + public void MultiplyMatrix_EmptyMatrices_ThrowsArgumentException() + { + int[,] empty = new int[0, 0]; + + Assert.Throws(() => MatrixUtils.MultiplyMatrix(empty, this.matrix2)); + Assert.Throws(() => MatrixUtils.MultiplyMatrixParallel(empty, this.matrix2)); } } From b6b0f8ad7a69215b3ffd664a17cbbb929e8a8465 Mon Sep 17 00:00:00 2001 From: khusainovilas Date: Wed, 7 Jan 2026 23:19:44 +0300 Subject: [PATCH 10/11] fix remarks --- HW1/MatrixMultiplication/{matrixBench.cs => MatrixBench.cs} | 0 HW1/MatrixMultiplication/{matrixUtils.cs => MatrixUtils.cs} | 0 .../{matrixmultiplicationTest.cs => MatrixmultiplicationTest.cs} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename HW1/MatrixMultiplication/{matrixBench.cs => MatrixBench.cs} (100%) rename HW1/MatrixMultiplication/{matrixUtils.cs => MatrixUtils.cs} (100%) rename HW1/matrixmultiplication.Test/{matrixmultiplicationTest.cs => MatrixmultiplicationTest.cs} (100%) diff --git a/HW1/MatrixMultiplication/matrixBench.cs b/HW1/MatrixMultiplication/MatrixBench.cs similarity index 100% rename from HW1/MatrixMultiplication/matrixBench.cs rename to HW1/MatrixMultiplication/MatrixBench.cs diff --git a/HW1/MatrixMultiplication/matrixUtils.cs b/HW1/MatrixMultiplication/MatrixUtils.cs similarity index 100% rename from HW1/MatrixMultiplication/matrixUtils.cs rename to HW1/MatrixMultiplication/MatrixUtils.cs diff --git a/HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs b/HW1/matrixmultiplication.Test/MatrixmultiplicationTest.cs similarity index 100% rename from HW1/matrixmultiplication.Test/matrixmultiplicationTest.cs rename to HW1/matrixmultiplication.Test/MatrixmultiplicationTest.cs From 3cb2fa283abe25b292aa780b4a1a8f1cd59b97b3 Mon Sep 17 00:00:00 2001 From: khusainovilas Date: Wed, 7 Jan 2026 23:23:42 +0300 Subject: [PATCH 11/11] fix remarks --- HW1/MatrixMultiplication/resultBenchmark.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/HW1/MatrixMultiplication/resultBenchmark.txt b/HW1/MatrixMultiplication/resultBenchmark.txt index 15de6a7..d85199e 100644 --- a/HW1/MatrixMultiplication/resultBenchmark.txt +++ b/HW1/MatrixMultiplication/resultBenchmark.txt @@ -1,6 +1,6 @@ Size Seq_Exp Seq_Dev Par_Exp Par_Dev - 100 5,7000 0,9000 24,9000 2,0712 - 200 49,5000 5,1039 52,9000 11,0494 - 300 158,2000 25,7674 67,6000 9,8914 - 400 385,9000 56,2538 123,1000 13,1640 - 500 811,2000 123,2119 313,0000 102,8669 + 100 9,6000 1,2806 7,7000 2,5710 + 200 46,6000 6,2960 15,7000 1,2689 + 300 164,4000 20,0659 97,3000 47,3984 + 400 1010,1000 55,4084 327,5000 204,1613 + 500 2477,7000 791,3668 306,6000 30,5817