|
\documentclass[a4paper,12pt]{article}
|
|
\usepackage{amsmath}
|
|
\usepackage{amssymb}
|
|
\usepackage[polish]{babel}
|
|
\usepackage{polski}
|
|
\usepackage[utf8]{inputenc}
|
|
\usepackage{indentfirst}
|
|
\usepackage{geometry}
|
|
\usepackage{array}
|
|
\usepackage[pdftex]{color,graphicx}
|
|
\usepackage{subfigure}
|
|
\usepackage{afterpage}
|
|
\usepackage{setspace}
|
|
\usepackage{color}
|
|
\usepackage{wrapfig}
|
|
\usepackage{listings}
|
|
\usepackage{datetime}
|
|
|
|
\renewcommand{\onehalfspacing}{\setstretch{1.6}}
|
|
|
|
\geometry{tmargin=2.5cm,bmargin=2.5cm,lmargin=2.5cm,rmargin=2.5cm}
|
|
\setlength{\parindent}{1cm}
|
|
\setlength{\parskip}{0mm}
|
|
|
|
\newenvironment{lista}{
|
|
\begin{itemize}
|
|
\setlength{\itemsep}{1pt}
|
|
\setlength{\parskip}{0pt}
|
|
\setlength{\parsep}{0pt}
|
|
}{\end{itemize}}
|
|
|
|
\newcommand{\linia}{\rule{\linewidth}{0.4mm}}
|
|
|
|
\definecolor{lbcolor}{rgb}{0.95,0.95,0.95}
|
|
\lstset{
|
|
backgroundcolor=\color{lbcolor},
|
|
tabsize=4,
|
|
language=C++,
|
|
captionpos=b,
|
|
tabsize=3,
|
|
frame=lines,
|
|
numbers=left,
|
|
numberstyle=\tiny,
|
|
numbersep=5pt,
|
|
breaklines=true,
|
|
showstringspaces=false,
|
|
basicstyle=\footnotesize,
|
|
identifierstyle=\color{magenta},
|
|
keywordstyle=\color[rgb]{0,0,1},
|
|
commentstyle=\color{Darkgreen},
|
|
stringstyle=\color{red}
|
|
}
|
|
|
|
\begin{document}
|
|
|
|
\noindent
|
|
\begin{tabular}{|c|p{11cm}|c|} \hline
|
|
Grupa 1 & Piotr Dergun, Dominik Waśko & \ddmmyyyydate\today \tabularnewline
|
|
\hline
|
|
\end{tabular}
|
|
|
|
|
|
\section*{Zadanie 6 - Rozmycie Gaussa GPU}
|
|
|
|
Celem zadania jest wykonanie rozmycia obrazu wykorzystując algorytm Gaussa za pomocą karty graficznej oraz technologii CUDA. Poniżej przedstawiono kod kernela, który oblicza rozmycie Gaussa.
|
|
\begin{lstlisting}
|
|
__global__ void gauss(int rows, int cols, unsigned char *in_r, unsigned char *in_g, unsigned char *in_b,unsigned char *out_r, unsigned char *out_g, unsigned char *out_b){
|
|
const int r=5;
|
|
int ratio[r][r] ={ {1, 4, 7, 4, 1},
|
|
{4, 16, 26, 16, 4},
|
|
{7, 26, 41, 26, 7},
|
|
{4, 16, 26, 16, 4},
|
|
{1, 4, 7, 4, 1}};
|
|
|
|
int N,i,row,col,poz,temp,sum_r,sum_g,sum_b,offset;
|
|
offset = 2;
|
|
N = rows * cols;
|
|
i = blockIdx.x * blockDim.x + threadIdx.x;
|
|
while(i<N){
|
|
col = i%cols;
|
|
row = (i/cols);
|
|
if(!(row<offset||row>rows-offset-1||col<offset||col>cols-offset-1)){
|
|
sum_r = 0;
|
|
sum_g = 0;
|
|
sum_b = 0;
|
|
row-=offset;
|
|
temp = col - offset;
|
|
|
|
for (int j=0; j<r; ++j,++row){
|
|
col= temp;
|
|
for (int k=0; k<r; ++k,++col){
|
|
poz = (row*cols) + col;
|
|
sum_r += ratio[j][k] * in_r[poz];
|
|
sum_g += ratio[j][k] * in_g[poz];
|
|
sum_b += ratio[j][k] * in_b[poz];
|
|
}
|
|
}
|
|
out_r[i] = sum_r / 273;
|
|
out_g[i] = sum_g / 273;
|
|
out_b[i] = sum_b / 273;
|
|
}else{
|
|
out_r[i] = in_r[i];
|
|
out_g[i] = in_g[i];
|
|
out_b[i] = in_b[i];
|
|
}
|
|
i+=blockDim.x * gridDim.x;
|
|
}
|
|
}
|
|
\end{lstlisting}
|
|
|
|
Obraz do kernela przesyłany jest w postaci 3 tablic jednowymiarowych( po jednej dla każdego koloru RGB). Konwersja obrazu z tablicy dwuwymiarowej A o rozmiarze NxM na jednowymiarową tablice B o rozmiarze N*M odbywa się wg wzoru: A[i][j] = B[M*i+j].
|
|
|
|
Każdy wątek oblicza co najmniej jeden piksel. Zaczyna od piksela o numerze równym numerowi wątku. W celu celu obliczenia numeru następnego piksela dodaje do aktualnego numeru liczbę wszystkich wątków. Następnie oblicza ten piksel i powtarza czynność z dodawaniem liczby wątków, sprawdzając oczywiście czy otrzymana wartość nie jest większa od całkowitej liczby pikseli w obrazie.
|
|
|
|
Zadanie zostało uruchomione na komputerze wyposażonym w kartę graficzna NVIDIA GeForce GT 640M. Karta posiada dwa multiprocesory po 192 rdzenie CUDA, taktowane zegarem 709 MHz. Pamięć karty to 980MB.
|
|
|
|
Program testowano na obrazie o rozmiarze 24107x4491 pikseli. Parametry dla jakich uruchomiono program to 3 rozmiary siatki: 16, 64, 256 oraz dla każdego rozmiaru siatki rozmiar bloku: 64,128,192,256,320.
|
|
|
|
Na rysunku 1. przedstawiono wykres zależności czasu obliczeń od rozmiaru bloku dla wszystkich trzech rozmiarów siatki. Można zauważyć, że czas obliczeń najbardziej spada przy zwiększeniu rozmiaru bloku do 128. Dalsze zwiększanie rozmiaru bloku nie powoduje tak dużego zmniejszenia czasu obliczeń, a w pewnym momencie zaczyna powodować wzrost czasu . Również rozmiar siatki ma wpływ na szybkość obliczeń: im siatka większa tym bardziej maleje czas.
|
|
|
|
|
|
|
|
|
|
|
|
\begin{figure}[h]
|
|
\includegraphics[width=1.1\textwidth]{wykres.png}
|
|
\caption{Wykres czasu obliczeń od rozmiaru bloku.}
|
|
\label{fig:figure2}
|
|
\end{figure}
|
|
|
|
\section*{Porównanie}
|
|
Porównanie technologii OpenMP i MPI wykonano na komputerze MacPro3.1 wyposażonym w 2 procesory Xeon E5462, przy czym do dyspozycji było 6 rdzeni. Program z CUDA uruchomiono na innym komputerze wyposażonym w katę graficzną NVIDIA GeForce GT 640M z dwoma multiprocesorami po 192 rdzenie CUDA, taktowane zegarem 709 MHz. Do porównania użyto wykonanych na laboratoriach programów obliczających rozmycie Gaussa . Do testów wybrano obraz o rozdzielczości 24107x4491. W tabeli 1. przedstawiono czas wykonania przez poszczególne programy oraz liczbę użytych przez nie wątków, w przypadku CUDA jest to iloczyn rozmiaru siatki oraz rozmiaru bloku.
|
|
Na podstawie danych w tabeli 1. oraz wniosków wyciągniętych z poprzednich laboratoriów można sformułować następujące wnioski:
|
|
|
|
\begin{itemize}
|
|
\item OpenMP przez to, że sam zarządza tym jak i co będzie zrównoleglone nie jest tak szybki jak pozostałe rozwiązania
|
|
|
|
\item MPI przy starannym zaprojektowaniu programu pozwana na dość dobre wyniki oraz umożliwia dużą skalowalność.
|
|
\item Umiejąc odpowiednio zdekomponować problem i przystosować go do obliczeń na karcie graficznej, CUDA okazuje się najlepszym wyborem do obliczeń równoległych.
|
|
\end{itemize}
|
|
|
|
|
|
\begin{table}
|
|
|
|
\centering
|
|
\begin{tabular}{|c|c|c|}
|
|
\hline
|
|
& \textbf{wątki} & \textbf{czas[ms]}\\
|
|
\hline
|
|
\
|
|
\textbf{OpenMP} & 6 & 2227\\
|
|
\hline
|
|
\textbf{MPI} & 6 & 1483\\
|
|
\hline
|
|
\textbf{CUDA} & 98304 & 571\\
|
|
\hline
|
|
\end{tabular}
|
|
\caption{Porównanie}
|
|
\end{table}
|
|
\end{document}
|