# Fun with matrix multiplication and unsafe code

In this post I will compare two methods that perform matrix multiplication. We start by defining the Matrix class:

```class Matrix
{
public Matrix(int dim1, int dim2)
{
_matrix = new double[dim1, dim2];
}

public int Height { get { return _matrix.GetLength(0); } }
public int Width { get { return _matrix.GetLength(1); } }

public double this[int x, int y]
{
get { return _matrix[x, y]; }
set { _matrix[x, y] = value; }
}
}```

Next we add the first algorithm to the Matrix class which performs a naive multiplication:

``` public static Matrix NaiveMultiplication(Matrix m1, Matrix m2)
{
Matrix resultMatrix = new Matrix(m1.Height, m2.Width);
for (int i = 0; i < resultMatrix.Height; i++)
{
for (int j = 0; j < resultMatrix.Width; j++)
{
resultMatrix[i, j] = 0;
for (int k = 0; k < m1.Width; k++)
{
resultMatrix[i, j] += m1[i, k] * m2[k, j];
}
}
}
return resultMatrix;
}```

The second method uses unsafe code:

```public unsafe static Matrix UnsafeMultiplication(Matrix m1, Matrix m2)
{
int h = m1.Height;
int w = m2.Width;
int l = m1.Width;
Matrix resultMatrix = new Matrix(h, w);
unsafe
{
fixed (double* pm = resultMatrix._matrix, pm1 = m1._matrix, pm2 = m2._matrix)
{
int i1, i2;
for (int i = 0; i < h; i++)
{
i1 = i * l;
for (int j = 0; j < w; j++)
{
i2 = j;
double res = 0;
for (int k = 0; k < l; k++, i2 += w)
{
res += pm1[i1 + k] * pm2[i2];
}
pm[i * w + j] = res;
}
}
}
}
return resultMatrix;
}```

Now it’s time to measure the performance:

```class Program
{
[DllImport("kernel32.dll")]
static extern void QueryPerformanceCounter(ref long ticks);

static long Measure(Action action, int count)
{
long startTicks = 0;
QueryPerformanceCounter(ref startTicks);
for (int i = 0; i < count; i++)
{
action();
}
long endTicks = 0;
QueryPerformanceCounter(ref endTicks);
return endTicks - startTicks;
}

static void Main(string[] args)
{
Random random = new Random();

Matrix m1 = new Matrix(20, 30);
for (int i = 0; i < m1.Height; i++)
{
for (int j = 0; j < m1.Width; j++)
{
m1[i, j] = random.Next(-100, 100);
}
}

Matrix m2 = new Matrix(30, 40);
for (int i = 0; i < m2.Height; i++)
{
for (int j = 0; j < m2.Width; j++)
{
m2[i, j] = random.Next(-100, 100);
}
}

Console.WriteLine(Measure(() => Matrix.NaiveMultiplication(m1, m2), 10000));
Console.WriteLine(Measure(() => Matrix.UnsafeMultiplication(m1, m2), 10000));
}
}```

In this test we perform 10000 multiplications of two randomly generated matrices with sizes 20×30 and 30×40 using both methods:

 Method CPU cycles unsafe multiplication 4485698 naive multiplication 58762273

The results show that the naive multiplication is slower by a factor of 13 compared to the multiplication using unsafe code and working directly with memory.