DAS_2024_1/kuzarin_maxim_lab_5/MatrixMultiplication/Program.cs
2024-09-22 22:14:00 +03:00

117 lines
3.2 KiB
C#

using System.Diagnostics;
internal class Program
{
private static string[] _resTableColumnsNames = new string[] { "m*m", "1 t", "2 t", "3 t", "4 t", "5 t", "6 t", "7 t", "8 t" };
private static void Main(string[] args)
{
Console.WriteLine(string.Join("\t", _resTableColumnsNames));
for (int i = 10; i < 10000; i *= 2)
{
var a = CreateMatrix(i, i);
var b = CreateMatrix(i, i);
List<long> times = new() { i };
for (int j = 1; j <= 8; j++)
{
var sw = new Stopwatch();
sw.Start();
MultiplyMatrix(a, b, j);
sw.Stop();
times.Add(sw.ElapsedMilliseconds);
}
Console.WriteLine(string.Join("\t", times));
}
}
/// <summary>
/// Создаём матрицу случайных элементов
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
private static int[,] CreateMatrix(int x, int y)
{
var rnd = new Random();
var res = new int[y, x];
for (int i = 0; i < y; i++)
{
for (int j = 0; j < x; j++)
{
res[i, j] = rnd.Next(0, 100);
}
}
return res;
}
/// <summary>
/// Вывести матрицу. Использовался при отладке
/// </summary>
/// <param name="mx"></param>
private static void PrintMatrix(int[,] mx)
{
for (int i = 0; i < mx.GetLength(0); i++)
{
for (int j = 0; j < mx.GetLength(1); j++)
{
Console.Write($"{mx[i, j].ToString("000")}\t");
}
Console.WriteLine();
}
}
/// <summary>
/// Непосредственно умножение матриц
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="maxTask"></param>
/// <returns></returns>
private static int[,] MultiplyMatrix(int[,] a, int[,] b, int maxTask)
{
int[,] res = new int[a.GetLength(0), b.GetLength(1)];
var semaphore = new SemaphoreSlim(maxTask, maxTask);
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < b.GetLength(1); j++)
{
semaphore.Wait();
int ci = i;
int cj = j;
_ = Task.Run(() =>
{
try
{
res[ci, cj] = CalculateElement(a, b, ci, cj);
}
finally
{
semaphore.Release();
}
});
}
}
semaphore.Wait(maxTask);
return res;
}
/// <summary>
/// Вычисление значение одного элемента
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="i"></param>
/// <param name="j"></param>
/// <returns></returns>
private static int CalculateElement(int[,] a, int[,] b, int i, int j)
=> Enumerable.Range(0, a.GetLength(1)).Sum(k => a[i, k] * b[k, j]);
}