You are on page 1of 87

UNIVERSIDADE DO VALE DO ITAJA

PR-REITORIA DE PS-GRADUAO, PESQUISA, EXTENSO E CULTURA


PROGRAMA DE MESTRADO ACADMICO EM COMPUTAO APLICADA

UM ESTUDO COMPARATIVO DE IMPLEMENTAES DO


FILTRO DE DIFUSO ANISOTRPICO PARA UNIDADES DE
PROCESSAMENTO CPU E GPU
Dissertao de Mestrado

por

Karl Phillip Purnhagen Ehlers Peixoto Dittrich Buhr

Eros Comunello, Dr. rer. nat.


Orientador

So Jos (SC), Outubro de 2010

UNIVERSIDADE DO VALE DO ITAJA


PR-REITORIA DE PS-GRADUAO, PESQUISA, EXTENSO E CULTURA
PROGRAMA DE MESTRADO ACADMICO EM COMPUTAO APLICADA

UM ESTUDO COMPARATIVO DE IMPLEMENTAES DO


FILTRO DE DIFUSO ANISOTRPICO PARA UNIDADES DE
PROCESSAMENTO CPU E GPU

por

Karl Phillip Purnhagen Ehlers Peixoto Dittrich Buhr

Relatrio de Dissertao apresentada como


requisito parcial obteno do grau de Mestre
em Computao Aplicada.
Orientador: Eros Comunello, Dr. rer. nat.

So Jos (SC), Outubro de 2010

RESUMO
BUHR, Karl Phillip Purnhagen Ehlers Peixoto Dittrich. Um Estudo Comparativo de
Implementaes do Filtro de Difuso Anisotrpico para Unidades de Processamento
GPU e CPU. So Jos, 2010, 86f. Dissertao (Mestrado em Computao Aplicada)
Programa de Mestrado Acadmico em Computao Aplicada, Universidade do Vale do Itaja,
So Jos, 2010.
A filtragem de imagens digitais tem um papel essencial em sistemas de viso computacional.
O objetivo consiste em suavizar e remover rudos em imagens digitais, auxiliando no
aumento do realce das bordas da imagem. Entretanto, um dos desafios inerentes rea de
processamento de imagens digitais o alto custo computacional existente para executar os
algoritmos com rapidez, o que dificulta sua utilizao em aplicaes em tempo real. Esta
dissertao apresenta um estudo de dois mtodos eficientes e de baixo custo para diminuir o
tempo de execuo do Filtro de Difuso Anisotrpico (FDA), uma tcnica de processamento
de imagens interessante para pr-processamento em sistemas de viso computacional. Os
mtodos fazem uso do processador grfico (GPU) como recurso computacional para acelerar
a execuo deste algoritmo. Atravs de duas implementaes do algoritmo em GPU
utilizando tecnologias diferentes para programao do hardware grfico (Cg e CUDA),
observou-se um aumento de desempenho bastante significativo na execuo do FDA nas duas
implementaes. Devido impreciso das GPUs para operaes de ponto flutuante, os
experimentos apresentam alm do comparativo de desempenho CPU-GPU, um mtodo para
quantificar o grau de similaridade dos resultados apresentados pelas GPUs em comparao
aos resultados da CPU.

ii

ABSTRACT
The filtering of digital images plays an essential role on computer vision systems. The aim is
to smooth and remove noises on digital images, assisting on the enhancement of edges on
images. However, one of the challenges of the field of digital image processing is the high
computational requirements needed to execute algorithms with speed, which makes it harder
to be used on real time applications. This master thesis presents a study of two low cost and
efficient methods to decrease the execution time of the Anisotropic Diffusion Filter (ADF),
an interesting image processing technique for pre-processing on computer vision systems.
Both methods use the graphics processor (GPU) as a computational resource to speed up the
execution of this algorithm. Through these two implementations of the algorithm on GPUs
using different technologies for the programming of the graphics hardware (Cg and CUDA),
a significant performance increase was observed on the execution of ADF on both
implementations. Due to the imprecision of the GPUs for floating point operations, the
experiments present not only CPU-GPU performance comparisons but also an efficient
method to quantify the degree of similarity between the results acquired by the GPUs, in
contrast with those of the CPU.

iii

LISTA DE ILUSTRAES
Figura 1 .................................................................................................................................. 11
Figura 2 .................................................................................................................................. 12
Figura 3 .................................................................................................................................. 29
Figura 4 .................................................................................................................................. 31
Figura 5 .................................................................................................................................. 32
Figura 6 .................................................................................................................................. 34
Figura 7 .................................................................................................................................. 41
Figura 8 .................................................................................................................................. 43
Figura 9 .................................................................................................................................. 44
Figura 10 ................................................................................................................................ 45
Figura 11 ................................................................................................................................ 52
Figura 12 ................................................................................................................................ 53
Figura 13 ................................................................................................................................ 56
Figura 14 ................................................................................................................................ 59
Figura 15 ................................................................................................................................ 59

iv

LISTA DE TABELAS
Tabela 1 .................................................................................................................................. 40
Tabela 2 .................................................................................................................................. 48
Tabela 3 .................................................................................................................................. 49
Tabela 4 .................................................................................................................................. 49
Tabela 5 .................................................................................................................................. 50
Tabela 6 .................................................................................................................................. 51
Tabela 7 .................................................................................................................................. 51
Tabela 8 .................................................................................................................................. 52
Tabela 9 .................................................................................................................................. 54
Tabela 10 ................................................................................................................................ 55
Tabela 11 ................................................................................................................................ 55
Tabela 12 ................................................................................................................................ 55
Tabela 13 ................................................................................................................................ 57
Tabela 14 ................................................................................................................................ 58
Tabela 15 ................................................................................................................................ 58

LISTA DE ABREVIATURAS E SIGLAS


APIs
ADF
Cg
CPU
CUDA
FBO
FDA
FPS
GHz
GFLOPS
GPGPU
GPU
MCA
MHz
OpenCV
OpenGL
PC
PCIe
PET
UNIVALI

Application Programming Interfaces


Anisotropic Diffusion Filter
C for Graphics
Central Processing Unit
NVIDIA Compute Unified Device Architecture
Frame Buffer Object
Filtro de Difuso Anisotrpico
Frames Por Segundo
Gigahertz
Gigaflops
General-purpose Computation on Graphics Processing Unit
Graphics Processing Unit
Mestrado em Computao Aplicada
Megahertz
Open Computer Vision Library
Open Graphics Library
Personal Computer
Peripheral Component Interconnect Express
Positron Emission Tomography
Universidade do Vale do Itaja

vi

SUMRIO
1 INTRODUO ................................................................................. 09
1.1 PROBLEMA DE PESQUISA .....................................................................12
1.1.1 Soluo Proposta....................................................................................13
1.1.2 Delimitao de Escopo ..........................................................................14
1.1.3 Justificativa ............................................................................................14
1.2 OBJETIVOS.................................................................................................16
1.2.1 Objetivo Geral........................................................................................16
1.2.2 Objetivos Especficos .............................................................................16
1.3 METODOLOGIA ........................................................................................16
1.3.1 Metodologia da Pesquisa .......................................................................16
1.3.2 Procedimentos Metodolgicos ..............................................................17
1.4 ESTRUTURA DA DISSERTAO ..........................................................18

2 FUNDAMENTAO TERICA ................................................... 20


2.1 PROCESSAMENTO DE IMAGENS DIGITAIS.....................................20
2.1.1 Processamento de Imagens em Tempo Real .......................................22
2.1.2 Filtro de Difuso Anisotrpico .............................................................24
2.1.3 Correlao Cruzada ..............................................................................26
2.2 GPGPU..........................................................................................................27
2.2.1 Pipeline Grfico .....................................................................................31
2.2.2 Cg: C for Graphics ................................................................................33
2.2.3 CUDA: Compute Unified Device Architecture ..................................35

3 TRABALHOS RELACIONADOS .................................................. 37


4 ESTUDO COMPARATIVO ............................................................ 41
4.1 IMPLEMENTAO EM CPU ..................................................................41
4.2 IMPLEMENTAO EM GPU..................................................................42
4.2.1 Implementao em Cg ...........................................................................42
4.2.2 Implementao em CUDA ....................................................................45

5 EXPERIMENTOS.............................................................................. 48
5.1 AMBIENTE EXPERIMENTAL ................................................................48
5.2 SIMILARIDADE DOS RESULTADOS COM A CPU ...........................50
5.3 TEMPO DE PROCESSAMENTO .............................................................54

6 CONCLUSO .................................................................................... 60
6.1 CONTRIBUIES .....................................................................................60
vii

6.2 TRABALHOS FUTUROS ..........................................................................61

7 REFERNCIAS ................................................................................ 63
APNDICE A ........................................................................................ 67
APNDICE B......................................................................................... 69
APNDICE C ........................................................................................ 82

viii

1 INTRODUO
A rea de processamento de imagens digitais tem recebido uma ateno muito grande
nos ltimos anos, como evidenciado pela enorme quantidade de artigos publicados
relacionados a acelerao de processamento, processamento em tempo real e tpicos
vinculados a aumento de performance. Estes tm sido temas recorrentes em diversos veculos
de comunicao cientficos, e pesquisadores da rea de processamento de imagens tm
aplicado suas solues a diversas reas industriais, como controle de robs, sistemas de
segurana, produtos eletrnicos com cmera digital, sistemas autnomos para navegao de
avies e tambm a outras reas do conhecimento, como meteorologia, medicina,
sensoriamento remoto e outros.
O notvel aumento de interesse da comunidade cientfica por solues que apresentem
resultados mais eficientes em termos de velocidade de processamento est ligado recente
evoluo tecnolgica dos processadores grficos e ao alto poder computacional que eles
oferecem. Estes processadores, conhecidos como GPUs (Graphics Processing Unit unidade
de processamento grfico), tm se mostrado uma plataforma atraente para tarefas
computacionalmente exigentes em uma variedade de domnios de aplicao, incluindo
simulao de dinmica de nuvens (HARRIS et al 2003), deteco de colises
(GOVINDARAJU et al. 2003), sequenciamento de DNA (cido desoxirribonucleico)
(ZHANG; ZHANG, 2006), simulaes fsicas (HARRIS et al. 2002),

ray tracing

(PURCELL et al. 2002), fiber tracking (MITTMANN et al. 2009), processamento de


imagens (MORELAND; ANGEL, 2003; FUNG; MANN, 2005), dentre outros.
Sistemas de processamento de imagens e vdeos digitais so normalmente projetados
com o objetivo de extrarem informaes relevantes a partir dos dados da imagem. Eles
buscam a restaurao da imagem ou o realce de determinadas estruturas visando facilitar sua
visualizao por seres humanos, ou, no caso do processamento de vdeo, proporcionar o
reconhecimento automtico de objetos, faces (ABATE et al. 2006) e gestos (BAYAZIT et al.
2009). Estes sistemas tambm encontram outras aplicaes, como acontece na indstria
automobilstica (HANDMANN et al. 2000). Durante o processo de aquisio da imagem,
uma etapa de pr-processamento pode ser necessria para eliminar rudos que podem ter sido
causados pelo prprio mecanismo de captura ou mesmo para suavizar determinadas

caractersticas e ressaltar outras, buscando atingir uma qualidade superior como resultado
final.
O desenvolvimento de um sistema eficiente de processamento de imagens ou vdeos
pode ser uma tarefa bastante desafiadora, especialmente quando o tempo de resposta um
fator crtico. Velocidade, preciso e robustez so aspectos importantes no projeto destes
sistemas. Nem sempre o melhor algoritmo consegue produzir a soluo tima dentro do
tempo esperado.
Pedrini e Schwartz (2008) definem formalmente um sistema de processamento de
imagens digitais como sendo constitudo por um conjunto de etapas capazes de produzir um
resultado a partir do domnio do problema. A Figura 1 sintetiza o conjunto de etapas de um
sistema de processamento de imagens, conforme proposto pelos autores, e destaca o contexto
no qual o FDA est inserido.
O pr-processamento de imagens acontece logo aps a etapa de aquisio das
imagens, que pode ser feita atravs de dispositivos ou sensores, como cmeras de vdeo,
scanners, satlites e outros. Dependendo do sensor escolhido, a imagem resultante pode
manifestar imperfeies decorrentes do prprio processo de aquisio. Desta forma, a etapa
de pr-processamento utiliza tcnicas de processamento de imagens para realizar atenuao
de rudos, correo de contraste ou suavizao de determinadas propriedades da imagem.
Atravs destas tcnicas, o pr-processamento busca melhorar a qualidade da imagem para a
etapa seguinte, de segmentao, que por sua vez procura realizar a extrao e identificao de
reas de interesse presentes na imagem.

10

Figura 1 Etapas de um sistema de processamento de imagens digitais, com destaque a etapa


de pr-processamento, da qual o FDA faz parte.
Fonte: Adaptado de Pedrini e Schwartz (2008, p. 4).
Neste contexto, o presente trabalho demonstra uma forma eficiente e de baixo custo
para melhorar o desempenho do FDA (Filtro de Difuso Anisotrpico) proposto por Weickert
(1998, 2000), um importante algoritmo para remoo de rudos e realce de contornos da
imagem (ver a Figura 2). O FDA auxilia na filtragem de imagens e processos de
segmentao, desempenhando um papel muito importante na anlise de imagens e na viso
computacional. Utilizando-se a unidade de processamento grfico, observou-se uma reduo
significativa no tempo de execuo deste algoritmo, aumentando o seu potencial para
aplicao em situaes onde a velocidade de resposta um fator determinante.

11

Figura 2 Da esquerda para a direita: uma foto digital; o resultado do processamento do FDA
utilizando um alto fator de contraste para eliminar eventuais rudos e realar as bordas dos
objetos na imagem.
A eficincia da abordagem proposta validada atravs da anlise do resultado da
execuo do algoritmo em CPU, comparando-se seu desempenho com a execuo do
algoritmo em GPUs. So investigadas duas arquiteturas diferentes de programao de GPUs
da NVIDIA, alm da utilizao de hardware grfico de famlias e datas de lanamento
diferentes.

1.1 PROBLEMA DE PESQUISA


Alguns dos grandes desafios da rea de processamento de imagens so a
disponibilidade e o custo financeiro do acesso a um dispositivo com poder computacional
suficiente para atingir grandes velocidades na execuo de sistemas ligados viso
computacional e interao homem-computador. Imagens e vdeos digitais so em essncia
sinais multidimensionais e, portanto, possuem um grande volume de dados. O processamento
em tempo real de quadros de vdeos algo difcil de se conseguir at mesmo com as CPUs
mais poderosas e modernas disponveis no mercado.
Como resultado da recente evoluo dos processadores grficos, pesquisadores e
desenvolvedores formaram uma comunidade interessada em usufruir o poder destes
processadores no contexto da computao cientfica. Essa tendncia ficou conhecida como
GPGPU (General-Purpose Computation on Graphics Processing Unit), e os fabricantes de
placas de vdeo reconhecendo este potencial de mercado, comearam a investir em APIs e
linguagens de programao de alto nvel para permitir o desenvolvimento de aplicativos
baseados em GPU.
12

As tecnologias utilizadas neste trabalho para programao de GPUs so


multiplataforma e ambas foram desenvolvidas pela pioneira NVIDIA. A primeira, a
linguagem Cg, surgiu aps o lanamento das primeiras GPUs programveis e era
inicialmente utilizada por desenvolvedores para a criao de efeitos visuais em aplicativos
com grficos em 3D. A segunda, CUDA, uma arquitetura de computao paralela projetada
para atender a demanda de desenvolvimento de aplicaes no grficas pela comunidade
GPGPU.
O FDA uma das tcnicas de processamento de imagens que bastante exigente com
relao aos recursos de memria e ao poder de processamento. Esta tcnica tem recebido
pouca ateno no desenvolvimento de aplicaes no mundo real devido ao seu alto custo
computacional, que pode inviabilizar uma soluo quando o tempo de processamento um
fator determinante, como na navegao de robs, na automao industrial e em aplicaes na
rea da sade.
Entretanto, as caractersticas deste algoritmo favorecem a sua paralelizao no
hardware grfico, como por exemplo, a interdependncia entre pixels da imagem e a
avaliao

dos

pixels

da

vizinhana.

Ambas

so

tarefas

bastante

exigentes

computacionalmente. Estas e outras caractersticas tornam este algoritmo um candidato


promissor para ter seu desempenho melhorado at mesmo em PCs convencionais. Neste
ponto surge a pergunta relevante para o desenvolvimento desta pesquisa: possvel melhorar
a performance do algoritmo FDA utilizando a GPU, levando-se em considerao o
desempenho e a qualidade dos resultados obtidos com a CPU?

1.1.1 Soluo Proposta


Diversos trabalhos que utilizam a tecnologia das GPUs tm se destacado na rea de
simulao de fluidos, computaes fsicas para jogos, lgebra linear, processamento de sinais,
processamento digital de imagens, processamento de bancos de dados, reconstruo de
imagens de tomografia e outros. Alguns trabalhos como o de Harris (2005), incluem
descries de como mapear conceitos computacionais para as GPUs, incluindo operaes
matemticas comuns da rea da viso computacional.
Trabalhos correlatos na rea de processamento de imagens digitais e processamento
de sinais (FUNG; MANN, 2004; GOVINDARAJU et al. 2003) apresentam ganhos
13

significativos relacionados acelerao do processamento de algoritmos. Sabe-se que a busca


por desempenho computacional envolve outros elementos, como, por exemplo, a preciso das
operaes de ponto flutuante realizadas pela GPU (HILLESLAND; LASTRA, 2004), que
influencia diretamente na qualidade dos resultados.
As GPUs modernas so de fato recursos computacionais poderosos, e este trabalho
analisa uma forma eficiente de paralelizar o algoritmo do FDA para sua execuo no
hardware grfico, utilizando a GPU como plataforma de processamento de baixo custo e alto
desempenho. Alm do tempo de execuo, outro aspecto avaliado a qualidade dos
resultados obtidos com o processamento da CPU e da GPU. Por causa da baixa preciso
numrica das computaes de ponto flutuante de algumas GPUs, que diferem das CPUs no
que se refere aos padres implementados, estima-se que podem ocorrer dissimilaridades entre
os resultados obtidos pelas implementaes. Considerando esta variabilidade, este trabalho
descreve um mtodo para mensurar e avaliar estas diferenas.

1.1.2

Delimitao de Escopo
Esta pesquisa se restringe a investigar as GPUs como uma plataforma de

processamento de alto desempenho atravs da linguagem de programao Cg e da arquitetura


de programao paralela da NVIDIA, conhecida como CUDA. So analisados os resultados
de processamento somente no quesito desempenho, cabendo aos resultados da
implementao em Cg serem avaliados tambm em termos qualitativos atravs de
comparao com resultados obtidos com a CPU.

1.1.3

Justificativa
Como mencionado anteriormente, o FDA normalmente empregado como filtro de

pr-processamento para melhorar operaes de deteco de bordas e para remoo de rudos.


Suas aplicaes tm sido observadas em imagens mdicas para detectar bordas em leses de
pele (CHUNG; SAPIRO, 2000), remoo de rudo em PET (Positron Emission Tomography)
(DEMIRKAYA, 2006) e outros (WEICKERT, 2001). No entanto, suas aplicaes tm sido
restringidas pelo fato da computao deste algoritmo ter alta intensidade numrica,
excedendo a capacidade da CPU em executar o algoritmo em tempo real.

14

Apesar das GPUs terem sido projetadas especificamente para renderizao e


modelagem 3D, a flexibilidade na programao das GPUs proporcionada pelas novas
arquiteturas e paradigmas de programao permite que elas sejam exploradas para tarefas
no-grficas. Isto fica evidenciado pelos diversos trabalhos publicados envolvendo GPUs
referenciados anteriormente que mostram ganhos na parte de desempenho em processamento.
Devido aos investimentos multibilionrios que so feitos anualmente no setor de
entretenimento, as placas de vdeo e suas unidades de processamento grfico evoluram muito
nos tempos recentes e se tornaram recursos computacionais de alto desempenho. Por
exemplo, a NVIDIA GeForce GTX 280, construda em um chip de 65nm com 240 cores de
processamento, operando a 602MHz, e com memria de 1GB GDDR3, operando a 1,1GHz e
acessada atravs de um barramento de 512 bits, capaz teoricamente de um poder de
processamento de 933 GFLOPS (NVIDIA, 2008). Em contraste, a CPU quad core 3GHz
Intel Xeon opera a cerca de 96 GFLOPS (INTEL, 2008).
Em contrapartida, o desenvolvimento de algoritmos para GPUs apresenta desafios
mesmo para problemas que so mapeados naturalmente para a GPU. De acordo com relatrio
do estado da arte de GPGPU (OWENS et al. 2005), apesar dos avanos na programabilidade,
continua sendo difcil utilizar o hardware grfico para realizar tarefas que no so
nativamente grficas. As GPUs utilizam um modelo de programao pouco comum, de forma
que programar GPUs no apenas uma questo de aprender uma nova linguagem de
programao.
Dentre os diferenciais deste trabalho, destaca-se a implementao do algoritmo FDA
na GPU atravs de duas tecnologias diferentes, Cg e CUDA. Outro ponto igualmente
importante a apresentao de um mtodo que permita avaliar a qualidade dos resultados
gerados pela GPU, visto o problema da diferena de preciso numrica de ponto flutuante
entre CPUs e GPUs. Com este propsito, o mtodo de validao proposto a correlao
cruzada normalizada (BROWN, 1992).

15

1.2 OBJETIVOS
1.2.1

Objetivo Geral
Elaborar um modelo de implementao do Filtro de Difuso Anisotrpico FDA que

utilize a GPU como recurso computacional, buscando acelerar o desempenho deste algoritmo
em comparao com a implementao tradicional que utiliza unicamente a CPU para o
processamento aritmtico.

1.2.2

Objetivos Especficos

Compreender o paradigma de programao das GPUs, incluindo seus limites,


restries e tecnologias disponveis para a programao do hardware grfico,
para modelar o FDA para esta arquitetura;

Projetar e implementar o algoritmo do FDA na GPU;

Realizar testes de desempenho com esta implementao em GPU;

Avaliar os resultados dos testes em contraste com os resultados apresentados


pela implementao em CPU; e

Utilizar o mtodo de correlao cruzada normalizada para avaliar a qualidade


dos resultados obtidos por ambas as implementaes.

1.3 METODOLOGIA
1.3.1

Metodologia da Pesquisa
Para a realizao deste trabalho foi empregado o mtodo hipottico-dedutivo, que

permite a verificao das hipteses atravs da anlise dos resultados encontrados. O problema
que foi identificado que a alta intensidade aritmtica do FDA tem um grande impacto no
tempo de processamento deste algoritmo. Foi formulada a hiptese de que possvel
aumentar o desempenho deste algoritmo empregando o poder de processamento da GPU,
desfrutando desta forma do baixo custo deste recurso computacional nos dias de hoje. A
utilizao de GPUs programveis tem mostrado resultados bem interessantes em pesquisas
feitas tanto na rea de processamento de imagens digitais como em outras reas. O primeiro
16

conjunto de experimentos mostra o tempo de execuo do algoritmo quando realizado na


CPU, e a segunda parte mostra o tempo de execuo do algoritmo na GPU. Por fim, atravs
dos resultados destes experimentos busca-se a validao da hiptese inicial.
Do ponto de vista da sua natureza, este trabalho se enquadra como pesquisa aplicada,
por dois motivos principais: primeiramente, ele objetiva atingir um resultado prtico visvel;
alm disto, ele tambm utiliza recursos que j esto disponveis nos computadores modernos,
evitando assim despesas adicionais e facilitando a sua utilizao pela sociedade.
Do ponto de vista da forma de abordagem do problema, este trabalho se classifica
como pesquisa quantitativa, pois possibilita mensurar e testar a hiptese. Os experimentos
contam com um determinado nmero de amostras, que buscam garantir uma preciso mais
alta nos resultados finais.
A pesquisa, quanto aos objetivos, conduz a uma experimentao, desta forma
caracterizando-se como pesquisa experimental.

1.3.2

Procedimentos Metodolgicos
Os procedimentos adotados para atingir os objetivos propostos foram formados

atravs de duas etapas: pesquisa bibliogrfica e pesquisa experimental. A pesquisa


bibliogrfica foi constituda de material cientfico publicado em peridicos, jornais, revistas e
congressos, e tambm a partir de livros.
Atravs do levantamento do estado da arte foi possvel delinear conceitos
computacionais de GPUs, modelos de programao, tcnicas e tecnologias empregadas na
programao de GPUs, possibilitando assim definir as ferramentas a serem utilizadas na
implementao do FDA em GPU.
Este estudo ajudou a esclarecer o funcionamento do pipeline grfico e do paradigma
de programao de GPUs. Levando-se em considerao o fato de que a NVIDIA, fabricante
de placas de vdeo, foi pioneira no desenvolvimento de GPUs programveis, optou-se por
utilizar GPUs deste fabricante. Consequentemente, utilizou-se as tecnologias de programao
Cg e CUDA, disponibilizadas pela prpria NVIDIA para programao de seus chips grficos.
Em uma das implementaes faz-se uso da linguagem Cg, que foi a primeira
linguagem de programao de alto nvel e multiplataforma disponibilizada pelo fabricante
17

para programao dos shaders da placa de vdeo. Nesta primeira implementao o algoritmo
do FDA foi programado no processador de fragmentos da placa de vdeo, tambm conhecido
como pixel shader, pois esta a soluo mais natural para realizar processamento de
imagens, visto que ele executa operaes no nvel do pixel.
A arquitetura paralela do pixel shader viabiliza o processamento de vrios pixels
simultaneamente. Para executar o algoritmo do FDA neste processador especfico foi
necessrio remodelar o algoritmo para encaix-lo no pipeline de renderizao da GPU.
Depois de determinar como o algoritmo deveria ser modelado, foram utilizados os recursos
do OpenGL para armazenar os dados da imagem e transferi-los para o pixel shader.
Na outra implementao utiliza-se CUDA, uma arquitetura de programao paralela,
mais moderna que Cg, e projetada para programao de propsito geral. Ao contrrio de Cg,
esta linguagem no requer conhecimento sobre o funcionamento do hardware grfico.
Para verificar o desempenho do algoritmo em GPU, foram realizados testes de
processamento com algumas GPUs, coletando-se o tempo gasto no processamento das
imagens. Foi utilizado um conjunto de imagens com 10 categorias de tamanhos diferentes,
sendo que cada categoria conta com 5 imagens coloridas, alcanando a soma de 50 testes
individuais para cada GPU.
Nos resultados obtidos observou-se uma certa discrepncia na qualidade das imagens
processadas com CPU e GPUs, devido a uma diferena de preciso na representao dos
nmeros de ponto flutuante existentes entre essas duas arquiteturas de processadores. Para
mensurar esta diferena que os resultados apresentaram, foi utilizada uma ferramenta
matemtica para quantificar a diferena nas imagens de CPU e GPU.

1.4 ESTRUTURA DA DISSERTAO


A seguir apresentada a organizao deste trabalho, descrevendo sucintamente o
contedo de cada captulo. O texto est organizado em 4 captulos. O Captulo 1, Introduo,
apresenta a contextualizao do tema deste trabalho, estabelece os resultados esperados
atravs dos objetivos propostos e apresenta as limitaes do trabalho, fornecendo um
panorama do escopo proposto.

18

O Captulo 2 apresenta a fundamentao terica, que revisa os principais conceitos


tericos utilizados no desenvolvimento do trabalho. Entre os tpicos abordados, encontra-se
uma introduo rea de processamento de imagens digitais, processamento de imagens em
tempo real, o filtro de difuso anisotrpico e o mtodo de correlao cruzada. Uma parte
deste captulo dedicada rea de GPGPU, com uma introduo ao pipeline grfico e s
tecnologias utilizadas no desenvolvimento do trabalho.
O Captulo 3 exibe uma anlise comparativa dos trabalhos correlatos e apresenta uma
tabela dos principais critrios analisados. Ele tambm salienta aspectos importantes que
diferenciam este trabalho dos demais.
O Captulo 4 apresenta o desenvolvimento do trabalho. Ele descreve detalhadamente
as implementaes do algoritmo em CPU e em GPU, utilizando pseudocdigo e ilustraes
para esclarecer as estratgias e as partes do algoritmo que foram mapeadas para o hardware
grfico.
Os experimentos so descritos no Captulo 5. Eles compreendem os dados das duas
implementaes a nvel de tempo de processamento CPU e GPUs e do grau de similaridade
dos resultados da implementao em Cg.
O Captulo 6 apresenta as concluses, as principais contribuies e sugestes de
trabalhos futuros.

19

2 FUNDAMENTAO TERICA
Este

captulo

apresenta

os

principais

conceitos

tericos

necessrios

ao

desenvolvimento do trabalho. A fundamentao terica aborda trs aspectos importantes do


trabalho: processamento de imagens digitais; GPGPU e o filtro de difuso anisotrpico.
A primeira seo faz uma sntese da rea de processamento de imagens e esclarece
conceitos bsicos. So destacadas algumas reas de aplicao onde as tcnicas de
processamento de imagens tm sido empregadas para solucionar problemas, e a seqncia de
passos que constituem um sistema de processamento de imagens exemplificada atravs de
ilustraes, de forma a auxiliar a compreenso de seus aspectos prticos e tericos. Com
relao ao desempenho das tcnicas de processamento de imagens, este captulo apresenta
ainda alguns conceitos sobre processamento de imagens e vdeos em tempo real.
Em seguida faz-se uma introduo ao filtro de difuso anisotrpico, descrevendo o
funcionamento do algoritmo e ressaltando algumas das caractersticas que fazem com que ele
seja uma soluo atraente para alguns tipos de problemas. Para demonstrar os efeitos do
algoritmo em imagens digitais, so apresentadas imagens obtidas como resultado direto do
processamento do algoritmo.
A segunda seo contextualiza a rea de GPGPU, apresentando as novas GPUs como
um recurso computacional de alto desempenho, que muitas vezes subutilizado ou at
mesmo permanece oculto aos olhos dos desenvolvedores. Ainda nesta seo so descritos os
avanos recentes destes equipamentos e tambm algumas das tcnicas e tecnologias,
livremente disponveis no mercado, para a programao deste hardware.

2.1 PROCESSAMENTO DE IMAGENS DIGITAIS


O processamento de imagens digitais uma rea que est em processo contnuo de
evoluo e que tem crescido muito devido rpida popularizao de produtos eletrnicos
como mquinas fotogrficas digitais, tomgrafos, cmeras de vdeo, celulares com cmeras
embutidas, sistemas de vigilncia inteligentes, satlites, etc. Equipamentos como estes
utilizam mtodos ou tcnicas de processamento de imagens por uma variedade de motivos,
como, por exemplo, para aumentar o contraste das imagens, reduzir rudos, extrair bordas,
realizar compresso de imagens ou realar determinadas caractersticas da imagem.
20

A rea de processamento de imagens digitais um campo dentro de uma cincia


maior conhecida como viso computacional. De acordo com Pedrini e Schwartz (2008),
a viso computacional procura auxiliar a resoluo de problemas altamente
complexos, buscando imitar a cognio humana e a habilidade do ser humano em
tomar decises de acordo com as informaes contidas na imagem.

Em outras palavras, a inteno da viso computacional disponibilizar um conjunto


de tcnicas para que sistemas computacionais possam interpretar e analisar informaes que
esto disponveis em imagens.
Apesar da viso computacional ser formalmente constituda por duas tarefas bastante
distintas, processamento de imagens e anlise de imagens, este estudo limita-se a uma viso
geral da parte de processamento de imagens.
Como apontado por Gonzales e Woods (2000), o interesse em mtodos de
processamento de imagens digitais decorre de duas reas principais de aplicao: melhoria de
informaes visuais para facilitar a interpretao humana e processamento de dados de cenas
para a percepo automtica atravs de mquinas.
Devido ao avano da tecnologia digital, possvel observar a aplicao de algoritmos
de processamento de imagens digitais em uma variedade de domnios, solucionando
problemas em reas como biologia, medicina, artes, arqueologia, meteorologia,
sensoriamento remoto, astronomia, automao industrial, microscopia e segurana, para
enumerar alguns.
Pedrini e Schwartz (2008) exemplificam algumas aplicaes, como, por exemplo, na
rea da medicina, onde a anlise e a interpretao de imagens capturadas por raios X,
tomografia computadorizada, ressonncia magntica e outros facilitam a identificao de
leses ou regies atingidas por cncer, permitindo maior preciso e rapidez nos diagnsticos.
No campo do sensoriamento remoto, a anlise de fotografias areas ou imagens de satlite
permitem uma melhor compreenso da superfcie terrestre, auxiliando o acompanhamento de
reas urbanas, a previso de fenmenos como terremotos, erupo de vulces, furaces,
monitorao de reas atingidas por eroso, previso de safras, determinao de reas de
desmatamento, etc. Na automao industrial, as aplicaes incluem a verificao de falhas
em circuitos impressos, a separao de peas por robs em uma linha de montagem e a
classificao de defeitos em soldas.

21

2.1.1

Processamento de Imagens em Tempo Real


Os sistemas de processamento de imagens e vdeos em tempo real, que envolvem uma

quantidade enorme de dados, desempenham um papel importante em sistemas de inspeo


industrial, onde indstrias empregam cmeras para capturar as atividades de produo e
controlar a qualidade do que est sendo produzido.
Estes sistemas permanecero fundamentais enquanto seu domnio continuar a
expandir no mercado de produtos eletrnicos, como o caso das cmeras de telefone celular,
cmeras digitais e de vdeo, media players portteis, sistemas de vigilncia e outros sistemas
embarcados de processamento de imagens ou vdeos.
Nesta seo so examinados alguns conceitos que esclarecem o significado do termo
tempo real, que utilizado frequentemente para descrever uma variedade muito grande de
algoritmos e sistemas de processamento de imagens e vdeos.
Devido variedade de interpretaes encontradas na literatura sobre tempo real,
neste trabalho so apresentados os conceitos de acordo com o entendimento de Gamadia e
Kehtarnavaz (2006). De acordo com os autores, existem trs interpretaes principais sobre
processamento em tempo real: o primeiro com relao ao senso de percepo, o segundo no
sentido de engenharia de software e o terceiro com relao a processamento de sinais.
Processamento em tempo real em relao ao senso de percepo utilizado para
designar a interao entre homem e um dispositivo computacional em casos onde o
dispositivo capaz de responder quase que instantaneamente a uma operao do usurio. No
contexto de processamento de vdeo, Bovik afirma que tempo real significa que o
resultado do processamento parece ser instantneo uma vez que a operao foi efetuada.
(BOVIK, 2005 apud GAMADIA; KEHTARNAVAZ, 2006). Da mesma forma, Guy (2004
apud GAMADIA; KEHTARNAVAZ, 2006) define o conceito de processamento de imagens
em tempo real como o processamento digital de uma imagem que ocorre imediatamente;
sem um atraso perceptvel pelo usurio.. Duas observaes importantes devem ser feitas: a
primeira que a definio de tempo real nestes casos envolve a interao do ser humano com
o computador, e a segunda que o retardo mximo tolervel definido com base na
percepo humana do atraso no domnio do tempo.

22

Segundo os autores, por exemplo, a atualizao de um algoritmo que realiza o balano


de cores em uma cmera digital no precisa ser executado em 33 milissegundos, o que
corresponde a uma taxa de exibio de 30 fps (frames por segundo). De fato, executar o
algoritmo a 100 milissegundos j seria suficiente para tornar imperceptvel ao ser humano o
processamento que ajusta o balano de cores para refletir as condies de luminosidade do
ambiente. Portanto, de acordo com os autores, se o algoritmo no demorar mais que 100
milissegundos para completar a tarefa seria considerado como tempo real pela percepo
do observador. A questo principal se o usurio final aceitaria a troca entre uma taxa de
atualizao mais demorada e uma melhor qualidade de imagem. A partir desta discusso fica
nitidamente claro que a definio de tempo real flexvel, pois o atraso mximo tolervel
completamente dependente da aplicao.
Processamento em tempo real de acordo com a engenharia de software tambm
baseado no conceito de um tempo limite de resposta, da mesma forma que o senso de
percepo. Dougherty e Laplante afirmam que um sistema de tempo real deve satisfazer
explicitamente as restries impostas quanto ao tempo de resposta aceitvel para evitar o
fracasso. (DOUGUERTY; LAPLANTE, 1995 apud GAMADIA; KEHTARNAVAZ, 2006).
Nesta interpretao, o importante o sistema respeitar os prazos estabelecidos. Da
perspectiva de um engenheiro de software, a questo do tempo real mais sobre o
desempenho ser previsvel do que somente o processamento ser veloz (LAPLANTE; NEILL,
2003 apud GAMADIA; KEHTARNAVAZ, 2006).
A interpretao dos autores sobre tempo real sob a tica do processamento de sinais
baseada na idia de completar o processamento no tempo disponvel entre a entrada
sucessiva de duas amostras. Por exemplo, para Kehtarnavaz tempo real completar o
processamento

dentro

do

tempo

disponvel

ou

permitido

entre

amostragens.

(KEHTARNAVAZ, 2004 apud GAMADIA; KEHTARNAVAZ, 2006) Em sistemas de


processamento de imagens, alm do perodo necessrio para o processamento, o tempo gasto
para transferir os dados da imagem e outras operaes pode introduzir pontos de congesto na
maioria dos sistemas, e estes devem ser levados em considerao (QURESHI, 2005 apud
GAMADIA; KEHTARNAVAZ, 2006).

23

2.1.2

Filtro de Difuso Anisotrpico


O filtro de difuso anisotrpico (FDA) uma tcnica importante de processamento de

imagens para remover rudos e melhorar determinadas caractersticas da imagem


(WEICKERT, 2001). Conforme apresentado por Weickert (1998), trata-se de uma tcnica de
convoluo que possui um kernel adaptativo responsvel por realizar uma suavizao seletiva
em imagens. De modo geral, ele inibe a suavizao em pixels de borda e a estimula em
regies internas.
Juntamente com outros mtodos de suavizao adaptativos, como filtros de
suavizao linear,

o FDA baseado na idia de aplicar um processo orientado por

propriedades locais da imagem. Ele tem sido utilizado como um filtro de pr-processamento
para melhorar operaes de deteco de bordas e de remoo de rudos. Trabalhos anteriores,
como o apresentado por Chung e Sapiro (2000), empregam o FDA em imagens mdicas para
auxiliar na segmentao de leses de pele.
A ideia bsica do FDA parte do modelo de Perona e Malik, apresentado em 1987, que
prope um modelo isotrpico e que, de acordo com Weickert, inibe problemas de borramento
e localizao (PERONA; MALIK, 1987 apud WEICKERT, 1998). O autor enfatiza que os
resultados dos experimentos de Perona e Malik eram visualmente impressionantes com
relao permanncia das bordas mesmo depois de algumas filtragens consecutivas
(PERONA; MALIK, 1990 apud WEICKERT, 1998), Foi demonstrado que a deteco de
bordas baseada neste processo claramente mostra resultados melhores do que o detector de
bordas Canny..
Eles aplicam um processo no uniforme que reduz a difusividade nos locais que
possuem uma probabilidade maior de serem bordas. Para isto, eles adaptam a equao de
difuso para que ela leve em conta esta probabilidade. A equao de difuso original

t u = div( D u ),

(1)

em que u a concentrao e D o tensor de difuso, um coeficiente do meio que, juntamente


com o gradiente da concentrao, define a intensidade do fluxo. Como a probabilidade de um
local fazer parte de uma borda pode ser expressa por | u |2 (WEICKERT, 1998), a equao
pode ser ajustada por uma funo g que leva em conta esta probabilidade, efetivamente

24

tornando a variao de concentrao dependente da intensidade da borda, resultando na


equao

t u = div( g (| u |2 )u ).

(2)

Entre as possveis funes g, os autores propem

g (s2 ) =

1
1 + s 2 / 2

( > 0).

(3)

Um dos problemas deste mtodo que, como a difuso inibida nas bordas da
imagem, os rudos presentes nas bordas no podem ser eliminados com sucesso
(WEICKERT, 1998). Para resolver este problema, segundo o autor, um mtodo mais
desejvel deveria dar preferncia difuso ao longo das bordas, deixando de lado a difuso
perpendicular a elas. Este objetivo pode ser alcanado construindo-se o tensor de difuso a
partir de autovalores e autovetores que refletem a orientao da borda na imagem. Partindo
de u , isto , do gradiente de concentrao transformado por uma suavizao gaussiana de
parmetro , os autovetores so

1 || u

v2 u .

(4)

Buscando dar preferencia suavizao ao longo das bordas, Weickert (1996, apud
WEICKERT, 1998) props definir os autovalores 1 e 2 como

1 (u ) := g (| u |2 ),

(5)

2 (u ) := 1.
A computao do FDA uma tarefa computacionalmente intensa, j que um
processo iterativo onde o coeficiente de difuso precisa ser calculado para cada pixel em cada
iterao da imagem, com base em sua vizinhana. Um algoritmo genrico para o filtro
anisotrpico pode ser dado como:
(1) Para cada pixel na imagem, um coeficiente de difusibilidade g calculado. uma
computao que envolve o pixel corrente, seus vizinhos e um fator de contraste que resulta
25

em 8 valores, cada um dos quais representa um vizinho. A frmula abaixo descreve a


computao do coeficiente g, que precisa ser calculado para a vizinhana de cada pixel:

qj =1

5
2
| |

5
4e

(6)

Aqui, g o fator de coeficiente, j a coordenada de um dos 8 possveis pixels


vizinhos, a diferena de intensidade entre o pixel atual e o vizinho que est sendo
considerado. O quociente do pixel calculado com base no quociente dos seus 8 vizinhos.
(2) Quocientes so alocados para cada pixel vizinho e usados como uma mscara
adaptativa para o clculo da convoluo.
(3) O valor de cada pixel calculado pela soma dos produtos de cada pixel vizinho
pelo seu respectivo peso atravs da convoluo.
Tendo em vista que o valor a ser calculado para cada pixel em cada iterao depende
s do estado dos seus vizinhos na ltima iterao, ele pode ser calculado separadamente dos
demais. Esta tcnica de processamento de imagens , portanto, um mtodo passvel de ser
implementada em uma arquitetura paralela.

2.1.3

Correlao Cruzada
A correlao cruzada (CC) utilizada neste trabalho para medir o grau de

similaridade entre as imagens resultantes de processamento em GPU com as de CPU.


Segundo Brown (1992), a correlao cruzada uma medida de similaridade entre duas
formas de onda. A correlao cruzada de duas imagens uma tcnica amplamente utilizada
para comparar duas imagens e encontrar sub-imagens, como demonstrado por Pratt (2001),
ou para realizar co-registro de imagens, como exemplificado por Crum (et al. 2003) e
tambm

Maintz e Viergever (1998), neste ltimo caso fornecendo uma medida de

similaridade entre as duas entidades que esto sendo comparadas.

26

Cada aplicao define um valor aceitvel para a similaridade, j que ele depende de
caractersticas intrnsecas da imagem. A maneira mais comum de usar a CC na sua forma
normalizada, dada pela equao (BROWN, 1992)

CC =

[I ( x, y) ][. I ( x, y) ]
[I ( x, y) ] . [I ( x, y) ]
x

(7)

que gera um nmero real no intervalo [0, 1], representando nveis entre nenhuma correlao
(caso em que CC = 0) ou uma combinao exata (CC = 1). No presente trabalho, a
similaridade entre duas imagens processadas deve ser igual a 1 no melhor cenrio, embora as
diferenas de ponto flutuante possam influenciar o resultado final.

2.2 GPGPU
Os avanos recentes na fabricao de processadores grficos transformaram as GPUs
em recursos computacionais extremamente atraentes, devido ao desempenho notvel
apresentado por estes dispositivos em termos de velocidade de processamento. Entre as
principais caractersticas das GPUs modernas, destacam-se o acesso rpido memria de
vdeo, clock de alta frequncia e mltiplos pipelines programveis (MIZUKAMI;
TADAMURA, 2006).
As modificaes no pipeline grfico possibilitaram que as GPUs deixassem de ser
utilizadas exclusivamente para processamento de primitivas grficas 3D e se tornassem
poderosos processadores paralelos de propsito geral (LUEBKE; HUMPHREYS, 2007). A
rpida evoluo dos processadores grficos foi uma conseqncia inevitvel do interesse da
indstria multibilionria do entretenimento. A demanda por jogos melhores e mais realistas
continua a impulsionar fortemente o desenvolvimento de chips grficos cada vez mais
potentes, capazes de prover experincias visuais mais ricas e interativas.
Esta evoluo despertou a ateno de comunidades de pesquisadores e
desenvolvedores interessados em utilizar o poder computacional das GPUs para outros
propsitos, no necessariamente ligados renderizao de grficos 3D. Esta tendncia
tecnolgica conhecida mundialmente como GPGPU (HARRIS et al. 2005). Por exemplo, a
27

NVIDIA GeForce GTX 280 contm 240 ncleos de processamento, que executam a
602MHz, e 1GB de memria GDDR3, acessada a 1.1GHz atravs de um barramento de
memria de 512 bits (PARK et al. 2008). Possui um poder de processamento que poderia
teoricamente chegar a 933 GFLOPS, ou seja, 933 bilhes de operaes de ponto flutuante por
segundo (NVIDIA, 2008). Em contraste, a CPU Intel Xeon quad core de 3GHz atinge no
mximo 96 GFLOPS (INTEL, 2008). Outro fato relevante apontado por Fan (et al. 2004) a
taxa de crescimento computacional das GPUs, que de aproximadamente 130% ao ano,
enquanto que a de CPUs de apenas 40%.
Em um trabalho publicado a alguns anos atrs, Owens (et al. 2005) revela os
desenvolvimentos de software e hardware que despertaram o interesse em GPGPU. Neste
trabalho os autores descrevem, resumem e analisam pesquisas que mapeiam a computao de
propsito geral no hardware grfico. Neste trabalho tambm so descritas as tcnicas
normalmente usadas no mapeamento de computao de propsito geral para o hardware
grfico.
Os fabricantes de processadores grficos, reconhecendo o potencial de mercado que a
comunidade de GPGPU representa, iniciaram um processo de transformao na arquitetura
das GPUs para torn-las um pouco mais flexveis e assim poderem disponibilizar linguagens
de programao de alto nvel para desenvolvedores produzirem aplicativos que utilizem a
GPU como um coprocessador aritmtico.
Embora as GPUs sejam mais eficientes para resolver tarefas computacionalmente
intensas, importante ressaltar que esta capacidade devida sua arquitetura altamente
especializada, projetada especificamente para a computao de primitivas grficas. Esta
natureza altamente especializada dificulta a utilizao de GPUs para realizar tarefas que no
so essencialmente grficas.
As CPUs atuais foram projetadas para lidar com aplicaes de forma diferente das
GPUs, de modo que as decises de projeto na arquitetura dos dois tipos de processadores os
levaram a caminhos bastante diferentes. Por exemplo, aplicativos grficos normalmente so
compostos por vrias tarefas sequenciais que podem ser realizadas simultaneamente, j que
os dados em questo no possuem interdependncia. Explorar o paralelismo dos dados , de
fato, um dos segredos para o sucesso no desenvolvimento de aplicativos para GPUs.

28

Segundo Owens (2003), o hardware da CPU utiliza o modelo de programao


seqencial, que geralmente no expe o paralelismo de dados em seus aplicativos como a
GPU faz. Entretanto, a CPU faz um trabalho interessante na forma com que explora o
paralelismo de instrues. Enquanto as GPUs adicionam transistores para aumentar o
processamento, grande parte dos transistores das CPUs so utilizados para implementar cache
de dados e estruturas complexas de controle de fluxo, como previso de desvio e execuo de
instrues fora de ordem, conforme ilustra a Figura 3, adaptada do guia de programao
CUDA da NVIDIA Corporation (2010).

Figura 3 A GPU dedica mais transistores ao processamento de dados.


Outra diferena observada na maneira com que os dois utilizam a memria. A CPU,
por exemplo, otimizada para ter a menor latncia possvel de memria, enquanto a GPU
concentra-se em maximizar a largura de banda de memria para transferncia de dados.
Devido falta de paralelismo, os programas em CPU devem retornar referncias a endereos
de memria o mais rpido possvel para continuar a sua execuo. Por consequncia, o
sistema de memria das CPUs contm vrios nveis de memria cache para minimizar esta
latncia. Caches so ineficientes para muitos tipos de dados, incluindo entradas de grficos e
dados que so acessados somente uma vez. Com relao s GPUs, Owens (2003) ainda
afirma:
Para o pipeline grfico, maximizar a taxa de transferncia para todos os elementos ao
invs de minimizar a latncia para cada elemento resulta num melhor aproveitamento
do sistema de memria e, acima de tudo, um desempenho melhor.

O modelo de programao orientado a streams caracterstico dos processadores


grficos e atualmente base para a programao de GPUs. Este modelo possui um paradigma
29

de programao pouco convencional, diferente daquele apresentado pelas CPUs. Desta


forma, desenvolver aplicativos para GPUs no somente uma questo de traduzir cdigos de
uma linguagem para outra. Obter melhor desempenho das GPUs requer um entendimento do
funcionamento do pipeline grfico e consequentemente das restries impostas pela
arquitetura.
Nem todos os algoritmos so passveis de serem mapeados de forma eficiente para a
GPU. Existem dois problemas principais, inerentes ao modelo de programao GPGPU, com
os quais os desenvolvedores precisam lidar. O primeiro, mencionado anteriormente, que
nem todos os algoritmos podem ser implementados de forma eficiente. A GPU mais rpida
somente para a resoluo de problemas que so inerentemente paralelos e que possuem alta
intensidade aritmtica. O segundo que a arquitetura impe limites quanto ao gerenciamento
dos dados. O acesso a dados atravs de opes de leitura e escrita algo bastante limitado e
conhecer o pipeline essencial na tarefa de adaptar o algoritmo para obter melhores
resultados na sua execuo pelo hardware grfico.
Mesmo o mais simples dos algoritmos requer uma reestruturao conceitual para ser
processado por APIs de computao grfica de baixo nvel, como OpenGL e DirectX, no
caso do desenvolvedor adotar a tecnologia Cg. Apesar da ateno crescente que a rea de
GPGPU tem recebido, o desenvolvimento para GPUs permanece uma tarefa tecnicamente
difcil j que ferramentas para escrita, depurao e otimizao so consideradas recentes, em
particular quando comparadas a alternativas disponveis h muito tempo para as CPUs.
Uma questo importante que deve ser levada em considerao no desenvolvimento de
certos aplicativos est relacionada preciso aritmtica, que ainda uma capacidade superior
do hardware da CPU. De acordo com Hillesland e Lastra (2004), algumas GPUs no seguem
o padro IEEE para operaes de ponto flutuante nem fornecem informaes necessrias para
estabelecer a margem de erro destas operaes. Isto se deve a razes histricas, j que o papel
inicial da GPU era exclusivamente o processamento de operaes do pipeline grfico, e estas
podiam ser resolvidas com sucesso atravs de preciso simples. As primeiras GPUs com
preciso dupla foram anunciadas recentemente pelos fabricantes.
As prximas sees descrevem o pipeline grfico moderno e as duas tecnologias
utilizadas para a implementao do algoritmo do FDA em GPU, Cg e CUDA. Ambas as
tecnologias so projetadas pela NVIDIA e permitem que desenvolvedores se beneficiem do
30

poder destes processadores para acelerar a execuo de tarefas computacionalmente


exigentes.

2.2.1

Pipeline Grfico
O pipeline grfico, tambm conhecido como pipeline de renderizao, o conjunto de

estgios de processamento pelos quais passam os dados enviados pelo usurio GPU.
Basicamente, o pipeline responsvel por converter coordenadas geomtricas em um cenrio
bidimensional para ser desenhado na tela. GPUs mais recentes podem trazer novos estgios
de processamento ao pipeline. Este trabalho refere-se ao pipeline moderno conforme definido
por Owens (et al. 2005).
Inicialmente, o aplicativo que executa na CPU envia os dados para a GPU atravs de
uma interface como OpenGL ou DirectX. Os dados podem incluir coordenadas dos vrtices,
coordenadas de textura e propriedades como valores de cor associados aos vrtices e grau de
transparncia. Este conjunto de dados descreve a cena que deve ser renderizada. O resultado
do pipeline consiste em objetos 2D que so salvos na memria do dispositivo grfico, mais
conhecida como frame buffer, para finalmente serem exibidos como uma imagem 2D no
monitor.
De certa forma, o pipeline semelhante a uma linha de montagem, onde cada estgio
adiciona algo ao resultado do estgio anterior, e todos funcionam em paralelo. A Figura 4
ilustra um diagrama simplificado do pipeline moderno.

Figura 4 Diagrama simplificado do pipeline moderno do hardware grfico.


Cohen e Mansour (2006) afirmam o seguinte com relao ao pipeline moderno:
No novo pipeline, as etapas de transformao + iluminao e texturizao +
colorizao de fragmentos so substitudas por estgios programveis, denominados
processador de vrtices e processador de fragmentos.

31

Uma verso adaptada do diagrama de alto nvel do pipeline moderno apresentado por
Goodnight (et al.2005) apresentada na Figura 5. Segundo o autor, a jornada de renderizao
comea no primeiro estgio do pipeline grfico, o processador de vrtices, que recebe vetores
de vrtices contendo alguns atributos, como, por exemplo, a localizao do vrtice no espao
3D e coordenadas de textura. A ordem de insero dos vrtices no vetor controla a maneira
como os tringulos so formados.

Figura 5 Diagrama de alto nvel do pipeline da GPU.

32

O processador de vrtices converte as coordenadas do objeto em coordenadas de


cmera e calcula suas respectivas posies de projeo na rea da tela, podendo ainda atribuir
cores e coordenadas de textura aos vrtices desenhados. A GPU conecta os vrtices
projetados para formarem tringulos, de acordo com a ordem com que as coordenadas foram
passadas pela aplicao 3D.
Em seguida, tringulos 2D so enviados ao estgio de rasterizao, que analisa cada
tringulo, descarta as partes que no sero exibidas na tela e divide a parte visvel em
fragmentos. Fragmentos so pixels que podero ser desenhados na tela. Eles carregam
informaes como coordenadas de textura, profundidade e cor.
Os fragmentos gerados so alimentados ao processador de fragmentos, que pode
realizar modificaes na cor dos fragmentos atravs de operaes de mapeamento de textura
e iluminao. O resultado deste estgio so cores e valores de profundidade que so
desenhados no frame buffer. O fato de que o processador de fragmentos programvel e
executa independentemente para cada pixel desenhado possibilita, por um lado, a realizao
de efeitos especiais sofisticados e, por outro, tem um papel decisivo no desempenho no
pipeline.
As GPUs so projetadas para seguirem esta estrutura bsica, apesar de que
arquiteturas mais recentes podem incorporar outros estgios e adicionar mais flexibilidade ou
desempenho s GPUs. Este modelo de pipeline fixo reinou durante quase duas dcadas. Os
estgios programveis permitem ao desenvolvedor de computao grfica implementar seus
prprios mtodos de iluminao de cena ou algoritmos de textura atravs de programas
chamados shaders. Como mencionado anteriormente, esta prtica se tornou bastante comum
e deu origem ao que conhecemos hoje como GPGPU.

2.2.2

Cg: C for Graphics


C for Graphics, mais conhecido como Cg, foi a primeira linguagem de alto nvel para

programao de GPUs disponibilizada pela NVIDIA. Ela surgiu logo aps as primeiras GPUs
programveis serem disponibilizadas, em uma poca em que os desenvolvedores s podiam
escrever programas para GPU em linguagens de baixo nvel como assembly. De acordo com
Fernando e Kilgard (2003), o intuito de Cg foi permitir aos desenvolvedores utilizarem o

33

hardware programvel de forma mais eficiente e criativa, mantendo o desempenho que a


linguagem assembly proporcionava.
Kilgard (et al. 2003) apresenta a linguagem Cg como sendo uma linguagem de
programao de alto nvel, semelhante a C em alguns aspectos mas voltada para programao
de GPUs.

Programas escritos em Cg so portveis entre geraes diferentes de GPUs e

sistemas operacionais, incluindo os mais conhecidos, como Microsoft Windows, Linux e Mac
OS X, e tambm entre as maiores APIs grficas, como OpenGL e DirectX. Normalmente,
programas em Cg so implementaes de algoritmos feitos por desenvolvedores para a
criao de efeitos visuais, como ilustra a Figura 6, adaptada de Mark e Kilgard (2003).

Figura 6 Capturas de tela de um programa de demonstrao em tempo real que utiliza Cg


para realizar um efeito de ferrugem na lataria do carro, como exibido na imagem B. A pintura
do carro A vai ficando mais enferrujada com o passar do tempo.
importante esclarecer que Cg no substitui as linguagens de propsito geral.
Programas escritos em C/C++ devem usar a API de Cg para carregar os programas em Cg, e
estes por sua vez sero executados na GPU. Isto quer dizer que Cg uma linguagem auxiliar.
O Cg runtime responsvel por carregar, compilar e gerenciar programas em Cg para serem
executados pelo processador de vrtices ou pelo processador de fragmentos da GPU.
Mark e Kilgard (2003) afirmam que, apesar de ser uma linguagem de programao
projetada para processadores de streams, Cg possui muitas semelhanas com a linguagem C,
sendo fortemente baseada na sua sintaxe e filosofia. Projetada para estar perto do nvel do
hardware, a linguagem C expe capacidades importantes da CPU, como tipos de dados e
ponteiros. A concepo de Cg segue uma filosofia similar, orientada ao hardware, permitindo

34

que tipos de dados e operadores tenham mapeamento direto, facilitando a escrita de cdigo de
alto desempenho.
Os autores ressaltam que, entre as principais caractersticas que guiaram a elaborao
da linguagem, destacam-se a facilidade na programao, a portabilidade, o suporte completo
a funcionalidades do hardware, o desempenho, a possibilidade de fcil adoo e o suporte
realizao de tarefas que no sejam necessariamente grficas.
O modelo de programao escolhido pelos projetistas da linguagem Cg segue o
modelo de programas mltiplos, que permite a ativao de um programa em Cg no
processador de vrtices independentemente de outro programa estar sendo executado no
processador de fragmentos. Este modelo exige que programas para os dois processadores
sejam escritos separadamente, sendo especficos para um processador ou para o outro, e que o
desenvolvedor tenha conhecimento da arquitetura do pipeline grfico.

2.2.3

CUDA: Compute Unified Device Architecture


CUDA uma nova arquitetura de computao paralela desenvolvida pela NVIDIA.

Foi projetada especialmente para a comunidade de GPGPU, para atender a demanda de


desenvolvimento de aplicaes no grficas. Ela serve como uma interface entre
desenvolvedores de software e a GPU, possibilitando que desenvolvedores executem seus
algoritmos diretamente na GPU atravs de extenses da NVIDIA para a linguagem C.
CUDA uma tentativa da NVIDIA de expandir seu pblico alvo, pois at pouco
tempo atrs as GPUs eram conhecidas somente pelo seu alto poder computacional no
processamento de streams, que so formados basicamente por conjuntos de vrtices, pontos e
pixels. Entretanto, a programao baseada em shaders, como oferece Cg, possui muitas
restries. Os algoritmos precisam ser mapeados para realizar transformaes de vrtices ou
iluminao de pixels, os dados precisam ser convertidos em mapas de texturas e,
diferentemente da CPU, os shaders no dispem de acesso aleatrio memria para
operaes de escrita de dados (PARK et al. 2008).
Umas das vantagens de CUDA que ela no exige que os desenvolveres tenham
conhecimento do pipeline grfico e nem do hardware das GPUs. Isto diminui a curva de
aprendizado para a maioria dos desenvolvedores de C/C++. Outra caracterstica que CUDA

35

tambm possui ponteiros para endereos de memria, o que permite acessos aleatrios para
operaes de leitura e escrita.
Castao-Dez (et al. 2008) listam algumas vantagens da plataforma CUDA, como, por
exemplo, o fato de a sintaxe ser constituda de extenses linguagem C, o que facilita a
adaptao de programas j existentes de forma rpida e intuitiva, a flexibilidade em estruturas
de dados, a melhoria no tempo de transferncia de dados entre CPU e GPU, o acesso
explcito a diferentes nveis de memria fsica e uma plataforma de desenvolvimento bem
documentada.
A arquitetura de CUDA trata a GPU como um coprocessador que aguarda instrues
vindas do aplicativo que est sendo executado na CPU. CUDA possui tambm uma API de
baixo nvel que apresenta os diferentes tipos de memria do hardware grfico, exigindo que o
desenvolvedor configure seus acessos memria global e ao cache, bem como o nmero e a
organizao dos threads, tudo isto para que o programa atinja um bom desempenho em
termos de tempo de execuo.
A GPU tem sua prpria memria DRAM. Isto faz com que os aplicativos
desenvolvidos com CUDA tenham espaos de memria separados. Desta forma, os dados so
movimentados da CPU para a GPU por um barramento PCIe atravs de funes da API de
CUDA que realizam alocao e cpia de memria para a GPU. Estas funes so muito
similares s funes em C que realizam este tipo de tarefa. Depois de enviar os dados para a
GPU, o programa que contm o algoritmo executado na GPU para processar os dados. Este
programa normalmente chamado de kernel. De acordo com a NVIDIA Corporation (2010),
o modelo de programao de CUDA define o kernel como uma funo em C que executada
na GPU por muitos threads, que por sua vez so agrupadas em blocos e executadas em
paralelo.
CUDA esta disponvel gratuitamente desde a sua primeira verso, lanada em 2007.
Desde ento foram desenvolvidas verses para Microsoft Windows, Linux e Mac OS X. A
tecnologia CUDA suportada por todas as GPUs que vieram depois da srie G8X da
NVIDIA, incluindo as linhas GeForce, Quadro e Tesla. O fabricante afirma que os programas
desenvolvidos para a srie GeForce 8 tero compatibilidade binria e por isto funcionaro
sem modificaes nas prximas placas de vdeo lanadas.

36

3 TRABALHOS RELACIONADOS
Este captulo descreve as contribuies de trabalhos correlatos a este, os quais foram
analisados de acordo com o hardware utilizado nos experimentos, fabricante, modelo de
GPU, e tecnologias empregadas para a programao do hardware e o tipo de processador de
acordo com o pipeline grfico. Um resumo da anlise comparativa dos trabalhos revisados
pode ser visualizado na Tabela 1.
Na Tabela 1 o sinal de hfen quer dizer que em alguns trabalhos os dados do critrio
avaliado em particular precisavam ser esclarecidos melhor ou simplesmente no foram
especificado no trabalho, e por isso no constam na tabela.
Este trabalho faz contribuies interessantes, pois at o presente momento no se tem
registro de implementaes abertas do algoritmo do FDA em GPU. Este trabalho contm
duas implementaes do algoritmo em GPU, ambas de cdigo aberto, e apresenta um
comparativo de desempenho no s entre CPU e GPU como normalmente visto em outros
traalhos, mas tambm entre GPUs diferentes, e tambm uma avaliao de implementaes do
algoritmo usando tecnologias diferentes e rodando na mesma GPU.
Uma outra contribuio do trabalho certamente a avaliao a nvel de qualidade de
resultado entre CPU e GPU. Esta contribuio bastante singular por levar essa questo em
considerao quando comparado com os trabalhos descritos a seguir. Uma caracterstica da
contribuio algo que foi pouco investigado pelos outros trabalhos, que a diversidade dos
testes de processamento realizados, que contam com uma diversidade de imagens com
tamanhos diferentes.
Purcell (et al. 2002) realizou uma das primeiras experincias envolvendo GPUs
programveis ao explicar a modelagem de um algoritmo de ray tracing para GPUs. Seu
trabalho demonstrou que o algoritmo escrito em assembly para a NVIDIA GeForce 3, no
processador de fragmentos, conseguia ter um desempenho maior em GPU. Este trabalho
publicado nos primrdios da era GPGPU demonstrou o potencial do hardware grfico
programvel como um dispositivo para computao genrica e paralela.
Harris (et al. 2003) mostra a utilizao do processador de fragmentos da GPU para
realizar simulaes da dinmica de nuvens em uma NVIDIA GeForce FX Ultra, com
37

programas de GPU escritos em Cg e usando OpenGL para transferncia dos dados. O


trabalho apresenta um mtodo interessante para otimizar a renderizao de cenas que
precisam de vrias iteraes de processamento, conhecido melhor atualmente como pingpong de frame buffers.
O trabalho de Bruyns e Feldman (2003) demonstra atravs da implementao em uma
GPU da NVIDIA, modelo FX 5900, a paralelizao de um algoritmo de busca que auxilia na
tarefa de rastrear movimentos de membros humanos e de animais. A implementao feita em
Cg, usa o processador de fragmentos da GPU para computao dos clculos envolvidos, entre
eles a Transformada Rpida de Fourier (Fast Fourier Transform). Para validar os resultados
os autores comparam o tempo de processamento da GPU com o CPU levando em
considerao apenas 3 tamanhos de imagens diferentes.
Fung e Mann (2004) examinam o processamento em GPU de alguns algoritmos de
viso computacional. Os algoritmos foram implementados utilizando OpenGL e Cg para
serem executados no processador de fragmentos de duas GPUs da NVIDIA, uma GeForce
FX 5900 e a outra uma GeForce FX 5200. Este trabalho tambm apresenta alguns conceitos
computacionais de GPUs e os resultados fornecem dados simples de comparaes de tempo
de processamento entre CPU e GPU.
Uma biblioteca e API de programao conhecida como OpenVIDIA foi apresentada
por Fung e Mann (2005) para acelerar tcnicas de processamento de imagens e viso
computacional em GPU. OpenVIDIA possui uma API projetada para aplicativos em C/C++ e
que usam OpenGL. Ela possui suporte a mltiplas GPUs e cdigo fonte do projeto
disponibilizado

como

cdigo

aberto.

Nesta biblioteca encontram-se tcnicas

de

processamento de imagens como o mtodo Canny para deteco de bordas, tcnicas para
filtragem e registro de imagens, entre outras tambm implementadas no processador de
fragmentos atravs da linguagem Cg.
Castao-Dez (et al. 2008) avaliam o desempenho em GPU de algoritmos comuns
utilizados para processamento de imagens em 3 dimenses. Os algoritmos foram avaliados na
NVIDIA QUADRO FX 5600, capaz de executar aplicativos desenvolvidos para a plataforma
CUDA, e entre eles esto algoritmos de transformao espacial, operaes de Fourier,
procedimentos de reconhecimento de padres, e de reconstruo e procedimentos de
classificao. O desempenho dos algoritmos varia de acordo com o tipo do algoritmo mas
38

segundo os autores, em geral so de 10 a 20 vezes mais rpidos que a implementao em


CPU.
Farrugia (et al. 2006) apresentam GPUCV, uma biblioteca de cdigo aberto para
desenvolvimento aplicativos de viso computacional e processamento de imagens que
acelerada por GPU. GPUCV fornece converso de cores, histograma e operaes
morfolgicas. Ela foi projetada para ser uma extenso de uma outra biblioteca de
processamento de imagens bastante conhecida como OpenCV, que foi originalmente
desenvolvida pela Intel. A biblioteca usa OpenGL para se comunicar com a GPU e GLSL
para implementar os algoritmos que so executados no processador de fragmentos e vrtices
da GPU. Os resultados envolvem comparaes simples de um CPU Pentium 4 com 1
gygabyte de RAM e uma GPU GeForce 7800 GTX.
Park (et al. 2008) demonstram a sua abordagem para paralelizao e otimizao do
algoritmo Canny para deteco de bordas e sua aplicao em conjunto com um algoritmo
para rastreamento de movimentao em vdeos. Este trabalho utiliza o framework de
programao CUDA e discute estratgias para otimizar o algoritmo. Para avaliar a
efetividade do mtodo sugerido por eles, so utilizadas duas GPUs diferentes, NVIDIA
8600M GT e NVIDIA 8800 GTS, em comparao com um CPU Intel Core 2 de 2.4 GHz.
Finalmente, o presente estudo analisa duas implementaes do FDA para GPU
levando em considerao duas tecnologias diferentes para tal, utilizando 5 GPUs diferentes
para realizar os experimentos. O trabalho apresenta um comparativo de desempenho entre
essas implementaes, e ainda um comparativo a nvel de qualidade de resultado entre CPU e
GPUs, algo que no foi abordado por nenhum dos trabalhos analisados anteriormente.

39

Tabela 1 Anlise comparativa dos trabalhos relacionados.


GPU(s)

Tecnologia

Purcell (et al. 2002)

NVIDIA GeForce 3

Assembly

Fragmentos

Harris (et al. 2003)

NVIDIA GeForce FX Ultra

Cg / OpenGL

Fragmentos

Bruyns e Feldman (2003)


Fung e Mann (2004)

NVIDIA FX 5900
NVIDIA GeForce FX 5900
NVIDIA GeForce FX 5200
-

Cg / Cg / OpenGL

Fragmentos
Fragmentos

Cg / OpenGL

Fragmentos

NVIDIA QUADRO FX 5600

CUDA

Farrugia (et al. 2006)

NVIDIA GeForce 7800 GTX

GLSL / OpenGL

Fragmentos e Vrtices

Park (et al. 2008)

NVIDIA GeForce 8600M GT


NVIDIA GeForce 8800 GTS

CUDA

Buhr (2010)

NVIDIA GeForce 6600


NVIDIA GeForce 7600 GT
NVIDIA GeForce 8600 GT
NVIDIA GeForce 8800 GTS
NVIDIA GeForce GTS 250

Cg, CUDA

Fragmentos

Fung e Mann (2005)


Castao-Dez (et al. 2008)

40

Tipo de Processador

4 ESTUDO COMPARATIVO
Para atingir os objetivos do trabalho foram feitas trs implementaes do algoritmo do
FDA, uma em CPU e outras duas em GPU. Este captulo est dividido em sees, e cada uma
delas descreve uma implementao do filtro em particular. A primeira seo mostra como foi
realizada a implementao do algoritmo em CPU, que serve como base para as outras. As
duas sees seguintes descrevem as implementaes em GPU utilizando Cg e CUDA,
respectivamente. A ltima seo do captulo descreve o procedimento de validao, que
envolve o clculo da correlao cruzada entre as imagens processadas.

4.1 IMPLEMENTAO EM CPU


Esta considerada a implementao original e de referncia no trabalho. Os
resultados obtidos com o processamento dos dados em CPU so utilizados como base de
comparao com os dados obtidos atravs das implementaes em GPU.
A implementao do algoritmo em CPU segue uma seqncia simples de tarefas,
conforme ilustrado no diagrama abaixo. Este modelo de execuo bastante similar ao que
utilizado na implementao em GPU usando CUDA. O cdigo desta implementao foi
escrito nas linguagens de programao C e C++.

Figura 7 Sequncia de operaes para execuo do FDA.


Primeiro, os dados que sero enviados para processamento so carregados a partir de
uma imagem no disco rgido e armazenados na memria RAM do computador. Para realizar
41

esta tarefa foi utilizada uma biblioteca prpria para processamento de imagens, que
multiplataforma e de cdigo aberto, chamada OpenCV.
Neste momento os dados devem ser convertidos para um outro formato antes de
serem submetidos ao processamento pelo algoritmo do FDA. Esta converso de dados
necessria porque a OpenCV disponibiliza os dados na memria como um vetor de bytes do
tipo unsigned char, que possui 8 bits. Processar os dados neste formato acarretaria perda de
preciso dos dados, e portanto eles so convertidos manualmente para o formato float, de 32
bits.
Depois da converso, os dados so submetidos a um conjunto de instrues que
executa o algoritmo do FDA e processa os dados. Como a Figura 7 sugere, no incio desta
etapa que o contador do tempo de processamento inicializado. Quando o algoritmo termina
sua execuo, os novos dados ficam disponveis na memria RAM e o contador de tempo
parado.
Basicamente, o tempo de processamento comea a contar a partir do momento em que
os dados da imagem foram convertidos e esto disponveis para a etapa de processamento, e
ele termina assim que o FDA encerra a sua execuo. Depois disto, os novos dados so
convertidos para o formato original e a OpenCV pode grav-los como uma imagem no disco
rgido. O tempo gasto para realizar esta tarefa no entra na contagem do tempo de
processamento.
Visto que o funcionamento do algoritmo j foi explicado no Captulo 2, o cdigofonte do ncleo do algoritmo, tambm chamado de kernel, pode ser encontrado no Apndice
A. A prxima seo descreve o funcionamento do kernel do FDA utilizando pseudocdigo.
Esta parte computacionalmente idntica em todas as implementaes.

4.2 IMPLEMENTAO EM GPU


4.2.1

Implementao em Cg
Esta implementao difere bastante das outras porque o cdigo-fonte precisou ser

transformado para se encaixar nos moldes do pipeline grfico. Para comear, a


implementao em Cg depende de uma biblioteca grfica, neste caso OpenGL, cuja funo
carregar os dados da imagem e transport-los para a memria da GPU.
42

Na GPU, uma imagem representada como uma textura 2D do OpenGL, j que as


texturas so utilizadas primariamente para armazenar informaes de cores da superfcie de
um determinado objeto. Nesta implementao foi adicionado suporte a texturas cujas
dimenses no precisam ser exclusivamente potncias de dois para habilitar a transferncia
de imagens de tamanhos diversos para a memria da GPU. Em essncia, as texturas so
mapeadas em quadrilteros em um ambiente virtual. Ao invocar a rotina de desenho da cena
virtual, a CPU envia informaes sobre este objeto e a textura associada para que a GPU
inicie o processamento.
Buscando reduzir o tempo de execuo do FDA, o ncleo da computao do
algoritmo foi implementado no processador de fragmentos da GPU, pois ele possibilita que
vrios pixels sejam processados simultaneamente. Apesar de esta estratgia melhorar o
desempenho do algoritmo, ela tambm dificulta o processador de monitorar a ordem em que
os pixels devem ser processados. Algoritmos como o FDA so baseados em varreduras
sequenciais da imagem e possuem uma taxa alta de referencia a localidade do pixel. Isso quer
dizer que o processamento do pixel atual depende do resultado obtido pelo processamento
anterior de pixels vizinhos.
Quando a rotina de desenho chamada, o Cg Runtime fica responsvel em executar o
algoritmo na GPU, que, entre outras coisas, computa o coeficiente de difusividade (DC). O
DC , na prtica, um clculo entre o pixel central e cada um dos seus 8 vizinhos, levando-se
em considerao um fator de contraste definido pelo usurio, conforme o pseudocdigo da
Figura 8.

Figura 8 Pseudocdigo para computao do DC no processador de fragmentos.


A Figura 9 expe o pseudocdigo onde os pesos so calculados para todos os 8 pixels
vizinhos. O valor final do pixel central ento calculado como a soma do produto de cada
pixel vizinho com seus respectivos pesos.
43

Figura 9 Pseudocdigo para calcular os pesos.


O FDA aplicado iterativamente na imagem at que seja executado um determinado
nmero de vezes estipulado pelo usurio. O aplicativo em GPU deveria ser capaz de executar
o kernel no processador de fragmentos inmeras vezes em cima dos dados enviados pela
CPU, mas a natureza altamente especializada da GPU probe que isto seja realizado de uma
forma simples e direta.
O modelo de memria da CPU permite a alocao de memria local e global em um
programa a qualquer momento, enquanto na GPU o modelo de memria segue um conjunto
de regras bem mais restrito. A GPU possui uma filosofia de acesso memria mais limitada,
onde a memria global s fica disponvel para operaes de escrita no estgio final do
pipeline grfico.
Para solucionar este problema, os dados devem interagir com o pipeline atravs de
acessos ao frame buffer via mltiplas passadas usando funcionalidades do hardware grfico,
como renderizao para textura e objetos de frame buffer (FBO Frame Buffer Object),
ambos disponibilizados pelo OpenGL. Um clculo tradicional em GPU requer que uma
textura possua os dados de entrada e outra esteja disponvel para armazenar os dados da sada
para cada iterao no pipeline.
Entretanto, uma abordagem de passadas mltiplas pode ser utilizada para processar a
imagem iterativamente. Esta estratgia, conhecida como ping-pong e ilustrada na Figura 10,
requer que dois FBOs sejam configurados e possuam uma textura anexada a cada um.
Enquanto o primeiro armazena os dados que sero processados no pipeline, o segundo fica
esperando para receber os dados do ltimo estgio no final do pipeline. Depois da primeira
passada pelo pipeline os dados so armazenados no segundo FBO. Neste momento acontece
uma inverso de papis, e o segundo toma o lugar do outro, alimentando o pipeline com
dados ao mesmo tempo em que o primeiro deslocado para substituir o segundo, que passa a
44

armazenar os dados processados pelo pipeline. Estas trocas de FBOs so necessrias para
evitar que os dados voltem para a CPU no final de uma iterao e depois tenham que voltar
novamente para a GPU para serem processados uma segunda vez.

Figura 10 Troca de FBOs, onde os dados de sada de uma iterao se tornam os dados de
entrada da prxima no pipeline da GPU.

4.2.2

Implementao em CUDA
Como framework de desenvolvimento para GPUs, CUDA foi projetada para facilitar a

transio do desenvolvedor tradicional para a programao paralela exigida pelas GPUs. Esta
caracterstica realmente possibilitou uma implementao mais rpida do FDA em GPU, j
que ela no requer conhecimentos profundos do hardware grfico e nem do seu pipeline.
Conforme mencionado nas sees anteriores, esta verso do FDA em GPU tambm
segue a mesma sequncia de operaes ilustrada na Figura 7 e utilizada nas outras
implementaes. A maior diferena est na etapa de processamento dos dados, que utiliza
chamadas da API de CUDA para transferir os dados e ativar a execuo do kernel que
contm o algoritmo do FDA, ao contrrio da implementao em Cg, que depende de uma
biblioteca grfica como OpenGL para realizar a mesma tarefa.
Apesar de ser considerada uma linguagem de baixo nvel, CUDA fornece diversas
abstraes para facilitar a programao das GPUs, como, por exemplo, na utilizao da
memria de textura, que uma das formas mais utilizadas para trafegar informaes entre
CPU e GPU. Diferentemente de Cg, alocar memria de textura e transferir os dados para a
GPU pode ser realizado de forma simples atravs de funes como cudaMallocArray,

45

cudaMemcpyToArray e cudaBindTextureToArray, que aloca memria na GPU, realiza a


transferncia dos dados e anexa estes dados a uma textura, respectivamente.
A escolha do tipo de memria tem um impacto significativo no tempo total de
execuo do algoritmo. Uma das vantagens da memria de textura a velocidade na
operao de leitura dos dados em memria. O kernel do algoritmo possui uma alta taxa de
referencia a localidade do pixel. Em termos leigos, o kernel realiza muitas operaes de
acesso memria para ler os dados dos pixels vizinhos para cada pixel que ele deve
processar, e exatamente neste tipo de situao que a memria de textura se torna atraente.
O kernel que contm o algoritmo do FDA em CUDA virtualmente o mesmo que o
utilizado na implementao em Cg. O que muda, basicamente, so os nomes das funes que
fazem o acesso aos dados e realizam as operaes matemticas. Do ponto de vista da
implementao do algoritmo, o ncleo da computao realizado da mesma maneira e pode
ser considerado idntico nas duas implementaes.
No final da execuo de uma iterao, a funo cudaMemcpyToArray chamada para
movimentar os dados na memria da GPU para o caso de eles precisarem ser processados
novamente. Esta operao poupa a transferncia desnecessria dos dados para a CPU quando
o algoritmo deve ser executado iterativamente. Esta operao o equivalente
implementao da tcnica de pingue-pongue de FBOs, discutida na seo anterior, que
necessria em Cg para alcanar o mesmo resultado.
Uma caracterstica importante da prpria tecnologia CUDA que ela executa o kernel
de maneira assncrona. Ou seja, a funo de CUDA que inicia a execuo do kernel na GPU
retorna imediatamente aps ser chamada e o controle das instrues volta para o CPU mesmo
antes do kernel terminar de ser executado. Inicialmente, isto representa um problema porque
a natureza iterativa do algoritmo obriga a CPU a reposicionar os dados na GPU para a
prxima iterao, e sem um mecanismo apropriado de controle os dados podem acabar sendo
movimentados na GPU antes mesmo de terem sido processados corretamente. Entretanto, a
API de CUDA tambm disponibiliza uma funo chamada cudaThreadSynchronize que
utilizamos logo aps o kernel ter sido ativado para garantir que a CPU aguarde o fim da
execuo do kernel na GPU antes de movimentar os dados na memria.
Outro detalhe importante da implementao e que tambm tem impacto significativo
no desempenho do aplicativo a definio do grid computacional, que especifica o tamanho
46

dos blocos e do nmero de threads. Nos testes realizados, observou-se que a configurao do
grid computacional que obteve melhor desempenho foi
block _ size = (image _ width / 8) (image _ heigh / 8),

(8)

em que a funo teto, e cada bloco contm 64 threads que executam o kernel do FDA em
paralelo.

47

5 EXPERIMENTOS
Este captulo descreve o ambiente aonde foram realizados os experimentos e
apresenta os grficos e as tabelas dos dados de correlao cruzada entre as imagens CPU e
GPU, e tambm do tempo de processamento obtidos durante a conduo dos experimentos.
No final do captulo algumas imagens so exibidas para ilustrar melhor as diferenas entre
imagens processadas pela CPU e pela GPU.

5.1 AMBIENTE EXPERIMENTAL


Como mencionado anteriormente, os experimentos realizados buscam avaliar a
eficincia das implementaes em nvel de tempo de execuo do algoritmo e tambm da
qualidade da imagem resultante deste processamento, comparando os resultados obtidos em
CPU com as implementaes em GPU.
No teste em CPU foi utilizado um computador com processador Intel Core 2 Duo com
o perfil de hardware descrito na Tabela 2. importante ressaltar que grande parte do
hardware utilizado nos testes foi gentilmente cedido temporariamente pelo Grupo Cyclops
(Grupo Cyclops, 2009), de forma que no houve necessidade de fazer investimentos na
compra de equipamentos, e desta forma manter a filosofia de utilizar apenas os recursos que
j estivessem disponveis no ambiente.
Tabela 2 Configurao de hardware do computador utilizado para rodar os experimentos
em CPU.
Componente

Especificao

Placa-me

ASUS P5NSLI

Processador

Intel Core 2 Duo Processor E8400

Frequncia

3.0 GHz

Cache L1

32Kb + 32 Kb

Cache L2

6 MB

Memria RAM

2 GB

Tipo

DDR2

Frequncia

667 MHz

Configurao

Dual Channel

Nos testes em GPUs foram utilizadas cinco placas de vdeo da NVIDIA com modelos
diferentes para testar as implementaes. Apesar de utilizarmos placas de vdeo diferentes, os
48

testes da implementao em Cg e da implementao em CUDA puderam utilizar o mesmo


computador com o propsito de manter uma nica configurao de hardware, conforme
descrito na Tabela 3.
Tabela 3 Configurao de hardware do computador utilizado para os experimentos em
GPU.
Componente

Especificao

Placa-me

ASUS M2N-E

Processador

AMD Athlon 64 X2 Dual Core 4400+

Frequncia
Cache L1

2.2 GHz
128 KB x 2

Cache L2

512 KB x 2

Memria RAM

2 GB

Tipo

DDR2

Frequncia

800 MHz

Configurao

Single Channel

As placas de vdeo para os testes em Cg so especificadas na Tabela 4, todas do


fabricante NVIDIA. Os modelos utilizados compreendem a GeForce 6600, a GeForce 7600
GT e a GeForce 8800 GTS, esta ltima tambm empregada nos testes da implementao em
CUDA.
Tabela 4 Configurao de hardware das GPUs utilizadas para avaliar a implementao em
Cg.
6600

7600 GT

8800 GTS

Agosto, 2004

Agosto, 2006

Novembro, 2006

256 MB

256 MB

320 MB

500 MHz

700 MHz

800 MHz

Tipo

DDR2

GDDR3

GDDR3

Interface

128 bits

128 bits

320 bits

Banda

8 GB/s

22.4 GB/s

64 GB/s

Processadores

17

96

Frequncia

300 MHz

560 MHz

1200 MHz

Lanamento
Memria
Frequncia

A idia de utilizar o mesmo computador para executar todos os testes em GPU surgiu
com o intuito de minimizar as variveis que poderiam ter alguma influncia na execuo dos
experimentos. A verso do Cg Toolkit utilizada durante os testes foi a verso 1.5. A verso
do CUDA SDK instalada para executar a implementao em CUDA foi a 3.1 juntamente com
o driver de vdeo da prpria NVIDIA verso 190.53.
49

Tabela 5 Configurao de hardware das GPUs utilizadas para avaliar a implementao em


CUDA.
8600 GT

8800 GTS

GTS 250

Abril, 2007

Novembro, 2006

Maro, 2009

256 MB

320 MB

512 MB

Frequncia

700 MHz

800 MHz

1100 MHz

Tipo

GDDR3

GDDR3

GDDR3

Interface

128 bits

320 bits

256 bits

22.4 GB/s

64 GB/s

70.4 GB/s

Processadores

32

96

256

Frequncia

1180 MHz

1200 MHz

1836 MHz

Lanamento
Memria

Banda

O cdigo fonte das implementaes podem ser encontrados na seo de apndices,


localizada no final do trabalho. importante ressaltar que a implementao do FDA no
descarta nenhuma operao aritmtica durante o seu processamento, como outros algoritmos
que levam em considerao a cor ou tonalidade dos pixels para iniciar uma operao. Isso
quer dizer que o clculo do FDA em uma determinada regio sempre acontece
independentemente das caractersticas dos pixels daquela regio, sejam eles coloridos,
brancos ou todos verdes.
Embora as imagens originais no sejam necessrias para reproduzir estes
experimentos, as imagens utilizadas nos testes bem como os resultados em CPU e tambm da
implementao

em

Cg

esto

disponibilizadas

no

endereo

http://www.lapix.ufsc.br/index.php/high-performance-gpu-based-anisotropic-diffusionfiltering- . Qualquer conjunto de imagens que respeitem os tamanhos especificados neste


trabalho pode ser utilizado para validar nossa abordagem.

5.2 SIMILARIDADE DOS RESULTADOS COM A CPU


Visto que as GPUs mais recentes resolvem o problema da impreciso numrica das
GPUs em operaes de ponto flutuante, optou-se por restringir os testes e medir o grau de
similaridade entre os resultados CPU e GPU apenas com a implementao em Cg do
algoritmo, que executada em GPUs mais antigas.
As comparaes qualitativas realizadas com base na correlao cruzada entre os
resultados do processamento em CPU e em GPU so muito prximas na maioria dos casos,
como mostram as Tabelas 6, 7 e 8.

Para compreender melhor as tabelas abaixo, deve-se


50

levar em considerao que o clculo da correlao cruzada normalizada retorna o grau de


similaridade entre duas imagens como um valor no intervalo entre 0 e 1, sendo 1 uma
comparao exata. Desta maneira, os valores das tabelas podem ser entendidos como o nvel
de similaridade entre uma imagem processada em GPU com relao mesma imagem sendo
processada em CPU.
Tabela 6 Correlao cruzada entre as imagens geradas pelo CPU e pela GPU NVIDIA
6600.
Tamanho
10x15
320x240
720x400
1024x768
1600x1024
2048x1536
2400x1600
2832x2128
3488x2616
3888x2592

Imagem #1
0,9419
0,9941
0,9897
0,9922
0,9984
0,9975
0,9978
0,9994
0,9980
0,9993

Imagem #2
0,9567
0,9960
0,9976
0,9947
0,9979
0,9947
0,9973
0,9981
0,9978
0,9990

Imagem #3
0,3512
0,9932
0,9972
0,9979
0,9974
0,9986
0,9970
0,9988
0,9973
0,9976

Imagem #4
0,7524
0,9975
0,9981
0,9969
0,9989
0,9980
0,9982
0,9984
0,9980
0,9967

Imagem #5
0,8759
0,9987
0,9982
0,9979
0,9986
0,9982
0,9988
0,9983
0,9989
0,9984

Nas Tabelas 6, 7 e 8 possvel perceber que os valores de correlao cruzada para


imagens de 10x15 fogem ao padro da tabela ao apresentar valores abaixo de 0,99. Isso se
deve ao fato de que esta uma imagem extremamente pequena, e, portanto, possui um
conjunto de dados igualmente pequeno quando comparado aos outros testes. Desta forma, por
menor que seja a diferena da imagem processada pela GPU, a menor variao na imagem
ter uma representatividade maior por se tratar de um conjunto pequeno de dados, o que no
acontece com conjuntos maiores.
Tabela 7 Correlao cruzada entre as imagens geradas pelo CPU e pela GPU NVIDIA 7600
GT.
Tamanho
10x15
320x240
720x400
1024x768
1600x1024
2048x1536
2400x1600
2832x2128
3488x2616
3888x2592

Imagem #1
0,9419
0,9941
0,9897
0,9922
0,9984
0,9975
0,9978
0,9994
0,9980
0,9993

Imagem #2
0,9567
0,9960
0,9976
0,9947
0,9979
0,9947
0,9973
0,9981
0,9978
0,9990

Imagem #3
0,3512
0,9932
0,9972
0,9979
0,9974
0,9986
0,9970
0,9988
0,9973
0,9976

Imagem #4
0,7524
0,9975
0,9981
0,9969
0,9989
0,9980
0,9982
0,9984
0,9980
0,9967

Imagem #5
0,8759
0,9987
0,9982
0,9979
0,9986
0,9982
0,9988
0,9983
0,9989
0,9984

possvel perceber que as Tabelas 6 e 7 apresentam os mesmos valores de correlao


cruzada. Esse fato no mera coincidncia. As GPUS NVIDIA 6600 e 7600 GT possuem a
mesma preciso numrica para operaes de ponto flutuante e, portanto, apresentam imagens
51

idnticas como resultado de processamento. Desta forma, era de se esperar que a correlao
cruzada das imagens resultantes tambm fosse exatamente igual. A NVIDIA 8800 GTS por
outro lado, possui uma preciso numrica mais para este tipo de operao e por isso apresenta
resultados levemente mais similares a CPU que as outras GPUs.
Tabela 8 Correlao cruzada entre as imagens geradas pelo CPU e pela GPU NVIDIA 8800
GTS.
Tamanho
10x15
320x240
720x400
1024x768
1600x1024
2048x1536
2400x1600
2832x2128
3488x2616
3888x2592

Imagem #1
0.9417
0.9941
0.9894
0.9922
0.9984
0.9975
0.9978
0.9994
0.9982
0.9993

Imagem #2
0.9568
0.9960
0.9977
0.9947
0.9979
0.9947
0.9973
0.9981
0.9978
0.9990

Imagem #3
0.3512
0.9932
0.9972
0.9979
0.9974
0.9986
0.9970
0.9988
0.9973
0.9977

Imagem #4
0.7524
0.9975
0.9981
0.9969
0.9989
0.9980
0.9982
0.9984
0.9980
0.9967

Imagem #5
0.8760
0.9987
0.9982
0.9979
0.9986
0.9982
0.9988
0.9983
0.9989
0.9984

A Figura 11 mostra um grfico das amostras obtidas nas tabelas acima apenas para
facilitar a sua visualizao, tornando possvel observar de forma mais clara o elevado grau de
similaridade das imagens geradas pela GPU com relao s geradas pelo CPU. As diferenas
nas imagens so sutis, como podemos observar na Figura 12, e observadores no treinados
podem encontrar um pouco de dificuldade para notar as diferenas.

Figura 11 Grfico do grau de similaridade das imagens geradas pela implementao em


GPU usando Cg sendo comparadas as imagens do algoritmo em CPU.

52

Figura 12 Em A, a imagem original utilizada no teste. Em B, a imagem processada pelo


CPU e em C, a imagem processada pela GPU.

53

5.3 TEMPO DE PROCESSAMENTO


Os resultados destes experimentos foram organizados em tabelas, de forma a agrupar os
tempos que cada unidade de processamento levou para executar o algoritmo no conjunto de
imagens selecionado para os testes. Os valores nas tabelas representam a quantidade de
tempo em segundos que o processador em questo levou para processar cada imagem, sendo
que os parmetros utilizados nos testes foram o fator de constraste, 15, e o nmero de
iteraes do algoritmo em uma mesma imagem tambm foi 15.
Um ponto importante a ser esclarecido, no conjunto de imagens de teste que foram
selecionados existem 5 exemplares de imagens para cada tamanho de imagem que
investigado nos experimentos. Desta forma, a tabela inclui tambm a mdia total do tempo
de processamento de cada tamanho e ainda o desvio padro destes dados, que mostra uma
disperso bem baixa do tempo de processamento entre as amostras, e que se acredita que no
cause um impacto significante nos resultados.
A Tabela 9 mostra os tempos de processamento do FDA em um CPU Intel Core 2
Duo 3 GHz. Atravs dela possvel observar que o processamento mais rpido aconteceu
com a menor imagem do conjunto, de 10x15, e as que levaram mais tempo para serem
processadas foram as maiores, de 3888x2592 pixels, como era de se esperar. As informaes
desta tabela servem de referncia e so comparadas mais tarde com os resultados das GPUs e
plotados em grficos para facilitar a visualizao das informaes.
Tabela 9 Resultado dos tempos de processamento do algoritmo no CPU Intel Core 2 Duo
3GHz.
CPU
10x15
320x240
720x400
1024x768
1600x1024
2048x1536
2400x1600
2832x2128
3488x2616
3888x2592

#1
0,009
3,796
13,794
40,739
77,851
152,826
186,435
287,924
434,626
481,418

#2
0,009
3,802
13,909
40,739
77,844
152,818
186,42
287,853
435,495
482,171

#3
0,009
3,797
13,795
40,745
77,845
152,818
186,437
287,875
434,596
481,335

#4
0,009
3,799
13,796
40,758
77,86
152,828
186,441
287,888
434,725
481,817

#5
0,009
3,794
13,794
40,738
77,848
152,824
186,428
287,853
434,498
482,171

Mdia
0,009
3,7976
13,818
40,744
77,85
152,82
186,43
287,879
434,788
481,782

Desvio P.
0,000
0,003
0,046
0,008
0,006
0,004
0,007
0,026
0,361
0,357

As Tabelas 10, 11 e 12 mostram os resultados do processamento em GPU, que rodam


a verso em Cg do algoritmo. Na tabela 10 j possvel observar os ganhos no tempo de
execuo do algoritmo apesar deste processador ser o mais fraco de todas as GPUs usadas
nos testes, em termos de poder computacional. Enquanto uma imagem de 3888x2592 leva
54

cerca de 8 minutos para ser processada no CPU, a mesma imagem processada em menos de
5 segundos na GPU da NVIDIA 6600, e em menos de 1 segundo na NVIDIA 8800 GTS, uma
placa de vdeo j lanada a cerca de dois anos atrs.
Tabela 10 Resultado dos tempos de processamento em GPU da implementao com Cg na
NVIDIA 6600.
GPU 6600
10x15
320x240
720x400
1024x768
1600x1024
2048x1536
2400x1600
2832x2128
3488x2616
3888x2592

#1
0,205
0,247
0,335
0,579
0,961
1,617
1,910
2,862
4,201
4,629

#2
0,212
0,242
0,338
0,666
0,963
1,626
1,911
2,861
4,195
4,633

#3
0,208
0,249
0,349
0,593
0,962
1,616
1,911
2,858
4,196
4,628

#4
0,230
0,249
0,344
0,589
0,963
1,613
1,921
2,861
4,194
4,632

#5
0,217
0,237
0,350
0,584
0,965
1,613
1,909
2,859
4,202
4,630

Mdia
0,214
0,245
0,343
0,602
0,963
1,617
1,912
2,860
4,198
4,630

Desvio P.
0,009
0,005
0,006
0,032
0,001
0,005
0,004
0,001
0,003
0,002

Tabela 11 Resultado dos tempos de processamento em GPU da implementao com Cg na


NVIDIA 7600 GT.
GPU 7600 GT
10x15
320x240
720x400
1024x768
1600x1024
2048x1536
2400x1600
2832x2128
3488x2616
3888x2592

#1
0,188
0,266
0,281
0,375
0,500
0,735
0,875
1,203
1,703
1,860

#2
0,187
0,250
0,297
0,375
0,500
0,765
0,890
1,203
1,719
1,844

#3
0,203
0,266
0,297
0,360
0,500
0,750
0,859
1,203
1,703
1,860

#4
0,203
0,281
0,297
0,375
0,500
0,750
0,859
1,250
1,688
1,843

#5
0,202
0,282
0,266
0,375
0,500
0,750
0,860
1,250
1,718
1,844

Mdia
0,197
0,269
0,288
0,372
0,500
0,750
0,869
1,222
1,706
1,850

Desvio P.
0,007
0,012
0,012
0,006
0,000
0,009
0,012
0,023
0,011
0,008

Tabela 12 Resultado dos tempos de processamento em GPU da implementao com Cg na


NVIDIA 8800 GTS.
GPU 8800 GTS
10x15
320x240
720x400
1024x768
1600x1024
2048x1536
2400x1600
2832x2128
3488x2616
3888x2592

#1
0,207
0,297
0,316
0,374
0,434
0,469
0,51
0,595
0,779
0,829

#2
0,208
0,293
0,339
0,346
0,433
0,46
0,508
0,597
0,758
0,83

#3
0,207
0,294
0,336
0,392
0,431
0,48
0,509
0,599
0,759
0,831

#4
0,208
0,317
0,348
0,337
0,406
0,453
0,487
0,596
0,761
0,83

#5
0,292
0,315
0,325
0,383
0,403
0,485
0,486
0,622
0,759
0,835

Mdia
0,224
0,303
0,333
0,366
0,421
0,469
0,500
0,602
0,763
0,831

Desvio P.
0,034
0,011
0,011
0,021
0,014
0,012
0,011
0,010
0,008
0,002

Analisando o desempenho entre as prprias GPUs no processamento daquela imagem


com 10x15 pixels, possvel notar um aspecto interessante. O tempo de execuo do
algoritmo nestas GPUs no mudou praticamente nada para esta imagem, o que a princpio
pode parecer estranho j que se trata de chips com uma diferena muito grande de poder

55

computacional. Isso sem levar em considerao que o CPU levou apenas 0,009 segundos para
processar esta imagem, cerca de 20 vezes mais rpido que qualquer uma das GPUs.
O motivo para esse comportamento que as GPUs possuem uma latncia de memria
que a CPU no tem. Enquanto a CPU pode acessar imediatamente os dados que esto
disponveis na memria RAM do computador, a GPU gasta uma parcela do tempo total do
processamento para transferir os dados para a sua memria de vdeo interna. Os dados dos
experimentos sugerem que esta latncia esta na casa dos 200 milisegundos, tornando a CPU
mais interessante que a GPU para o processamento de imagens pequenas. importante
ressaltar que os parmetros utilizados, como o nmero de iteraes do algoritmo, tem
impacto direto no tempo de execuo. Nos testes, a GPU acaba realizando 15 iteraes do
algoritmo na imagem antes de transport-la de volta memria RAM do computador.
De acordo com a Tabela 12, o tempo de processamento de uma imagem de
2048x1536 pixels utilizando os parmetros padres leva um pouco menos que 500
milisegundos. Neste tempo, como discutido anteriormente, j est embutido o tempo gasto
pela GPU para transportar os dados entre a memria interna da placa de vdeo e a memria
RAM, que algo em torno de 200 milisegundos. Sabendo que a NVIDIA 8800 GTS leva
menos que meio segundo para processar a imagem 15 vezes, seguro afirmar que essa GPU
capaz de executar 30 vezes o algoritmo do FDA em menos de 1 segundo, caracterizando
desta maneira o processamento em tempo real do FDA em imagens de at 2048x1536 pixels
utilizando uma NVIDIA 8800 GTS.
Atravs da Figura 13 torna-se evidente que a implementao do algoritmo em GPU
utilizando Cg causou uma melhora bastante significativa no tempo de execuo do FDA.
Como por exemplo, na imagem de 3888x2592 pixels, onde a GeForce 8800 GTS processou a
imagem 580 vezes mais rpida que a CPU. O grfico abaixo tambm mostra mais claramente
que nesta implementao em particular existe um ganho crescente em desempenho, e que
essa tendncia est diretamente ligada ao tamanho da imagem.

56

Figura 13 Grfico que compara os ganhos das 3 GPUs que rodaram a implementao em
Cg do algoritmo, com relao a CPU.
Nas Tabelas 13, 14 e 15 encontram-se as informaes do tempo de processamento da
verso do algoritmo que utiliza CUDA para rodar na GPU. Das placas de vdeo utilizadas nos
testes anteriores somente a NVIDIA 8800 GTS suporta a tecnologia CUDA, e por isso no
foi possvel fazer um comparativo com as outras placas de vdeo utilizadas no experimento
em Cg.
Tabela 13 Resultado dos tempos de processamento em GPU da implementao em CUDA
na NVIDIA 8600 GT.
GPU 8600 GT
10x15
320x240
720x400
1024x768
1600x1024
2048x1536
2400x1600
2832x2128
3488x2616
3888x2592

#1
0,046
0,148
0,301
1,124
1,471
2,784
3,4
5,294
8,02
8,84

#2
0,042
0,142
0,325
0,745
1,469
2,782
3,416
5,308
8,022
8,79

#3
0,039
0,129
0,299
0,75
1,473
2,603
3,391
5,29
7,923
8,881

#4
0,046
0,143
0,328
0,732
1,49
2,782
3,393
5,373
8,019
8,873

#5
0,044
0,148
0,3
0,725
1,49
2,792
3,398
5,295
8,003
8,757

Mdia
0,043
0,142
0,311
0,815
1,479
2,749
3,400
5,312
7,997
8,828

Desvio P.
0,003
0,007
0,013
0,155
0,009
0,073
0,009
0,031
0,038
0,048

Na Tabela 14 tambm pode-se observar alguns aspectos interessantes, como por


exemplo, no existe tempo de execuo registrado para as imagens de 3488x2616 e
3888x2592 porque a GPU abortou o processamento destas imagens. Apesar de no poder
afirmar com absoluta certeza o motivo exato disto ter acontecido, existe uma forte suspeita de
que o problema tenha sido falta de memria na prpria GPU, j que a funo do aplicativo
57

que falhou era relacionada a essa tarefa. Outro detalhe que tambm desconhecemos a causa
variao inexplicvel no tempo de processamento das imagens com 2832x2128 pixels.
Tabela 14 Resultado dos tempos de processamento em GPU da implementao em CUDA
na NVIDIA 8800 GTS.
GPU 8800 GTS
10x15
320x240
720x400
1024x768
1600x1024
2048x1536
2400x1600
2832x2128
3488x2616
3888x2592

#1
0,027
0,064
0,152
0,653
0,527
0,984
1,2
1,861
-

#2
0,028
0,051
0,148
0,302
0,528
0,983
1,203
5,308
-

#3
0,031
0,057
0,148
0,299
0,554
0,987
1,196
5,29
-

#4
0,034
0,053
0,143
0,293
0,536
0,928
3,393
1,197
-

#5
0,03
0,058
0,156
0,303
0,534
0,986
3,398
1,212
-

Mdia
0,030
0,057
0,149
0,370
0,536
0,974
2,078
2,974
-

Desvio P.
0,002
0,004
0,004
0,142
0,010
0,023
1,076
1,914
-

Tabela 15 Resultado dos tempos de processamento em GPU da implementao em CUDA


na NVIDIA GTS 250.
GPU GTS 250
10x15
320x240
720x400
1024x768
1600x1024
2048x1536
2400x1600
2832x2128
3488x2616
3888x2592

#1
0,047
0,093
0,145
0,231
0,34
0,618
0,742
1,139
1,723
1,896

#2
0,046
0,098
0,143
0,205
0,341
0,621
0,759
1,14
1,715
1,99

#3
0,053
0,095
0,143
0,2
0,34
0,617
0,74
1,147
1,785
1,898

#4
0,046
0,097
1,44
0,227
0,364
0,589
0,739
1,158
1,89
2,461

#5
0,053
0,092
0,143
0,228
0,342
0,617
0,742
1,144
1,778
1,883

Mdia
0,049
0,095
0,403
0,218
0,345
0,612
0,744
1,146
1,778
2,026

Desvio P.
0,003
0,002
0,519
0,013
0,009
0,012
0,007
0,007
0,063
0,221

O grfico dos ganhos de desempenho do algoritmo em CUDA pode ser observado na


Figura 14. Percebe-se claramente que as GPUs que executaram o algoritmo em Cg tiveram
melhores resultados, ainda que as GPUs que suportam CUDA sejam consideravelmente mais
poderosas.

58

Figura 14 Grfico que compara os ganhos das 3 GPUs que rodaram a implementao em
CUDA do algoritmo, com relao a CPU.
O grfico comparativo da Figura 15 exibe os ganhos de tempo de processamento das
duas implementaes em GPU quando executadas na GeForce 8800GTS. O fato de que a
implementao em CUDA no foi capaz de apresentar resultados para as duas imagens
maiores j foi discutido anteriormente neste captulo.

Figura 15 Comparao de desempenho entre as implementaes em GPU, Cg e CUDA,


rodando na GeForce 8800GTS.
59

6 CONCLUSO
Neste trabalho analisou-se as GPUs como um ambiente alternativo para a execuo do
FDA, levando em considerao a impreciso numrica nas operaes de ponto flutuante de
algumas GPUs. Baseado nos resultados obtidos possvel afirmar que as GPUs so
plataformas

computacionais

interessantes

para

implementao

deste

algoritmo,

apresentando ganhos bastante significativos e podendo em alguns casos atingir at mesmo o


processamento em tempo real do algoritmo.

6.1 CONTRIBUIES
Nesta dissertao demonstrou-se duas maneiras eficientes para implementar o FDA
em GPUs da NVIDIA e utilizar o poder do hardware grfico, objetivando diminuir o tempo
de execuo do algoritmo. O poder computacional das GPUs para computao numrica
trouxe um aumento notvel no desempenho do algoritmo, tornando o FDA um algoritmo
mais vivel para solues onde a velocidade da resposta um fator crucial. Apesar do
algoritmo ter caractersticas que facilitam a sua paralelizao, ainda sim existem outras
caractersticas juntamente com as limitaes ligadas a tecnologia das GPUs que dificultam
esta tarefa. Explorou-se tambm, duas tecnologias para programao de GPUs, e foram
desenvolvidas duas implementaes do algoritmo, uma em CUDA e a outra em Cg.
Os experimentos descritos no Captulo 5 mostram o desempenho do algoritmo em
CPU e em GPUs, utilizando um conjunto de imagens com diversos tamanhos para mensurar
o desempenho das implementaes e medir o grau de semelhana das imagens resultantes dos
processamentos CPU e GPU. A verso em Cg do algoritmo merece destaque pelo
desempenho alcanado, sendo superior at mesmo a implementao em CUDA que faz uso
de GPUs bem mais poderosas. Estas duas implementaes em GPU do algoritmo so
consideradas contribuies visto que at o presente momento no se tm conhecimento de
implementaes abertas deste algoritmo para a GPU.
Em geral, os resultados dos experimentos so bastante relevantes. Durante os
experimentos, foi empregado o mtodo de correlao cruzada normalizada para verificar a
qualidade dos resultados obtidos por ambos processadores. Este trabalho diferenciado no
sentido de que no foi encontrada na literatura uma proposta de avaliao do FDA em GPU
que medisse o grau de similaridade dos resultados das GPUs com os do CPU. Os resultados
60

mostram o tempo de execuo do algoritmo em diversas GPUs, fazendo um comparativo com


os resultados obtidos com o processamento em CPU.
Apesar dos ganhos bvios em desempenho, as implementaes em GPU requerem um
esforo significativo. Cg apesar de ser uma linguagem de programao de shaders bem
estabelecida, exige que o desenvolvedor conhea profundamente a arquitetura do hardware
grfico para poder utiliz-lo. CUDA continua sendo uma tecnologia recente e por isso pode
trazer dificuldades que so intrnsecas sua natureza jovem, como por exemplo, pouca
documentao a respeito e atualizaes do SDK que ainda podem trazer mudanas drsticas a
API de desenvolvimento.

6.2 TRABALHOS FUTUROS


Os resultados dos experimentos sugerem a possibilidade de executar o FDA em tempo
real. Atualmente existem APIs multi-plataformas de viso computacional e processamento de
imagens digitais, como OpenCV, que so suportadas por Mac OS X, Windows, Linux e
outras plataformas, oferecendo uma estrutura bsica para se trabalhar mais facilmente com
cmeras digitais, webcams e processamento de vdeos em geral. Uma integrao do FDA
para GPUs ao OpenCV por exemplo, tornaria possvel a sua aplicao em sistemas de
processamento de vdeos multi-plataforma.
Certamente uma investigao mais profunda da arquitetura CUDA necessria para
desenvolver uma implementao mais eficiente do FDA em CUDA. Suspeita-se que os
resultados obtidos pela implementao em CUDA, apesar de terem sido positivos, poderiam
ter sido melhores, levando em considerao que as GPUs utilizadas pelo algoritmo em Cg
tinham bem menos poder de processamento.
Atualmente

desenvolvedor

que

escolhe

CUDA

como

plataforma

de

desenvolvimento fica automaticamente amarrado as GPUs da NVIDIA. Existem outras


tecnologias que esto disponveis e so multi-plataforma, e que esto comeando a despertar
a ateno de desenvolvedores. Uma delas o OpenCL (Open Computing Language), uma
proposta de framework para desenvolvimento para executar aplicativos em plataformas
heterogneas como CPUs, GPUs e outros, que contou inicialmente com a colaborao de
grandes companhias como a Apple, a Intel, a AMD e a prpria NVIDIA. Avaliar OpenCL

61

como uma alternativa para programao de GPUs interessante pois abre as portas para o
FDA ser integrado a outras plataformas que no possuem uma GPU da NVIDIA.

62

7 REFERNCIAS
ABATE, A.F.; NAPPI, M.; RICCIARDI, S.; SABATINO, G. Ultra Fast GPU Assisted Face
Recognition Based on 3D Geometry and Texture Data. International Conference on Image
Analysis and Recognition, p.353-364, 2006.
ALLUSSE, Y.; HORAIN, P.; AGARWAL, A.; SAIPRIYADARSHAN, C. GpuCV: An
OpenSource GPU-Accelerated Framework for Image Processing and Computer Vision. To
be published in the Proceedings of the Open Source Software Competition, ACM
International Conference on Multimedia, Vancouver, BC, Canada, p. 1089-1092, October
27 31, 2008.
BAYAZIT, M.; COUTURE-BEIL, A.; MORI, G: Real-time Motion-based Gesture
Recognition using the GPU. The International Association for Pattern Recognition,
Conference on Machine Vision Applications, 2009.
BROWN, L. G. A Survey of Image Registration Techniques. ACM Computing Surveys,
New York, 1992.
BRUYNS, C.; FELDMAN, B. Image Processing on the GPU: a Canonical Example.
Computer Architecture Course Project, Department of Computer Science, University of
Berkeley, 2003.
CASTAO-DEZ, D.; MOSER, D.; SCHOENEGGER, A.; PRUGGNALLER, S.;
FRANGAKIS, A. S. Performance evaluation of image processing algorithms on the GPU.
Journal of Structure Biology, v. 164, p. 153-160, October 2008.
CHUNG, D. H.; SAPIRO, G. Segmenting skin lesions with partial differential equations
based image processing algorithm. IEEE Transactions on Medical Imaging, v. 19, n. 7, p.
763-767, 2000.
COHEN, M.; MANSSOUR, I.H. OpenGL Uma Abordagem Prtica e Objetiva. So
Paulo: Novatec, 2006. ISBN 85-7522-084-5
CRUM, W.R.; GRIFFIN, L.D.; HILL, D.L.G.; HAWKES, D.J. Zen and the art of medical
image registration: correspondence, homology and quality. Neuroimage, v. 20, n. 3, p. 14251437, November 2003.
DEMIRKAYA, O. Anisotropic diffusion filtering of PET attenuation data to improve
emission images. Physics in Medicine and64
Biology, v. 47, p. 271-278, 2002.
DOLAN, R.; DESOUZA, G. GPU-based simulation of cellular neural networks for image
processing. Proceedings of International Joint Conference on Neural Networks, Atlanta,
Georgia, USA, June 14-19, 2009.
FAN, Z.; QIU, F.; KAUFMAN, A.; YOAKUM-STOVER, S. GPU Cluster for High
Performance Computing. In Proceedings of ACM/IEEE Conference on Supercomputing,
2004.

63

FARRUGIA, J. P.; HORAIN, P.; GUEHENNEUX, E.; ALUSSE, Y. GPUCV: A Framework


for Image Processing Acceleration with Graphics Processors. IEEE International
Conference on In Multimedia and Expo, p. 585-588, 2006.
FERNANDO, R.; KILGARD, M.J. The Cg Tutorial. Addison-Wesley, 2003. ISBN 0-32119496-9
FUNG, J. MANN, S. Computer vision signal processing on graphics processing units. In
Proceedings of the IEEE International Conference on Acoustics, Speech, and Signal
Processing - ICASSP . Montreal, Quebec, Canada, May 17-21 2004. p. 83-89.
FUNG, J.; MANN, S. OpenVIDIA: parallel gpu computer vision. In Proceedings of the
13th annual ACM international conference on Multimedia, New York, USA, p. 849852,
2005.
GAMADIA, M.; KEHTARNAVAZ, N. Real-Time Image and Video Processing: From
Research to Reality. Morgan & Claypool Publishers, 2006.
GONZALES, R.C.; WOODS, R.E. Processamento de Imagens Digitais. Editora Edgard
Blcher, 2000. ISBN: 85-212-0264-4
GOODNIGHT, N.; WANG, R.; HUMPHREYS, G. Computation on Programmable Graphics
Hardware. IEEE Computer Graphics and Applications, v. 25, n. 5, p. 12-15, Sep/Oct
2005.
GOVINDARAJU, N.; REDON, S.; LIN, M.; CULLIDE, D.M. Interactive collision detection
between complex models in large environments using graphics hardware. In Proceedings of
the ACM SIGGRAPH/Eurographics Workshop on Graphics Hardware, p. 25-32, 2003.
GRUPO CYCLOPS, 2009.
http://www.cyclops.ufsc.br/

Pgina

do

Grupo

Cyclops,

disponvel

em:

HANDMANN, U.; KALINKE, T.; TZOMAKAS, C.; WERNER, M.; VON SEELEN, W. An
Image Processing System for Driver Assistence. Image and Vision Computing, v. 18, n. 5,
pp. 367-376, April 2000.
HARRIS, M.; BAXTER, W.; SCHEUERMANN, T.; LASTRA, A. Simulation of cloud
dynamics on graphics hardware. In Proceedings of Graphics Hardware, p. 92-101, 2003.
HARRIS, M. Computer Vision on the GPU. In GPU Gems 2, Addison-Wesley, New York,
p. 649-666, 2005.
HARRIS, M.; COOMBE, G.; SCHEUERMANN, T.; LASTRA, A. Physically-based visual
simulation on graphics hardware. In Proceedings of the ACM SIGGRAPH/Eurographics
Workshop on Graphics Hardware, p. 109-118, 2002.
HARRIS, M. Mapping computational concepts to GPUs. In GPU Gems 2, Addison-Wesley,
New York, p. 493508, 2005.
HILLESLAND, K.; LASTRA, A. GPU floating-point paranoia. In ACM Workshop on
General Purpose Computing on Graphics Processors, C8, August 2004.

64

INTEL. Quad-Core Intel Xeon Processor 5400 series. Intel Corporation: Santa Clara,
California, 2008.
LUEBKE, D.; HUMPHREYS, G. How GPUs Work. IEEE Computer, v. 40, n. 2, p. 96-100,
February 2007.
MAINTZ, A.J.B.; VIERGEVER, M.A. A survey of medical image registration. Medical
Image Analysis, v. 2, n. 1, p. 1-36, March 1998.
MARK, W.R.; GLANVILLE, R.S.; AKELEY, K.; KILGARD, M.J. Cg: a system for
programming graphics hardware in a C-like language. ACM Transactions on Graphics TOG, v. 22, n. 3, July 2003.
MITTMANN, A., DANTAS, M., VON WANGENHEIM, A.; Design and implementation of
brain fiber tracking for GPUs and PC clusters. Proceedings of the 21st Symposium on
Computer Architecture and High Performance Computing. p. 101108, 2009.
MIZUKAMI, Y.; TADAMURA, K. GPU implementation of deformable pattern recognition
using prototype-parallel displacement computation. In Workshop on Image Registration in
Deformable Environments, 2006.
MORELAND, K; ANGEL, E. The FFT on a gpu, In Proceedings of the ACM
SIGGRAPH/Eurographics Workshop on Graphics Hardware, p. 112119, July 2003.
NVIDIA. CUDA Programming Guide Version 2.0. NVIDIA Corporation: Santa Clara,
California, 2008.
NVIDIA. CUDA Programming Guide Version 3.1. NVIDIA Corporation: Santa Clara,
California, 2010.
OWENS, J. GPU Gems 2. Addison-Wesley, p. 457-470, 2005. ISBN 0-321-33559-7
OWENS, J.D.; HOUSTON, M.; LUEBKE, D.; GREEN, S.; STONE, J.E.; PHILLIPS, J.C.
GPU Computing. Proceedings of the IEEE In Proceedings of the IEEE, v. 96, n. 5, p. 879899, May 2008.
OWENS, J.D.; LUEBKE, D.; GOVINDARAJU, N.; HARRIS, M.; KRGER, J.; LEFOHN,
A.E.; PURCELL, T.J. A Survey of General-Purpose Computation on Graphics Hardware.
State of the Art Reports, Eurographics 2005, Dublin, Ireland, p. 21-51, August 2005.
PARK, S.I, PONCE, P. S.; HUANG J.; CAO, Y.; QUEK, F. Low-Cost, High-Speed
Computer Vision Using NVIDIAs CUDA Architecture. 37th IEEE Applied Imagery
Pattern Recognition Workshop, p. 1-7, 2008.
PEDRINI, H.; SCHWARTZ, W.R. Anlise de Imagens Digitais: Princpios, Algoritmos e
Aplicaes. Editora Thomson, 2008. ISBN 978-85-221-0595-3
PRATT, W.K. Digital Image Processing. Piks Inside. 3rd ed, 2001. ISBN-13: 9780471374077
PURCELL, T.; BUCK, I.; MARK, W.; HANRAHAN, P. Ray tracing on programmable
graphics hardware. ACM Transactions on Graphics, v. 21, n. 3, p. 703-712, July 2002.
65

SEITZ, C. GPGPU: Is a Supercomputer Hiding in Your PC? 2008. Disponvel em:


<http://www.informit.com/articles/article.aspx?p=398882>. Acesso em: 15 de jun. 2008.
WEICKERT, J. Anisotropic Diffusion in Image Processing. ECMI Series, Teubner,
Stuttgart, 1998.
WEICKERT, J. Applications of nonlinear diffusion in image processing and computer vision.
Acta Mathematica Universitatis Comenianae, v. 70, n. 1, p. 33-50, 2001.
ZHANG, Q.; ZHANG, Y. Hierarchical clustering of gene expression profiles with graphics
hardware acceleration. Pattern Recognition Letters, v. 27, n. 6, p. 676-681, April 2006.

66

APNDICE A - CDIGO FONTE DO NCLEO DO FDA EM


CPU
/**
* Executar o FDA em um array bidimensional de floats com tamanho definido por [nx][ny].
* @param lambda Fator de constraste.
* @param nx Largura do array.
* @param ny Altura do array.
* @param[in] f Array contendo a imagem a ser processada.
* @param[out] f Array com a imagem processada.
** /
void cpu_fda(float lambda, long nx, long ny, float** f)
{
long i, j;
float qC, qN, qNE, qE, qSE, qS, qSW, qW, qNW;
float ** g;
g = (float **) malloc ((nx+2) * sizeof(float *));
if (!g) {
printf("!!! ERROR: Not enough memory !!!\n");
exit(1);
}
for (i=0; i <= nx+1; i++) {
g[i] = (float *) malloc ((ny+2) * sizeof(float));
if (!g[i]) {
printf("("!!! ERROR: Not enough memory !!!\n ");
exit(1);
}
}
for (i=1; i <= nx; i++)
for (j=1; j<=ny; j++)
g[i][j] = f[i-1][j-1]; // Copy data to g
// Create dummy boundaries
for (i=1; i <= nx; i++) {
g[i][0] = g[i][1];
g[i][ny+1] = g[i][ny];
}
for (j=0; j <= ny+1; j++) {
g[0][j] = g[1][j];
g[nx+1][j] = g[nx][j];
}

float ht = 0.5f;
for (i=1; i <= nx; i++) // Diffusive averaging
for (j=1; j <= ny; j++) {
// Compute weights
qN = (1.0 - exp(-8.0 * ht * dco(g[i][j], g[i ][j+1], lambda))) / 8.0;
qNE = (1.0 - exp(-8.0 * ht * dco(g[i][j], g[i+1][j+1], lambda))) / 8.0;
qE = (1.0 - exp(-8.0 * ht * dco(g[i][j], g[i+1][j ], lambda))) / 8.0;
qSE = (1.0 - exp(-8.0 * ht * dco(g[i][j], g[i+1][j-1], lambda))) / 8.0;
qS = (1.0 - exp(-8.0 * ht * dco(g[i][j], g[i ][j-1], lambda))) / 8.0;

67

qSW = (1.0 - exp(-8.0 * ht * dco(g[i][j], g[i-1][j-1], lambda))) / 8.0;


qW = (1.0 - exp(-8.0 * ht * dco(g[i][j], g[i-1][j ], lambda))) / 8.0;
qNW = (1.0 - exp(-8.0 * ht * dco(g[i][j], g[i-1][j+1], lambda))) / 8.0;
qC = 1.0 - qN - qNE - qE - qSE - qS - qSW - qW - qNW;
// Weighted averaging
f[i-1][j-1] = qNW * g[i-1][j+1] + qN * g[i][j+1] + qNE * g[i+1][j+1] + \
qW * g[i-1][j ] + qC * g[i][j ] + qE * g[i+1][j ] + \
qSW * g[i-1][j-1] + qS * g[i][j-1] + qSE * g[i+1][j-1];
}
for (i=0; i <= nx+1; i++) free(g[i]); // Free allocated resources
free(g);
return;
}

68

APNDICE B - CDIGO FONTE DO NCLEO DO FDA PARA


GPU EM CG
Contedo do arquivo: gpu-diff.cpp
/*************************************************************************
* File: gpu-diff.cpp
*
* GPU Non-Linear Anisotropic Diffusion Filtering (console version)
*
- GLUT
*
- BMP image I/O
*
- Cg Runtime
*
- Cg environment setup
*
- Cg standard library
*
- Processing time counter
*
*
- GL_TEXTURE_RECTANGLE_ARB support (OpenGL 1.1 is required)
*
- GL_ARB_texture_non_power_of_two support (OpenGL 1.4 is required)
*
- GL_FRAMEBUFFER_EXT (FBO) support is required
*
* Libs needed for Windows: opengl32.lib glu32.lib glew32.lib glut32.lib cg.lib cgGL.lib
* Linux: g++ -lGLEW -lglut -lCg -lCgGL -lpthread -lfreeimage -o gpu-diff gpu-diff.cpp
*************************************************************************/
#ifdef WIN32
#include <windows.h>
#endif
//#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/timeb.h>
#include <time.h>
#include <GL/glew.h>
// OpenGL extension wrapper
#include <GL/glut.h>
// GLUT should be included after glew.h
#include <Cg/cg.h>
#include <Cg/cgGL.h>
#include <FreeImagePlus.h>
// Disable linker warning on VS2005: "scanf/fopen is deprecated"
#pragma warning(disable:4996)
#define T_RECTANGLE_ARB 0 // texture target ID = GL_TEXTURE_RECTANGLE_ARB
#define T_2D_WITH_ARB_NPOT 1 // texture target ID = GL_ARB_texture_non_power_of_two
#define CG_PRG_DIFF_P1
#define CG_PRG_DIFF_P2
#define CG_PROGRAMS
#define FBOs

0
1
2
2

// #1 Cg program ID
// #2 Cg program ID
// amount of Cg programs
// amount of FBOs

/*
*Global variables
*/
struct framebuffer {
GLuint fb_obj;
GLuint tex_obj;
} fbuffer[FBOs];

69

struct timeb start_time_st;


struct timeb stop_time_st;
char* out_filename = NULL;
fipImage * imagem = NULL;
int IMAGE_WIDTH = 0;
int IMAGE_HEIGHT = 0;
int TIME_COUNTER = 1;
int IT_NUM = 1; // number of iterations
int SOURCE
=
0;
// FBO #1 source
int DEST
=
1;
// FBO #2 destination
float HT;
// time step size
float LAMBDA;
// contrast parameter
GLint GL_max_texture_image_units;
GLint GL_texture_coordinate_units;
GLuint glutWindowHandle;
GLuint texture;
// texture #1
GLuint g_texture_target = T_RECTANGLE_ARB; // switch between texture targets
GLenum fbo_status;
// fbo status
GLenum texture_target = GL_TEXTURE_RECTANGLE_ARB;
// primary texture target
// second option would be GL_TEXTURE_2D
CGcontext
CGprofile
CGprogram
CGparameter
CGparameter

cg_context;
// Cg context
cg_profile;
// Cg profile
cg_program[CG_PROGRAMS];// Cg programs
cg_ht;
cg_lambda;

static const char *program_filename[CG_PROGRAMS] =


{
"diff_p1.cg",
"diff_p2.cg"
};
bool silentMode = false;
bool strictSilentMode = false;
/*
* Local functions prototypes
*/
void
cg_choose_profile
(void);
void
cg_env_init
(void);
void
init_opengl
(void);
int
isExtensionSupported
(const char *extension);
void
gl_draw_quad
(int height, int width, int inverted);
void
save_framebuffer_to_disk(char *filename);
void
save_texture_to_disk
(char *filename);
void
show_instruction
(void);
void
system_check
(void);
void
check_fbo_stat
(void);
void
gpu_processing
(void);
void
cg_error_callback
(void);
/*
* Extern functions
*/
void printUsage(char * executavel)
{

70

fprintf(stderr, "Uso: %s <input.ppm> <output.ppm> #iteracoes #lambda [options]\n\n \


[options] \n\
-s: Se deve exibir as informacoes do sistema \n\
-S: Se deve ocultar inclusive as informacoes de erro \n\n", executavel);
}
int main(int argc, char **argv)
{
char *filename = NULL;
int i;
char c;
if (argc < 5) {
printUsage(argv[0]);
return -1;
}
// acquire input_FILENAME from console
if (argc > 1)
filename = argv[1];
// acquire output_FILENAME from console
if (argc > 2)
out_filename = argv[2];

// acquire NUMBER OR ITERATIONS from console


if (argc > 3)
IT_NUM = atoi(argv[3]);
// acquire LAMBDA from console
if (argc > 4)
LAMBDA = atof(argv[4]);
// normalizing value from CPU range [0,255] to GPU range [0,1]
LAMBDA = LAMBDA / 255;
if (argc > 5) {
if (strcmp(argv[5], "-s") == 0) {
silentMode = 1;
} else if (strcmp(argv[5], "-S") == 0) {
strictSilentMode = 1;
}
}
// fixed time-step size - range [0.1,0.5]
HT = 0.5;
// GLUT initialization
glutInit(&argc, argv);
// read in the input image
imagem = new fipImage();
if (imagem->load(filename) == FALSE) {
imagem->convertTo24Bits();
fprintf(stderr, "[ERROR] File not found!\n\n");
exit(1);
}
// set the displaying-window size

71

IMAGE_WIDTH = imagem->getWidth();
IMAGE_HEIGHT = imagem->getHeight();
glutWindowHandle = glutCreateWindow("GPU-based nisotropic Diffusion Filter");
glutHideWindow();
// do some initialization for OpenGL
init_opengl();
// gpu processing
gpu_processing();
// kill Cg programs
for (i = 0; i < CG_PROGRAMS; ++i)
cgDestroyProgram(cg_program[i]);
cgDestroyContext(cg_context);
delete imagem;
return 0;
}
void init_opengl(void)
{
// check for OpenGL support
system_check();
//glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &GL_max_texture_image_units);
//fprintf(stderr, "\n> GL_MAX_TEXTURE_IMAGE_UNITS_ARB : %d\n",
GL_max_texture_image_units);
//glGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, &GL_texture_coordinate_units);
//fprintf(stderr, "> GL_MAX_TEXTURE_COORDS_ARB : %d", GL_texture_coordinate_units);
// start counting: get current system time
ftime(&start_time_st);
// model-view-projection transformation
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// orthogonal projection
gluOrtho2D(0, IMAGE_WIDTH, 0, IMAGE_HEIGHT);
// viewport transformation
glViewport(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
// set the RGBA color for background clearing
glClearColor(0.0, 0.0, 0.0, 1.0);
// when working with 2D textures dont "glEnable(GL_DEPTH_TEST)"
// If you do, add "glDepthFunc(GL_LEQUAL)" to prevent a f***** up result
// enable texture_target
glEnable(texture_target);
// extension initialization (allowing the use of FBO's functions)
glewInit();
// create FBOs
for (i = 0; i <FBOs; ++i)

72

{
glGenFramebuffersEXT(1, &fbuffer[i].fb_obj);
glGenTextures(1, &fbuffer[i].tex_obj);

/* generate a framebuffer ID */
/* generate a texture ID */

}
// generate a new texture
glGenTextures(1, &texture);
// define current texture to work with
glBindTexture(texture_target, texture);
// Note that further modifications will affect this specific texture until it's disabled
// set the texture properties
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE_EXT);
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE_EXT);
// enlarge and create dummy boundaries
//larger_pixel_array = enlarge_pixel_boundaries(*g_input_image1->pixel, g_input_image1->height,
g_input_image1->width);
// If you uncomment the above line, comment all glTexParameteri() "GL_CLAMP_TO_EDGE_EXT"
instructions
// disable alignment of rows of source data
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// uploading image to GPU's texture memory
glTexImage2D(
texture_target,
// texture target
0,
// mipmap level
GL_RGBA,
// texture internal format
IMAGE_WIDTH,
IMAGE_HEIGHT,
0,
// border
GL_BGR_EXT,
// pixel format of the image
// (matching internal format is better)
GL_UNSIGNED_BYTE,
// channel type
imagem->accessPixels()
// image data
//larger_pixel_array
);
// restore the texture state (i.e. disable texture)
glBindTexture(texture_target, 0);
// initializing CG environment
cg_env_init();
/************************************************************************/
// initialize framebuffer objects
for (int i = 0; i < FBOs; ++i)
{
// bind the output texture as the second FBO working texture
glBindTexture(texture_target, fbuffer[i].tex_obj);
// allocate memory for the output texture, the GPU version for malloc()
glTexImage2D(
texture_target,
// texture target

73

0,
GL_RGBA,
IMAGE_WIDTH,
IMAGE_HEIGHT,
0,
GL_RGBA,

// mipmap level
// texture internal format

// border
// pixel format of the image
// (matching internal format is better)
GL_UNSIGNED_BYTE, // channel type
NULL
// with NULL in input data
);
// set the texture properties
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//glTexParameteri(texture_target, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE_EXT);
//glTexParameteri(texture_target, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE_EXT);
// bind the next FBO as the current working FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbuffer[i].fb_obj);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT, texture_target, fbuffer[i].tex_obj, 0);
// check success of FBOs' creation
check_fbo_stat();
}
// restore the texture state
glBindTexture(texture_target, 0);
// restore the FBO state
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
void gpu_processing(void)
{
int i;
double elapsed;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (i = 0; i < IT_NUM; ++i)
{
// switch source and dest for next pass
SOURCE = (SOURCE + 1) % 2;
DEST = (DEST + 1) % 2;
// select source: If it's the first iteration we must use "texture"
if (i == 0)
glBindTexture(texture_target, texture);
else
glBindTexture(texture_target, fbuffer[SOURCE].tex_obj);
// select destination
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbuffer[DEST].fb_obj);
// first pass
cgGLEnableProfile(cg_profile);
// activate Diffusion pass-One
cgGLBindProgram(cg_program[CG_PRG_DIFF_P1]);
gl_draw_quad(IMAGE_HEIGHT, IMAGE_WIDTH, 0); // draw a quadrangle

74

// second pass
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
// activate Diffusion pass-Two
cgGLBindProgram(cg_program[CG_PRG_DIFF_P2]);
gl_draw_quad(IMAGE_HEIGHT, IMAGE_WIDTH, 0); // draw a quadrangle
// third pass
cgGLDisableProfile(cg_profile);
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
gl_draw_quad(IMAGE_HEIGHT, IMAGE_WIDTH, 0);
glDisable(GL_BLEND);
}
// copy image from dest buffer to screen (and invert it this time)
glBindTexture(texture_target, 0);
glBindTexture(texture_target, fbuffer[DEST].tex_obj);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
gl_draw_quad(IMAGE_HEIGHT, IMAGE_WIDTH, 1);
// note: glutSwapBuffers only calls glFlush. glFlush makes sure all
// pending commands are sent to the GPU, but it doesn't wait until
// they're finished rendering. glFinish actually doesn't return until
// everything's finished rendering. So, our time funtion will give
// the expected result.
glFinish();
// blitting
glutSwapBuffers();
// stop counting: get current system time and substract from start_time
if (TIME_COUNTER == 1)
{
TIME_COUNTER++;
ftime(&stop_time_st);
elapsed = ((double) stop_time_st.time + ((double) stop_time_st.millitm * 0.001)) ((double) start_time_st.time + ((double) start_time_st.millitm * 0.001));
if (!silentMode)
fprintf(stderr, "> Processing time: %5.3fs\n\n", elapsed);
}
save_texture_to_disk(out_filename);
glutDestroyWindow(glutWindowHandle);

// glutHideWindow();

void gl_draw_quad(int height, int width, int inverted)


{
switch (g_texture_target) {
case T_RECTANGLE_ARB:
glBegin(GL_QUADS);
{
if (inverted)
{
// these coordinates are inverted
glTexCoord2i
(0, height);

75

glVertex2i(0, 0);
glTexCoord2i(width, height);
glVertex2i(width, 0);
glTexCoord2i(width, 0);
glVertex2i(width, height);
glTexCoord2i(0, 0);
glVertex2i(0, height);
}
else
{
// these coordinates are normal
glTexCoord2i
(0, 0);
glVertex2i
(0, 0);
glTexCoord2i
glVertex2i

(width, 0);
(width, 0);

glTexCoord2i
glVertex2i

(width, height);
(width, height);

glTexCoord2i
glVertex2i

(0, height);
(0, height);

}
}
glEnd();
break;
case T_2D_WITH_ARB_NPOT:
glBegin(GL_QUADS);
{
if (inverted)
{
// these coordinates are inverted
glTexCoord2f
(0.0f, 1.0f);
glVertex2f(0.0f, 0.0f);
glTexCoord2f
(1.0f, 1.0f);
glVertex2f(width, 0.0f);
glTexCoord2f
(1.0f, 0.0f);
glVertex2f(width, height);
glTexCoord2f
(0.0f, 0.0f);
glVertex2f(0.0f, height);
}
else
{
// these coordinates are normal
glTexCoord2f
(0.0f, 0.0f);
glVertex2f(0.0f, 0.0f);
glTexCoord2f
(1.0f, 0.0f);
glVertex2f(width, 0.0f);
glTexCoord2f
(1.0f, 1.0f);
glVertex2f(width, height);

76

glTexCoord2f
(0.0f, 1.0f);
glVertex2f(0.0f, height);
}
}
glEnd();
break;
}
}
/* save_texture_to_disk() : Saves image from the [DEST] FBO texture */
void save_texture_to_disk(char *filename)
{
glBindTexture(texture_target, fbuffer[DEST].tex_obj);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glGetTexImage(
texture_target,
// texture target
0,
// level
GL_BGR_EXT,
// pixel format for the image
GL_UNSIGNED_BYTE, // channel type
imagem->accessPixels() // destination address
);
glBindTexture(texture_target, 0);
//reverse_image_row(g_output_texture_img);
imagem->save(filename);
}
/* cg_env_init() : Initializing CG environment */
void cg_env_init(void)
{
// create the Cg context
cg_context = cgCreateContext();
// get the latest profile available:
// cg_profile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cg_choose_profile();
// for optimal compilation
cgGLSetOptimalOptions(cg_profile);
// register the callback function for error handling in Cg
cgSetErrorCallback(cg_error_callback);
for (int i = 0; i < CG_PROGRAMS; ++i) {
cg_program[i] = cgCreateProgramFromFile(cg_context, CG_SOURCE, program_filename[i],
cg_profile, "main", 0);
if (!cg_program[i]) {
const char *errmsg = cgGetLastListing(cg_context);
fprintf(stderr, "[ERROR] Could not create program from %s:\n%s\n",
program_filename[i], errmsg);
exit(1);
}
cgGLLoadProgram(cg_program[i]);

77

// get the handles of input variables in the Cg program


cg_ht
= cgGetNamedParameter(cg_program[i], "ht");
cg_lambda
= cgGetNamedParameter(cg_program[i], "lambda");
cgGLSetParameter1f(cg_ht, (float)HT);
cgGLSetParameter1f(cg_lambda, (float)LAMBDA);
}
}
/* cg_choose_profile() : Chooses the best fragment/vertex profile avaiable on the system */
void cg_choose_profile(void)
{
// check for Fragment Profiles support
if (cgGLIsProfileSupported(CG_PROFILE_FP40))
cg_profile = CG_PROFILE_FP40;
else {
fprintf(stderr, "\n[WARNING] Fragment profile 'fp40' is NOT supported on this system.
(NVIDIA)");
if (cgGLIsProfileSupported(CG_PROFILE_FP30))
cg_profile = CG_PROFILE_FP30;
else {
fprintf(stderr, "\n[WARNING] Fragment profile 'fp30' is NOT supported on this
system. (NVIDIA)");
if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1))
cg_profile = CG_PROFILE_ARBFP1;
else {
fprintf(stderr, "\n[Error] Fragment profile 'arbfp1' is NOT supported on this
system. (ATI)");
exit(1);
}
}
}
//cg_profile = CG_PROFILE_ARBFP1;
assert(cg_profile != CG_PROFILE_UNKNOWN);
if (!silentMode)
fprintf(stderr, "\n\n> Using fragment profile: '%s'\n", cgGetProfileString(cg_profile));
}
/* cg_error_callback() : Prints "Cg runtime" erros */
void cg_error_callback(void) {
CGerror last_error;
if (last_error = cgGetError())
{
fprintf(stderr, "%s\n\n", cgGetErrorString(last_error));
fprintf(stderr, "%s\n", cgGetLastListing(cg_context));
fprintf(stderr, "Cg error!\n");
}
}
/* isExtensionSupported() : can be used to determine at run-time if the OpenGL implementation really supports
a particular extension */
int isExtensionSupported(const char *extension)
{
const GLubyte *extensions = NULL;
const GLubyte *start;
GLubyte *where, *terminator;

78

// Extension names should not have spaces


where = (GLubyte *) strchr(extension, ' ');
if (where || *extension == '\0')
return 0;
extensions = glGetString(GL_EXTENSIONS);
/* It takes a bit of care to be fool-proof about parsing the
OpenGL extensions string. Don't be fooled by sub-strings,
etc. */
start = extensions;
for (;;) {
where = (GLubyte *) strstr((const char *) start, extension);
if (!where)
break;
terminator = where + strlen(extension);
if (where == start || *(where - 1) == ' ')
if (*terminator == ' ' || *terminator == '\0')
return 1;
start = terminator;
}
return 0;
}
void check_fbo_stat(void)
{
fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (fbo_status != GL_FRAMEBUFFER_COMPLETE_EXT)
{
switch(fbo_status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
fprintf(stderr,"\n[WARNING] framebuffer complete!\n");
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
fprintf(stderr,"\n[WARNING] framebuffer
GL_FRAMEBUFFER_UNSUPPORTED_EXT");
// you gotta choose different formats
assert(0);
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
fprintf(stderr,"\n[WARNING] framebuffer
INCOMPLETE_ATTACHMENT");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
fprintf(stderr,"\n[WARNING] framebuffer
FRAMEBUFFER_MISSING_ATTACHMENT");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
fprintf(stderr,"\n[WARNING] framebuffer
FRAMEBUFFER_DIMENSIONS");
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
fprintf(stderr,"\n[WARNING] framebuffer INCOMPLETE_FORMATS");
break;

79

case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
fprintf(stderr,"\n[WARNING] framebuffer
INCOMPLETE_DRAW_BUFFER");
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
fprintf(stderr,"\n[WARNING] framebuffer
INCOMPLETE_READ_BUFFER");
break;
case GL_FRAMEBUFFER_BINDING_EXT:
fprintf(stderr,"\n[WARNING] framebuffer BINDING_EXT\n");
break;
default:
// programming error; will fail on all hardware
assert(0);
}
}
}

/* system_check(void) : Displays information about the OpenGL Vender/Renderer/Version and


and check if the system supports certain OpenGL extensions */
void system_check(void)
{
if (!silentMode)
fprintf(stderr, "> Analising system configuration..\n\n");
int errors = 0;
#ifdef WIN32
OSVERSIONINFO OSinfo;
ZeroMemory(&OSinfo, sizeof(OSVERSIONINFO));
OSinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&OSinfo);
fprintf(stderr, "

Operating System: ");

if ((OSinfo.dwMajorVersion == 4) && (OSinfo.dwMinorVersion == 0))


fprintf(stderr, "Windows 95\n");
if ((OSinfo.dwMajorVersion == 4) && (OSinfo.dwMinorVersion == 10))
fprintf(stderr, "Windows 98\n");
if ((OSinfo.dwMajorVersion == 4) && (OSinfo.dwMinorVersion == 90))
fprintf(stderr, "Windows ME\n");
if ((OSinfo.dwMajorVersion == 5) && (OSinfo.dwMinorVersion == 0))
fprintf(stderr, "Windows 2000\n");
if ((OSinfo.dwMajorVersion == 5) && (OSinfo.dwMinorVersion == 1))
fprintf(stderr, "Windows XP\n");
if ((OSinfo.dwMajorVersion == 5) && (OSinfo.dwMinorVersion == 2))
fprintf(stderr, "Windows Server 2003\n");

80

if (OSinfo.dwMajorVersion == 6)
fprintf(stderr, "Windows Vista\n");
#endif
if (!silentMode) {
fprintf(stderr, " OpenGL Vendor: %s\n", glGetString(GL_VENDOR));
fprintf(stderr, " OpenGL Renderer: %s\n", glGetString(GL_RENDERER));
fprintf(stderr, " OpenGL Version: %s\n", glGetString(GL_VERSION));
}
//fprintf(stderr, " Supported OpenGL extensions: %s\n", glGetString(GL_EXTENSIONS));
if (!isExtensionSupported("GL_ARB_texture_rectangle")) {
fprintf(stderr, "\n[WARNING] GL_TEXTURE_RECTANGLE_ARB NOT found!");
errors += 1;
texture_target = GL_TEXTURE_2D;
g_texture_target = T_2D_WITH_ARB_NPOT;
}
if (!isExtensionSupported("GL_ARB_texture_non_power_of_two")) {
fprintf(stderr, "\n[WARNING] ARB_texture_non_power_of_two NOT found!");
errors += 1;
texture_target = GL_TEXTURE_RECTANGLE_ARB;
g_texture_target = T_RECTANGLE_ARB;
}
if (!isExtensionSupported("GL_EXT_framebuffer_object")) {
fprintf(stderr, "\n[WARNING] Framebuffer_object NOT found!");
errors += 1;
}
if (errors > 1) {
fprintf(stderr, "\n[ERROR] OpenGL extensions not supported: %d\n\n", errors);
exit(1);
}
}

81

APNDICE C - CDIGO FONTE DO NCLEO DO FDA


PARA GPU EM CUDA
Contedo do arquivo: main.cu
#include <stdio.h>
#include <stdlib.h>
#include <cutil.h>
#include <iostream>
#include <cuda_runtime.h>
#include <driver_types.h>
#include "filtro.cu"
#include "image.h"
extern "C" void cuda_filtro_difusao(image_t * imagem, int w, int h, float lambda, float ht, dim3 blocks, dim3
block_size);
int iDivUp(int a, int b)
{
// round a / b to nearest higher integer value
return ((a % b) != 0) ? (a / b + 1) : (a / b);
}
int main(int argc, char * argv[])
{
if (argc < 5)
{
std::cout << "Usage: " << argv[0] << " <input.png>" << " <output.png> <iterations> <lambda>" <<
std::endl;
exit(1);
}
int iterations = atoi(argv[3]);
if (iterations == 0)
{
std::cout << "!!!!! Error while reading <iterations>. Using default value: 1 !!!!!" << std::endl;
iterations = 1;
}
float lambda = atof(argv[4]);
if (lambda == 0)
{
std::cout << "!!!!! Error while reading <lambda>. Using default value: 15 !!!!!" << std::endl;
lambda = 15;
}
// load image from file
int width, height, bpp;
float* host_data;
ReadImage(argv[1], &host_data, &width, &height, &bpp); //host_data stores pixels
unsigned int gpuTime = 0;
CUT_SAFE_CALL( cutCreateTimer( &gpuTime));
CUT_SAFE_CALL( cutStartTimer( gpuTime));
// allocate device memory (gpu) for the result
image_t* device_data = NULL;

82

CUDA_SAFE_CALL( cudaMalloc( (void**) &device_data, width * height * sizeof(image_t)) );


// transfer imagem to the gpu
cudaArray* cu_array;
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<image_t>();
CUDA_SAFE_CALL( cudaMallocArray( &cu_array, &channelDesc, width, height ) );
CUDA_SAFE_CALL( cudaMemcpyToArray( cu_array, 0, 0, host_data, sizeof(float) * 4 * width * height,
cudaMemcpyHostToDevice) );
CUDA_SAFE_CALL( cudaBindTextureToArray( texImage, cu_array, channelDesc));
dim3 block(8, 8);
dim3 grid(iDivUp(width, block.x), iDivUp(height, block.y));
const float ht = 0.5f;
for (int iter = 0; iter < iterations; ++iter)
{
cuda_filtro_difusao(device_data, width, height, lambda, ht, grid, block);
CUDA_SAFE_CALL( cudaThreadSynchronize() );
CUT_CHECK_ERROR("Kernel execution failed");
CUDA_SAFE_CALL( cudaThreadSynchronize() );
CUDA_SAFE_CALL( cudaMemcpyToArray( cu_array, 0, 0, device_data, sizeof(image_t) * width *
height, cudaMemcpyDeviceToDevice) );
}
// copy result from device to host
float* result = new float[width * height * 4];
CUDA_SAFE_CALL( cudaMemcpy( result, device_data, sizeof(float) * 4 * width * height,
cudaMemcpyDeviceToHost) );
CUT_SAFE_CALL( cutStopTimer(gpuTime) );
WriteImage(argv[2], result, width, height, bpp);
CUDA_SAFE_CALL(cudaFree(device_data));
CUDA_SAFE_CALL(cudaFreeArray(cu_array));
delete[] result;
delete[] host_data;
printf("Tempo total de gpu: %5.3fs\n", cutGetTimerValue(gpuTime)/1000);
CUT_SAFE_CALL( cutDeleteTimer(gpuTime) );
return EXIT_SUCCESS;
}

Contedo do arquivo image.h:


void ReadImage(const char *file_name, float **data, int *width, int *height, int *bpp);
void WriteImage(const char *file_name, const float *data, int width, int height, int bpp);

Contedo do arquivo image.cpp:


#include <iostream>
#include <cv.h>
#include <highgui.h>

83

#include "image.h"
void ReadImage(const char *file_name, float **data, int *width, int *height, int* bpp)
{
IplImage* input_image = NULL;
input_image = cvLoadImage(file_name, CV_LOAD_IMAGE_UNCHANGED);
if(!input_image)
{
std::cout << "ERROR: Failed to load input image" << std::endl;
return;
}
*width = input_image->width;
*height = input_image->height;
*bpp = input_image->nChannels;
std::cout << ">> Width:" << *width << std::endl <<
">> Height:" << *height << std::endl <<
">> Bpp:" << *bpp << std::endl <<
">> depth:" << input_image->depth << std::endl;
*data = new float[*width * *height * 4];
for (int i = 0; i < *width * *height; i++)
{
(*data)[i * 4 + 0] = (unsigned char)input_image->imageData[i * *bpp + 0] / 1.f;
(*data)[i * 4 + 1] = (unsigned char)input_image->imageData[i * *bpp + 1] / 1.f;
(*data)[i * 4 + 2] = (unsigned char)input_image->imageData[i * *bpp + 2] / 1.f;
}
cvReleaseImage(&input_image);
return;
}
void WriteImage(const char *file_name, const float *data, int width, int height, int bpp)
{
//float 2 char
char* buff = new char[width * height * bpp];
for (int i = 0; i < (width * height); i++)
{
buff[i * bpp + 0] = (char)floor(data[i * 4 + 0] * 1.f);
buff[i * bpp + 1] = (char)floor(data[i * 4 + 1] * 1.f);
buff[i * bpp + 2] = (char)floor(data[i * 4 + 2] * 1.f);
}
IplImage* out_image = cvCreateImage( cvSize(width, height), 8, bpp);
out_image->imageData = buff;
if( !cvSaveImage(file_name, out_image) )
{
std::cout << "ERROR: Failed to write image file" << std::endl;
}
delete[] buff;
cvReleaseImage(&out_image);
}

Contedo do arquivo filtro.cu:


typedef float color_t;

84

typedef float4 image_t;


texture<image_t, 2, cudaReadModeElementType> texImage;
__device__ float dot(float4 a, float4 b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
__device__ float dco(float4 u, float4 v, float contrast)
{
float result, tt1,tt2,tt3,tt4;
const float rolloff = 5.0;
float4 w;
w.x = v.x - u.x;
w.y = v.y - u.y;
w.z = v.z - u.z;
tt1 = sqrtf(dot(w, w)); // for colored RGB textures
tt2 = tt1/contrast;
tt3 = powf(tt2, rolloff);
tt4 = -tt3 / rolloff;
result = expf(tt4);
return result;
}
__device__ image_t get_pixel(int w, int h, float x, float y)
{
return tex2D(texImage, x, y);
}
__global__ void filtro_difusao(image_t* output, int width, int height, float lambda, float ht)
{
const int iy = blockDim.y * blockIdx.y + threadIdx.y;
const int ix = blockDim.x * blockIdx.x + threadIdx.x;
if (ix < width && iy < height) {
float qC, qN, qNE, qE, qSE, qS, qSW, qW, qNW;
float4 pC = get_pixel(width, height, ix,iy);
float4 pN = get_pixel(width, height, ix+1, iy);
float4 pNE = get_pixel(width, height, ix+1, iy+1);
float4 pNW = get_pixel(width, height, ix+1, iy-1);
float4 pE = get_pixel(width, height, ix , iy+1);
float4 pW = get_pixel(width, height, ix , iy-1);
float4 pSE = get_pixel(width, height, ix-1, iy+1);
float4 pS = get_pixel(width, height, ix-1, iy);
float4 pSW = get_pixel(width, height, ix-1, iy-1);
qN = (1.0 - expf(-8.0 * ht * dco(pC, pN , lambda))) / 8.0;
qNE = (1.0 - expf(-8.0 * ht * dco(pC, pNE, lambda))) / 8.0;
qNW = (1.0 - expf(-8.0 * ht * dco(pC, pNW, lambda))) / 8.0;
qE = (1.0 - expf(-8.0 * ht * dco(pC, pE , lambda))) / 8.0;
qW = (1.0 - expf(-8.0 * ht * dco(pC, pW , lambda))) / 8.0;
qSE = (1.0 - expf(-8.0 * ht * dco(pC, pSE, lambda))) / 8.0;
qS = (1.0 - expf(-8.0 * ht * dco(pC, pS , lambda))) / 8.0;
qSW = (1.0 - expf(-8.0 * ht * dco(pC, pSW, lambda))) / 8.0;
qC = 1.0 - qN - qNE - qE - qSE - qS - qSW - qW - qNW;
float red =
qNW * pNW.x + qN * pN.x + qNE * pNE.x + qW * pW.x + qC * pC.x + qE * pE.x +
qSW * pSW.x + qS * pS.x + qSE * pSE.x;

85

float green = qNW * pNW.y + qN * pN.y + qNE * pNE.y + qW * pW.y + qC * pC.y + qE * pE.y +
qSW * pSW.y + qS * pS.y + qSE * pSE.y;
float blue = qNW * pNW.z + qN * pN.z + qNE * pNE.z + qW * pW.z + qC * pC.z + qE * pE.z + qSW
* pSW.z + qS * pS.z + qSE * pSE.z;
if (red > 255) red = 255; if (red < 0) red = 0;
if (green > 255) green = 255; if (green < 0) green = 0;
if (blue > 255) blue = 255; if (blue < 0) blue = 0;
output[iy * width + ix] = make_float4( red, green, blue, 0 );
}
}
extern "C" void cuda_filtro_difusao(image_t * imagem, int w, int h, float lambda, float ht, dim3 blocks, dim3
block_size)
{
filtro_difusao <<<blocks, block_size>>> (imagem, w, h, lambda, ht);
}

86

You might also like