using Cudafy;
using Cudafy.Host;
using CudafyTest.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CudafyTest.Calculations
{
class MatrixMultiplication : GpuCalculation
{
private float[,] m_A;
private float[,] m_B;
private float[,] m_Result;
private float[,] m_ResultCpu;
private int m_Dimension;
public MatrixMultiplication(GPGPU gpgpu, int number) : base(gpgpu)
{
m_Dimension = number;
InitExampleArrays(number);
}
private void InitExampleArrays(int number)
{
m_A = new float[number, number];
m_B = new float[number, number];
m_Result = new float[number, number];
//fill the array
for (int i = 0; i < number; i++)
{
for (int j = 0; j < number; j++)
{
m_A[i, j] = 1.0f + (float)i * (float)(number - j) / (float)number;
m_B[i, j] = 1.0f + (float)(number - i) * (float)j / (float)number;
}
}
//PrintResult(m_A);
//PrintResult(m_B);
}
protected override void OnExecute()
{
float[,] devA = Gpu.CopyToDevice(m_A);
float[,] devB = Gpu.CopyToDevice(m_B);
float[,] devResult = Gpu.Allocate(m_Result);
Gpu.Launch(new dim3(m_Dimension, m_Dimension), 1).Multiply(m_Dimension, devA, devB, devResult);
Gpu.CopyFromDevice(devResult, m_Result);
Gpu.FreeAll();
//PrintResult(m_Result);
}
[Cudafy]
public static void Multiply(GThread gthread, int dimension, float[,] a, float[,] b, float[,] result)
{
int x = gthread.blockIdx.x * gthread.blockDim.x + gthread.threadIdx.x;
int y = gthread.blockIdx.y * gthread.blockDim.y + gthread.threadIdx.y;
if (x >= dimension || y >= dimension)
{
return;
}
float sum = 0.0f;
for (int k = 0; k < dimension; k++)
{
sum += a[x, k] * b[k, y];
}
result[x, y] = sum;
}
public void CpuCalculation()
{
Stopwatch watch = new Stopwatch();
watch.Start();
m_ResultCpu = new float[m_Dimension, m_Dimension];
for (int x = 0; x < m_Dimension; x++)
{
for (int y = 0; y < m_Dimension; y++)
{
float sum = 0.0f;
for (int k = 0; k < m_Dimension; k++)
{
sum += m_A[x, k] * m_B[k, y];
}
m_ResultCpu[x, y] = sum;
}
}
Console.WriteLine("CPU Calculation:");
//PrintResult(m_Result);
watch.Stop();
Console.WriteLine("Time elapsed {0} ms", watch.ElapsedMilliseconds);
}
private void PrintResult(float[,] m_Result)
{
for (int y = 0; y < m_Dimension; y++)
{
for (int x = 0; x < m_Dimension; x++)
{
Console.Write("{0:F} ", m_Result[x, y]);
}
Console.WriteLine();
}
Console.WriteLine();
}
}
}