\section{Task 1: Matrix Transpose}
The code for this assignment can be found in the \textit{src/Task1} folder
handed in with this report. All functions (where applicable) have been templated
so the datatype contianed in the matrices can be any class \texttt{T}.

The code ships with a make file that supports the \texttt{clean},
\texttt{compile} and \texttt{run} targets. The current setup of the file will
run both GPU kernels on an assymetric matrix and compare to the CPU runs.

\subsection{Task 1.a: Sequential CPU Code}
The code for this subtask is implemented in the file \textit{cpuFunc.cu.h},
there is not a whole lot of spectacular work going on, the file just contains
convenience functions for creating, comparing and freeing matrices of specific
sizes. The transpose function itself is implemented in
\texttt{flatMatrixTranspose}.

\subsection{Task 1.c: Naive GPU Code}
The code for this subtask is implemented in \textit{gpuFunc.cu.h} as well as
in \textit{task1.cu}. The following functions are implemented to solve this
task:
\begin{itemize}
    \item \textit{gpuFunc.cu.h:}\begin{itemize*}
        \item \texttt{flatNaiveTransposeKernel} The actual transpose kernel.
        \item \texttt{flatMatrixCudaMalloc} Allocates device memory for a
        matrix of a given size.
        \item \texttt{flatmatrixCudaFree} Frees the device memory.
        \item \texttt{flatMatrixHostToDevice} Copies a matrix from host- to
        device memory.
        \item \texttt{flatMatrixDeviceToHost} Copies a matrix from device- to
        host memory.
    \end{itemize*}

    \item \textit{task1.cu}\begin{itemize*}
        \item \texttt{gpuNaiveTranspose} Does the setup for a transepose and
        calls the actual transpose kernel.
        \item \texttt{naiveTransposeTest} Compares the results of the CPU
        transpose and the GPU transpose as well as printing the result and how
        long each call took on average.
    \end{itemize*}
\end{itemize}

In the \texttt{main} part of the \textit{task1.cu} file, there is a region that
contains tests I used to find where the CPU transpose starts being slower than
the GPU transpose. The timings are listed in Table \ref{tab:task1time}.


\subsection{Task 1.d: Shared-Memory GPU Code}
For this task additional code is implemented in \textit{task1.cu} and
\textit{gpuFunc.cu.h}, the following methods we're implemented:
\begin{itemize}
    \item \textit{gpuFunc.cu.h:}\begin{itemize*}
        \item \texttt{flatSharedTransposeKernel} The actual transpose kernel.
    \end{itemize*}

    \item \textit{task1.cu}\begin{itemize*}
        \item \texttt{gpuSharedTranspose} Does the setup for a transepose and
        calls the actual transpose kernel.
        \item \texttt{sharedTransposeTest} Compares the results of the CPU
        transpose and the GPU shared memory kernel and prints results and
        running times.
    \end{itemize*}
\end{itemize}

\subsection{Execution Time}

Table \ref{tab:task1time} shows the running times of the CPU code and the
Shared-Memory GPU kernel. Time time is done for 10 runs of each method and the
time represents the average time for a single run. The times only cover the time
spent in the calulation kernels, and does not cover the overhead for copying
data to device memory.

\begin{table}
    \begin{tabular}{|r|r|r|r|}
        \hline
        \textbf{Matrix Dimensions} & \textbf{CPU Time} & \textbf{Naive GPU Time} & \textbf{Tiled-Memory GPU Time}\\\hline
        $100 \times  50$  & $28 \mu s$  & $31 \mu s$ & $21 \mu s$ \\
        $50 \times  100$  & $18 \mu s$  & $19 \mu s$ & $17 \mu s$ \\
        $10 \times  10$   & $>0 \mu s$  & $16 \mu s$ & $15 \mu s$ \\
        $100 \times  100$ & $37 \mu s$  & $19 \mu s$ & $17 \mu s$ \\
        $200 \times  200$ & $163 \mu s$ & $33 \mu s$ & $26 \mu s$ \\
        $300 \times  300$ & $349 \mu s$ & $57 \mu s$ & $46 \mu s$ \\
        $1024\times 1025$ & $18303 ms$  & $272\mu s$ & $145\mu s$ \\\hline

    \end{tabular}
    \caption{The running times for the CPU and GPU code as the average over 10
    runs.}
    \label{tab:task1time}
\end{table}

Table \ref{tab:task1time} shows that the CPU based code while very fast for the
first small entry is quickly overtaken by both GPU kernels. Among the GPU
kernels the Shared-Memory is the fastest from the beginning.
