Professional Documents
Culture Documents
por
por
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
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
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
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
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
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.
dos
pixels
da
vizinhana.
Ambas
so
tarefas
bastante
exigentes
1.1.2
Delimitao de Escopo
Esta pesquisa se restringe a investigar as GPUs como uma plataforma de
1.1.3
Justificativa
Como mencionado anteriormente, o FDA normalmente empregado como filtro de
14
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
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
1.3.2
Procedimentos Metodolgicos
Os procedimentos adotados para atingir os objetivos propostos foram formados
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.
18
19
2 FUNDAMENTAO TERICA
Este
captulo
apresenta
os
principais
conceitos
tericos
necessrios
ao
21
2.1.1
22
dentro
do
tempo
disponvel
ou
permitido
entre
amostragens.
23
2.1.2
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)
24
t u = div( g (| u |2 )u ).
(2)
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
qj =1
5
2
| |
5
4e
(6)
2.1.3
Correlao Cruzada
A correlao cruzada (CC) utilizada neste trabalho para medir o grau de
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
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.
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.
32
2.2.2
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
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).
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
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
como
cdigo
aberto.
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
39
Tecnologia
NVIDIA GeForce 3
Assembly
Fragmentos
Cg / OpenGL
Fragmentos
NVIDIA FX 5900
NVIDIA GeForce FX 5900
NVIDIA GeForce FX 5200
-
Cg / Cg / OpenGL
Fragmentos
Fragmentos
Cg / OpenGL
Fragmentos
CUDA
GLSL / OpenGL
Fragmentos e Vrtices
CUDA
Buhr (2010)
Cg, CUDA
Fragmentos
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.
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.
Implementao em Cg
Esta implementao difere bastante das outras porque o cdigo-fonte precisou ser
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
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.
Especificao
Placa-me
ASUS P5NSLI
Processador
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
Especificao
Placa-me
ASUS M2N-E
Processador
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
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
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
em
Cg
esto
disponibilizadas
no
endereo
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
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
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.
52
53
#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
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
#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
#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
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
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
-
#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
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.
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,
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
desenvolvedor
que
escolhe
CUDA
como
plataforma
de
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
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
66
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
68
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
cg_context;
// Cg context
cg_profile;
// Cg profile
cg_program[CG_PROGRAMS];// Cg programs
cg_ht;
cg_lambda;
70
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();
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
78
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);
}
}
}
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
82
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);
}
84
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