diff --git a/texto/resumo/resumo-erad.tex b/texto/resumo/resumo-erad.tex index 85cf5cf56bbd868f3da49e069402c1206a1becd9..0872b42678b85533874dcd7f2090b87ebe794ef4 100644 --- a/texto/resumo/resumo-erad.tex +++ b/texto/resumo/resumo-erad.tex @@ -146,13 +146,7 @@ E, por default, ICC usa um modelo de ponto flutuante (\texttt{-fp-model=fast=1}) que habilita otimizações que sacrificam a acurácia da aritmética, ao contrário dos demais. O comportamento default destes compiladores foi equiparado com a flag -\texttt{-fp-model=precise} do ICC.\footnote -{A flag \texttt{-fp-model=precise} desabilita otimizações que usam instruções -FMA. -Enquanto isso é uma desvantagem para o ICC, reduzindo o ganho com -\texttt{-march=native}, a diferença provavelmente é pouco significativa: -com os demais compiladores, o impacto de instruções FMA é inferior a 1\%. -} +\texttt{-fp-model=precise} do ICC. \begin{table}[h] \scriptsize @@ -179,100 +173,100 @@ têm problemas ao tentar utilizar extensões como AVX2. \section{Análise dos códigos} -Para investigar as causas das diferenças observadas, analisamos os código -do programa particle-filter. -Foram escolhidos os códigos gerados com as flags \texttt{-O3} e -\texttt{-march=native}, além de \texttt{-funroll-loops} com GCC e -\texttt{-fp-model=precise} com ICC. +Para investigar as causas das diferenças observadas, analisamos o código do +programa em que o compilador da Intel obteve maior vantagem, Particle Filter. +O assembly foi gerado com as flags \texttt{-O3} e \texttt{-march=native}, +além de \texttt{-funroll-loops} com GCC e \texttt{-fp-model=precise} com ICC. +Com estas flags, ICC mostrou um desempenho 42\% superior ao do GCC, que, por sua +vez, foi 24\% mais rápido que Clang e AOCC. -A Listagem~\ref{list:pfilter.c.1} contém um segmento do programa. -A seção que o inclui executa aproximadamente \(2.4\) vezes mais rápido no -programa gerado pelo ICC do que no produzido pelo GCC, e cerca de \(1.4\) -vezes mais rápido no GCC do que no Clang e AOCC. +A Listagem~\ref{list:pfilter.c.1} contém um segmento de Particle Filter. +Os quatro compiladores o vetorizam. +No entanto, GCC usa registradores de 128 bits (2 doubles), enquanto os +demais usam registradores de 256 bits (4 doubles). +A cada iteração, GCC opera sobre 8 vetores (16 elementos) e AOCC, Clang e +ICC operam sobre 1 vetor (4 elementos). \begin{lstlisting}[label=list:pfilter.c.1,basicstyle=\small, -caption={Segmento de particle-filter (linhas 288--293)}] - for(x = 0; x < lengthCDF; x++) { - if(CDF[x] >= value) { - index = x; - break; - } +caption={Segmento de Particle Filter (linhas 445--447)}] + for(x = 0; x < Nparticles; x++){ + weights[x] = weights[x]/sumWeights; } \end{lstlisting} -AOCC e Clang geram, para este trecho, um código praticamente idêntico e -menos otimizado que os dos outros dois compiladores. +As observações feitas para a Listagem~\ref{list:pfilter.c.1} se aplicam a +quase todo segmento de Particle Filter analisado. +GCC é o mais agressivo no loop unrolling e, ao vetorizar, sempre se limita ao +uso de registradores XMM, de 128 bits. +De acordo com o tamanho do laço, tipicamente é usado um fator de 4, 8 ou 16, +com o caso típico sendo 8 elementos ou, em código vetorizado, 8 vetores +(16 elementos). +Ao vetorizar o código, ICC geralmente opera sobre 1 vetor (4 elementos) por +iteração. +Mas em código não vetorizado, opera sobre 4 ou 8 elementos por iteração. +Clang e AOCC geram códigos bastante parecidos entre si e geralmente operam +sobre um único elemento ou vetor por iteração. + +Seguindo o padrão observado, AOCC e Clang geram, para o segmento na +Listagem~\ref{list:pfilter.c.2}, um código praticamente idêntico e sem loop +unrolling. O laço principal consiste de 6 instruções, incluindo 1 leitura da memória, 1 comparação ponto flutuante e 2 saltos condicionais. -GCC otimiza o segmento com loop unrolling: o laço principal compara 8 -elementos por iteração e consiste de 35 instruções, incluindo 8 leituras da -memória, 8 comparações ponto flutuante e 9 saltos condicionais. -ICC vetoriza o fragmento. -O laço principal realiza comparações e consiste de 12 instruções, +Com GCC, o laço principal compara 8 elementos por iteração e consiste de 35 +instruções, incluindo 8 leituras da memória, 8 comparações ponto flutuante e 9 +saltos condicionais. +ICC é o único que vetoriza o fragmento. +O laço principal realiza 16 comparações e consiste de 12 instruções, incluindo 4 comparações de (vetores) ponto flutuante lidos da memória e 2 saltos condicionais. -A Listagem~\ref{list:pfilter.c.2} contém outro segmento de particle-filter. -Os quatro compiladores foram capazes vetorizar este código. -No entanto, GCC usa registradores de 128 bits, enquanto os demais usam -registradores de 256 bits. -GCC realiza loop unrolling com fator 16, e AOCC e CLANG, 8. -ICC não realiza loop unrolling, copiando 4 elementos (um registrador -de 256 bits) por laço. - \begin{lstlisting}[label=list:pfilter.c.2,basicstyle=\small, -caption={Segmento de particle-filter (linhas 499--504)}] - for(x = 0; x < Nparticles; x++){ - arrayX[x] = xj[x]; - arrayY[x] = yj[x]; - weights[x] = 1/((double)(Nparticles)); - } +caption={Segmento de Particle Filter (linhas 288--293)}] + for(x = 0; x < lengthCDF; x++) { + if(CDF[x] >= value) { + index = x; + break; + } + } \end{lstlisting} -O segmento na listagem~\ref{list:pfilter.c.2} está dentro de um outro laço, -em que o valor de \texttt{Nparticles} não muda. -Clang e AOCC computam a divisão de ponto flutuante \texttt{1/Nparticles} -cada vez que entram no laço interno. -Já GCC e ICC ambos tiram proveito do fato que o resultado não muda para -computá-lo uma única vez, no laço exterior: o código correspondente ao segmento -apenas carrega este valor. -Nenhum dos compiladores, no entanto, remove toda a atribuição da linha 4. - -Outro trecho é apresentado na Listagem~\ref{list:pfilter.c.3}. -Como no primeiro exemplo, apenas o ICC vetoriza o código. -Para tanto, o laço principal mantém quatro acumuladores em um registrador. -Ao sair do laço, o valor dos quatro acumuladores é somado. -Como no segundo exemplo, ICC não realiza loop unrolling. -Já o laço principal do GCC soma dezesseis elementos por iteração. -Clang e AOCC nem vetorizam nem realizam loop unrolling. - -\begin{lstlisting}[label=list:pfilter.c.3,caption={Segmento de particle-filter (linhas 439--441)}] - for(x = 0; x < Nparticles; x++){ - sumWeights += weights[x]; - } -\end{lstlisting} +%O segmento na listagem~\ref{list:pfilter.c.2} está dentro de um outro laço, +%em que o valor de \texttt{Nparticles} não muda. +%Clang e AOCC computam a divisão de ponto flutuante \texttt{1/Nparticles} +%cada vez que entram no laço interno. +%Já GCC e ICC ambos tiram proveito do fato que o resultado não muda para +%computá-lo uma única vez, no laço exterior: o código correspondente ao segmento +%apenas carrega este valor. +%Nenhum dos compiladores, no entanto, remove toda a atribuição da linha 4. + +O segmento na Listagem~\ref{list:pfilter.c.2} é a principal parte da seção que +domina o tempo de execução do programa e que executa aproximadamente \(2.4\) +vezes mais rápido no programa gerado pelo ICC do que no produzido pelo +GCC, e cerca de \(1.4\) vezes mais rápido no GCC do que no Clang e AOCC. \section{Conclusão} -A análise dos códigos demonstra que o compilador da Intel identifica -possibilidades de vetorização automática que os outros compiladores ignoram. +A análise demonstra que o compilador da Intel identifica possibilidades de +vetorização que os outros compiladores ignoram. GCC, em especial, mesmo ao vetorizar um código, pode não ser capaz de utilizar -toda a largura dos registradores, como visto para a -Listagem~\ref{list:pfilter.c.2}. +toda a largura dos registradores. +%como visto para a Listagem~\ref{list:pfilter.c.2}. De fato, como mostra a Tabela~\ref{tab:resultados-medios}, ICC é o compilador mais afetado ao se desabilitar a vetorização automática, com sua performance média piorando em cerca de 4\%. A vantagem frente ao GCC é reduzida para cerca de 1\%. -Mas essa diferença não reflete totalmente o efeito da vetorização na performance -do ICC. -A análise do código revela que o código compilado com \texttt{-no-vec} ainda -mantém vetorizações mais simples, incluindo as correspondentes aos segmentos -na Listagem~\ref{list:pfilter.c.2} e Listagem~\ref{list:pfilter.c.3}, em que -não apenas a vetorização é mantida, mas o compilador passa a realizar -loop unrolling para operar sobre oito elementos (dois vetores) por iteração. +Mas a análise do código revela que, mesmo com a flag \texttt{-no-vec}, ICC ainda +mantém vetorizações mais simples, incluindo a correspondentes ao segmento na +Listagem~\ref{list:pfilter.c.1}, em que não apenas a vetorização é mantida, mas +o compilador passa a realizar loop unrolling para operar sobre dois vetores +(oito elementos) por iteração. +Portanto, a variação de desempenho observada não reflete totalmente o efeito +da vetorização na performance do ICC. +Isto sugere que, enquanto várias diferenças nas estratégias de otimização afetam +o resultado, a principal vantagem do ICC é sua capacidade de vetorização. \bibliographystyle{sbc} \bibliography{resumo-erad} -\end{document} +\end{document} \ No newline at end of file