Avançar para a área de conteúdo

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Todas as informações enviadas são seguras.

  • Fechar [x]

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Todas as informações enviadas são seguras.

  • Fechar [x]

Como melhorar o desempenho de programas chamando funções matemáticas

Tirando proveito da autovetorização do compilador IBM XL C/C++ ou XL Fortran

Robert F. Enenkel, Software developer, IBM
Robert Enenkel trabalha no Optimizing Compiler Group no IBM Toronto Laboratory; antes, foi pesquisador no IBM Centre for Advanced Studies (CAS). Enenkel é bacharel, mestre e doutor pela University of Toronto, com tese na área de métodos numéricos paralelos para equações diferenciais. Ele atualmente realiza pesquisas e desenvolvimentos em computação numérica, no que ela está relacionada a compiladores e sistemas operacionais, incluindo aritmética de ponto flutuante, bibliotecas de funções matemáticas e o ajuste de desempenho de algoritmos. Dr. Enenkel recebeu da IBM vários prêmios por inventos e de reconhecimento como autor. Mais informações podem ser encontradas nesta página: https://www-927.ibm.com/ibm/cas/toronto/people/members/renekel.shtml.
Daniel M. Zabawa, Software developer, IBM
Daniel Zabawa trabalha no Optimizing Compiler Group no IBM Toronto Laboratory. Ele é mestre e doutor em ciência da computação pela University of Toronto. Zabawa atualmente realiza pesquisas e desenvolvimento em planejamento e otimização de loop, algoritmos de ponto flutuante para arquiteturas superescalares e ajuste de desempenho de funções matemáticas de ponto flutuante.

Resumo:  Este artigo apresente as bibliotecas matemáticas de alto desempenho IBM MASS e mostra como aproveitar os seus benefícios — sem a necessidade de alterações nos programas de origem — com o uso do recurso de autovetorização dos compiladores IBM® XL C/C++ e XL Fortran. Após apresentar o conceito de autovetorização e as opções de compilador associadas, um estudo de caso de um programa de transformação Fourier discreto é oferecido como exemplo real de autovetorização. Os resultados da sincronização mostram que os aumentos de velocidade de até 8,94 vezes são obtidos pelos compiladores no programa de exemplo, por meio da chamada automática de MASS pela autovetorização.

Data:  29/Set/2010
Nível:  Intermediário
Atividade:  2139 visualizações
Comentários:  


As bibliotecas de alto desempenho MASS

MASS significa Mathematical Acceleration Subsystem (subsistema de aceleração matemática). É composto por bibliotecas de funções matemáticas especificamente ajustadas para desempenho ideal em várias plataformas de computação IBM. MASS foi originalmente lançado pela IBM em 1995 e tem sido aprimorado e expandido continuamente desde então.

Há versões atuais de MASS para todos os processadores IBM® POWER™, executando sistemas operacionais AIX® ou Linux®. Há também versões para os supercomputadores IBM System BlueGene®/L e IBM System BlueGene®/P, bem como para a solução IBM Cell Broadband Engine™ (Cell/B.E.™). As bibliotecas contêm implementações aceleradas de funções elementares, como trigonométricas e hiperbólicas e seus inversos, potência, logaritmos, exponenciais, função de erro e outras. Listas completas das funções incluídas estão disponíveis na página IBM Mathematical Acceleration Subsystem.

Há bibliotecas escalares e de vetor e, para Cell/B.E. e POWER7, há bibliotecas de dados múltiplos com instrução única (SIMD). Observe que a precisão e o tratamento de exceções não podem ser idênticos nas funções de MASS e nas funções da biblioteca de sistema. As bibliotecas MASS vêm com os compiladores IBM XL C/C++ e XL Fortran e estão também disponíveis no site de MASS para usuários de outros compiladores (como gcc) para o hardware de destino.

As bibliotecas podem ser chamadas a partir de programas de origem C, C++ ou Fortran. Os compiladores IBM XL C/C++ e IBM XL Fortran são capazes de reconhecer oportunidades de usar MASS para acelerar o programa de origem e invocá-lo automaticamente sem a necessidade de alterações no programa de origem. Este artigo mostra como implementar uma técnica que pode ajudar a sua organização a aproveitar esse poderoso recurso.

Quais programas podem se beneficiar?

Qualquer programa C, C++ ou Fortran que tenha chamadas a funções de bibliotecas matemáticas (como exp, log, sin, cos, etc.) em um loop pode se beneficiar das técnicas descritas neste artigo.


O que é autovetorização?

A autovetorização é um processo pelo qual os compiladores IBM XL C/C++ ou Fortran reconhecem uma oportunidade de aprimorar o desempenho do programa sendo compilado substituindo uma chamada a uma função de biblioteca padrão (C/C++ libm ou Fortran intrinsic) em um loop com uma chamada para a função de vetor MASS correspondente. Como as funções de vetor MASS são muito mais rápidas (por um fator de até aproximadamente 30) do que uma chamada repetida a uma função de biblioteca padrão, o aumento no desempenho resultante pode ser substancial.

Um exemplo simples é um loop que calcula uma determinada função para vários argumentos, como o seguinte programa Fortran.

subroutine sub (y, x, n)
    real*8 y(*), x(*)
    integer n, i
    intrinsic exp
    do i=1,n
        y(i) = exp(x(i))  ! standard intrinsic
    end do
end subroutine

Com as opções de compilador apropriadas, o compilador reconhecerá a oportunidade de acelerar o programa substituindo a chamada repetida a exp() por uma única chamada à função de vetor de MASS correspondente vexp(), resultando em um programa que se comporta como se fosse originalmente escrito assim:

include 'massv.include'
subroutine sub (y, x, n)
    real*8 y(*), x(*)
    integer n
    call vexp (y, x, n)  ! MASS vector function
end subroutine

Esse é apenas um exemplo simples, mostrando a ideia básica que está por trás da autovetorização. Os compiladores XL são na verdade capazes de reconhecer oportunidades muito mais complicadas e também tentarão reorganizar as instruções no programa de origem se necessário para que sejam criadas oportunidades de autovetorização.

Um exemplo mais complicado e realista é examinado na seção de estudo de caso deste artigo.


Opções de compilador para autovetorização

É possível compilar programas com qualquer um dos seguintes conjuntos de opções:

  1. -qhot -qnostrict (para Fortran)
  2. -qhot -qnostrict -qignerrno (para C/C++)
  3. -qhot -O3
  4. -O4
  5. -O5

Quando se compila um programa usando um desses conjuntos de opções, o compilador automaticamente tenta vetorizar as chamadas às funções matemáticas do sistema chamando as funções de vetor de MASS equivalentes (exceto para chamadas às seguintes funções, que são exceções: vatan2, vsatan2, vdnint, vdint, vcosisin, vscosisin, vqdrt, vsqdrt, vrqdrt, vsrqdrt, vpopcnt4, vpopcnt8, vexp2, vexp2m1, vsexp2, vsexp2m1, vlog2, vlog21p, vslog2 e vslog21p). Se o compilador não conseguir vetorizar o programa, ele automaticamente tentará chamar as funções escalares MASS equivalentes. Para escalação ou vetorização automática, o compilador usa versões das funções de MASS contidas na biblioteca do compilador libxlopt.a. Não é necessário adicionar nenhuma chamada especial às funções de MASS no seu código ou criar um link para a biblioteca xplot.

Além de qualquer um dos conjuntos de opções anteriores, quando a opção -qipa estiver ativa, se o compilador não puder vetorizar, ele tentará processar sequencialmente as funções escalares de MASS antes de decidir chamá-las.

Se quiser desativar a autovetorização, adicione a opção -qhot=novector.


Estudo de caso

A seguir, temos um estudo de caso de um aplicativo real — uma transformação Fourier discreta (DFT) — mostrando as melhorias no desempenho resultantes da compilação com diversas opções de compilador. O aplicativo é simples o suficiente para ser claramente ilustrativo, e ainda assim complexo o bastante para oferecer oportunidades de otimização não triviais.

A sincronização para ambos os programas foi feita com o programa de driver fornecido no Apêndice 3, em um computador POWER6 em execução a 4,704 GHz.

O Apêndice 1 mostra o programa de origem Fortran DFT. Ele contém um loop aninhado que chama exp(), cos() e sin(), seguido por um loop que chama sin() e sqrt(). O programa foi compilado com -O3 (que não faz a autovetorização) e também com -O4 (que faz a autovetorização). Os resultados são mostrados na Figura 1.

Observe que o benefício da autovetorização cresce à medida que o tamanho do problema aumenta, alcançando um fator de melhoria de 8,94x em um tamanho de problema igual a 2000.


Figura 1: Comparação do desempenho de DFT Fortran com as opções de compilação -O3 e -O4, para vários tamanhos de problema.
Graph shows seconds per element vs. problem size.

O Apêndice 2 mostra uma versão C do programa de Fortran DFT no Apêndice 1 (ele contém uma rotina consume() simulada, de forma que a análise interprocessual do compilador [IPA] não consegue ver que o resultado do cálculo não é realmente usado nesse exemplo ilustrativo e, dessa forma, ele otimizará todo o programa).

O programa foi compilado com -O3 (que não oferece a autovetorização), com -O4 (que oferece a autovetorização) e com -O5 (que oferece a autovetorização e também IPA). Os resultados são mostrados na Figura 2.

Como ilustrado no exemplo de Fortran, o benefício da autovetorização cresce à medida que o tamanho do problema cresce, alcançando um fator de 6,00x a n=2000. Além disso, a ativação de IPA a -O5 oferece um aumento de velocidade adicional de 1,22x, visto que pode determinar que as entradas e as saídas não tenham alias (ou seja, não se sobreponham na memória), permitindo a vetorização da chamada para atan2 na conversão para coordenadas polares. O aumento da velocidade de -O5 em relação a -O3 é 7,33x a n=2000.


Figura 2: Comparação do desempenho de DFT C com as opções de compilação -O3, -O4 e O5, para vários tamanhos de problema.
Graph shows seconds per element vs. problem size.

Conclusão

Este artigo ofereceu uma descrição das bibliotecas IBM MASS e dos recursos de autovetorização dos compiladores IBM XL C/C++ e XL Fortran. Além disso, o artigo mostrou o uso de várias opções de compilador em um programa de exemplo (transformação de Fourier discreta), mostrando como acelerações de até 8,94 vezes em relação às velocidades anteriores podem ser obtidas com o uso dos compiladores por meio de chamada automática de MASS pela autovetorização.

Essa demonstração tem o objetivo de incentivar os usuários com programas que chamam funções matemáticas a fazer experiências com as opções de compilador disponíveis, beneficiando-se assim com os aumentos de velocidade resultantes da autovetorização do compilador IBM XL C/C++ ou XL Fortran.


Apêndice 1 – Programa de origem Fortran DFT

  subroutine dft (x, a, phi , n)
    real*8 x(n), a(n), phi(n)
    integer n

    ! Compute discrete Fourier transform of real inputs         
    ! x(i) and convert to polar form.

    real*8, parameter :: pi=3.1415926535897932384d0
    real*8 y_re(n), y_im(n), t, term_re, term_im
    intrinsic exp, cos, sin, sqrt, atan

    y_re(1:n) = 0.d0
    y_im(1:n) = 0.d0
    do k=1,n
      ! compute y(k), k-th DFT output
      do i=1,n
        ! compute i-th term of y(k):
        ! x(k)*exp(-2*pi*I*(k-1)*(i-1)/n)
        ! compute real and imaginary parts of i-th term
        ! using exp(I*t)=exp(t)*(cos(t)+I*sin(t))

        t = -2.d0*pi*(k-1)*(i-1)/n
        term_re = x(i) * cos(t) * exp(t)
        term_im = x(i) * sin(t) * exp(t)

        ! add term to sum
        y_re(k) = y_re(k) + term_re
        y_im(k) = y_im(k) + term_im
      end do
    end do

    ! transform y to polar coordinates
    do k=1,n
      ! compute amplitude of y(k)
      a(k) = sqrt (y_re(k)**2 + y_im(k)**2)
      ! compute phase of y(k)
      phi(k) = atan (y_im(k) / y_re(k))
    end do

  end subroutine

  ! initialize input data
  subroutine init (a, n)
    real*8 a(n)
    integer n
    intrinsic sin,sqrt
    
    do j=1,n
      a(j)=sin(1.d0/sqrt(real(j,8)))
    end do
  end subroutine


Apêndice 2 – Programa de origem C DFT

#include <math.h>
#define PI 3.1415926535897932384
void dft(double x[],double a[],double phi[],int *m)
{
  double y_re[NMAX], y_im[NMAX], t, s, term_re, term_im;
  int i,j,k,n=*m;
  for(i=0;i<n;++i) {
    y_re[i]=y_im[i]=0;
  }
  for(k=0;k<n;++k) 
  {
    // compute y(k), k-th DFT output
    for(i=0;i<n;++i)
    {
      // compute i-th term of y(k):
      // x(k)*exp(-2*pi*I*(k-1)*(i-1)/n)
      // compute real and imaginary parts of i-th term
      // using exp(I*t)=exp(t)*(cos(t)+I*sin(t))

      t=-2.*PI*k*i/(double)n;
      term_re=x[i]*exp(t)*cos(t);
      term_im=x[i]*exp(t)*sin(t);

      // add term to sum
      y_re[k]+=term_re;
      y_im[k]+=term_im;
    }
  }

  // transform y to polar coordinates
  for(k=0;k<n;++k)
  {
    // compute amplitude of y(k)
    a[k]=sqrt(y_re[k]*y_re[k]+y_im[k]*y_im[k]);
    // compute phase of y(k)
    phi[k]=atan2(y_im[k],y_re[k]);
  }
}

// initialize input data
void init(double a[],int *m)
{
  int j,n=*m;
  for(j=0;j<n;++j) 
  {
    a[j]=sin(1./sqrt((double)j+1.0));
  }
}

// Dummy function to use result, preventing compiler from
// optimizing away the computation.
void consume(double a[],double b[],double c[])
{
}


Apêndice 3 – Programa de driver

Aqui, apresentamos o programa de driver Fortran que foi usado para sincronizar os códigos DFT.

  program main
    interface
      subroutine dft(x,a,phi,n)
      real*8 x(n),a(n),phi(n)
      integer n
      end subroutine
      subroutine init(a,n)
      real*8 a(n)
      integer n
      end subroutine
      subroutine consume(a,b,c)
      real*8 a(*),b(*),c(*)
      end subroutine
    end interface

    ! Parameters:
    !   nmax is the problem size.
    !   nrep is the number of repetitions of the
    !        problem. This should be chosen so that
    !        the elapsed time is long enough to give
    !        sufficient timing resolution.
    !   cyc is the clock frequency in Hz for the
    !       processor that the program is to be run on.
    !       (Can be found from AIX command pmcycles.)
    
    integer, parameter :: nmax=1000
    integer, parameter :: nrep=100
    real*8, parameter :: cyc=4704000000.d0

    real*8 x(nmax), a(nmax), phi(nmax)
    real*8 tx, ty, accum, del(4)
    intrinsic sin, sqrt
    real*8 rtc

    del(4)=0.d0
    acc = 0.d0
    do k=1,nrep
      tx=rtc()
      call init(x,nmax)
      call dft(x,a,phi,nmax)
      ty=rtc()
      call consume(x,a,phi)
      do j=1,nmax
        acc = acc + a(j) + phi(j)
      end do
      del(4) = del(4) + (ty-tx)
    end do
    del(1) = del(4)/real(nmax,8)
    del(2) = del(1)/real(nrep,8)
    del(3) = cyc*del(2)
    print *,'acc=',acc/real(nrep,8),' n=',nmax,
 &    ' r=',nrep, ' a=',del(1),' b=',del(2),
 &    ' c=',del(3),' w=',del(4)
  end program


Isenção de Responsabilidade

O desempenho exato obtido pode variar dependendo do modelo de processador usado e de sua configuração, bem como da versão dos compiladores usados. Por isso, é possível que você tenha uma experiência de desempenho diferente da obtida nos experimentos descritos aqui.


Recursos

Aprender

Obter produtos e tecnologias

  • Software de teste IBM: Elabore seu próximo projeto de desenvolvimento com o software disponível para download diretamente do developerWorks.

Discutir

Sobre os autores

Robert Enenkel trabalha no Optimizing Compiler Group no IBM Toronto Laboratory; antes, foi pesquisador no IBM Centre for Advanced Studies (CAS). Enenkel é bacharel, mestre e doutor pela University of Toronto, com tese na área de métodos numéricos paralelos para equações diferenciais. Ele atualmente realiza pesquisas e desenvolvimentos em computação numérica, no que ela está relacionada a compiladores e sistemas operacionais, incluindo aritmética de ponto flutuante, bibliotecas de funções matemáticas e o ajuste de desempenho de algoritmos. Dr. Enenkel recebeu da IBM vários prêmios por inventos e de reconhecimento como autor. Mais informações podem ser encontradas nesta página: https://www-927.ibm.com/ibm/cas/toronto/people/members/renekel.shtml.

Daniel Zabawa trabalha no Optimizing Compiler Group no IBM Toronto Laboratory. Ele é mestre e doutor em ciência da computação pela University of Toronto. Zabawa atualmente realiza pesquisas e desenvolvimento em planejamento e otimização de loop, algoritmos de ponto flutuante para arquiteturas superescalares e ajuste de desempenho de funções matemáticas de ponto flutuante.

Ajuda para Relatar Abuso

Relatar abuso

Obrigado. Esta entrada foi sinalizada para atenção do moderador.


Ajuda para Relatar Abuso

Relatar abuso

Falha no envio do Relatório de abuso. Tente novamente mais tarde.


developerWorks: Registre-se


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Selecione seu nome de exibição

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

(Deve possuir de 3 a 31 caracteres.)


Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Classificar este artigo

Comentários

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Rational
ArticleID=486103
ArticleTitle=Como melhorar o desempenho de programas chamando funções matemáticas
publish-date=09292010
author1-email=enenkel@ca.ibm.com
author1-email-cc=
author2-email=dzabawa@ca.ibm.com
author2-email-cc=

Conheça a IBM da sua cidade

Virtual Branch Office Brasil

A IBM está mais perto do que você imagina!


Tags

Help
Use o campo de pesquisa para encontrar todos os tipos de conteúdo no My developerWorks com essa tag.

Use a barra de rolagem para ver mais ou menos tags.

Tags populares mostra as principais tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Minhas tags mostra suas tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Use o campo de pesquisa para localizar todos os tipos de conteúdo no Meu developerWorks com essa tag. Tags populares mostra as tags principais para essa zona de conteúdo particular (por exemplo, tecnologia Java, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere). Minhas tags mostra as suas tags para essa zona de conteúdo em particular (por exemplo, tecnologia Java, Linux, WebSphere).