• Nenhum resultado encontrado

4.3 Interpola¸c˜ao de HRTFs com a Transformada Wavelet

4.3.3 Mapeamento dos Pesos

O exemplo a seguir ilustra, na pr´atica, como os componentes polif´asicos s˜ao represen- tados. Considere um filtro H(z) = 1 + 2z−1+ 3z−2+ 4z−3. Seus componentes polif´asicos

desse filtro s˜ao: E0(z) = 1 + 3z−1 (pares) e E1(z) = 2 + 4z−1 (´ımpares).

4.3.3

Mapeamento dos Pesos

Conforme apresentado na Se¸c˜ao 4.3, existe um valor de peso w que ´e multiplicado com seus respectivos filtros esparsos para cada sub-banda e posi¸c˜ao no triˆangulo de interpola- ¸c˜ao. O m´etodo utilizado para a obten¸c˜ao dos pesos de cada sub-banda ´e o de otimiza¸c˜ao linear atrav´es de m´ınimos quadrados em pontos em que os coeficientes s˜ao conhecidos. Entretanto, esta abordagem n˜ao contempla os pesos de posi¸c˜oes desconhecidas. Assim, torna-se necess´aria a cria¸c˜ao de uma fun¸c˜ao de interpola¸c˜ao destes pesos tendo como refe- rˆencia os pesos obtidos nas dire¸c˜oes conhecidas. Com isso, ´e poss´ıvel reconstruir as HRIRs das posi¸c˜oes n˜ao conhecidas [13].

Escolheu-se o m´etodo de interpola¸c˜ao polinomial cubic spline pois, dentre os testes realizados em [13], ele se mostrou mais eficiente. Este m´etodo consiste em gerar os pesos de todos os azimutes para cada sub-banda em um ˆangulo de eleva¸c˜ao fixo. Em [14], o autor nomeia este procedimento de azimuth interpolation. Para o c´alculo dos pesos em eleva¸c˜oes intermedi´arias, que n˜ao s˜ao m´ultiplas de 10°, procedimento semelhante pode ser realizado. Para cada sub-banda e uma posi¸c˜ao de azimute constante, podem ser calculados os pesos para diferentes ˆangulos de eleva¸c˜ao. Isto ´e chamado de elevation interpolation.

Neste mecanismo de interpola¸c˜ao de HRTFs no dom´ınio da transformada wavelet, a interpola¸c˜ao na eleva¸c˜ao acontece da seguinte maneira. Dado um azimute θ, calcula-se a m´edia ponderada dos resultados da interpola¸c˜ao na eleva¸c˜ao para as duas eleva¸c˜oes mais pr´oximas.

˜

w(θ, φ) = α ˆw(θ, φL) + (1− α) ˆw(θ, φH) (4.38)

onde ˆw ´e o resultado da interpola¸c˜ao na eleva¸c˜ao para o azimute θ e as eleva¸c˜oes mais pr´oxima da eleva¸c˜ao de φ. φL e φH s˜ao, respectivamente, as eleva¸c˜oes mais pr´oximas

abaixo e acima da eleva¸c˜ao de P. α ´e calculado conforme equa¸c˜ao abaixo: α = φH− φ

φH − φL

Cap´ıtulo 5

Computa¸c˜ao Paralela com o uso de

Unidades de Processamento Gr´afico

Nos ´ultimos anos, o interesse no desenvolvimento e utiliza¸c˜ao de unidades de proces- samento gr´afico, GPUs, em projetos que demandam alto poder de processamento cresceu bastante. O r´apido aumento de performance juntamente com as melhorias em sua pro- gramabilidade associados ao baixo custo, quando comparadas a outras tecnologias, abriu caminhos para que esta se tornasse uma plataforma de pesquisa e desenvolvimento de aplica¸c˜oes intensas computacionalmente, nos mais diversos dom´ınios de aplica¸c˜ao.

O poder de processamento de placas gr´aficas cresce mais rapidamente que o poder de processamento das unidades centrais de processamento, CPUs, devido a diferen¸cas arquiteturais entre elas. A Figura 5.1 mostra este crescimento. Enquanto placas gr´aficas superam a marca de 1500 multiplicado por 106 opera¸c˜oes em ponto flutuante por segundo,

Giga Floating point Operations Per Second (GFLOPS)1, as CPUs ainda est˜ao abaixo de

250 GFLOPS.

As CPUs s˜ao projetadas para alcan¸carem melhor performance na execu¸c˜ao de c´odigos sequenciais, tendo que lidar tamb´em com caching de dados e controle de fluxo (branch predictions - previs˜ao de desvios). J´a as GPUs s˜ao especializadas em computa¸c˜ao paralela e projetadas de tal forma que mais transistores s˜ao dedicados ao processamento de dados, ao inv´es de utiliz´a-los no controle de fluxo e caching de informa¸c˜oes [54, 55]. A Figura 5.2 apresenta as principais diferen¸cas arquiteturais entre CPU e GPU. Enquanto na primeira o espa¸co destinado ao controle e a cache de dados ´e maior que o espa¸co destinado `as uni- dades l´ogicas e aritm´eticas, do inglˆes Arithmetic Logic Units (ALUs), na segunda, muito mais espa¸co ´e destinado para unidades de processamento de dados do que ao controle de execu¸c˜ao e a cache de informa¸c˜oes.

A GPU ´e ideal para problemas em que o mesmo programa pode ser executado parale- lamente em v´arios elementos de dados e que tenha alta densidade aritm´etica - o n´umero de opera¸c˜oes aritm´eticas deve ser maior que o n´umero de opera¸c˜oes em mem´oria. O processamento paralelo de dados permite que aplica¸c˜oes que necessitam processar um grande conjunto de informa¸c˜oes sejam executadas mais rapidamente. Desta maneira, o mesmo programa ´e executado sobre elementos de dados diferentes e n˜ao precisa de um mecanismo altamente eficiente de controle de fluxo. Muitos algoritmos fora do contexto de renderiza¸c˜ao e processamento de imagens s˜ao acelerados pelo processamento paralelo

Figura 5.1: Opera¸c˜oes em ponto flutuante por segundo. Fonte: NVIDIA CUDA C Pro- gramming Guide. Version 4.0 [54].

Figura 5.2: Diferen¸cas arquiteturais entre CPU e GPU. Fonte: NVIDIA CUDA C Pro- gramming Guide. Version 4.0 [54].

de dados, dentre eles, os softwares voltados para a resolu¸c˜ao de problemas da biologia (biologia computacional), softwares de processamento de sinais, simula¸c˜oes f´ısicas, dentre outros [54].

5.1

Breve Hist´orico da Computa¸c˜ao com GPU

´

E interessante entender o processo evolutivo desde os primeiros pipelines gr´aficos at´e os modelos de programa¸c˜ao conhecidos atualmente tais como CUDA™ e OpenCL™. Isso permite o entendimento do contexto que possibilitou a evolu¸c˜ao dos dispositivos gr´aficos e tamb´em facilita a cria¸c˜ao de melhores projetos para as futuras vers˜oes das GPUs.

Durante duas d´ecadas, de 80 e 90, houve a predominˆancia de hardwares gr´aficos con- figur´aveis mas n˜ao program´aveis. Neste per´ıodo, fun¸c˜oes fixas (fixed-functions) eram utilizadas e as interfaces de programa¸c˜ao de aplica¸c˜oes, Application Programming Inter- faces (APIs), tornaram-se populares. Dentre elas, destacam-se o DirectX™ da Microsoft e o OpenGL™, um padr˜ao aberto bastante popular e suportado por uma grande quantidade de fabricantes. Durante esta fase, a interface para o host recebia comandos, que chama- vam fun¸c˜oes da API gr´afica, e dados gr´aficos provenientes da CPU. A interface para o host tamb´em era respons´avel por retornar o estado e resultados de volta `a CPU ap´os a execu- ¸c˜ao dos comandos. Durante estas duas d´ecadas, cada nova gera¸c˜ao de hardwares oferecia novas melhorias aos diferentes est´agios do pipeline gr´afico. Entretanto, essa evolu¸c˜ao n˜ao acompanhava a demanda dos programadores por funcionalidades mais sofisticadas [56].

Assim que mecanismos de programa¸c˜ao para GPU surgiram, pesquisadores foram atraidos pela possibilidade de utilizar esse hardware gr´afico para o processamento e solu- ¸c˜ao de problemas de natureza diferente da gr´afica. Como inicialmente as ´unicas formas de construir aplica¸c˜oes que utilizassem o hardware gr´afico era por meio das APIs gr´aficas pa- dr˜oes como, por exemplo, OpenGL e DirectX, pesquisadores exploraram a computa¸c˜ao de prop´osito geral, ou seja, de prop´osito que n˜ao seja gr´afico, utilizando estas APIs. Assim, embora as aplica¸c˜oes que eles desenvolviam em GPU n˜ao fossem aplica¸c˜oes gr´aficas, estas eram progamadas de maneira que se parecesse com uma renderiza¸c˜ao gr´afica tradicional para a GPU [57].

Os pesquisadores perceberam, no come¸co do s´eculo XXI, que as GPUs foram projeta- das para produzir uma cor para cada pixel presente na tela como resultado de opera¸c˜oes realizadas sobre valores de entrada. Assim, a partir de algumas entradas, a cor de sa´ıda era calculada pela GPU. Como o c´alculo executado sobre esses parˆametros de entrada eram controlados pelos programadores, estes pesquisadores observaram que os parˆame- tros de entrada (cores, textura e outros) poderiam ser qualquer tipo de dado. Assim, a cor retornada pela GPU para cada um dos pixels da tela poderia ser interpretada como o resultado de qualquer opera¸c˜ao que foi executada em GPU solicitada pelo programador.

Entretanto, apesar de apresentar resultados motivadores, este modelo de programa¸c˜ao era muito restrito. Al´em da incapacidade de c´alculo de valores em ponto flutuante de algumas GPUs, quando o programa trazia resultados incorretos ou falhava na sua finali- za¸c˜ao, n˜ao existia um m´etodo eficiente de verificar como o c´odigo estava sendo executado naquele dispositivo. Al´em disso, o pesquisador que desejasse criar aplica¸c˜oes para serem executadas em GPU deveria aprender OpenGL ou DirectX, o que era um obst´aculo para uma maior aceita¸c˜ao dessa arquitetura [57].