Skip to content
Snippets Groups Projects
Commit 0931bc93 authored by jigjunior's avatar jigjunior
Browse files

Versão final do relatório...

parent 8169eaa6
No related branches found
No related tags found
No related merge requests found
...@@ -38,15 +38,16 @@ ...@@ -38,15 +38,16 @@
\begin{abstract} \begin{abstract}
O algoritmo de Floyd Warshall consiste em encontrar todos os menores caminhos O algoritmo de Floyd Warshall consiste em encontrar todos os menores caminhos
entre pares de vértices de um grafo. entre pares de vértices de um grafo com peso, direcionado ou não. Uma de suas
Esse trabalho se propõe a implementar esse algoritmo de forma serial e paralela restrições é que não pode haver ciclos negativos no grafo.
Esse trabalho se propõe a implementar esse algoritmo de forma sequencial e paralela
considerando uma matriz de adjacência usando apenas uma dimensão (row-wise). considerando uma matriz de adjacência usando apenas uma dimensão (row-wise).
\end{abstract} \end{abstract}
\section{Desenvolvimento} \section{Desenvolvimento}
O algoritmo foi escrito em linguagem C++ e consiste na utilização O algoritmo foi implementado em linguagem C++ e consiste na utilização
de uma matriz de adjacência com tamanho k x k. de uma matriz de adjacência com tamanho k x k.
Inicialmente, o grafo é lido do arquivo de entrada na matriz de Inicialmente, o grafo é lido do arquivo de entrada na matriz de
...@@ -365,10 +366,79 @@ index % time self children called name ...@@ -365,10 +366,79 @@ index % time self children called name
\includegraphics[scale=0.45]{imagens/speedup} \includegraphics[scale=0.45]{imagens/speedup}
\end{center} \end{center}
\section{Complexidade}
\subsection{Sequencial}
Na versão sequencial, tem-se claramente a seguinte complexidade:
\begin{items}
\item \texttt{Busca na matriz de adjâcencia}: \newline
Como deve-se passar n-etapas, percorrendo toda a matriz, a
complexidade é de $ O(|V|^3) $ no pior ou melhor caso; \newline
\item \texttt{Inicialização da matriz de adjacência}: \newline
Como é necessário inicializar toda a matriz de adjacência, temos
temos aqui $ O(|V|^2) $.
\end{items}
\subsection{Paralela}
Desconsiderando o tempo de leitura do arquivo de entrada e
criação da matriz de adjacência (que será igual na implementação
paralela), temos dois trechos de código candidatos à implementação
em paralelo:
\begin{items}
\item \texttt{Busca na matriz de adjâcencia}; \newline
\item \texttt{Inicialização da matriz de adjacência}.
\end{items}
\section{Implementação paralela}
\subsection{Modelo PRAM}
Na seção Complexidade estão as duas partes do algoritmo que
podem ser melhoradas se implementadas em paralelo.
Uma das vantagens no modelo PRAM é o fato de se poder usar
tantos processadores quanto forem necessários.
Com isso em mente, podemos melhorar as três partes do código
da seguinte maneira:
\begin{items}
\item \texttt{Busca na matriz de adjâcencia}: \newline
Como deve-se passar n-etapas, percorrendo toda a matriz, a
complexidade é de $ O(|V|) $ no pior ou melhor caso,
utilizando-se $ p ^ 2 $ processadores, levando-se em conta
que o laço das k-etapas não é facilmente paralelizável; \newline
\item \texttt{Inicialização da matriz de adjacência}: \newline
Como é necessário passar por todos os elementos dos vetores
de vértices anteriores e distância, temos aqui $ O(1) $.
\end{items}
O trabalho executado em paralelo é o mesmo que na versão sequencial,
já que não existem operações adicionais de gerenciamento e todas
as arestas da matriz de adjacência devem ser visitadas. \newline
Dessa forma, teremos um ganho considerável no speedup comparando as
duas versões.
\begin{items}
\item \texttt{$n^2$ processadores}: \newline
\begin{equation}
S_p(n^2) = \frac{|V|^3}{|V|} = |V| ^ 2
\end{equation}
\end{items}
Temos aqui um speedup linear, na teoria.
Na prática, o ideal é limitarmos o número de threads para o mesmo
da arquitetura, pois se tivermos $n^2$ threads, apenas algumas estarão
em execução ao mesmo tempo, enquanto as outras esperarão até que
aconteça uma troca de contexto, gerando um overhead muito grande.
\newpage
\section{Análise do Código e resultados obtidos} \section{Análise do Código e resultados obtidos}
O código foi implementado e testado no seguinte hardware:
\begin{items}
\item Intel® Core™ i5-4210U CPU @ 1.70GHz x 4 (2 threads / 4 núcleos);
\item 6GB de RAM;
\item Sistema Operacional Linux Debian SID.
\end{items}
\subsection{Fontes de ganho e queda de desempenho} \subsection{Fontes de ganho e queda de desempenho}
Existem algumas fontes influenciadoras de desempenho. Existem algumas fontes influenciadoras, que podem melhorar ou piorar o desempenho.
Ganhos: Ganhos:
\begin{items} \begin{items}
...@@ -384,6 +454,11 @@ index % time self children called name ...@@ -384,6 +454,11 @@ index % time self children called name
diminuição na granularidade, no último laço. Cada thread passa a ser diminuição na granularidade, no último laço. Cada thread passa a ser
responsável apenas por calcular uma aresta da matriz de adjacência. responsável apenas por calcular uma aresta da matriz de adjacência.
O tempo chega a dobrar nesse caso; \newline O tempo chega a dobrar nesse caso; \newline
\item \texttt{schedule}: alterar o schedule de static para dynamic ou guided
piora um pouco o desempenho. Tendo em vista que as tarefas são
homogêneas e cada thread vai executar uma quantidade parecida, pode-se
escalonar inicialmente todas as tarefas para cada uma delas. \newline
Alterar o valor do chunk para o static schedule também não melhora nada.
\end{items} \end{items}
\subsection{Resultados obtidos} \subsection{Resultados obtidos}
...@@ -403,63 +478,6 @@ index % time self children called name ...@@ -403,63 +478,6 @@ index % time self children called name
diminuição do tempo (baseando-se na parte do código que pode ser diminuição do tempo (baseando-se na parte do código que pode ser
paralelizado), quanto na tendência do overhead, speedup e eficiência. paralelizado), quanto na tendência do overhead, speedup e eficiência.
\section{Complexidade}
\subsection{Sequencial}
Desconsiderando o tempo de leitura do arquivo de entrada e
criação da lista de adjacência (que será igual na implementação
paralela), temos três trechos de código candidatos à implementação
em paralelo:
\begin{items}
\item \texttt{Busca na árvore binária}: \newline
Utilizando a estrutura \emph{set} do C++, que utiliza uma árvore binária,
temos como complexidade $ O(|A| * log |V|) $; \newline
\item \texttt{Desempilha / Empilha}: \newline
O empilhamento/desempilhamento, possui custo $ O(log |V|) $; \newline
\item \texttt{Inicialização das estruturas de dados (vetor de vértices e caminho)}: \newline
Como é necessário passar por todos os elementos dos vetores
de vértices anteriores e distância, temos aqui $ O(|V|) $.
Considerando um grafo conexo, temos: $ |A| \leq |V| - 1 $ ou
$ |V| \geq |A| + 1 $.
Assim, a complexidade total é igual à
$ O(|V| * log |V| + |A| * log |V|) $, ou $ (|A| * log |V|) $.
\end{items}
\section{Implementação paralela}
\subsection{Modelo PRAM}
Na seção Complexidade estão as três partes do algoritmo que
podem ser melhoradas se implementadas em paralelo.
Uma das vantagens no modelo PRAM é o fato de se poder usar
tantos processadores quanto forem necessários.
Com isso em mente, podemos melhorar as três partes do código
da seguinte maneira:
\begin{items}
\item \texttt{Busca na árvore binária}: \newline
Possuindo $n^2$ processadores, podemos utilizar um
algoritmo de busca com complexidade O(1), visto em
sala de aula.
\item \texttt{Desempilha / Empilha}: O(log V); \newline
A princípio, fica igual.
\item \texttt{Inicialização das estruturas de dados (vetor de vértices e caminho)}: \newline
Com $2n$ processadores, cada um ajustando o valor
inicial em algum item do vetor de anteriores ou do
vetor de distâncias, teremos aqui também complexidade
O(1).
\end{items}
A diferença nessa abordagem, fica por conta da separação entre
p-processadores.
Inicialmente, o vetor é separado em p clusters, de modo
que os menores caminhos sejam calculados para cada cluster,
baseado no vértice que estiver mais perto do vértice inicial.
Após o cálculo local, a distância será enviada a todos os
processadores, para que atualizem os seus respectivos vetores
de distância.
\newpage \newpage
\section{Execução do código} \section{Execução do código}
...@@ -475,7 +493,7 @@ index % time self children called name ...@@ -475,7 +493,7 @@ index % time self children called name
\end{lstlisting} \end{lstlisting}
\item \texttt{Compile e gere a documentação}: \item \texttt{Compile e gere a documentação}:
\begin{lstlisting} \begin{lstlisting}
$ make dijkstra && make doc $ make && make doc
\end{lstlisting} \end{lstlisting}
\item \texttt{Execute} \item \texttt{Execute}
\begin{lstlisting} \begin{lstlisting}
...@@ -497,9 +515,9 @@ index % time self children called name ...@@ -497,9 +515,9 @@ index % time self children called name
\end{lstlisting} \end{lstlisting}
\end{items} \end{items}
\section{Verificação de corretude} \section{Utilitários}
\subsection{Script de benchmark} \subsection{Teste de corretude - script de benchmark}
No diretório /build/ do projeto foi criado um script (gera\_bench.sh) que roda todos No diretório /build/ do projeto foi criado um script (gera\_bench.sh) que roda todos
os executáveis com todas as entradas de grafos cíclicos (do diretório /entrada/) e os executáveis com todas as entradas de grafos cíclicos (do diretório /entrada/) e
joga a saída (matriz de adjacência final, depois de todas as atualizações feitas) joga a saída (matriz de adjacência final, depois de todas as atualizações feitas)
...@@ -507,4 +525,15 @@ index % time self children called name ...@@ -507,4 +525,15 @@ index % time self children called name
As saídas foram checadas e são iguais para as mesmas entradas. As saídas foram checadas e são iguais para as mesmas entradas.
\subsection{Gerador de entradas}
No diretório /entrada/ do projeto foi criado um script (gera\_grafo.py) que
gera entradas cíclicas ou aciclicas.
\begin{items}
\item \texttt{Para gerar a entrada, basta executar o script}:
\begin{lstlisting}[language=bash]
$ ./gera_grafo A 50
$ ./gera_grafo C 50 2
\end{lstlisting}
\end{items}
\end{document} \end{document}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment