You are on page 1of 79

LUIS HENRIQUE ALVES LOURENCO

PROCESSAMENTO PARALELO DE AUDIO EM GPU

CURITIBA 2009

LUIS HENRIQUE ALVES LOURENCO

PROCESSAMENTO PARALELO DE AUDIO EM GPU

Trabalho de Conclus o de Curso apresentado a ` como requisito parcial a obtencao do grau de Bacharel em Ci ncia da Computacao. Proe grama de Graduacao, Setor de Ci ncias Exatas, e Universidade Federal do Paran . a Orientador: Prof. Dr. Luis Carlos Erpen de Bona

CURITIBA 2009

Sum rio a

Lista de Figuras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

vi

Introducao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Programacao Paralela . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 2.2 2.3 2.4 Paralelismo em Nvel de Instrucao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multiprocessadores e Paralelismo em Nvel de Thread . . . . . . . . . . . . . . . . . . . . . . . Paralelismo em Nvel de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compute Unied Device Architecture (CUDA) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.1 2.4.2 2.4.3 Escondendo Processadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gerenciamento de Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4 4 5 6 6 8 9

Hierarquia de Mem ria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 o

Audio Digital . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.1 3.2 3.3 Processamento de Audio Digital . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Compress o de Audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 a O padr o MPEG-1 Layer III . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 a 3.3.1 Banco de Filtros Polif sicos de An lise . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 a a

ii

iii

3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.4

Transformacao Discreta de Cosseno Modicada . . . . . . . . . . . . . . . . . . . . . 17 Modelagem Psicoac stica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 u Quanticacao n o-Uniforme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 a Codicacao de Huffman . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Formatacao da Seq encia de Bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 u

LAME Aint an Mp3 Encoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

Processamento de Audio em GPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4.1 4.2 Modelo de Servidor de Audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Um Servidor de Audio com codicacao em GPU . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 4.2.1 4.2.2 4.3 Detalhes da Implementacao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Codicacao em GPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

Resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

Conclus o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 a

Refer ncias Bibliogr cas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 e a

Anexo A -- CUDA Application Programming Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 A.1 Extens es da Linguagem C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 o A.1.1 Qualicadores de Funcao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 A.1.2 Qualicadores de Vari veis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 a A.1.3 Par metros de Conguracao da Execucao . . . . . . . . . . . . . . . . . . . . . . . . . . 38 a A.1.4 Vari veis Pr -denidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 a e A.1.5 O Compilador NVCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

iv

A.2 Componente de Execucao Comum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 A.2.1 Tipos Pr -denidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 e A.2.2 Funcoes Matem ticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 a A.2.3 Funcoes de Tempo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 A.2.4 Tipo Textura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 A.3 Componente de Execucao em GPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 A.3.1 Funcoes Matem ticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 a A.3.2 Funcao de Sincronizacao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 A.3.3 Funcoes de Textura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 A.3.4 Funcoes At micas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 o A.4 Componente de Execucao em CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 A.4.1 API de Execucao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 A.4.2 API do Driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

Anexo B -- Speaker (servidor) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

Anexo C -- Listener (cliente) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

Anexo D -- lhal04.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

Anexo E -- psyKernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

Lista de Figuras

Figura 2.1 Exemplo de Soma Paralela de um Vetor

................................. ..........

6 8

Figura 2.2 Modelo da Arquitetura NVidia (GeForce 8) [HALFHILL, 2008] Figura 2.3 Hierarquia de Mem ria em CUDA o Figura 3.1 Processo de Codicacao MP3 Figura 3.2 Limiar Absoluto de Audicao Figura 3.3 Mascaramento de Freq encia u Figura 3.4 Quanticacao n o-Uniforme a Figura 4.1 Modelo de Servidor de Audio

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

Resumo

Este trabalho se prop e a demonstrar que o processamento paralelo em Unidades de o Processamento Gr co (GPU, do ingl s, Graphics Processing Unit) pode ser amplamente utilia e zado para o processamento de audio a m de melhorar o desempenho dos algoritmos existentes e permitir que mais dados sejam processados com menor lat ncia. Com isso, pode permite-se e uma melhora sensvel na qualidade do conte do. Esse tipo de abordagem torna-se util de u ` vido as novas tecnologias multimdia, como a TV digital de alta denicao, os conte dos online u (Streamming de audio e vdeo) e a comunicacao atrav s de meios digitais, como o VoIP ou e videoconfer ncia. e

Palavras-chave: Processamento Paralelo, GPU, CUDA, MPEG-1 Layer III, MP3, Servidor de Audio.

vi

Introducao

A producao e o processamento de multimdia no formato digital est o se popularizando a cada vez mais. Isso pode ser percebido na evolucao da ind stria do cinema e dos jogos, no u desenvolvimento da tv digital, nos est dios de gravacao de m sica, na utilizacao dos meios u u digitais para comunicacao, na popularizacao dos aparelhos celulares, reprodutores de vdeo e de m sica, entre outros [PEDDIE, 2001]. u Um dos aspectos fundamentais para os sistemas multimdia e a baixa lat ncia [LAGO, e 2004], especialmente no caso de mdias contnuas como o audio e o vdeo. Esses sistemas exigem baixa lat ncia para um grande volume de dados. Uma abordagem que tem se mostrado e eciente para aplicacoes que necessitam de alta capacidade de processamento ou que processam um grande volume de dados e o processamento paralelo [HENNESSY; PATTERSON, 1990]. A exig ncia do mercado de processadores gr cos resultou na evolucao das Unidae a des de Processamento Gr co (GPU1 ) em um dispositivo altamente paralelo, com suporte a a multithreading2 , com muitos processadores de alto desempenho e com largo barramento do mem ria. O grande desao e desenvolver aplicacoes que permitam usar a capacidade de escao lar em grau de paralelismo e, assim, aproveitar o aumento constante do n mero de n cleos de u u processamento. Devido a sua estrutura altamente paralela as GPUs est o deixando de ser dispositivos a exclusivos para o processamento de aplicacos gr cas, e comecam a ser utilizadas para reali a zar o processamento de aplicacoes de prop sito geral. A Programacao de prop sito geral em o o
1 em 2 Capacidade

ingl s, Graphics Processing Unit e de executar v rios processos simult neamente a a

GPU (GPGPU3 ) tem como objetivo aproveitar todo o poder de processamento das GPUs que atualmente possuem centenas de processadores independentes e diferentes tipos de mem rias. o Os primeiros programas de prop sito geral que aproveitavam o potencial das GPUs foo ram escritos atrav s de APIs4 desenvolvidas exclusivamente para a computacao gr ca, como e e a o caso das bibliotecas gr cas OpenGL5 e Direct3D6 que por muito tempo foram a unica forma a de criar programas capazes de utilizar as GPUs. Por m o modelo de programacao voltado para e aplicacoes gr cas era muito confuso e n o se mostrou ideal a programacao de prop sito geral. a a o Assim foram desenvolvidos modelos de programacao de prop sito geral para permitir que o o hardware das GPUs fosse utilizado. O modelo desenvolvido pela NVidia e o Compute Uni ed Device Architecture (CUDA7 ). O objetivo desse modelo e simplicar a programacao em GPU para que o programador possa se concentrar no paralelismo. Isso e possvel porque a API desenvolvida abstrai o hardware da GPU enquanto bibliotecas na linguagem C simplicam o acesso aos recursos do dispositivo. A ATI desenvolveu um modelo semelhante ao da NVidia, o Close to Metal (CTM) [PEERCY; SEGAL; GERSTMANN, 2006]. O CTM permite que o desenvolvedor acesse o conjunto nativo de instrucoes diretamente e, com isso, tenha mais e xibilidade no desenvolvimento e obtenha o melhor desempenho de seu hardware. Al m dessas, e outras APIs, como a RapidMind8 que implementa abstracoes das GPUs Intel e AMD, foram criadas para possibilitar a programacao de prop sito geral em GPUs. o Este trabalho apresenta o estudo do modelo programacao paralela CUDA e do padr o a MPEG-1 Layer III9 de compress o de audio para demonstrar que o paralelismo das GPUs pode a ser aplicado na criacao e na melhoria de t cnicas que permitam melhorar o desempenho de e sistemas multimdia. O objetivo do trabalho e propor um modelo de Servidor de Audio que permita a implementacao de um Servidor de Audio que utilize o processamento em GPU. E,
ing s, General Purpose computing on Graphic Processing Units e Application Programming Inteface, e o conjunto de rotinas e padr es denidos por um software para o utilizacao de suas funcionalidades 5 http://www.opengl.org/ 6 http://en.wikipedia.org/wiki/Direct3D 7 em ingl s, Compute Unied Device Architecture e 8 www.rapidmind.net 9 O padr o MPEG-1 Layer III tamb m e conhecido como MP3 a e
4 API, 3 em

com isso, possa demonstrar que a implementacao de t cnicas de processamento de audio em e a GPU, especialmente utilizando o modelo CUDA, e vi vel. O captulo 2 introduz conceitos da programacao paralela necess rios para em seguida entender o modelo de programacao CUDA. a O captulo 3 introduz os conceitos do Audio Digital relevantes a este trabalho, apresenta um estudo do padr o MPEG-1 Layer III e faz uma breve apresentacao do codicador LAME. O a captulo 4 apresenta um modelo de Servidor de Audio e uma implementacao baseada no mo delo, que utiliza um codicador de audio implementado em partes em CUDA. Al m disso s o e a analisados os resultados dos testes realizados com o codicador e com o Servidor de Audio implementado. Por m, o captulo 5 conclui o trabalho.

Programacao Paralela

A programacao paralela em geral e relacionada com o aumento de desempenho, uma vez que permite mais de uma execucao simultaneamente. Por m esse aumento de desempenho e est associado ao grau de paralelismo de cada programa, ou seja, a capacidade de cada programa a executar suas instrucoes ou seu c digo ao mesmo tempo. o Neste captulo ser o abordados os tipos de paralelismo para introduzir os conceitos ne a ` cess rios a programacao paralela e, em seguida, um estudo do modelo de programacao CUDA. a Uma revis o da API do modelo CUDA encontra-se no anexo A. a

2.1

Paralelismo em Nvel de Instrucao


Desde 1985, os processadores utilizam a sobreposicao da execucao de instrucoes atrav s e

da t cnica de pipelining para melhorar seu desempenho [HENNESSY; PATTERSON, 1990]. A e esta sobreposicao de execucoes se d o nome de Paralelismo em Nvel de Instrucao. Com isso e a possvel permitir que duas instrucoes seriais sejam executadas de forma paralela, uma vez que nem toda instrucao depende de sua antecessora. A maior limitacao do Paralelismo em Nvel de Instrucao e a depend ncia entre as e instrucoes, isso signica que muitas vezes uma instrucao deve esperar um ou mais est gios at a e que outra instrucao disponibilize o dado necess rio por ela. Aumentar o paralelismo em nvel a de instrucao signica diminuir o nvel de depend ncia entre as intrucoes. e

2.2

Multiprocessadores e Paralelismo em Nvel de Thread


A armacao de que os processadores convencionais est o chegando a seus limites a

fsicos pode ser constatada pela desaceleracao da melhora de desempenho destes processadores e pela reducao da melhora de desempenho trazida pelo paralelismo em nvel de instrucao. Ou seja, a melhora de desempenho dos processadores e cada vez menor e o paralelismo em nvel de instrucao melhora cada vez menos o desempenho desses dispositivos. Com isso, os mul tiprocessadores passam a desempenhar o papel principal na arquitetura de computadores para continuar a melhorar o desempenho dos computadores. Al m disso a tend ncia por tr s dos multiprocessadores e reforcada por outros fatores: e e a

Aumento no interesse em servidores e no desempenho dos servidores; Crescimento no n mero de aplicacoes de processamento intenso de dados; u Melhora no entendimento de como usar os multiprocessadores de uma forma eciente;

Por m, existem dois problemas: a arquitetura de multiprocessadores e um campo exe tenso e diverso que em sua maior parte e novo e com muitas id ias [HENNESSY; PATTERSON, e 1990]. E uma grande abrang ncia implica necessariamente em discutir abordagens que podem e n o permanecer com o tempo. a Uma Thread, ou processo leve, e uma linha de execucao de um programa que possui suas pr prias vari veis de controle como o contador1 e outras estruturas, por m ela compartilha o a e o mesmo c digo e pode compartilhar a mesma regi o de dados com outras threads. O advento o a dos multiprocessadores permite um paralelismo real no qual as threads executam em processadores diferentes simultaneamente ao inv s de alternarem sua execucao no mesmo processador. e N o h depend ncia entre threads, portanto elas podem executar de forma livre umas das outras. a a e
1 Program

Counter (PC)

Figura 2.1: Exemplo de Soma Paralela de um Vetor

2.3

Paralelismo em Nvel de Dados


No Paralelismo em Nvel de Dados os dados s o divididos em partes que s o execu a a

tadas paralelamente em unidades de processamento diferentes. O exemplo mais simples do paralelismo em nvel de dados e o incremento paralelo dos valores de um vetor. Como exempli cado na Figura 2.1, que mostra a aplicacao paralela de uma funcao que soma 4 (representada pelos crculos) ao valor de cada posicao de um vetor. Dessa forma, o tempo de execucao de todas as somas equivale a execucao de uma unica soma, pois todas s o executadas ao mesmo a tempo em unidades de processamento diferentes. As GPUs foram desenvolvidas para utilizar esse tipo de paralelismo e permitir o processamento de grandes quantidades de dados simultaneamente.

2.4

Compute Unied Device Architecture (CUDA)


Com a compra da ATI pela AMD, a NVidia permaneceu como a maior empresa de-

senvolvedora exclusivamente de GPUs. Com isso a concorr ncia pelo mercado de GPUs se e concentrou nos tr s principais desenvolvedores: A Intel, a AMD e a NVidia. Por m, a Intel e e e a AMD, como produtoras de CPUs2 , pretendem integrar n cleos gr cos aos seus procesu a sadores em um futuro breve [HALFHILL, 2008]. Essa integracao pode fazer o mercado de placas gr cas reduzir, pois a venda desse tipo de dispositivo se restringiria a aplicacoes que a
2 Central

Processing Unit em ingl s, ou Unidade Central de Processamento e

necessitam de um desempenho gr co realmente alto. Por outro lado, j existem placas gr cas a a a vendidas integradas ao computador, portanto as conseq encias da integracao de n cleos gr cos u u a ` as CPUs n o deve ser t o graves. a a Com isso a NVidia encontrou na GPGPU3 uma forma de se diferenciar no mercado e aproveitar ainda mais a capacidade de processamento de suas GPUs. Por m os modelos de e programacao GPGPU existentes eram muito complexos. Esses modelos haviam sido criados para o processamento gr co (OpenGL e Direct3D). E mapear um problema de prop sito geral a o para o domnio gr co nem sempre e uma tarefa simples. Al m disso, o resultado nal de a e pende do mapeamento escolhido. Portanto, os modelos existentes se mostraram invi veis para a a programacao GPGPU. Assim, a NVidia aproveitou a oportunidade de criar um novo modelo de programacao GPGPU. E ent o surgiu o CUDA. a CUDA, em ingl s, Compute Unied Device Architecture, e a API que implementa o e novo modelo de programacao GPGPU desenvolvido pela NVidia. Seu objetivo e proporcionar um ambiente de programacao simples, por isso CUDA implementa um mecanismo de abstracao do hardware da GPU atrav s de bibliotecas de funcoes nas linguagens C/C++. CUDA permite e que o programador mantenha o foco na programacao paralela, pois n o requer o gerenciamento a convencional de threads, esse gerenciamento e abstrado pela API. Al m disso, a API per e mite que programas desenvolvidos em CUDA n o deixem de funcionar devido a atualizacao do a harware [NVIDIA, 2008]. CUDA e uma solucao para o paralelismo real em nvel de thread com alto n mero de processadores que possui uma arquitetura amplamente difundida. Al m u e disso a GPU e especialmente adequada para resolver problemas que podem ser expressados por computacao de dados paralela (ou seja, o mesmo programa e executado em v rios elementos de a dado paralelamente - paralelismo em nvel de dados) com alta intensidade aritm tica (taxa de e operacoes aritm ticas em relacao a taxa de operacoes de mem ria). Como o mesmo programa e e o executado para cada elemento de dado, a necessidade de uxos de controle sosticados e baixa. Portanto, o modelo de programacao CUDA se mostra adequado para utilizar de forma eciente
de Prop sito Geral em Unidades de Processamento Gr co (GPU), em ingl s, General Propose o a e computing on Graphics Processing Units
3 Programacao

Figura 2.2: Modelo da Arquitetura NVidia (GeForce 8) [HALFHILL, 2008] o paralelismo das GPUs.

2.4.1

Escondendo Processadores
NVidia sempre escondeu a arquitetura de suas GPUs atrav s de uma API. Como resule

tado disso, os programas n o acessam o hardware diretamente. Ao inv s disso, as funcoes que a e manipulam diretamente o hardware est o implementadas na API. a A gura 2.2 mostra um modelo da arquitetura GPU que serviu como base para o modelo da API de programacao em CUDA. As threads s o executadas nos processadores de thre a ads4 e gerenciadas pela pr pria arquitetura de forma transparente ao usu rio. Funcoes CUDA, o a chamadas de kernel5 , s o executadas em paralelo6 por um conjunto de processadores de threa ads e possuem acesso a alguns tipos de mem ria, incluindo a mem ria principal da GPU e uma o o mem ria compartilhada entre conjuntos de processadores. Al m disso, CUDA permite uma o e programacao heterog nea, ou seja, a programacao pode ser dividida entre a CPU e a GPU de e forma que o c digo C serial seja executado em CPU, enquanto kernels paralelos em CUDA o executam em GPU.
ingl s, Thread Processors. Tamb m s o conhecidos por Stream Processors. Na arquitetura de GPU eram e e a conhecidos como Shaders 5 Um Kernel consiste em uma funcao CUDA que cont m o c digo que ser executado em GPU e o a 6 Paralelismo em nvel de Thread [HENNESSY; PATTERSON, 1990]
4 do

2.4.2

Gerenciamento de Threads
As threads em CUDA s o identicadas por blocos, ou seja, cada bloco possui um cona

junto de threads que executam o mesmo trecho de c digo de forma independente entre si. Os o blocos de threads podem ser unidimensionais, bidimensionais ou tridimensionais. As threads ` de um mesmo bloco podem cooperar, pois t m acesso a mesma mem ria compartilhada. Al m e o e disso, existem funcoes denidas na biblioteca CUDA que implementam barreiras [SILBERS CHATZ; GALVIN, 2000] para sincronizar a execucao das threads. O n mero de threads por u bloco e limitado pelos recursos de mem ria. o Os blocos de um kernel em CUDA s o identicados por grids, que podem ser unia dimensionais ou bidimensionais. As threads de cada bloco em um grid executam de forma independente das threads dos outros blocos. A arquitetura Tesla [NVIDIA, 2008] implementada nas placas NVidia mais recentes e baseada em um vetor de multiprocessadores7 . Quando um programa CUDA executando em CPU chama o grid de um kernel, os blocos do grid s o ordenados e distribudos aos multiprocesa sadores da GPU. As threads de um bloco executam concorrentemente em um multiprocessador. Ao terminar a execucao de um bloco, novos blocos s o lancados para ocupar os multiprocessa a dores vagos. Na arquitetura Tesla, um multiprocessador consiste em 8 n cleos de processamento u escalar8 . O multiprocessador cria, gerencia e executa threads concorrentes em hardware sem overhead de escalonamento. Ele tamb m implementa barreiras de sincronizacao com uma unica e instrucao. Para gerenciar centenas de threads executando diferentes programas, o multiprocessador implementa um novo tipo de arquitetura chamada de SIMT (Single Intruction, Multiple Thread). O multiprocessador mapeia cada thread para um n cleo de processamento. E cada u thread executa de forma independente com seu pr prio endereco de instrucao e registradores. o
7 em 8 em

ingl s, Streaming Multiprocessors e ingl s, Scalar Processor e

10

O SIMT cria, gerencia e executa threads em grupos de at 32 threads paralelas, chamadas e warps. As threads que comp e um warp iniciam juntas no mesmo endereco, mas s o livres o a para executar independentemente. Quando um multiprocessador recebe conjunto de um ou mais blocos para executar, ele o divide em warps que ser o escalonados pelo SIMT. A cada instrucao, o SIMT seleciona um a warp que est pronto para executar e passa para a pr xima instrucao nas threads ativas. Um a o warp executa uma instrucao comum por vez, assim, quando todas as threads est o executando a juntas, isto e, de forma semelhante, o warp e executado com maior eci ncia. e

2.4.3

Hierarquia de Mem ria o


` De forma semelhante a arquitetura do SIMT, que ger ncia as threads, o multiprocese

sador implementa o SIMD (Single Instruction, Multiple Data), que com uma instrucao simples controla o processamento de v rios elementos. a Como ilustrado na gura 2.3, cada thread pode acessar 4 tipos de mem ria. Cada o thread possui uma mem ria local privada e um conjunto de registradores de 32 bits. Cada bloco o de threads possui uma mem ria compartilhada9 visvel a todas as threads do bloco. Todas as o ` threads do dispositivo possuem acesso a mesma mem ria global10 , que e a mem ria principal o o da GPU. E existem tamb m as mem rias de Constante11 e de Textura12 que s o acessveis a e o a todas as threads. S o mem rias somente-leitura otimizadas utilizadas para a entrada de dados a o ` externos ao dispositivo o que permite o acesso indireto a mem ria RAM da m quina13 . o a Um programa pode manipular as mem rias global, de contante e de textura atrav s da o e biblioteca CUDA. Isso inclui alocacao de mem ria, liberacao de mem ria alocada, assim como o o a transfer ncia entre a mem ria do computador e do dispositivo. e o O n mero de blocos que um multiprocessador comporta depende de quantos regisu
10 em

memory ingl s, Device Memory e 11 Constant memory 12 Texture memory 13 Host Memory

9 Shared

11

Figura 2.3: Hierarquia de Mem ria em CUDA o tradores por thread e quanta mem ria compartilhada por bloco s o necess rios para um dado o a a kernel. Se n o houver registradores ou mem ria compartilhada suciente por multiprocessador a o para processar pelo menos um bloco, o kernel ir falhar. a Se uma instrucao executada por um warp escreve na mesma posicao de mem ria para o mais de uma thread do warp, a ordem que as escritas ocorrem e indenida.

12

Audio Digital

Um sinal anal gico de audio e um sinal el trico que representa as vibracoes mec nicas o e a do ar. Tais sinais possuem duas dimens es que representam a press o do ar variando de acordo o a com o tempo. Os sistemas anal gicos, utilizam a voltagem do sinal el trica para representar a o e variacao da press o do ar. Por m os sistemas anal gicos s o bastante vulner veis a distorcoes a e o a a de sinal [WATKINSON, 2001]. O audio digital e simplesmente um meio alternativo de transportatr um sinal de audio. Embora existam v rias maneiras de implementar isso, h um sistema conhecido por Pulse Code a a Modulation (PCM [POHLMANN, 2000]), que e amplamente utilizado. No sistema PCM, o tempo e representado de forma discreta. Dessa forma, o sinal de audio n o e composto por uma a representacao contnua, mas por medidas em intervalos regulares. Este processo e chamado de amostragem e a freq encia cujas amostras s o medidas e chamado de taxa de amostragem. u a Cada amostra ainda varia innitamente como o sinal original, por m, assim como o tempo, e sua representacao e um valor discreto. E para completar a convers o para o formato PCM, a cada amostra e representada por um valor discreto em um processo chamado quantizacao. Esse processo consiste em representar a press o do audio no instante da captura em um valor de a amostra. Al m de n o ser t o vulner vel a distorcoes, a representacao de audio em formato digie a a a tal ofecere v rias vantagens [PAN, 1993], como a reprodutibilidade, e ainda permite a aplicacao a de implementacoes ecientes para v rias funcoes de processamento de audio. a

13

3.1

Processamento de Audio Digital


O processamento de audio digital1 e empregado na gravacao e armazenamento de

audio, para mixagem de sons e producao de programas de tv, assim como em produtos co merciais como CDs. O audio digital e, de uma forma digital, todo o caminho do microfone at e os alto-falantes, onde procesadores de sinais digitais ecientes permitem o processamento em tempo-real. Atrav s do processamento de audio e possvel modelar o conjunto de amostras de e audio de forma a se obter os efeitos desejados. Com o processamento de audio e possvel obter [ROADS et al., 1996]:

Manipulacao a din mica da amplitude do som; a Mixagem para combinar v rias faixas de audio; a Filtros e equalizadores para modicar o espectro de freq encia de um som; u Efeitos de atraso (time-delay); Convolucao, transformacoes simult neas nos domnios do tempo e da freq encia; a u Projecao espacial, incluindo reverberacao; Reducao de rudo.

3.2

Compress o de Audio a
A Compress o de Audio Digital utiliza de t cnicas de processamento de audio para a e

permitir o armazenamento e a transmiss o de informacao de audio de forma eciente [PAN, a 1993]. Otimizar o processo de compress o de audio permite aumentar a variedade de aplicacoes a para o audio digital. Isso inclui os dispositivos de m sica port teis; o audio para cinema; r dio u a a e televis o digital de alta qualidade; aparelhos de DVD e muito mais [CAVAGNOLO; BIER, ]. a
1 Processamento

de Sinais de Audio Digital

14

As t cnicas de compress o de audio diferem pela complexidade de seus algoritmos, e a pela qualidade da compress o do audio e pela quantidade de dados comprimidos. T cnicas a e simples como a transformacao -law2 [PAN, 1993] e a modulacao diferencial adaptaviva por c digos de pulsos (ADPCM3 ) [PAN, 1993] podem ser facilmente implementados para processar o audio em tempo-real. O desao e desenvolver uma implementacao em tempo-real para o padr o a de audio MPEG-1 layer III [PAN, 1995]. As pr ximas secoes explicam alguns dos conceitos o mais importantes do padr o MPEG-1 Layer III. a

3.3

O padr o MPEG-1 Layer III a


O MPEG, Motion Pictures Experts Group, e o grupo formado pela ISO4 para denir

padr es de compress o e transmiss o de audio e vdeo. Os padr es MPEG cobrem diferentes o a a o aspectos. Dentre eles, o padr o MPEG-1, foi o primeiro a denir a codicacao do audio. a O padr o MPEG-1 de audio efetua a compress o do audio baseado nas limitacoes a a fsicas da audicao humana. O ouvido humano e capaz de detectar sons em uma faixa de freq encia que varia de 20Hz a 20KHz. De forma que, n o faz sentido armazenar todos os u a dados referentes a freq encias fora dessa faixa. Al m disso, dentro da faixa de freq encias u e u ` audveis, a percepcao da audicao humana obedece a uma curva (Figura 3.2) onde a percepcao da intensidade de um som varia com a freq encia. E, por m, o ouvido humano n o consegue u a captar todos os sons simultaneamente, o que e conhecido como efeito de mascaramento de sons, onde alguns sons s o escondidos por outros mais fortes. Ou seja, o padr o MPEG-1 de audio a a se utiliza das limitacoes da percepcao da audicao humana para eliminar informacoes de audio sem causar alteracoes perceptveis, sendo por isso conhecido tamb m como um algoritmo de e codicacao perceptiva. No padr o MPEG-1 Layer III, o audio capturado no formato PCM passa por um banco a de ltros que decomp e 1152 amostras5 PCM do audio em 32 sub-bandas de freq encias de o u
2 http://en.wikipedia.org/wiki/M-law 3 Adaptative

algorithm Differential Pulse-Code Modulation 4 International Organization for Standardization 5 Um quadro MP3 e composto de 1152 amostras PCM

15
Sinal Digital de udio(PCM)
Banco de Filtros MDCT Quantificao no-Uniforme Controle de Distoro Controle de Taxa Codificao de Huffman

Sinal de udio Codificado


Formatao da Seqncia de Bits

FFT

Modelagem Psicoacstica

Figura 3.1: Processo de Codicacao MP3 mesma largura. Ap s esse processo, a Transformada Discreta de Cosseno Modicada [PRINo CEN; BRADLEY, 1986] (MDCT6 ) e aplicada a cada amostra de cada sub-banda. Com isso, as sub-bandas, que pertencem ao domnio do tempo, ser o mapeadas para o domnio da freq encia. a u Enquanto isso, aplica-se a Transformada R pida de Fourier [DUHAMEL; VETTERLI, 1990] a (FFT7 ) nas amostras originais para revelar seu espectro sonoro. O espectro, por sua vez, passa pela modelagem psicoac stica que determina a taxa de energia8 do sinal para o limiar de masu caramento de cada sub-banda, que ser utilizada na fase de quanticacao. O bloco de controle a de distorcao utiliza as taxas da relacao sinal / mascaramento (SMR9 ) do modelo psicoac stico u para decidir quantos bits disponibilizar para a quanticacao dos sinais das sub-bandas para re duzir o rudo de quanticacao. Em seguida as amostras quanticadas passam pela codicacao de Huffman [HUFFMAN, 1952] para reduzir a entropia das amostras. Por m, as amostras codicadas e suas informacoes s o empacotadas. As subsecoes a seguir descrevem os detalhes a das principais operacoes realizadas. O processo descrito acima est ilustrado na Figura 3.1. a

3.3.1

Banco de Filtros Polif sicos de An lise a a


O primeiro passo do processo de codicacao e a passagem do sinal de audio PCM por

um banco de ltros. O Banco de Filtros Polif sicos de An lise tem como objetivo decompor o a a sinal em 32 sub-bandas. Essa decomposicao agrupa as amostras de sub-banda da mesma forma
Discret Cosine Transform Fourier Transform 8 Nvel de press o do ar determinada pelo sinal, em decib is (dB) a e 9 Signal-to-Mask Ratio
7 Fast 6 Modied

16

que no sinal original, por m pode causar algumas distorcoes10 . e A seq encia de 1152 amostras PCM de audio de um quadro MP3 s o ltradas de u a maneira que cada sub-banda possua 36 amostras. O resultado do banco de ltros e denida pela seguinte equacao:

63

S[i] =

k=0 j=0

M[i][k] (C[k + 64 j] X[k + 64 j])

Onde i e o ndice de cada uma das 32 sub-bandas; S[i] e a amostra resultante para a sub-banda i e tempo11 t; C[n] e um dos 512 coecientes da janela de an lise denida pelo padr o [PRINCEN; a a BRADLEY, 1986]; X[n] e uma amostra de audio de um buffer de amostras de 512 posicoes; M[i][k] e a matriz de coecientes da an lise que e denido pela equacao: a

M[i][k] = cos[

(2 i + 1) (k 16) ] 64

Esse conjunto de equacoes est otimizado para reduzir o n mero de c lculos. Para a u a melhorar o entendimento desse c lculo, essas equacoes podem ser simplicadas na seguinte a equacao de convolucao:

511

St[i] =

n=0

X[t n] Hi[n]

Onde X[t] representa uma amostra de audio no tempo t. H[i] que e denido pela equacao H[i] = h[i] cos[ (2i+1)(n16) ], representa o ltro respons vel por decompor o audio a 64 em sub-bandas de freq encia adequadas, por isso e chamado de ltro polif sico. E, por m, u a h[n] e denido por C[n] se o resultado de n/64 for mpar, caso contr rio h[n] = C[n]. a
10 Aliasing 11 O

[VAIDYANATHAN, 1987] tempo t e representado por um inteiro m ltiplo de 32 intervalos de amostra u

17

3.3.2

Transformacao Discreta de Cosseno Modicada


Nesse processo, as amostras das 32 sub-bandas recebidas do banco de ltros s o maa

peadas em uma transformacao discreta de cosseno modicada (MDCT). Como resultado, as amotras, que pertencem ao domnio do tempo, ser o mapeadas no domnio da freq encia. a u ` Antes de computar a MDCT, quatro funcoes janela12 s o aplicadas as amostras. Funcoes a janela, s o funcoes utilizadas em processamento de sinais para melhorar a eci ncia da an lise a e a do espectro de onda (espectro sonoro no caso do processamento de audio). O padr o MPEG-1 a Layer III especica dois tamanhos de blocos MDCT: o bloco longo de 18 amostras e o bloco curto de 6 amostras. H 50% de sobreposicao entre sucessivas janelas de transformadas uma a vez que o tamanho da janela e 36 ou 12 respectivamente. Da mesma forma, dependendo da din mica de cada sub-banda s o usadas janelas longas ou curtas. Se as amostras de uma dada a a sub-banda se comportam de forma estacion ria, a janela regular, longa, e usada. Se as amostras a s o transit rias, a janela curta e aplicada para subdividir o resultado da sub-banda em freq encia a o u e intensicar a resolucao de tempo. Este mecanismo ajuda a evitar o aparecimento do fen meno o de pr -eco13 , o que pode acontecer quando aplicamos a FFT sobre um conjunto de amostras. e O efeito de pr -eco ocorre quando h uma demanda muito alta de bits em um curto espaco de e a tempo (por exemplo, um momento de sil ncio seguido de um ataque abrupto), e com isso o e rudo de quantizacao exagerado de um determinado trecho de audio e espalhado para instantes ` anteriores a sua ocorr ncia causando um rudo audvel no sinal codicado, nos instantes anterie ` ores a ocorr ncia do ataque. As outras duas janelas utilizadas para manipular as transicoes de e longo para curto ou de curto para longo s o chamadas de janela de incio e janela de parada, a respectivamente. O bloco curto e um terco do bloco longo, de forma que tr s blocos curtos e substituem um bloco longo. O n mero de amostras de um quadro de amostras n o e alterado u a pela tamanho do bloco. Para um dado quadro de amostras, a MDCT possui 3 modos de blocos, 2 modos com o mesmo tamanho de blocos (longos ou curtos) e um modo misto, onde as duas sub-bandas de mais baixa freq encia usam blocos de longos e as 30 sub-bandas de mais u
12 http://en.wikipedia.org/wiki/Window

function echo

13 http://wiki.hydrogenaudio.org/index.php?title=Pre

18

alta freq encia utilizam blocos curtos. Assim e possvel fornecer melhor resolucao para as u freq encias mais baixas, sem sacricar as resolucao de tempo para as freq encias mais altas. u u

3.3.3

Modelagem Psicoacustica
A modelagem psicoac stica e o componente chave para o desempenho do codicador. u

Com ela e possvel simular a percepcao do som pelo sistema auditivo humano. Na codicacao, a modelagem psicoac stica decide quais partes s o acusticamente irrelevantes e quais n o s o, u a a a e remove as partes inaudveis. Para isso, ela se aproveita da falta habilidade do sistema au ditivo humano em ouvir sons quanticados sobre um mascaramento. O mascaramento e uma propriedade do sistema auditivo humano que ocorre quando um sinal de audio forte se encontra pr ximo de um sinal de audio mais fraco no espectro ou no tempo, tornando o sinal de audio o mais fraco imperceptvel. O limiar absoluto de audicao14 consiste na quantidade mnima de energia necess ria a para um tom puro ser detectado em um ambiente silencioso. Se a energia de um n mero de tons u de freq encia for medida, obt m-se o gr co da gura 3.2. Isso signica que todos os valores u e a abaixo da linha do gr co n o podem ser detectados. a a O mascaramento de freq encia e um fen meno que torna um sinal de baixa freq encia u o u inaudvel pela ocorr ncia simult nea de um sinal mais forte em uma freq encia sucientemente e a u pr xima. O limiar do mascaramento de freq encia pode ser medido e qualquer sinal abaixo o u dele n o ser audvel, como demonstra o gr co da Figura 3.3. O limiar depende da intensidade a a a sonora e da freq encia da m scara. Com isso e possvel intensicar o rudo de quanticacao de u a uma sub-banda o que signica que menos bits ser o neces rios para representar o sinal nessa a a sub-banda. Al m do mascaramento no domnio da freq encia, tamb m existe o mascaramento e u e temporal. Isso acontece quando dois sons aparecem em um intervalo muito pequeno de tempo. O som mais forte pode mascarar o mais fraco. Os efeitos do mascaramento temporal aconte14 Absotute

Threshold of Hearing(ATH)

19

Figura 3.2: Limiar Absoluto de Audicao cem antes e depois de um som forte. Um som pode sofrer de p s-mascaramento, quando isso o acontece ap s um som mais forte, ou pr -mascaramento, quando o som mais forte ocorre logo o e em seguida. O pr -mascaramento pode prevenir a ocorr ncia de pr -eco. e e e

3.3.4

Quanticacao n o-Uniforme a
O bloco de Quanticacao n o-Uniforme recebe o resultado da MDCT, uma janela de a

mudanca e informacoes de mascaramento da modelagem psicoac stica para efetuar a quanticacao. u O resultado e um dado codicado de acordo com as limitacoes da audicao humana. A Quanticacao n o-Uniforme e a parte que mais consome tempo no algoritmo de codicacao. Ela e dividida em a tr s nveis: A execucao do bloco de Quanticacao n o-Uniforme que executa o loop externo, e a respons vel pela an lise da distorcao, que, por sua vez, executa o loop interno que e respons vel a a a pela quanticacao e codicacao. Como demonstrado na Figura 3.4, as amostras das sub-bandas s o quanticadas em um a processo iterativo. O loop interno quantica a entrada e incrementa o passo do quanticador at e que os dados possam ser codicados com um certo n mero de bits. Ap s a execucao do loop u o

20

Nvel de Presso do Ar

Mscara

Limiar de audio modificado

Freqncia

Sinal no Mascarado

Sinais Mascarados

Limiar de Audio

Figura 3.3: Mascaramento de Freq encia u interno, o loop externo faz a vericacao de cada fator de escala da sub-banda, se a distorcao permitida for excedida, o fator de escala e incrementado e o loop interno e executado novamente. O loop externo, tamb m conhecido como loop de controle de distorcao, controla o e rudo produzido pela quanticacao no loop interno. O rudo e eliminado pela multiplicacao das amostras por um fator de escala. O loop externo e executado at que o rudo permaneca abaixo e do limiar de mascaramento para cada fator de escala da sub-banda. O loop interno, ou loop de controle de taxa, realiza a quanticacao do audio no domnio da freq encia e o prepara a operacao de formatacao. A tabela do c digo de Huffman atriu o bui palavras menores aos menores valores quanticados. O n mero total de bits resultados da u codicacao pode exceder o n mero de bits disponveis em um quadro, isso pode ser corrigido u ajustando o ganho global para resultar em um passo de quanticacao maior e, conseq ente u mente, um valor quanticado menor. Essa operacao e repetida com diferentes tamanhos de passos de quanticacao at que o n mero de bits necess rios pela codicacao de Huffman seja e u a sucientemente pequeno.

21

Loop Externo
Ajusta o fator de escala e volta ao loop interno, Repete enquanto o rudo da quantificao no for aceitvel Amostras de Sub-banda

Loop Interno Compara o rudo de Ajusta o ganho at que o valor quantificao de cada quantificado seja menor que o sub-banda com o limiar bitrate udio de mascaramento Codifica- bitrate QuantiCodificado S S o de ficao Huffman
Ajuste Global de Ganho Ajuste do Fator de escala

Figura 3.4: Quanticacao n o-Uniforme a

3.3.5

Codicacao de Huffman
Dependendo da implementacao, a codicacao de Huffman baseada em 32 tabelas

est ticas de Huffman e efetuada durante ou ap s a quanticacao. A codicacao de Huffman a o fornece uma compress o sem perda de dados, portanto e capaz de reduzir o tamanho sem perda a de qualidade. Na Codicacao de Huffman a entropia e baseada na distribuicao estatstica de um grupo de valores. Uma tabela de substituicao cobrindo todos os valores e estabelecida a partir dos dados estatsticos. Nessa tabela, os valores com maiores possibilidades de aparecerem nos dados s o associados a uma palavra menor e dados que raramente aparecem s o associados a a a palavras maiores. Entretanto, a codicacao de Huffman e um c digo de tamanho vari vel e o a portanto a construcao da tabela de c digos n o e uma tarefa trivial. As amostras s o ordenadas o a a pela freq encia e ent o divididas em tr s faixas distintas. Isso permite que cada faixa seja cou a e dicada com um conjunto diferente de tabelas especcamente ajustadas para as estatsticas de cada faixa.

3.3.6

e Formatacao da Sequ ncia de Bits


A ultima parte da codicacao consiste na producao da seq encia de bits compatvel u

com o padr o MPEG-1 Layer III. A seq encia de bits e particionada em quadros que represena u

22

tam 1152 amostras PCM. O cabecalho descreve a taxa de bits e a freq encia de amostragem u usadas para o audio codicado. Informacoes como tipo de bloco, tabelas de huffman, ganho de sub-banda e fatores de sub-banda s o selecionados. Uma t cnica utilizada para ajustar a a e variacao do tempo de codicacao e a utilizacao de um reservat rio de bits. O codicador pode o doar alguns bits quando ele precisa de menos do que a m dia de bits necess ria para codicar e a um quadro. Em seguida, quando o codicador precisar de mais bits, ele pode emprestar do reservat rio. O codicador pode emprestar apenas bits doados de quadros passados, n o pode o a emprestar de quadros futuros.

3.4

LAME Aint an Mp3 Encoder


Considerado um dos melhores, se n o o melhor, codicador MP3, o LAME 15 (acr nimo a o

recursivo de LAME Aint an Mp3 Encoder) iniciou em 1998 como um projeto open source que visava melhorar o modelo psicoac stico, a eliminacao de rudo e o desempenho do codicador u dist1016 da ISO, que e a implementacao do padr o MPEG-1 Layer III. Portanto, a princpio, a o LAME n o era tecnicamente um codicador (por isso o seu nome), apenas uma tentativa de a melhorar o codicador da ISO. Para evitar problemas legais, o LAME foi desenvolvido sob uma licensa aberta (a LGPL) ao contr rio do c digo da ISO e da patente da organizacao de a o pesquisa alem Fraunhofer-Gesellschaft17 , que desenvolveu o algoritmo de compress o MP3. a a Em 1999, o projeto apresentou seu pr prio modelo psicoac stico, chamado de GPSYCHO, que o u tem como objetivo melhorar o modelo da ISO. Finalmente, em Maio de 2000, todo o c digo o da ISO havia sido reescrito e o LAME surgiu com seu pr prio codicador desenvolvido pela o equipe de programadores open source por tr s do projeto LAME. a

15 lame.sourceforge.net 16 padr o a

ISO 11172-3

17 http://www.fraunhofer.de

23

Processamento de Audio em GPU

E possvel melhorar a eci ncia das t cnicas de processamento de audio, como a com e e press o de audio digital, atrav s do desenvolvimento do hardware, do desenvolvimento de novas a e t cnicas de processamento de sinais ou de melhorias nas t cnicas existentes. Nesse sentido a e e programacao de prop sito geral em GPU pode ser vista como um meio para tornar algoritmos o de processamento de audio digital mais ecientes atrav s do paralelismo desses dispositivos. e Dessa forma o hardware das GPUs pode ser usado para incrementar o desempenho dos algo ritmos apenas com algumas modicacoes nas t cnicas de processamento de audio existentes e e sem a necessidade de desenvolver novas t cnicas de processamento de sinais. e Neste trabalho propomos a implementacao de Servidor de Audio que utiliza a programacao paralela em GPUs do modelo CUDA para melhorar o desempenho do processamento do audio. Para demonstrar que essa abordagem e possvel, as pr ximas secoes deste captulo descrevem o um modelo de servidor de audio que captura o audio de um microfone, processa o audio e transmite o audio processado a um cliente que, ap s conectado ao servidor, recebe o audio, o realiza um novo processamento, se necess rio, e reproduz o audio. Tamb m e descrita a a e implementacao de um servidor de audio baseado nesse modelo. O processamento de audio realizado por essa imlpementacao e a codicacao do audio capturado. Para melhorar o de sempenho da codicacao, o codicador foi modicado a m de ter sua execucao paralelizada atrav s da implementacao de funcoes em CUDA. e

24

4.1

Modelo de Servidor de Audio


Este trabalho comecou como um estudo do modelo CUDA de programacao paralela em

GPU e uma an lise das possveis aplicacoes para tal tecnologia. Entre as possveis aplicacoes a para o processamento paralelo em GPU citadas est o: algoritmos gen ticos, criptograa [MAa e NAVSKI., 2007], compactacao, processamento de imagens, processamento de audio, reconhe cimento de fala [CHONG et al., 2008] e VoIP. Por m, foi decidido que este trabalho deveria desenvolver um modelo de Servidor de Audio e aplicar o processamento em GPU. Dessa forma, foi possvel unir as propostas de trabalhar com redes de computadores, processamento paralelo em GPU e processamento de audio. O modelo proposto consiste em um servidor que captura o sinal anal gico do audio o de um microfone e converte-o para o formato digital atrav s de uma biblioteca de audio, repree sentada na Figura 4.1 pela Captura de Audio. Ap s a captura, o audio, j no formato digital, e o a processado utilizando uma t cnica de processamento de audio implementado em CUDA. Essa e etapa corresponde ao Processamento de Audio na Figura 4.1. Em seguida, o audio processado e enviado para um cliente atrav s de um protocolo de rede. Essa comunicacao entre o servidor e e o cliente est representada na Figura 4.1 pela Transfer ncia do Audio Processado. O cliente, a e ent o, recebe os dados do servidor e realiza um novo processamento, caso seja necess rio. E, a a por m, o audio digital e convertido em um sinal anal gico para ser executado pelas caixas de o som do cliente. Essa acao e representada na Figura 4.1 pela Reproducao do Audio. Esse modelo de Servidor de Audio serve como base para demonstrar a utilizacao do modelo CUDA de programacao paralela em GPU para realizar o processamento de audio. E dessa forma mostrar que a programacao paralela em GPU pode ser utilizada como um meio de melhorar o desempenho de t cnicas de processamento de audio existentes, como por exemplo, e a codicacao de audio.

25

Processamento do udio

Envio Processado

Processamento do udio

Figura 4.1: Modelo de Servidor de Audio

4.2

Um Servidor de Audio com codicacao em GPU


A primeira implementacao do modelo desenvolveu um Servidor de Audio que utiliza

a biblioteca ALSA1 para capturar o sinal anal gico de audio do microfone e convert -lo no o e formato PCM de 16 bits little-endian sinalizado; ou seja, cada amostra de audio possui valores entre -32768 e 32767; em apenas um canal (mono); com taxa de amostragem de 44100Hz, isso signica que s o capturadas 44100 amostras de audio por segundo. E, al m disso, o Servidor a e de audio possui um socket2 congurado com o protocolo UDP [POSTEL, 1980] para enviar os dados do audio para um cliente. Foi implementado tamb m um cliente que se conecta ao e servidor atrav s do mesmo protocolo de rede, recebe o audio do servidor e reproduz o audio e digital utilizando o ALSA. O algoritmo do servidor consiste em capturar e enviar o audio para o cliente, esses procedimentos s o executados repetidamente nessa ordem de at que a execucao a e do servidor seja interrompida pelo usu rio. Da mesma forma o cliente recebe e reproduz o audio a do servidor, esses procedimentos tamb m s o executados nessa ordem at que o servidor pare e a e
1 Advanced

Linux Sound Architecture socket

2 http://en.wikipedia.org/wiki/Internet

26

de enviar mais dados, pois a funcao de recebimento de dados do cliente e bloqueante. Com essa implementacao e possvel capturar o audio em formato digital e reproduz-lo em outra m quina. a Por m essa implementacao n o representava o modelo proposto, pois n o realizava nee a a nhum processamento de audio entre a captura e a reproducao do audio. Para que a implementacao correspondesse ao modelo era necess rio a implementacao alguma t cnica para processar o a e audio do Servidor de Audio implementado. Depois de analisar algumas alternativas, como a criptograa do audio, foi decidido que o processamento seria uma codicacao do audio cap turado. Dessa forma, foi possvel reduzir a quantidade de dados enviados para o cliente e, portanto, melhorar a qualidade do audio capturado sem aumentar o tempo de envio do audio para o cliente. Ent o, foram pesquisados alguns codicadores de audio, entre eles o Speex3 , que e um a codicador de audio especializado em fala4 . Por m o codicador escolhido foi o LAME. Pois, e dessa forma, foi possvel aproveitar a documentacao do concurso da NVidia de implementacao do codicador LAME em CUDA5 . Na p gina do concurso, a NVidia disponibiliza uma vers o a a pr -modicada da vers o 3.97 do LAME que foi utilizada como base para o codicador deste e a trabalho. O codicador LAME recebe o audio em formato digital, realiza a eliminacao das partes inaudveis pelo ouvido humano e comprime o audio restante gerando dados no formato MP3. Com isso, a API da biblioteca do codicador LAME foi utilizada para implementar a codicacao do Servidor de Audio que codica os dados capturados pelo microfone com a nalidade de diminuir o tempo de envio. Enquando a implementacao do LAME em CUDA tem o objetivo de reduzir o tempo da compress o dos dados. a
3 http://speex.org/ 4 em

ingl s, speech codec e

5 http://cudacontest.nvidia.com/index.cfm?action=contest.contest&contestid=2

27

4.2.1

Detalhes da Implementacao
O cliente e o servidor foram implementados na linguagem C e para as modicacoes

do c digo da biblioteca LAME foram utilizados C e CUDA. A primeira coisa a ser feita em um o ciclo e a conguracao do LAME. A cada codicacao o LAME deve ser congurado pois algu mas vari veis de conguracao n o podem ser reutilizadas. A geracao do audio e feita atrav s a a e de um microfone congurado pela biblioteca de audio ALSA que captura o audio no formato PCM de 16 bits little-endian sinalizado, em apenas um canal, com uma taxa de amostragem de 44100Hz. Para conter o audio capturado, utiliza-se um buffer implementado em um vetor de elementos do tipo short int (16 bits) com 1152 posicoes6 . Logo, cada leitura do microfone captura 1152 amostras PCM. Ap s a captura, o audio e copiado para a mem ria da GPU e codicado utilizando o o uma funcao de codicacao da biblioteca LAME mantendo as mesmas conguracoes supracita das. Os dados do audio codicado retornados pela funcao s o armazenados em um buffer de a unsigned char de tamanho denido atrav s de uma funcao da biblioteca LAME que calcula o e tamanho do buffer de acordo com as conguracoes denidas. Por m, o buffer MP3 e enviado a um cliente em outra m quina atrav s de um soca e ket que utiliza o protocolo UDP. Do outro lado, o cliente recebe o buffer MP3 e realiza sua descodicacao utilizando uma funcao de descodicacao da biblioteca LAME que retorna o audio em amostras PCM e na seq encia esse audio e reproduzido atrav s da biblioteca de audio u e ALSA.

4.2.2

Codicacao em GPU
Para codicar o audio foram utilizadas funcoes da biblioteca LAME, foi utilizada a

vers o 3.97 do LAME disponibilizada pelo concurso da NVidia de implementacao do codia cador LAME em CUDA. Essa vers o do LAME possui uma implementacao em CUDA para a o ltro passa-alta do modelo psicoac stico e do ajuste de escala de amostra da funcao de u
6 Tamanho

do quadro MP3

28

codicacao. O ltro passa-alta do modelo psicoac stico e usado para a deteccao de ataques e, u com isso, evitar o pr -eco. A implementacao paralela do ltro passa-alta permite que todas e as 576 sub-bandas executem o ltro simultaneamente. O ajuste de escala das amostras ocorre na preparacao do processo de codicacao e consiste em multiplicar o valor de cada amos tra PCM por um valor de escala. Este ajuste tem como objetivo alterar o volume sonoro das amostras. A implementacao dessa funcao em CUDA permite a execucao das multiplicacoes em paralelo. Essas funcoes foram implementadas pela NVidia no c digo disponibilizado para o o concurso de implementacao do codicador LAME em CUDA. E importante para que estas implementacao possam ter ganhos de desempenho que o buffer de amostras seja copiado para a ` mem ria da GPU na preparacao para a codicacao, pois com isso o tempo de acesso a mem ria o o e otimizado. Portanto foi necess rio incluir no Servidor de Audio funcoes da API CUDA para a implementar a c pia dos dados para a GPU. o

4.3

Resultados
As m quinas utilizadas para os testes dessa implementacao possuem processador Intel R a

CoreTM 2 Quad 2.4GHz de 64 bits, 2GB de mem ria RAM, equipada com uma GPU Geo Force 8600 GT com 256MB de mem ria global. O sistema operacional utilizado e o Debian o GNU/Linux vers o 5.0 (lenny/sid) com o kernel 2.6.24-1-amd64. a Para medir o desempenho do codicador LAME com modicacoes implementadas em CUDA, foi realizado um teste comparando o tempo de codicacao do LAME modicado com a vers o 3.97 original do LAME7 . No teste realizado, cada implementacao codicou um a conjunto de 6 arquivos no formato WAV [BORN, 1995] com diferentes tamanhos, onde 3 desses arquivos possuiam amostras em Mono (um canal) e os outros 3 arquivos possuiam amostras em Stereo (dois canais). Os arquivos foram codicados utilizando a conguracao padr o do LAME a com taxa de bits constante8 , mantendo a escala (volume sonoro) e o n mero de canais. Cada u
7 http://sourceforge.net/project/showles.php?group 8 Constant

id=290&package id=309

Bit Rate (CBR)

29

implementacao codicou cada um dos arquivos 15 vezes para ns estatsticos, pois, enquanto o desvio padr o do codicador LAME original (com processamento em CPU) variou entre a 0,5% e 1,1%, o codicador modicado (com parte do processamento em GPU) variou entre 1,6% e 5,4%. Com esses valores, foi produzida uma m dia dos tempos de execucao de cada e implementacao do LAME para cada arquivo. Os valores est o demonstrados na Tabela 4.1. a
Tamanho dos Arquivos Tempo M dio de codicacao do LAME em GPU e Maior Tempo de codicacao do LAME em GPU Menor Tempo de codicacao do LAME em GPU Tempo M dio de codicacao do LAME original e Maior Tempo de codicacao do LAME original Menor Tempo de codicacao do LAME original Ganho M dio de Desemenho do LAME em GPU e 3MB 0,76s 0,79s 0,76s 0,85s 0,86s 0,85s 1,12x 6MB 1,18s 1,19s 1,18s 2,06s 2,07s 2,06s 1,75x 12MB 2,48s 2,57s 2,47s 3,06s 3,07s 3,06s 1,23x 24MB 3,52s 3,69s 3,49s 6,65s 6,67s 6,64s 1,89x 41MB 8,56s 8,64s 8,50s 11,98s 12,01s 11,97s 1,41x 82MB 13,81s 13,88s 13,70s 27,08s 27,24s 27,01s 1,97x

Tabela 4.1: Tempo de execucao por tamanho dos arquivos

Os valores da Tabela 4.1 mostram uma variacao muito maior nos tempos do LAME modicado (com parte do processamento em GPU) ao contr rio do que acontece com os tempos a do LAME original (com processamento em CPU). De forma que para um dos testes do LAME modicado o desvio padr o chegou ao valor de 5,4% enquanto o desvio padr o do LAME origia a nal n o passou de 1,1%. Apesar disso, os valores m dios dos tempos de codicacao do LAME a e modicado caram mais pr ximos do menor tempo. Demonstrando que os maiores tempos o ocorreram em menor quantidade no teste. Tamb m foi possvel constatar que o desempenho e das implementacoes que utilizaram CUDA foi at 1,97 vezes maior se comparado com codi e cadores que n o utilizaram o modelo de programacao paralela. E que mesmo no pior caso, a as implementacoes que utilizaram CUDA foram pelo menos 1,12 vezes mais r pidas. Com a tudo isso, foi possvel comprovar que e possvel melhorar o desempenho dos algoritmos de processamento de audio ao utilizar um modelo de programacao paralela em GPU. Outro teste realizado foi o de desempenho do Servidor de Audio implementado a partir do modelo proposto neste trabalho. Esse teste tem como objetivo demonstrar que a aplicacao desenvolvida foi capaz de se utilizar plenamente do ganho de desempenho proporcionado pela implementacao de tecnicas de processamento de audio em GPU.

30 TCL 3263s 3196s TCA 54035s 50734s 47123s TM 13s TCo 12s 7 TE 4s 3s 3s TT 54045s 54043s 51200s

Servidor de Audio sem codicacao Servidor de Audio com codicacao em CPU Servidor de Audio com codicacao em GPU

Tabela 4.2: Desempenho do Servidor de Audio

Esse teste mediu os tempos de execucao de algumas funcoes de diferentes vers es do o Servidor de Audio. As vers es do Servidor de Audio utilizadas foram: um Servidor de Audio o sem codicacao que apenas captura o audio e envia ao cliente que reproduz o audio recebido; um Servidor de Audio com codicacao em CPU que captura o audio, codica-o utilizando o codicador LAME original do teste anterior e envia o resultado da codicacao ao cliente que o descodica e reproduz o audio resultante; e o Servidor de Audio com codicacao em GPU, descrito na secao anterior, que utiliza o codicador LAME modicado (com parte do processamento em GPU). Os tempos medidos para esse teste foram o tempo de conguracao do codicador LAME (TCL), o tempo de captura do audio (TCA), o tempo de c pia das amostras para a o mem ria da GPU (TM), o tempo de codicacao (TCo), o tempo de envio dos dados (TE) e o o tempo total de cada ciclo do servidor (TT). Os valores foram medidos em micro segundos (s). Com isso obteve-se a Tabela 4.2. Vale destacar que a captura do audio est sujeita a variacoes de acordo com o audio a introduzido. Logo, o desvio padr o nesse caso chegou a 35% no Servidor de Audio sem a codicacao, a 37,2% no Servidor de Audio com codicacao em CPU e a 62% Servidor de Audio com codicacao em GPU. Al m disso pode-se considerar que o tempo de captura, em e teoria, deve ser semelhante para os diferentes servidores de audio e, portanto, seus valores n o alteram o resultado desejado, que era medir a eci ncia da implementacao do codicador a e LAME em GPU. Como demontra a Tabela 4.2, foi possvel conseguir uma reducao no tempo de envio dos dados, pois com a codicacao a quantidade de dados enviados ao cliente por ciclo9 reduziu
9 Cada

ciclo corresponde ao processo de captura, codicacao e envio do audio.

31

de 2304 bytes10 para aproximadamente 208 bytes. Deve-se lembrar que o tempo de envio dos dados medido neste teste consiste no tempo de execucao da funcao respons vel por essa a acao. Por m, para isso, foi necess rio introduzir a conguracao do LAME, que precisa ser e a recongurado para cada codicacao. Da mesma forma, foi possvel reduzir o tempo de codicacao utilizando a vers o mo a dicada do LAME que possui parte de seu processamento em GPU. Nessa comparacao, o Servi dor de Audio com codicacao em GPU conseguiu codicar o audio 1,71 vezes mais r pido que a o Servidor de Audio com codicacao em CPU. Por m, mais uma vez, foi necess rio acrecentar e a o tempo da c pia dos dados do audio para a mem ria da GPU. Dessa forma, apesar do desemo o penho geral do Servidor de Audio n o ter sido melhorado, pois, em proporcao ao tempo total a de execucao de um ciclo, o tempo de codicacao e muito pequeno e somado ao tempo gasto transferindo os dados para a mem ria da GPU, ou seja, o ganho de desempenho de codicacao o n o foi suciente para compensar o tempo gasto transferindo os dados para a mem ria da GPU. a o Por m, o aumento da quantidade de dados a serem processados podem permitir que o ganho de e desempenho do processamento compense o tempo de c pia dos dados para a mem ria da GPU. o o Mas para comprovar esta armacao e necess rio analisar a variacao dos tempos de c pia dos a o dados para a mem ria da GPU e de codicacao em relacao ao aumento da quantidade de dados. o Ainda existem partes do codicador LAME que podem ser implementadas em CUDA a m de melhorar ainda mais seu desempenho. Por exemplo, reescrever as funcoes que uti lizam a FFT11 em CUDA; paralelizar os ltros Replay Gain12 e passa-baixa13 , assim como outras otimizacoes na funcao de an lise psicoac stica e nas funcoes de codicacao, entre outras a u possveis implementacoes que n o foram citadas aqui. Al m disso um novo teste medindo o a e tempo de execucao das funcoes do LAME que foram implementadas em CUDA seria util para analisar o ganho de desempenho obtido pelo codicador.

10 1152 11 E

amostras de 2 bytes cada ` possvel utilizar a biblioteca cuFFT que possui um amplo suporte as funcoes de FFT. 12 Respons veis por normalizar o rudo perceptvel nas amostras de audio a 13 Respons vel por atenuar a amplitude das freq encias a u

32

Conclus o a

Neste trabalho foram introduzidos os principais conceitos a respeito da programacao paralela e alguns conceitos que envolvem o audio digital e o processamento de sinais, com o objetivo de desenvolver um modelo de Servidor de Audio que permita o desenvolvimento de uma aplicacao que utilize o processamento em GPU para melhorar o desempenho de t cnicas e de processamento de audio. Demostrando, com isso, que o modelo de programacao paralela em GPU e adequado para ser utilizado em aplicacoes multimdia. Foi implementado um Servidor de Audio, baseado no modelo proposto, que utiliza a programacao em GPU para implementar a codicacao do audio. A id ia foi utilizar a codicacao e do audio para reduzir a quantidade de dados enviada e reduzir o tempo de codicacao utilizando uma implementacao do codicador LAME em CUDA. Para avaliar o Servidor de Audio imple mentado, foram realizados experimentos. O primeiro experimento comparou o desempenho do codicador de audio em GPU com o desempenho de sua vers o em CPU. Enquanto o sea gundo experimento comparou os tempos de execucao das funcoes de tr s vers es do Servidor de e o Audio: uma vers o sem codicacao, uma com codicacao em CPU e a ultima com codicacao a em GPU. Os experimentos demostraram que a aplicacao implementada n o possuia volume de a dados intenso ou grau de paralelismo sucientes para tornar o resultado do uso da t cnica de e processamento paralelo em GPU expressivo. Por m, os resultados mostraram que o modelo de e programacao paralela em GPU foi capaz de otimizar o desempenho da codicacao do audio, como foi proposto. Assim, foi possvel demonstrar que a utilizacao da GPU para a programacao de prop sito o

33

geral est evoluindo rapidamente de maneira a se tornar um meio eciente e vi vel para a a a implementacao de diversos tipos de aplicacoes. E que os sistemas multimdia podem se aprovei tar do aumento da capacidade de processamento, proporcionado pelos modelos de programacao em GPU, para melhorar do desempenho das t cnicas existentes e para a criacao de novas e t cnicas. e

34

Refer ncias Bibliogr cas e a

BORN, G. Formats Handbook. London: Thomson Computer Press, 1995. CAVAGNOLO, B.; BIER, J. Introduction to digital audio compression. CHONG, J. et al. Data-parallel large vocabulary continuous speech recognition on graphics processors. In: Proceedings of the 1st Annual Workshop on Emerging Applications and Many Core Architecture (EAMA). [S.l.: s.n.], 2008. p. 2335. DUHAMEL, P.; VETTERLI, M. Fast fourier transforms: A tutorial review and a state of the art. Signal Process., Elsevier North-Holland, Inc., Amsterdam, The Netherlands, The Netherlands, v. 19, n. 4, p. 259299, 1990. ISSN 0165-1684. HALFHILL, T. R. Parallel Processing with CUDA. January 28 2008. InStat Microprocessor Report. HENNESSY, J. L.; PATTERSON, D. A. Computer Architecture; A Quantitative Approach. San Francisco, CA, USA: Morgan Kauffman Publishers Inc., 1990. ISBN 1558600698. HUFFMAN, D. A. A method for the construction of minimum-redundancy codes. Proceedings of the IRE, v. 40, n. 9, p. 10981101, 1952. Disponvel em: <http://ieeexplore.ieee.org/xpls/abs all.jsp?arnumber=4051119>. LAGO, N. P. Processamento Distribudo de Audio em Tempo Real. Abril 2004. MANAVSKI., S. A. Cuda compatible gpu as an efcient hardware accelerator for aes cryptography. In: . [S.l.: s.n.], 2007. p. 6568. NVIDIA. NVIDIA CUDA Compute Unied Device Architecture Programming Guide. Version 2.0. June 7 2008. PAN, D. Y. Digital audio compression. Digital Tech. J., Digital Equipment Corp., Acton, MA, USA, v. 5, n. 2, p. 2840, 1993. ISSN 0898-901X. PAN, D. Y. A tutorial on mpeg/audio compression. IEEE MultiMedia, IEEE Computer Society Press, Los Alamitos, CA, USA, v. 2, n. 2, p. 6074, 1995. ISSN 1070-986X. PEDDIE, J. Digital Media Technology: Industry Trends and Developments. 2001. IEEE Computer Graphics and Applications. PEERCY, M.; SEGAL, M.; GERSTMANN, D. A performance-oriented data parallel virtual machine for gpus. In: SIGGRAPH 06: ACM SIGGRAPH 2006 Sketches. New York, NY, USA: ACM, 2006. p. 184. ISBN 1-59593-364-6. POHLMANN, K. C. Principles of Digital Audio. [S.l.]: McGraw-Hill Professional, 2000. ISBN 0071348190.

35

POSTEL, J. User Datagram Protocol. [S.l.], August 1980. 3 p. Disponvel em: <http://www.rfc-editor.org/rfc/rfc768.txt>. PRINCEN, J. P.; BRADLEY, A. B. Analysis/synthesis lter bank design based on time domain aliasing cancellation. IEEE Transaction on Acoustics, Speech and Signal Processing, n. 5, p. 11531161, out. 1986. ROADS, C. et al. The Computer Music Tutorial. Cambridge, MA, USA: MIT Press, 1996. ISBN 0-252-18158-3. SILBERSCHATZ, A.; GALVIN, P. B. Operating System Concepts. New York, NY, USA: John Wiley & Sons, Inc., 2000. ISBN 0471418846. VAIDYANATHAN, P. P. Quadrature mirror lter banks, M-band extensions and perfect reconstruction techniques. v. 4, n. 3, p. 420, jul. 1987. WATKINSON, J. Introduction to Digital Audio. Newton, MA, USA: Butterworth-Heinemann, 2001. ISBN 0240516435.

36

ANEXO A -- CUDA Application Programming Interface

A interface de programacao (API) do modelo CUDA fornece um meio de programa dores familiarizados com a linguagem C escreverem facilmente programas para executar em GPU. Para isso um conjunto mnimo de extens es da linguagem C permitem indicar partes do o c digo para ser executado em GPU. A API consiste tamb m em uma biblioteca de execucao1 o e que permite o controle de mais de uma GPU a partir da CPU; funcoes especcas para execu tarem em GPU; e uma componente comum que dene tipos e um subconjunto da biblioteca padr o C permitem a execucao tanto em CPU quanto em GPU. As unicas funcoes da biblioteca a padr o C suportadas para executar em GPU s o as disponibilizadas pela componente comum a a da biblioteca de execucao.

A.1

Extens es da Linguagem C o
A API CUDA dene 4 extens es para a linguagem C: qualicadores de funcao, que o

denem se a funcao deve ser chamada em CPU ou GPU e onde ela deve ser executada; qualica dores de vari veis que especicam em qual mem ria a vari vel ser alocada; uma nova diretiva a o a a que especica como um kernel deve ser executado; e vari veis pr -denidas que especicam as a e dimens es do grid e dos blocos e os ndices dos blocos e threads. o

A.1.1

Qualicadores de Funcao
Os qualicadores de funcao device , global e host s o respons veis por de a a

nir se a funcao denida ser executada em CPU ou GPU e a partir de onde ela pode ser a
1 CUDA

runtime library

37

invocada. O qualicador device declara uma funcao que e executada em GPU e pode ser global declara uma funcao como sendo

chamada apenas a partir da GPU. O qualicador

um kernel. Tal funcao e executada em GPU e pode ser chamada apenas a partir da CPU. O qualicador host declara uma funcao que e executada em CPU e pode ser chamada apenas a partir da CPU. E equivalente declarar uma funcao com o qualicador host ou sem nenhum dos qualicadores de funcao. O qualicador host pode ser utilizado em conjunto com o

qualicador device . Nesse caso o c digo ser compilado para GPU e CPU. o a Os qualicadores de funcao possuem restricoes. Funcoes denidas para executar em GPU n o suportam recurs o; n o podem possuir declaracoes de vari veis est ticas; e n o poa a a a a a dem ter n mero vari vel de argumentos. Ponteiros para funcoes device n o s o suportados. u a a a Os qualicadores global e host n o podem ser usados juntos. Funcoes a global de-

vem retornar void, pois essas funcoes s o assncronas, ou seja, a chamada retorna antes do m a de sua execucao. Par metros de funcoes a compartilhada e s o limitados a 256 bytes. a global s o passados para a GPU pela mem ria a o

A.1.2

Qualicadores de Vari veis a


Os qualicadores de vari veis denem em qual tipo de mem ria a vari vel declarada a o a

ser alocada. a Varaveis declaradas com o qualicador device ser o alocadas na mem ria global a o

da GPU; que permanecem em mem ria durante o tempo de execucao do kernel; e acessveis por o todas as threads do grid e a partir da CPU atrav s da biblioteca de execucao. Qualquer um dos e outros qualicadores de vari veis podem ser utilizados junto com o qualicador device . O a qualicador constant dene vari veis que residem na mem ria constante; que permanecem a o em mem ria durante o tempo de execucao do kernel; e acessveis por todas as threads do grid o e a partir da CPU atrav s da biblioteca de execucao. O qualicador shared dene vari veis e a alocadas na mem ria compartilhada de um bloco de threads; que permanecem em mem ria o o

38

durante a execucao do bloco; e acessveis a todas as threads do bloco. Apenas ap s a execucao o do comando syncthreads() que a escrita a vari veis compartilhadas s o garantidas de serem a a

vistas pelas outras threads do bloco. Os qualicadores de vari veis possuem restricoes. N o e permitido utiliz -los em a a a struct ou union, em par metros formais e em vari veis locais de uma funcao que executa a a em CPU. Os qualicadores shared e constant implicam em armazenamento est tico. a

a a a Vari veis device e constant s o declaradas fora de funcoes. Vari veis constant n o a podem ser denidas em GPU, apenas atrav s de funcoes de execucao especcas em CPU. e Vari veis a shared n o podem possuir uma declaracao como parte de suas declaracoes. Os a

enderecos obtidos de vari veis device , shared ou constant podem ser utilizadas ape a nas em GPU. Entretanto, os enderecos de vari veis a device ou constant obtidos atrav s e

da funcao cudaGetSymbolAddress()2 podem ser usadas em CPU.

A.1.3

Par metros de Conguracao da Execucao a


Qualquer chamada de uma funcao global deve especicar uma conguracao de

execucao para a chamada. A conguracao de execucao dene a dimens o do grid e dos blocos que ser o usados a a para executar a funcao no dispositivo. A especicacao da conguracao e feita inserindo uma express o da forma <<< Dg, Db, Ns, S >>> entre o nome da funcao e a lista de argumentos. a Dg e do tipo dim3, que ser abordado na secao A.2.1, e especica o tamanho do grid em a at duas dimens es, onde o n mero de blocos a serem lancados e Dg.x * Dg.y (o n mero de e o u u blocos na dimens o x vezes o n mero de blocos na dimens o y). Db tamb m e do tipo dim3 a u a e e especica o tamanho de cada bloco em at tr s dimens es, tal que Db.x * Db.y * Db.z (o e e o n mero de blocos na dimens o x vezes o n mero de blocos na dimens o y vezes o n mero de u a u a u blocos na dimens o z) equivale ao n mero de threads por bloco. Ns e do tipo size t e especica a u o n mero de bytes na mem ria compartilhada que ser alocada dinamicamente em cada bloco u o a para uma chamada al m da mem ria alocada estaticamente. Esse valor e usado para denir o e o
2 Secao

4.5.2.3 do Guia de Programacao CUDA [NVIDIA, 2008]

39

tamanho de vetores alocados dinamicamente. O argumento Ns e opcional e tem valor padr o a igual a 0. S e do tipo cudaStream t e especica o stream associado. O argumento S e opcional e tem valor padr o igual a 0. a Os argumentos de conguracao de execucao s o avaliados antes dos argumentos da a funcao e ambos s o passados atrav s da mem ria compartilhada para a GPU. Se algum dos a e o par metros de conguracao da execucao forem maior que o permitido a execucao ir falhar. a a

A.1.4

Vari veis Pr -denidas a e


As vari veis pr -denidas s o vari veis denidas automaticamente a partir da chamada a e a a

de uma funcao. Elas possuem as dimens es e tamanhos do grid e dos blocos e os ndices dos o blocos e threads. A vari vel gridDim e do tipo dim3 e cont m o tamanho do grid para todas as suas a e dimens es. A vari vel blockIdx e do tipo uint3, que ser explicado na secao A.2.1, e cont m o o a a e ndice do bloco corrente para cada uma das dimens es do grid. A vari vel blockDim e do tipo o a dim3 e cont m o tamanho do bloco todas as suas dimens es. A vari vel threadIdx e do tipo e o a uint3 e cont m o ndice da thread corrente para cada uma das dimens es do bloco. E a vari vel e o a warpSize e do tipo int e cont m o tamanho do warp em threads. e N o e possvel indicar o endereco ou atribuir valor a nenhuma dessas vari veis. a a

A.1.5

O Compilador NVCC
O compilador nvcc busca simplicar o processo de compilacao do c digo CUDA. O o

compilador prov opcoes de linha de comando simples e familiares. e A rotina b sica do nvcc consiste em separar o c digo GPU do c digo CPU e compilar a o o o c digo GPU em uma forma bin ria conhecida como cubin. O c digo CPU gerado permanece o a o em C e ser compilado com outra ferramenta no ultimo est gio da compilacao. a a Aplicacoes podem ignorar o c digo CPU gerado e carregar e executar o c digo cubin o o

40

em GPU diretamente utilizando a API do driver3 ou podem linkar o c digo cubin com o c digo o o CPU. O c digo CUDA e compilado de acordo com as regras de sintaxe da linguagem C++. o C++ e totalmente suportado no c digo CPU, no entanto, apenas o subconjunto de regras de o C s o totalmente suportadas em GPU. Caractersticas especcas como classes, heranca, ou a declaracao de vari veis em blocos b sicos n o s o suportadas. Como conseq encia do uso das a a a a u regras de sintaxe de C++, ponteiros void n o podem ser associados a ponteiros n o-void sem o a a uso de typecast. O nvcc introduz duas diretivas: noinline e # pragma unroll.

Por padr o, uma funcao device e denida como inline, ou seja, a funcao e copiada a inteira para cada posicao onde ela e chamada. A diretiva noinline e utilizada para indicar

para o processador n o fazer isso se possvel. Ainda assim, a funcao deve estar no mesmo a arquivo em que ela e chamada. Por padr o o compilador desenrola pequenos loops para melhorar o desempenho da a aplicacao. A diretiva # pragma unroll permite controlar o desenrolamento de qualquer loop. A diretiva deve ser inserida imediatamente antes do loop. Ela pode ser opcionalmente seguida pelo n mero de vezes que o loop ser desenrolado. # pragma unroll 1 indica ao compilador u a que o loop n o deve ser desenrolado. Se o n mero de vezes que o loop ser desenrolado, o a u a compilador desenrola o loop todo.

A.2

Componente de Execucao Comum


A componente de execucao comum4 , como o nome diz, pode ser usada tanto em GPU

quanto em CPU.
3 Ver 4 Common

secao A.4.2 Runtime Component

41

A.2.1

Tipos Pr -denidos e
char1, uchar1, char2, uchar2, char3, uchar3, char4, uchar4, short1, ushort1,

short2, ushort2, short3, ushort3, short4, ushort4, int1, uint1, int2, uint2, int3, uint3, int4, uint4, long1, ulong1, long2, ulong2, long3, ulong3, long4, ulong4, oat1, uoat1, oat2, uoat2, oat3, uoat3, oat4, uoat4 s o estruturas baseadas dos tipos b sicos inteiro e ponto a a utuante. Suas primeira, segunda, terceira e quarta componentes s o acessveis atrav s dos a e campos x, y, z e w respectivamente. Todos esses tipos possuem um construtor com a forma make <nome do tipo>(). Por exemplo: make int2(int x, int y) cria uma vari vel do tipo int2 a com valor (x, y). O tipo dim3 e baseado no tipo uint3. Esse tipo e usado para especicar dimens es. o Quando uma vari vel e denida com esse tipo, qualquer componente n o especicada possuir , a a a por padr o, valor 1. a

A.2.2

Funcoes Matem ticas a


As funcoes matem ticas da biblioteca padr o C/C++ suportadas em CUDA s o espe a a a

cicadas na componente de execucao comum, ou seja, podem ser executadas tanto em CPU como em GPU. A Secao B.1 do Guia de Programacao CUDA [NVIDIA, 2008] cont m uma lista das e funcoes matem ticas da biblioteca padr o C/C++ que s o suportadas em CUDA. a a a

A.2.3

Funcoes de Tempo
Quando a funcao clock t clock(); e executada em GPU, ela retorna o valor de um

contador do multiprocessador que e incrementado a cada ciclo do clock. Cada multiprocessador da GPU possui um contador individual. Coletando o valor desse contador no incio e no nal de um kernel, tirando a diferenca entre as duas coletas e guardando o resultado por thread e possvel medir o n mero de clocks que cada thread precisou para completar a execucao do u

42

kernel.

A.2.4

Tipo Textura
A biblioteca de execucao CUDA suporta um subconjunto de instrucoes para o acesso

a mem ria de textura. E possvel obter benefcios de desempenho ao ler dados da mem ria de o o textura ao inv s da mem ria global. e o A mem ria de textura e lida atrav s de um kernel usando funcoes chamadas de feto e ches de textura. O primeiro par metro de um fetch e um objeto chamado de refer ncia de a e textura. Uma refer ncia de textura dene qual parte da textura ser buscada. Ela deve ser limie a tada atrav s da CPU a algumas regi es de mem ria, chamadas texturas, antes de serem usadas e o o pelo kernel. V rias regi es distintas podem ser limitadas a uma mesma textura ou a texturas a o sobrepostas na mem ria. o Uma refer ncia de textura possui v rios atributos. Um deles e a dimens o da textura, e a a que especica onde a textura est enderecada. Uma textura e enderecada como um vetor de at a e 3 dimens es. Os elementos do vetor s o chamados de elementos de textura. o a Outros atributos denem os tipos de entrada e sada do fetch de textura; como as coor denadas das entradas s o interpretadas e que processamento deve ser feito. a Alguns atributos de textura s o imut veis e devem ser conhecidos em tempo de compilacao. a a Eles s o especicados ao declarar a refer ncia de textura. Uma refer ncia de textura e declarada a e e no escopo do arquivo como uma vari vel do tipo textura: texture<Type, Dim, ReadMode> a texRef;. Onde Type especica o tipo do dado que ser retornado pela busca da textura. Type e a restrito a tipos inteiros b sicos, ponto utuantes de precis o simples e qualquer dos tipos com a a 1, 2 ou 4 componentes denidos na secao A.2.1. Dim especica a quantidade de dimens es o da refer ncia de textura e pode possuir valor igual a 1, 2 ou 3. Dim e um argumento opcioe nal e, por padr o, possui valor igual a 1. ReadMode possui valor igual a cudaReadModea ElementType ou cudaReadModeNormalizedFloat. Caso ReadMode seja cudaReadMode NormalizedFloat e Type seja um inteiro de 16 ou 8 bits, o valor retornado e convertido para

43

ponto utuante. Caso ReadMode seja cudaReadModeElementType, nenhuma convers o e a realizada. O atributo ReadMode e opcional e possui como valor padr o cudaReadModeElea mentType. Os outros atributos de uma refer ncia de textura s o mut veis e podem ser alteradas e a a em tempo de execucao atrav s de instrucoes da CPU. Eles especicam onde as coordenadas da e textura est o normalizadas ou n o; o modo de enderecamento; e ltros de textura. a a

A.3

Componente de Execucao em GPU


As funcoes da componente de execucao em GPU podem ser utilizadas apenas em

funcoes que executam na GPU.

A.3.1

Funcoes Matem ticas a


Para algumas das funcoes referenciadas na secao A.2.2 existe uma vers o menos pre a

cisa por m mais r pida na componente de execucao em GPU. Seus nomes possuem o mesmo e a prexo com (por exemplo: sinf(x)). Essas funcoes est o listadas na Secao B.2 do Guia de a

Programacao CUDA [NVIDIA, 2008]. O compilador tamb m possui uma opcao (-use fast math) para forcar cada funcao a e compilar a sua vers o menos precisa, se ela existir. a

A.3.2

Funcao de Sincronizacao
A funcao syncthreads() sincroniza todas as threads em um bloco. Uma vez que

todas as threads atingiram este ponto, a execucao prossegue normalmente. E permitido utilizar a funcao syncthreads() instrucoes condicionais, apenas se as

condicoes forem avaliadas identicamente para todas as threads do bloco. Se essa condicao n o a for atendida, a execucao pode resultar efeitos n o desejados. a

44

A.3.3

Funcoes de Textura
Uma textura pode ser qualquer regi o de mem ria linear ou um vetor CUDA (que s o a o a

regi es de mem ria otimizadas para utilizar texturas). o o Utilizando uma regi o de mem ria linear, a textura pode ser acessvel atrav s da a o e famlia de funcoes tex1Dfetch(). Quando vetores CUDA s o usados para acessar uma textura, utiliza-se as funcoes a tex1D(), tex2D ou tex3D.

A.3.4

Funcoes At micas o
Uma funcao at mica realiza leitura, modicacao e escrita em uma unica operacao em o

uma palavra de 32 ou 64 bits em algum endereco na mem ria global ou na compartilhada. Por o exemplo, a funcao atomicAdd() l uma palavra de 32 bits de algum endereco de mem ria na e o ` mem ria global na compartilhada, soma um inteiro a palavra e escreve o resultado no mesmo o endereco. A operacao e at mica no sentido de garantir que ser executada sem interfer ncia de o a e outras threads.

A.4

Componente de Execucao em CPU


A componente de execucao em CPU fornece um conjunto de funcoes para manipular o

gerenciamento da GPU; o gerenciamento de contexto; o gerenciamento de mem ria; o controle o de execucao; o gerenciamento das refer ncias de textura; e a interoperabilidade com OpenGL e e Direct3D. A componente de execucao em CPU e composta de duas partes: a API do driver CUDA e a API de execucao CUDA. Essas partes s o mutuamente exclusivas, ou seja, s e a o permitido a uma aplicacao usar uma delas.

45

A.4.1

API de Execucao
N o h uma inicializacao explcita para a API de execucao. Ela e inicializada ao exea a

cutar a primeira funcao da biblioteca de execucao. Para gerenciar as GPUs instaladas no sistema, s o utilizadas as funcoes cudaGetDea viceCount(), cudaGetDeviceProperties() e cudaSetDevice(). cudaGetDeviceCount() e cudaGetDeviceProperties() fornecem um meio de enumerar as GPUs e obter suas informacoes. Enquanto cudaSetDevice e usada para denir a GPU que ser associada a thread da CPU. a Regi es de mem ria linear s o alocadas usando a funcao cudaMalloc() ou cudaMalo o a locPitch() e liberadas usando cudaFree(). Vetores CUDA s o alocados pela funcao cudaa MallocArray() e liberadas pela funcao cudaFreeArray(). cudaMallocArray() exige que uma descricao de formato seja criada atrav s da funcao cudaCreateChannelDesc(). Um endereco e de vari vel alocada ne mem ria global pode ser obtido pela funcao cudaGetSymbolAddress(). a o E o tamanho da mem ria alocada e obtido pela funcao cudaGetSymbolSize(). o O Gerenciamento da refer ncia de textura utiliza o tipo textureReference para denir e uma refer ncia de textura. Antes que um kernel possa usar uma refer ncia de textura para ler da e e mem ria de textura, a refer ncia de textura deve ser vinculada a uma textura usando a funcao o e cudaBindTexture() ou a cudaBindTextureToArray(). E para desvincular uma refer ncia de e textura, utiliza-se a funcao cudaUnbindTexture(). Para a interoperabilidade com o OpenGL, um buffer deve ser registrado em CUDA antes que ele possa ser mapeado. Isso e feito com a funcao cudaGLRegisterBufferObject(). Uma vez registrado, o buffer pode sr lido ou escrito por kernels usando o endereco de mem ria o da GPU retornado por cudaGLMapBufferObject(). E para eliminar o mapeamento e o registro utiliza-se, respectivemente, as funcoes cudaGLUnmapBufferObject() e cudaGLUnregister BufferObject(). E para a interoperabilidade com o Direct3D e necess rio determinar qual GPU ser utia a lizada antes de qualquer execucao. Isso e feito atrav s da funcao cudaD3D9SetDirect3DDevice(). e

46

Os recursos Direct3D s o registrados em CUDA pela funcao cudaD3D9RegisterResources(). a Para remover o registro utiliza-se cudaD3DUnregisterVertexBuffer(). Assim que os recursos foram registrados, eles podem ser mapeados em CUDA quantas vezes forem necess rias atrav s a e da funcao cudaD3D9MapResources(). E da mesma forma, para eliminar o mapeamento utiliza-se cudaD3D9UnmapResources(). Um recurso mapeado pode ser lido ou escrito por kernels utilizando o endereco de mem ria retornado por cudaD3D9ResourceGetMappedPointer() o e o tamanho e o pitch s o retornados pelas funcoes: cudaD3D9ResourceGetMappedSize(), a cudaD3D9ResourceGetMappedPitch() e cudaD3D9ResourceGetMappedPitchSlice().

A.4.2

API do Driver
Antes de executar qualquer funcao da API do driver, e necess rio uma inicializacao a

com a funcao cuInit(). Para manipular as GPUs instaladas no sistema, s o utilizadas, entre outras, as funcoes a cuDeviceGetCount() e cuDeviceGet(). A API do driver tamb m permite a manipulacao do contexto. Todos os recursos e e acoes realizados atrav s da API do driver s o encapsuladas em um contexto CUDA. Uma th e a read de CPU pode possuir apenas um contexto ativo por vez. Para criar um contexto, usa-se a funcao cuCtxCreate(). Cada thread da CPU possui uma pilha de contextos. cuCtxCreate() p e um novo contexto no topo da pilha. Para desvincular o contexto ativo de uma thread da o CPU, a funcao cuCtxPopCurrent(). Se houver algum contexto anterior, ele ser reativado. a Uma contagem de uso e mantida para cada contexto. A funcao cuCtxCreate() cria um con texto com contagem igual a 1 que e incrementado pela funcao cuCtxAttach() e decrementado pela funcao cuCtxDetach(). Um contexto e destrudo quando a contagem chega a 0 ao chamar a funcao cuCtxDetach() ou cuCtxDestroy(). Clientes da API podem usar as funcoes cuCtx PushCurrent() e cuCtxPopCurrent() para criar contextos. O controle de execucao pode ser manipulado pelas seguintes funcoes. A funcao cu FuncSetBlockShape() que dene o n mero de threads por bloco para uma dada funcao. cuu

47

FuncSetSharedSize() dene o tamanho de mem ria compartilhada para a funcao. A famlia o de funcoes cuParam*() e usada para especicar os par metros do kernel que ser invocado. a a cuLaunchGrid() ou cuLaunch() s o utilizadas para invocar um kernel. a O gerenciamento de mem ria e feito atrav s das funcoes cuMemAlloc(), cuMemAlo e locPitch() e cuMemFree() para manipular mem ria linear. E atrav s das funcoes cuArrayo e Create() e cuArrayDestroy() para manipular vetores CUDA. Para utilizar a mem ria de textura, uma refer ncia de textura deve ser criada utilizando o e a funcao cuTexRefSetAddress() ou cuTeXRefSetArray(). A interoperabilidade com o OpenGL requer uma inicializacao pela funcao cuGLInit(). Ap s isso, um buffer deve ser registrado utilizando a funcao cuGLRegisterBufferObject() o e mapeado com a funcao cuGLMapBufferObject(). Para eliminar o mapeamento, utiliza se a funcao cuGLUnmapBufferObject(). E a funcao cuGLUnregisterBufferObject() para remover o registro o buffer. E para a interoperabilidade com o Direct3D e necess ria a criacao de um contexto. Isso a pode ser feito pela funcao cuD3D9CtxCreate(). Os recursos Direct3D podem ser registrados em CUDA usando a funcao cuD3D9RegisterResource(). Esse registro pode ser eliminado pela funcao cuD3D9UnregisterVertexBuffer(). Ap s os recursos serem registrados em CUDA, eles o podem ser mapeados pela funcao cuD3D9MapResources(). E o mapeamento pode ser elimi nado pela funcao cuD3D9UnmapResources(). Um recurso mapeado pode ser lido e escrito pelo kernel atrav s do ponteiro retornado pela funcao cuD3D9ResourceGetMappedpointer(), e do tamanho retornado pela funcao cuD3D9ResourceGetMappedSize() e do pitch retornado pelas funcoes cuD3D9ResourceGetMappedPitch() e cuD3D9ResourceGetMappedPitchSlice().

48

ANEXO B -- Speaker (servidor)

/******************************************************************************* * Este codigo foi escrito por mim e tem a finalidade de capturar o audio * codifica-lo de forma paralela e envia-lo a um cliente ******************************************************************************/

/* Bibliotecas Gerais */ #include <cuda.h> #include <cuda_runtime.h> #include <lhal04.h> #include <lhal04_lame/include/lame.h>

void reusePort(int s){ int one=1;

if ( setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *) &one,sizeof(one)) == -1 ){ printf("error in setsockopt,SO_REUSEPORT \n"); exit(-1); } }

49

int get_gpu_buffer_size( lame_global_flags *gf, int bytesPerSample, int pad ) { int nsamp = lame_get_num_samples(gf); return } nsamp*bytesPerSample + pad; //assume 2 bytes per sample (16-bit)

int main(int argc, char **argv){

/* Variaveis para manipulacao do socket */ int sd; struct sockaddr_in server; struct hostent *hp, *gethostbyname(); struct servent *sp; struct sockaddr_in to; int to_len; int length; char localhost[MAXHOSTNAME]; char msg[MAXHOSTNAME];

/* Variaveis para manipulacao do dispositivo de audio */

int rc,i; snd_pcm_t *handle = NULL; snd_pcm_hw_params_t *params; unsigned int val;

50

int direction; snd_pcm_uframes_t frames; buffer_t *buffer; int size; int num_samples_read;

lame_global_flags *gfp; unsigned char *mp3buffer; float *gpu_buffers[2]; int gpu_buffer_sz; float in_buffer_l[1152]; float in_buffer_r[1152];

struct timeval tt1,tt2; struct timeval tcl1,tcl2; struct timeval tca1,tca2; struct timeval ta1,ta2; struct timeval tco1,tco2; struct timeval te1,te2;

/* Configuracao do Socket */

if(argc > 2){ fprintf(stderr, "Uso correto: speaker <porta>\n"); exit(1); }

sp = getservbyname("echo", "udp");

51

/* get Host information, NAME and INET ADDRESS */ gethostname(localhost, MAXHOSTNAME);

printf("----Speaker running at host NAME: %s\n", localhost); if ( (hp = gethostbyname(localhost)) == NULL ) {

fprintf(stderr, "Cant find host name\n"); exit(-1); } bcopy ( hp->h_addr, &(server.sin_addr), hp->h_length); printf(" (Speaker INET ADDRESS is: %s )\n", inet_ntoa(server.sin_addr));

/* Construct name of socket to send to. */ server.sin_family = AF_INET;

server.sin_addr.s_addr = htonl(INADDR_ANY); if (argc == 1) server.sin_port = htons(0); else server.sin_port = htons(atoi(argv[1]));

/* Create socket on which to send

and receive */

sd = socket (AF_INET,SOCK_DGRAM,0);

/* to allow another process to use the same port howver, only ONE gets the message */ reusePort(sd);

52

if ( bind( sd, (struct sockaddr *) &server, sizeof(server) ) < 0 ) { close(sd); perror("binding name to datagram socket"); exit(-1); }

/* get port information and length = sizeof(server);

prints it out */

if ( getsockname (sd, (struct sockaddr *)&server,&length) ) { perror("getting socket name"); exit(0); } printf("Server Port is: %d\n", ntohs(server.sin_port));

to_len = sizeof(to); printf("\n...server is waiting...\n"); if ((rc=recvfrom(sd, msg, sizeof(msg), 0, (struct sockaddr *) &to, &to_len)) < 0) perror("receiving datagram message");

printf("Enviando audio para: %s:%d\n", inet_ntoa(to.sin_addr), htons(to.sin_port));

if ((hp = gethostbyaddr((char *)&to.sin_addr.s_addr, sizeof(to.sin_addr.s_addr), AF_INET)) == NULL) fprintf(stderr, "Cant find host %s\n", inet_ntoa(to.sin_addr));

53

/* Configuracao do dispositivo de audio */

/* Abre o dispositivo PCM "default" para captura (gravacao) */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0){ fprintf(stderr, "Nao consegui abrir o dispositivo pcm: %s\n", snd_strerror(rc)); exit(1); }

/* Aloca um objeto de parametros do harware */ snd_pcm_hw_params_malloc(&params);

/* Preenche os parametros com valores default */ snd_pcm_hw_params_any(handle, params);

/* Define os parametros de hardware desejados */

printf("Configuracoes de Audio...\n");

/* Define modo de acesso pcm como sendo entrelacado (interleaved) */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);

/* Define o formato do audio como signed 16 bits little-endian */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);

/* Define dois canais (stereo) */ snd_pcm_hw_params_set_channels(handle, params, CANAIS);

54

/* Define a taxa de amostragem aproximada como 44100 bits/s (qualid. de CD) */ val = SAMPLE_RATE; direction = 0; snd_pcm_hw_params_set_rate_near(handle, params, &val, &direction);

/* Define o tamanho do periodo em frames */ frames = 32; direction = 0; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &direction);

/* Escreve os parametros no Driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0){ fprintf(stderr, "\nNao consegui definir os parametros de hw: %s\n", snd_strerror(rc)); exit(1); }

snd_pcm_hw_params_get_channels(params, &val); printf("Numero de canais: %d\n",val); snd_pcm_hw_params_get_rate(params, &val, &direction); printf("Taxa de Amostragem: %d Hz\n",val); printf("...OK\n\n");

gfp = lame_init(); lame_set_num_channels(gfp,CANAIS); lame_set_mode(gfp,MONO);

55

lame_set_in_samplerate(gfp,SAMPLE_RATE); lame_set_num_samples(gfp,1152); lame_init_params(gfp); lame_print_config(gfp); lame_print_internals(gfp);

size = lame_get_size_mp3buffer(gfp); buffer = (buffer_t *) malloc(NSAMPLES*2); mp3buffer = (unsigned char *) malloc(size);

printf("Tamanho do buffer pcm: %d amostras\n",NSAMPLES); printf("Tamanho do buffer mp3: %d bytes\n\n",size);

lame_close(gfp);

/* Loop principal */ while(1){

gfp = lame_init(); lame_set_num_channels(gfp,CANAIS); lame_set_mode(gfp,MONO); lame_set_num_samples(gfp,NSAMPLES); lame_set_in_samplerate(gfp,SAMPLE_RATE); lame_set_num_samples(gfp,1152);

rc = lame_init_params(gfp);

/* Captura Audio */

56

rc = snd_pcm_readi(handle, buffer, NSAMPLES*2);

if (rc == -EPIPE){ fprintf(stderr, "Overrun ocurred\n"); snd_pcm_prepare(handle); rc = NSAMPLES*2; } else if (rc < 0){ fprintf(stderr, "Erro na leitura: %s\n", snd_strerror(rc)); } else if (rc != NSAMPLES*2){ fprintf(stderr, "Short read. Expected %d samples, read %d samples\n", NSAMPLES, rc/2); /* As amostras sao de 2 bytes cada, por isso eh necessario dividir o * tamanho do buffer e o rc por 2, uma vez que estas variaveis sao medidas * em bytes, nao em amostras. */ }

num_samples_read = rc/2;

gpu_buffer_sz = get_gpu_buffer_size( gfp, sizeof(float), 0);

cudaMalloc((void *)&(gpu_buffers[1]), gpu_buffer_sz); cudaMalloc((void *)&(gpu_buffers[0]), gpu_buffer_sz);

for ( i = 0; i < num_samples_read; i++){ // valores esperados: +/- 32768.0 in_buffer_l[i] = (float) buffer[i];

57

in_buffer_r[i] = (float) buffer[i]; }

cudaMemcpy( &gpu_buffers[0], in_buffer_l, cudaMemcpy( &gpu_buffers[1], in_buffer_r,

rc = lame_encode_buffer(gfp, &gpu_buffers[0], &gpu_buffers[1], num_samples_read

rc = lame_encode_flush(gfp, mp3buffer, sizeof(mp3buffer));

sendto(sd, mp3buffer, size, 0, (struct sockaddr *) &to, sizeof(to));

lame_close(gfp);

} }

58

ANEXO C -- Listener (cliente)

/******************************************************************************* * Este codigo foi escrito por mim e tem a finalidade de receber o audio de um * servidor, descodifica-lo e reproduzi-lo ******************************************************************************/

/* Bibliotecas Gerais */ #include <lhal04.h> #include <orig/include/lame.h>

int main(int argc, char **argv){

/* Variaveis para manipulacao do socket */ int sd; struct sockaddr_in server; struct hostent *hp, *gethostbyname(); struct servent *sp; struct sockaddr_in from; struct sockaddr_in addr; int fromlen; int cc;

59

char localhost[MAXHOSTNAME]; char msg[MAXHOSTNAME];

/* Variaveis para manipulacao do audio */ int rc; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int direction; snd_pcm_uframes_t frames; buffer_t *buffer;

lame_global_flags *gfp; unsigned char *mp3buffer;

/* Configuracao do Socket */

if(argc != 3){ fprintf(stderr, "Uso correto: listener <end_servidor> <porta>\n"); exit(1); }

sp = getservbyname("echo", "udp");

/* get Listener Host information, NAME and INET ADDRESS */

gethostname(localhost, MAXHOSTNAME);

60

printf("----Listener running at host NAME: %s\n", localhost); if ( (hp = gethostbyname(localhost)) == NULL ) {

fprintf(stderr, "Cant find host %s\n", argv[1]); exit(-1); } bcopy ( hp->h_addr, &(server.sin_addr), hp->h_length); printf("(Listener INET ADDRESS is: %s )\n", inet_ntoa(server.sin_addr));

/* get Speaker Host information, NAME and INET ADDRESS */ if ( (hp = gethostbyname(argv[1])) == NULL ) {

addr.sin_addr.s_addr = inet_addr(argv[1]); if ((hp = gethostbyaddr((char *)&addr.sin_addr.s_addr, sizeof(addr.sin_addr.s_addr),AF_INET)) == NULL) { fprintf(stderr, "Cant find host %s\n", argv[1]); exit(-1); } } printf("----Speaker running at host NAME: %s\n", hp->h_name); bcopy ( hp->h_addr, &(server.sin_addr), hp->h_length); printf("(Speaker INET ADDRESS is: %s )\n", inet_ntoa(server.sin_addr));

/* Construct name of socket to send to. */ server.sin_family = AF_INET;

server.sin_port = htons(atoi(argv[2]));

/* Create socket on which to send

and receive */

61

sd = socket (hp->h_addrtype,SOCK_DGRAM,0);

if (sd<0) { perror("opening datagram socket"); exit(-1); }

/* Comunica com o Servidor */ strcpy(msg, hp->h_name);

if (sendto(sd, msg, strlen(msg), 0, (struct sockaddr *)&server, sizeof(server)) < perror("N~o consegui comunicar com o servidor"); a

/* Configuracao do dispositivo de audio */

printf("Configuracoes de Audio...\n");

/*snd_pcm_open(pcm handle, handler identifier, direction, mode)*/ /*mode pode ser bloqueante (0) ou nao bloqueante (1) */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (rc < 0){ fprintf(stderr, "Nao consegui abrir o dispositivo pcm: %s\n", snd_strerror(rc)); exit(1); }

/* Define os parametros de hardware desejados */

62

snd_pcm_hw_params_malloc(&params); snd_pcm_hw_params_any(handle, params); snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(handle, params, CANAIS);

val = SAMPLE_RATE; snd_pcm_hw_params_set_rate_near(handle, params, &val, &direction);

frames = 32; snd_pcm_hw_params_set_period_size_min(handle, params, &frames, &direction);

rc = snd_pcm_hw_params(handle, params); if (rc < 0){

fprintf(stderr, "Nao consegui definir os parametros de hw: %s\n", snd_strerror( exit(1); }

snd_pcm_hw_params_get_channels(params, &val); printf("Numero de canais: %d\n", val); snd_pcm_hw_params_get_rate(params, &val, &direction); printf("Taxa de Amostragem: %d Hz\n", val);

printf("...OK\n\n");

gfp = lame_init(); lame_set_num_channels(gfp,CANAIS); lame_set_mode(gfp,MONO);

63

lame_set_out_samplerate(gfp,SAMPLE_RATE); lame_set_num_samples(gfp,1152); lame_set_brate(gfp, 16); lame_init_params(gfp); lame_decode_init(); lame_set_decode_only(gfp,1); lame_print_config(gfp); lame_print_internals(gfp);

buffer = (buffer_t *) malloc(NSAMPLES*2); mp3buffer = (unsigned char *) malloc(MAXMP3);

printf("Tamanho do buffer pcm: %d amostras\n",NSAMPLES); printf("Tamanho do buffer mp3: %d bytes\n\n",MAXMP3);

lame_close(gfp);

/* Loop principal */ while(1){

gfp = lame_init(); lame_set_num_channels(gfp,CANAIS); lame_set_num_samples(gfp,NSAMPLES); lame_set_mode(gfp,MONO); lame_set_num_samples(gfp,1152); lame_set_brate(gfp, 16); lame_set_decode_only(gfp,1);

64

rc = lame_init_params(gfp);

lame_decode_init();

/* cc = numero de bytes recebidos */ fromlen = sizeof(from); cc = recvfrom(sd, mp3buffer, MAXMP3, 0, (struct sockaddr *) &from, &fromlen);

rc = lame_decode(mp3buffer, MAXMP3, buffer, NULL);

rc = snd_pcm_writei(handle, buffer, NSAMPLES*2);

if (rc < 0) rc = snd_pcm_recover(handle, rc, 0); if (rc < 0){ fprintf(stderr, "Reproducao de Audio falhou: %s\n", snd_strerror(rc)); break; } else if (rc != NSAMPLES*2) fprintf(stderr, "Short write. Expected %d samples, written %d samples\n", NSAMPLES, rc/2);

lame_close(gfp);

} }

65

ANEXO D -- lhal04.h

/******************************************************************************* * Biblioteca de Configuracao do Servidor de Audio escrita por mim que e * incluida no cdigo do servidor e do cliente o ******************************************************************************/

/* Bibliotecas Gerais */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h>

/* Bibliotecas de Audio */ #include <alsa/asoundlib.h>

/* Bibliotecas de Socket */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <arpa/inet.h>

#include <sys/time.h>

66

#include <time.h>

#define MAXHOSTNAME 80

/* Usa a API mais recente */ #define ALSA_PCM_NEW_HW_PARAMS_API

typedef short int buffer_t;

/* Define configuracoes de Audio */ #define CANAIS 1 #define SAMPLE_RATE 44100 #define NSAMPLES 1152 #define MAXMP3 lame_get_size_mp3buffer(gfp)

67

ANEXO E -- psyKernel

/******************************************************************************* * Este codigo e parte das modificaoes feitas no LAME pela NVidia como ponto c~ * inicial para o concurso de implementa~o do LAME em CUDA. Ele possui os ca * Kernels em CUDA e as funcoes em C utilizadas pelo LAME para executar em GPU ******************************************************************************/

#include <stdio.h> #include "cuda_runtime.h" #include "cutil.h" #include "cufft.h"

#include "../include/lame.h" #include "lame_global_flags.h"

#ifdef __cplusplus extern "C" void hpf( float *firc , float *samples, float *out, int nCoeff, int nSamples) ; extern "C" void scaler( float *data, int num_d, float scale) ; extern "C" void gpu_init(void); extern "C" void scaler2( float *d, float *d2, int num_d, float scl); #else

68

void hpf( float *firc , float *samples, float *out, int nCoeff, int nSamples); void scaler( float *data, int num_d, float scale); void gpu_init(void); void scaler2( float *d, float *d2, int num_d, float scl); #endif

/* Filtro passa-alta do modelo psicoacstico */ u

// filter coefficients taken from libmp3lame/pysmodel.c __constant__ float fircoef[] = { -8.65163e-18*2, -0.00851586*2, -6.74764e-18*2, 0.0209036*2, -3.36639e-17*2, -0.0438162 *2, -1.54175e-17*2, 0.0931738*2, -5.52212e-17*2, -0.313819 }; *2

__global__ void HPFilter(float *firc, float *firbuf, float *ns_hpfsmpl, int szCoeff, int nSamps ){

int idx = blockIdx.x * gridDim.x + threadIdx.x; int j = 0; float sum1; float sum2;

sum1 = firbuf[idx+10]; sum2 = 0.0f;

69

for( j=0 ; j<10; j+=2 ) { sum1 += fircoef[j ] * ( firbuf[idx+j ] + firbuf[idx+21-j] );

sum2 += fircoef[j+1] * ( firbuf[idx+j+1 ] + firbuf[idx+21-j-1] ); } ns_hpfsmpl[idx] = sum1+sum2; }

static float *gpuBuf = NULL; static float *hpfBuf = NULL;

void gpu_init(void) { CUDA_SAFE_CALL( CUDA_SAFE_CALL( } cudaMalloc((void**)&gpuBuf, 50000) cudaMalloc((void**)&hpfBuf, 50000) ); );

void hpf(float *coeff , float *samples, float *out, int nCoeff, int nSamples){

int nThreads = 32; int nBlocks = nSamples/nThreads; dim3 gridSz( nBlocks, 1, 1); dim3 blockSz( nThreads, 1 , 1);

if( gpuBuf == NULL ) gpu_init();

70

CUDA_SAFE_CALL(

cudaMemcpy(gpuBuf, samples, sizeof(float)*(nSamples +

nCoeff), cudaMemcpyHostToDevice));

HPFilter<<< gridSz, blockSz >>>( coeff, gpuBuf, hpfBuf, nThreads, nBlocks );

CUDA_SAFE_CALL(

cudaMemcpy(out, hpfBuf, sizeof(float) * nSamples, );

cudaMemcpyDeviceToHost)

/* Ajuste de escala de amostra */

__global__ void scaler_cuda(float *data_in, float *data_out, float scale){

int idx = (32 * blockIdx.x) + threadIdx.x;

data_out[idx] = data_in[idx] * scale;

void scaler(float *d, int num_d, float scl){

int nThreads = 32;

71

int nBlocks = num_d/nThreads; if(num_d % nThreads) { nBlocks++; }

dim3 gridSz( nBlocks, 1, 1); dim3 blockSz( nThreads, 1 , 1);

CUDA_SAFE_CALL(

cudaMemcpy(gpuBuf, d, sizeof(float)*num_d,

cudaMemcpyHostToDevice));

scaler_cuda<<< gridSz, blockSz >>>(gpuBuf, hpfBuf, scl);

CUDA_SAFE_CALL(

cudaMemcpy(d, hpfBuf, sizeof(float) * num_d, );

cudaMemcpyDeviceToHost) }

void scaler2(float *d, float *d2, int num_d, float scl){

int nThreads = 32; int nBlocks = (num_d * 2)/nThreads; if((num_d *2) % nThreads) { nBlocks++; }

72

dim3 gridSz( nBlocks, 1, 1); dim3 blockSz( nThreads, 1 , 1);

CUDA_SAFE_CALL(

cudaMemcpy(gpuBuf, d, sizeof(float)*num_d,

cudaMemcpyHostToDevice)); CUDA_SAFE_CALL( cudaMemcpy(&gpuBuf[num_d], d2, sizeof(float)*num_d,

cudaMemcpyHostToDevice));

scaler_cuda<<< gridSz, blockSz >>>(gpuBuf, hpfBuf, scl);

CUDA_SAFE_CALL(

cudaMemcpy(d, hpfBuf, sizeof(float) * num_d, );

cudaMemcpyDeviceToHost) CUDA_SAFE_CALL(

cudaMemcpy(d2, &hpfBuf[num_d], sizeof(float) * num_d, );

cudaMemcpyDeviceToHost) }

You might also like