Escolar Documentos
Profissional Documentos
Cultura Documentos
PARALELIZAÇÃO DE ALGORITMOS DE
SÍNTESE DE IMAGENS FOTO-REALISTAS
São Paulo
2006
BRUNO GONÇALVES DE JESUS
DOUGLAS DIONÍSIO FERNANDEZ DAS NEVES
PARALELIZAÇÃO DE ALGORITMOS DE
SÍNTESE DE IMAGENS FOTO-REALISTAS
São Paulo
2006
“Dê-me memória e tempo e computarei o mundo.”
Jussara Maria Marins
“You know you have been ray tracing too long when ...
... You wonder which ray tracer God used.”
David Kraics
AGRADECIMENTOS
Since the beginning of Computer Graphics countless researchers and scientists have been
trying to create more and more realistic image synthesis reducing distances between the real and
virtual worlds. Nowadays, it's possible to create landscapes with shadows, natural light, water,
clouds, wind, fire etc. with incredible detail precision, rich in colors and shapes. This process is
called photorealism: an image created by computational meanings which is difficult or
impossible to distinguish the real and virtual. This ability demands for better computers and
specially made platforms for graphic engineering, creating lots of new research areas that can be
studied. The performance problem have been solved in complex ways, making better hardware
with new accelerated graphic boards or distributing the process between different
processors/computers (parallelism). The main research objective is to look for parallelism points
for the Ray-Tracing algorithm and Radiosity implemented by POV-Ray creating new versions of
this algorithm which will merge the power of parallel computing from clusters and the high
performance need that graphic computing have, making smaller the time to complete the process.
We intend to see how much speedup can be obtained in the realistic computer image synthesis.
Keywords: Paralelism; 3D; Fotorealism; POV-Ray; Graphic Computing; Cluster;
SUMÁRIO
Cap. I - Introdução ...................................................................................................... 14
1.1 – Objetivos ....................................................................................................................................... 14
1.2 – Descrição dos Capítulos ................................................................................................................ 14
Cap. II - Processamento Gráfico ................................................................................ 16
2.1 – Renderização ................................................................................................................................. 17
2.2 – Iluminação Local e Global ............................................................................................................ 18
2.3 – Ray-Tracing................................................................................................................................... 19
2.4 – Radiosidade ................................................................................................................................... 21
2.5 – Photon Mapping ............................................................................................................................ 23
2.6 – Anti-aliasing .................................................................................................................................. 28
2.7 – Jittering .......................................................................................................................................... 29
Cap. III - POV-Ray ........................................................................................................ 31
3.1 – Iluminação ..................................................................................................................................... 33
3.2 – Ray-Tracing no POV-Ray ............................................................................................................. 34
3.3 – Radiosidade no POV-Ray ............................................................................................................. 35
3.4 – Photon Mapping no POV-Ray ...................................................................................................... 36
3.5 – Anti-alias no POV-Ray ................................................................................................................. 38
Cap IV - Computação Paralela ................................................................................... 39
4.1 Modelos de Computadores Paralelos ............................................................................................... 39
4.1.1 Multiprocessamento com Memória Compartilhada ................................................................. 40
4.1.2 Multicomputador via Passagem de Mensagens ........................................................................ 40
4.1.3 Memória Compartilhada Distribuída ....................................................................................... 41
4.2 – Modelos de Arquiteturas Paralelas ................................................................................................ 41
4.3 – Clusters .......................................................................................................................................... 42
4.4 – Modelos de Algoritmos Paralelos ................................................................................................. 43
4.5 – Modelos de Programação Paralela ................................................................................................ 44
4.6 – Biblioteca MPI .............................................................................................................................. 44
4.6.1 – Rotinas de Passagem de Mensagens...................................................................................... 45
Cap. V – Paralelização do POV-Ray .......................................................................... 47
5.1 – Trabalhos Relacionados ................................................................................................................ 48
5.2 – Ray-Tracing em Paralelo ............................................................................................................... 51
5.2.1 – O Crivo de Raios.................................................................................................................... 51
5.2.2 – O Crivo de Raios Mestre/Escravo ......................................................................................... 53
5.3 – Radiosidade em Paralelo. .............................................................................................................. 54
5.4 – Photon Mapping em Paralelo ........................................................................................................ 56
Cap. VI – Testes e Resultados ................................................................................... 58
6.1 – Woodbox ....................................................................................................................................... 58
6.2 – Glasschess ..................................................................................................................................... 60
6.3 – Skyvase ......................................................................................................................................... 62
Cap. VII – Conclusão................................................................................................... 65
7.1 – Trabalhos Futuros.......................................................................................................................... 65
Referências Bibliográficas ......................................................................................... 66
Anexo A - Registro Oficial de Testes do Software em Paralelo .............................. 69
Anexo B - Utilização do POV-Ray na Linha de Comando........................................ 70
Anexo C - Código da função de Ray-Tracing do POV-Ray...................................... 71
Anexo D - Código da Radiosidade no POV-Ray ....................................................... 73
Anexo E - Código da função parcial do Photon Mapping no POV-Ray .................. 75
14 - CAPÍTULO I - INTRODUÇÃO
Cap. I - Introdução
A síntese de imagens na computação é um processo demorado e que exige considerável poder de
processamento da máquina utilizada. Cada vez mais os algoritmos de renderização estão sendo
aperfeiçoados e hoje é possível criar imagens tão reais que ninguém teria a capacidade de
diferenciar uma imagem feita no computador de uma foto. Mas isso tem conseqüências, e
mesmo nas máquinas mais modernas o processamento de uma única imagem pode levar dias
dependendo de sua complexidade.
Essa técnica, se considerando o contexto de elaboração de um filme, apresenta a seguinte
problemática: para cada segundo de filme são necessárias cerca de 25 imagens para animação
fluida no modelo de vídeo PAL, se cada imagem levasse um dia sendo renderizada, cada segundo
de filme poderia levar até um mês para ficar pronto.
A idéia foi então utilizar um cluster de computadores para aumentar o poder de
processamento de modo eficaz e de baixo custo. Os testes de desempenho realizados mostraram
quanto os algoritmos podem ficar mais rápidos quando executados em paralelo, trazendo
soluções para as empresas que se utilizam dessas técnicas de computação gráfica além do
impacto acadêmico na área de pesquisa científica.
1.1 – Objetivos
Para atingir a proposta de tornar a síntese de imagens foto-realistas mais eficaz, o objetivo do
trabalho está focado nos três principais algoritmos usados em conjunto para a geração dessas
imagens: Ray-Tracing, Radiosidade e Photon Mapping.
O POV-Ray foi a ferramenta escolhida para servir de base para a implementação paralela
por possuir implementação seqüencial de todos os métodos citados. Além disso, o programa foi
codificado em C, pode ser executado em múltiplos sistemas operacionais e possui código aberto.
Sendo assim, o foco principal do trabalho foi a modificação das implementações
seqüenciais desses algoritmos para execução paralela em um cluster usando GNU/Linux. Com
isso feito, testes comprovam o fator de aceleração (speedup) que os algoritmos em paralelo
conseguiram sobre os seqüenciais, exibindo os testes feitos em um cluster composto por oito
nós.
2.1 – Renderização
Renderizar uma imagem significa converter modelos tridimensionais em imagens bidimensionais
que possam ser visualizadas e impressas (figura 2), efetuando transformações geométricas,
projeções, mapeamento de texturas, iluminação, efeitos especiais e rasterização. Isso se faz a
partir da geometria da cena, das informações sobre os materiais de que são feitos os objetos
(cores, texturas e transparências), das condições de iluminação ambiente e da posição de
observação da cena (denominada câmera virtual ou observador).
2.3 – Ray-Tracing
Atualmente, o Ray-Tracing é uma das mais populares técnicas de síntese de imagens e possui
fácil implementação. Ele pode usar a representação de cenas complexas com muitos objetos e
muitos efeitos diferentes. Baseado no algoritmo de Ray-Casting, desenvolvido por Arthur Appel
em 1968, o princípio do Ray-Tracing é simular a geometria ótica envolvida no trajeto de feixes
de luz que viajam pelo espaço da cena (COHEN; WALLACE, 1995).
O algoritmo de Ray-Casting dispara um feixe de luz em cada pixel (ponto da imagem) da
cena, partindo do ponto de observação, e encontra o objeto mais próximo que bloqueia esse raio
(figura 5). Então, a partir do ponto onde ocorreu a colisão, para cada ponto de luz da cena é
disparado um novo raio. Se este raio encontra em seu caminho um objeto que impede que ele
chegue até a luz, tem-se então uma sombra para aquele ponto do objeto. Caso consiga encontrar
a luz sem obstáculos, a cor do pixel é calculada baseando-se no material e intensidade do ponto
de luz (APPEL, 1968).
2.4 – Radiosidade
Como método de renderização, a Radiosidade foi introduzida em 1984 por pesquisadores da
universidade de Cornell. Antes disso a teoria da Radiosidade era usada para resolver problemas
de transferência de calor desde 1950. Diferentemente do Ray-Tracing, a radiosidade não é um
algoritmo de renderização e sim de iluminação global. Ele não foi largamente implementado em
seu conceito original porque utilizava uma solução de matrizes muito complexas para melhorar o
cálculo de radiância (BATTAILE; et al, 1984).
Radiância é vista como a quantidade de radiação projetada pela energia luminosa em uma
determinada região de uma cena. Ela representa a intensidade da luz em cada ponto da cena e
contribui para colorir corretamente todas as suas regiões. Trabalha-se com a idéia de que a
energia sendo distribuída na cena encontra o equilíbrio de luz entre os objetos. Assim que os
raios disparados das fontes de luz colidem com os objetos, a informação da iluminação é
guardada no próprio objeto.
O algoritmo da Radiosidade divide as superfícies em regiões menores também chamadas
de patches. Isso cria uma subdivisão da geometria original da cena sendo que quanto menor
forem os patches por superfície, melhor será a qualidade da iluminação. Na figura 7, pode-se ver
uma cena renderizada e sua correspondente divisão em patches.
Figura 10 - Esquerda: cena gerada com Ray-Tracing. Direita: mesma cena com efeitos de
Radiosidade.
Um efeito de iluminação gerado pela Radiosidade ocorre quando, por exemplo, uma
partícula azul, emitida de uma fonte de luz, choca-se contra uma superfície A e parte dessa luz é
re-emitida para superfícies vizinhas, como a superfície B, essas superfícies recebem parte da
informação da cor azul. Se a superfície B fosse originalmente branca, agora teria partículas da
cor azul espalhando-se sobre sua cor branca. A superfície B está agora composta de partículas
azuis e brancas. Esta é uma grande vantagem sobre o Ray-Tracing, porque a energia luminosa de
uma superfície pode se misturar com outras superfícies. O efeito ocorrido na superfície B é
conhecido como Color Bleeding, e aumenta o realismo da síntese de imagens, como pode ser
visto na figura 10 (JOHN, 2003).
A vantagem da Radiosidade é que ela não precisa ser recalculada caso o ponto de
observação seja alterado. Como a iluminação é calculada em toda cena usando-se os patches,
esses valores não mudam se apenas ocorrer uma mudança no ponto de observação. A
Radiosidade só precisa ser recalculada caso a iluminação da cena seja modificada. Por esse
motivo a Radiosidade é conhecida como um algoritmo independente do ponto de observação.
Mesmo sendo um algoritmo de cálculo de iluminação para sombras, a Radiosidade pode ser
construída de forma híbrida combinando um algoritmo de renderização (que pode ser o Ray-
Tracing, por exemplo) ao seu processo. Assim, pode-se usar a radiosidade para o cálculo das
sombras usando reflexões difusas e Color Bleeding, e o outro algoritmo para o cálculo de
reflexões especulares e efeitos de transparência.
Figura 11 – Imagem com efeitos cáusticos gerado pelo algoritmo de Photon Mapping.
Um exemplo simples de geração de cáusticos é a lente de aumento (lupa) que faz com
que a luz se concentre em apenas uma região. (JENSEN, 2001).
Há duas formas diferentes que um cáustico pode assumir: catacáustico e diacáustico. O
efeito catacáustico é provocado pela reflexão dos feixes de luz na superfície enquanto o
diacáustico é provocado pela refração desses feixes (quando o raio atravessa a superfície)
(JENSEN, 2001).
Assim como o algoritmo de Radiosidade, o Photon Mapping é um algoritmo de
iluminação global, podendo também ser implementado de forma híbrida com o Ray-Tracing,
funcionando assim em duas passagens:
• Na primeira, geram-se os feixes de luz saindo das fontes de luz e não do olho
observador. Cada vez que um feixe se choca com um objeto ele deposita uma
quantidade de energia nesse ponto em uma estrutura chamada photon-map.
• Na segunda passada, os feixes são disparados pelo olho de observação e as
informações do photon-map são cruzadas para a geração dos cáusticos na cena.
A figura 12 demonstra o funcionamento do algoritmo de Photon Mapping. Linhas
disparadas a partir de um ponto de luz no teto da cena chocam-se com o objeto de cristal.
Ocorrem refrações desviando os raios de luz que acabam por se encontrar em uma mesma região
formando o cáustico. O mapa de fótons é representado pelos círculos no final de cada linha, e é
C A P . 2 . 5 - P H O T O N - M A P P I N G - 25
essa informação que será usada para gerar o efeito de cáustica no processo de Ray-Tracing
(GÜNTHER; WALD; SLUSALLEK, 2004).
2.6 – Anti-aliasing
Como mostrado anteriormente, o algoritmo de Ray-Tracing dispara um raio contra cada pixel da
imagem. Essa técnica pode levar ao serrilhado das imagens, visões distorcidas de linhas finas e
detalhes perdidos na imagem. O anti-aliasing é uma técnica utilizada para ajudar a eliminar tais
erros ou reduzir o impacto negativo que eles dão na imagem. Resumindo, o anti-aliasing faz com
que a imagem pareça mais suave (POV-RAY; 2005).
Na figura 16 é possível notar a diferença entre uma imagem gerada com uma técnica de
Ray-Tracing sem anti-aliasing (esquerda) e uma com anti-aliasing. Na imagem à esquerda
existem diversas mudanças de tonalidades bruscas. Com a aplicação de um filtro de anti-alias é
feita uma suavização nos pontos onde a mudança de tonalidade é mais brusca, gerando uma
imagem mais suave e próxima do real.
Onde r1, g1 e b1 são as cores (rgb) de um ponto e r2, g2 e b2 são as cores do outro ponto.
Se essa diferença é maior do que o threshold, em ambos os pixels é feito o super-
sampling. Os valores rgb estão no intervalo de 0.0 a 1.0, dessa forma a maior diferença possível
é 3.0. Se o threshold for 0.0 o super-sampling é feito em todos os pixels; se o threshold é 3.0
nenhum pixel recebe o processo.
2.7 – Jittering
Um dos grandes problemas quando se busca o foto-realismo é o excesso de perfeição que uma
renderização pode acabar gerando. Não existem imperfeições nas imagens, todas as formas
geométricas calculadas são matematicamente perfeitas. Por isso, imagens geradas usando Ray-
Tracing, apesar de perfeitas, às vezes parecem estranhas ou até surreais.
Para que sejam geradas imagens mais próximas à realidade é utilizada uma técnica
chamada Jittering. A idéia principal dessa técnica é utilizar um par de números aleatórios (ou
informados) para evitar o disparo de raios sempre contra o centro de um pixel da imagem (figura
18). Dessa forma evita-se que ocorra o efeito de grade, e também, a perfeição absoluta dos
objetos. A cada pixel, o par de números é somado de forma que o raio saia do centro e seja
disparado contra outro local próximo dentro do pixel (SHIRLEY, 1994).
30 - C A P Í T U L O I I - P R O C E S S A M E N T O G R Á F I C O
Nos sistemas Unix e suas variações não existe tal ambiente gráfico oficial, mas sim
diversos programas de código aberto – pode-se citar, por exemplo, o KpovModeler (KDE, 2006)
e o Y.A.P.R.M (POV-RAY, 2005). De fato, o POV-Ray não precisa de nenhuma GUI ou
qualquer outra parte gráfica para executar as renderizações. Diversos argumentos ligados ao
executável do programa resolvem esse problema (Anexo B) e a edição de códigos pode ser feita
em qualquer editor de texto comum respeitando-se as regras da linguagem de modelagem do
POV-Ray. A versão utilizada do programa foi a 3.6.1, que é a versão estável mais recente até a
data deste trabalho.
32 - C A P Í T U L O I I I – P O V - R A Y
3.1 – Iluminação
O tipo de iluminação básico feito pelo POV-Ray é a iluminação pontual. Nessa iluminação, um
ponto de luz emite fótons em todas as direções uniformemente. Fontes de luz spot são fontes de
luz com formato cônico que emitem fótons em uma determinada direção baseando-se no raio de
abertura do cone.
Luzes retangulares ou em área são fontes de luz que emitem fótons partindo de um plano.
Essas luzes são basicamente um grupo de luzes pontuais alinhadas sobre uma grade retangular. A
potência que a luz chega a um objeto é dada pela soma das emissões de cada uma das luzes
pontuais.
struct Image_Colour_Struct{
unsigned float Red, Green, Blue, Filter, Transmit;
};
CAP. 3.3 – RADIOSIDADE NO P O V - R A Y - 35
Uma linha é composta por essa estrutura de pixel multiplicado pelo número de colunas
existentes na renderização. O código do método que implementa o Ray-Tracing no POV-Ray é
mostrado no Anexo C.
Os próximos dois laços são uma repetição dos laços anteriores, porém agora de acordo
com um número pré-estabelecido de fótons durante a construção da cena, todos esses fótons são
disparados de forma distribuída entre as luzes de grupo e luzes globais. O número padrão de
fótons emitidos é de 20000 (POV-RAY, 2005).
Os últimos dois laços são feitos para os disparos de fótons a partir de fontes de luz
cilíndricas tanto para grupos quanto para iluminação global. Ao fim de todos os laços, uma kd-
tree balanceada é construída para posterior utilização pelo Ray-Tracing.
A estrutura que guarda cada fóton do Photon Mapping é composta por um vetor de três
posições que possui a localização do fóton no espaço tridimensional da cena (SNGL_VECT), um
vetor de quatro caracteres que identifica a cor (vermelha, verde e azul) e a intensidade da luz do
fóton (SMALL_COLOUR), um caractere que representa uma informação de localização relativa
da kd-tree e dois caracteres que representam os ângulos de direção de onde veio o fóton. Fótons
podem assumir qualquer cor, já que os objetos que tem a propriedade filter alteram o modo como
a luz passa por eles. Os ângulos de direção que compõem um fóton são relativos à última
reflexão ou refração que a este fóton sofreu.
struct photon_struct {
SNGL_VECT Loc; /* location */
SMALL_COLOUR Colour; /* color & intensity (flux) */
unsigned char info; /* info byte for kd-tree */
signed char theta, phi; /* incoming direction */
};
struct photon_map_struct {
/* these 3 are render-thread safe - NOT pre-process thread safe */
PHOTON_BLOCK *head; // the photon map - array of blocks of photons
int numBlocks; /* number of blocks in base array */
int numPhotons; /* total number of photons used */
1
Um bilhão de instruções de ponto flutuante por segundo.
42 – C A P Í T U L O I V – C O M P U T A Ç Ã O P A R A L E L A
processamento da malha pode possuir mais de um processador e essas máquinas
podem contem milhares de nós. Esse tipo de máquina não possui memória
compartilhada.
• Multiprocessadores com Memória Compartilhada Distribuída (DSM, Distributed
Shared Memory) – Estas máquinas são semelhantes às SMP possuindo um conjunto
de microprocessadores interligados através de uma rede de interconexão de alta
velocidade. A diferença está no fato de que a memória global compartilhada na
verdade está fisicamente distribuída entre os nós; porém, para o usuário é como se ele
estivesse acessando um espaço de endereçamento único.
• Clusters – Sob este nome estão máquinas cujo princípio básico é o emprego de uma
rede de custo baixo, porém de alto desempenho, interligando nós que podem possuir
mais de um processador. Geralmente são utilizados computadores pessoais comuns.
4.3 – Clusters
Por definição, “clusters” são pilhas de PCs de uso exclusivo para paralelismo, ligados por uma
rede de alta velocidade (Gigabit Ethernet, Myrinet, SCI, Infiniband) podendo conter milhares de
processadores no total. Cada nó (computador) do cluster geralmente é “sem cabeça”, ou seja, não
possui teclado, mouse, monitor ou qualquer outro periférico (PACHECO, 1997).
A figura 28 mostra um exemplo de cluster. Nesta figura vê-se o nó mestre à direita e 12
nós “sem cabeça” (headless) ligados por um switch (equipamento de conexão para interligar
vários computadores).
É chamada computação paralela trivial o tipo de aplicação onde após a divisão da carga
de processamento, não há necessidade de que os processos se comuniquem para chegar a um
resultado. Dessa forma, evita-se perda de tempo trocando mensagens desnecessárias entre os
processos. Cada nó faz o seu trabalho e o retorna ao mestre que se encarrega de organizar os
dados e exibir os resultados.
1
Um bilhão de instruções de ponto flutuante por segundo.
44 – C A P Í T U L O I V – C O M P U T A Ç Ã O P A R A L E L A
1
Um bilhão de instruções de ponto flutuante por segundo.
46 – C A P Í T U L O I V – C O M P U T A Ç Ã O P A R A L E L A
Uma maneira trivial de se renderizar uma cena paralelamente seria seccioná-la em pequenas
faixas de forma que cada processo renderizasse uma ou mais faixas gerando um arquivo de
imagem, e, ao final, uníssemos essas faixas por meio de algum processo realizado em um
aplicativo processador de imagens. Isso poderia ser feito manualmente ou através de algum
programa que executa operações em lote para cada processador/computador envolvido no
processo. Porém essa técnica não alcança bons resultados porque mesmo que as secções sejam
facilmente renderizadas, teríamos o trabalho de uni-las posteriormente.
Em muitos casos, apenas um quadro pode levar um tempo significante para ser
renderizado. Isso pode ocorrer por muitos fatores, tanto da cena – geometria complicada,
iluminação sofisticada, aplicação de anti-aliasing ou simplesmente dimensões muito grandes da
imagem – quanto do computador que está efetuando a renderização – poder de processamento,
memória disponível, escalonamento de tarefas.
Uma quarta e última definição exibida na última parte da figura 32 seria uma divisão
dinâmica em sub-grades, baseando-se na complexidade das partes da cena. O problema desse
método seria o tipo de cálculo que seria realizado, pois não é possível prever qual parte da cena
C A P . 5 . 1 – T R A B A L H O S R E L A C I O N A D O S - 49
será mais complexa que outra. Uma previsão pode ser feita de acordo com o número de objetos e
seus respectivos materiais, porém, tal cálculo seria complexo e adicionaria maior tempo ao
processo final ao invés de reduzi-lo.
Um pool de tarefas poderia ser implementado de forma que um processo mestre receberia
requisições de trabalho e enviaria pontos ou blocos de pontos da matriz para que cada processo
escravo calculasse o valor do(s) ponto(s) recebido(s) (figura 33). Dessa forma teríamos um
trabalho uniforme já que todo processo sem trabalho pediria um ponto ao mestre e trabalharia
sobre esse ponto enquanto os outros processos estão trabalhando em outros pontos. Se um
processo está em um ponto de difícil renderização os outros processos podem seguir adiante
pegando os próximos pontos paralelamente. O problema desse método é que se estivéssemos
trabalhando em um cluster ocorreria um overhead de comunicações já que cada ponto precisa ser
pedido e transmitido para cada computador. Como todos os computadores pediriam os pontos
para apenas um mestre teríamos também um gargalo que diminuiria a velocidade da
renderização.
Um algoritmo paralelo de Ray-Tracing chamado Tachyon foi proposto por Stone (1998)
como sua tese de mestrado. O algoritmo suporta MPI para clusters, threads para computadores
com memória compartilhada e suporta as duas arquiteturas simultaneamente em computadores
que permitam isso. A figura 34 exibe o funcionamento híbrido deste algoritmo exibindo como
50 - C A P Í T U L O V – P A R A L E L I Z A Ç Ã O DO POV-RAY
fica a divisão entre os pixels da cena em um cluster de três máquinas com 4 processadores cada
um.
A figura 36 exibe o trabalho feito para cada nó em um cluster com quatro máquinas. Os
quadrados em amarelo representam os pontos calculados pelo nó zero, os quadrados em azul
pelo nó um, em vermelho pelo nó dois e em verde pelo nó três.. A cada iteração o nó zero salta
52 - C A P Í T U L O V – P A R A L E L I Z A Ç Ã O DO POV-RAY
três pixels e faz o cálculo de quarto em quatro pixels apenas. Em coordenadas, ele fez o cálculo
dos pixels (0,y); (4,y); (8,y); (12,y), onde y representa cada linha da imagem.
Este método foi batizado de “Crivo de Raios” (JESUS, NEVES; 2006). Implementada e
testada, esta modificação do algoritmo de Ray-Tracing para clusters provou que uma aceleração
escalável pode ser atingida. Ou seja, se dobrado o número de máquinas no cluster, o tempo final
de geração da imagem tende a diminuir pela metade, como será apresentado no capítulo com os
resultados da implementação.
Existem dois laços que compõem o Ray-Tracing, um deles itera sobre as linhas enquanto
o outro itera sobre as colunas, dessa forma, modificou-se o laço que itera sobre as colunas
fazendo com que um salto relativo ao número de computadores no cluster fosse somado para o
cálculo da próxima coluna ao invés de um incremento de uma unidade. Ao fim do laço que itera
sobre as colunas, criou-se um mecanismo de sincronização de forma que todos os nós
participantes do cluster (excetuando o nó zero) enviassem seus resultados de cálculos para o nó
zero. O nó mestre por sua vez adiciona o pixel à coluna correta, exibe na tela e salva em arquivo
a linha concluída. Essa etapa do processo é feita de forma síncrona. Se o nó zero ainda não
terminou o processamento de sua linha atual, os outros processos que terminaram os seus
cálculos previamente aguardam o nó zero para que receba suas mensagens.
A estrutura, que contém os dados sobre as cores dos pixels, enviada ao nó mestre é
composta por um vetor de tamanho dado pela equação abaixo:
CAP. 5.2 –RAY-TRACING EM P A R A L E L O - 53
TamVet = (colunas/numprocs)*5
Além disso, há sobrecarga de informação sobre o nó mestre porque além de ele ter que
calcular os pixels, também é necessário que alinhe os pixels, exiba na tela e salve em arquivo
toda a imagem. Quando não é utilizada saída em tela, arquivo e nem anti-alias, a sobrecarga é
diminuída fazendo com que o algoritmo alcance um speedup quase linear.
Nesse modelo, o nó mestre não executa disparos de raios contra a cena, apenas aguarda
dados dos outros nós e aplica anti-aliasing sobre eles. Essa técnica torna o uso do anti-aliasing
possível, pois o nó mestre sempre recebe os dados de todos os computadores possuindo sempre a
54 - C A P Í T U L O V – P A R A L E L I Z A Ç Ã O DO POV-RAY
linha completa. Logo, após o recebimento de dados de uma linha por todos os processos, o nó
mestre alinha os dados de forma correta e aplica o anti-aliasing. O funcionamento é correto
também quando não se aplica o anti-aliasing, dessa forma não se atinge um balanceamento
completo já que o nó mestre aguarda mais tempo do que trabalha sobre os pixels.
Com isso, uma execução em um cluster de dois computadores funciona de forma similar
à execução seqüencial já que apenas um computador efetuará os disparos enquanto o outro
aguarda os resultados. Só se ganha em velocidade quando são usados três ou mais computadores.
De forma similar ao crivo original, o mesmo laço de iteração sobre as colunas foi
modificado, porém os nós não mais saltam o número total de computadores no cluster, mas sim
o número de computadores decrescido de um, que seria o nó mestre.
A figura 39 mostra como fica a mesma distribuição do método anterior com quatro
computadores, não há mais quatro cores diferentes já que o nó mestre não trabalha mais no
processo de disparo de raios.
Com esse novo modelo, mesmo contando com um processador a menos no cálculo da cor
dos pixels, nota-se uma melhora na aceleração do processo à medida que mais máquinas são
utilizadas (os testes do capítulo VI comprovam essa melhoria).
Essa nova abordagem trouxe um novo problema. Quando o threshold escolhido para o
anti-aliasing é muito baixo, mais pixels sofrem o processo de super-sampling. Como o nó mestre
é o único que faz o anti-alias, para clusters com muitas máquinas esse método gera um gargalo
de comunicação. Se um nó escravo termina uma linha enquanto o nó mestre está calculando anti-
aliasing, este terá que esperar até o fim do processo para que sua mensagem possa ser
transmitida já que esse método, assim como seu antecessor, trabalha com passagem de
mensagens síncrona.
A primeira idéia foi a solução pelo método do crivo de raios, porém, este gerou imagens
diferentes das imagens geradas pelo algoritmo seqüencial como vê-se na figura 40. Nela exibe-se
a diferença entre as imagens geradas, a imagem da esquerda foi gerada no algoritmo seqüencial e
a da direita no paralelo. Há ondas na imagem da versão paralela que deformam a sombra, isso
prova que diferentemente do Ray-Tracing onde o disparo de raios e cálculo das cores dos pixels
é independente, nesse caso todos os nós precisam das informações geradas pelos outros nós.
Para que o cálculo distribuído funcionasse da mesma forma que o seqüencial, a média da
luz ambiente deveria ser igual entre os nós, porém como cada nó trabalha sobre pixels diferentes,
a média é gerada separadamente. A solução para esse problema foi a sincronização dos dados
das médias no nó zero que soma as médias e redistribui aos nós do cluster de forma que todos
tenham os mesmos dados ao fim de cada linha do Mosaic Preview.
56 - C A P Í T U L O V – P A R A L E L I Z A Ç Ã O DO POV-RAY
O Photon Mapping foi o algoritmo mais complexo a ser paralelizado devido à estrutura do
photon-map utilizada no POV-Ray. O mesmo problema da Radiosidade é encontrado no Photon
Mapping, todos os nós devem ter as informações completas sobre o Photon Mapping para
posterior utilização pelo Ray-Tracing.
Como dito no sub-capítulo 3.4, a estrutura do Photon Mapping é composta por uma lista
de listas de fótons (matriz esparsa) onde cada fóton é composto por três floats de localização (x,
y, z), uma estrutura de cor composta por quatro caracteres, mais um caractere sobre a informação
da localização do fóton na kd-tree e dois caracteres que representam o ângulo de incidência do
fóton.
Com essa estrutura, o envio de informações utilizando MPI (que permite apenas o envio
de dados primitivos como números inteiros, caracteres ou floats) tornou-se quase impossível já
que para cada fóton seriam necessários quatro envios de mensagens para que o fóton pudesse ser
reconstruído nas outras máquinas. Juntando-se as informações de caracteres em apenas uma
mensagem, pôde-se reduzir o número de mensagens para duas por fóton. Duas mensagens por
fóton não resolvem o problema, contando-se que serão disparados milhares de fótons sobre a
cena, a sobrecarga de informações seria muito elevada tornando inviável tal implementação.
A primeira idéia para implementação do algoritmo paralelo que evitasse essa sobrecarga
de troca de informação entre os nós foi colocar cada um dos seis laços existentes no algoritmo
em máquinas diferentes. A sincronização de fótons deveria ser feita ao fim dos seis laços e, em
seguida, cada nó construiria sua própria kd-tree balanceada e a passada do Ray-Tracing seria
feita. Essa abordagem provou ser ineficiente em teoria e não foi posta em prática primeiramente
porque limitava o número de máquinas para um número fixo retirando a propriedade escalar
conseguida com os algoritmos de Radiosidade e Ray-Tracing. Outro problema decorre do fato
que nem sempre os outros laços são usados já que cada laço desses representa um tipo de luz e
luzes em grupo, luzes cilíndricas ou retangulares nem sempre estão presentes na cena.
Uma nova abordagem foi separar a iluminação da cena de forma que cada computador
calculasse o disparo de fótons para um mesmo número de objetos de luz. Dessa forma,
conseguiu-se uma razoável divisão de trabalho para cenas com muitos pontos de luz. Por
exemplo, se em uma cena composta por doze pontos de luz fosse utilizado um cluster de duas
máquinas, cada nó do cluster executaria o cálculo de seis pontos de luz emissores de fótons. Os
fótons seriam sincronizados ao fim dos seis laços.
Essa abordagem teve o início de sua implementação testada sem a sincronização para
checar o impacto gerado pela falta de informações de fótons sobre a renderização final.
Infelizmente a sincronização dos fótons não pode ser construída devido à complexidade com a
qual o POV-Ray adiciona os fótons ao photon-map. Por ser um programa construído em
programação estruturada com variáveis globais tornou-se muito difícil encontrar as ligações
entre os arquivos de código que se referenciavam ao photon-map ou a própria kd-tree.
CAP. 5.4 – PHOTON MAPPING EM P A R A L E L O - 57
O projeto de paralelização do Photon Mapping não pôde ser concluído nesse estudo mas
foi agendado como projeto futuro e será realizado com uma melhor inspeção sobre o código
buscando melhores formas e as estruturas corretas para devida distribuição e sincronização de
tarefas.
58 - C A P Í T U L O V I – T E S T E S E RESULTADOS
Cap. VI – Testes e Resultados
Foram escolhidas três imagens de exemplo. Duas dessas imagens vêm com o POV-Ray
3.6.1: woodbox.pov e glasschess.pov. A imagem woodbox é uma imagem clássica do POV-Ray.
A glasschess contém um grande número de cálculo de refrações e reflexões por pixel, sendo
assim uma boa imagem para os testes. A terceira imagem (skyvase.pov) foi usada para uma
comparação oficial dos algoritmos de acordo com o Official POV-Ray Benchmarking (Anexo A).
Para gerar grande carga de trabalho sobre os nós, as dimensões de 4000x3000 foram escolhidas
para as imagens woodbox.pov e skyvase.pov. A imagem glasschess.pov foi renderizada em
1024x768 devido a alta complexidade da cena. Foram feitos testes com os dois crivos, com e
sem anti-alias, variando entre 2 e 8 nós para os algoritmos paralelos.
Para todos os testes das versões paralelas foram utilizados de dois a oito nós do cluster
tendo o nó de identificação zero como inicial. Cada renderização foi executada cinco vezes e a
média entre elas foi calculada. Nenhum dos testes gerou saída em arquivo ou tela, isso significa
que apesar da renderização ser efetivamente realizada, os dados da imagem gerada não são
salvos. Além disso, todas as mensagens impressas pelo POV-Ray no console foram suprimidas
para evitar ao máximo o desperdício de tempo.
6.1 – Woodbox
A tabela da próxima página exibe os resultados dos testes com o cálculo da eficiência e speedup
para cada conjunto de nós usados. O tempo do algoritmo seqüencial aparece em primeiro lugar
seguido dos tempos para o Crivo Mestre/Escravo e o Crivo de Raios. A secção esquerda da
tabela exibe os dados para a renderização sem anti-aliasing e a secção direita, com anti-aliasing.
C A P Í T U L O 6 . 1 – W O O D B O X - 59
Woodbox.pov 4000x3000
Sem anti-aliasing Com anti-aliasing
Segundos Speedup Eficiência Segundos Speedup Eficiência
Seqüencial Seqüencial
1 273 1 315
Crivo Crivo
Mestre/Escravo Mestre/Escravo
2 232 1,177 0,588 2 231 1,364 0,682
3 117 2,333 0,778 3 118 2,669 0,890
4 79 3,456 0,864 4 82 3,841 0,960
5 59 4,627 0,925 5 64 4,922 0,984
6 47 5,809 0,968 6 57 5,526 0,921
7 40 6,825 0,975 7 53 5,943 0,849
8 35 7,800 0,975 8 50 6,300 0,788
Crivo de Raios
2 137 1,993 0,996
3 94 2,904 0,968
4 70 3,900 0,975
5 55 4,964 0,993
6 47 5,809 0,968
7 41 6,659 0,951
8 36 7,583 0,948
5 5
4 4
3 3
2 2
1 1
0 0
2 3 4 5 6 7 8 2 3 4 5 6 7 8
Speedup Linear Speedup Linear
Crivo de Raios
Núm ero de Máquinas Núm ero de Máquinas
Cr ivo Mest re/ Escravo
Crivo M estre Escravo
60 - C A P Í T U L O V I – T E S T E S E RESULTADOS
Esse terceiro gráfico dispõe a aproximação ocorrida entre os métodos quando se aumenta
o número de nós no cluster sem o uso de anti-aliasing. Nota-se o gargalo ocorrido pelo nó zero
do Crivo de Raios, pois além de calcular os pixels ele precisa sincronizar os dados com os outros
processos. Isso não ocorre com o Crivo Mestre/Escravo onde o nó zero apenas aguarda os
cálculos dos outros nós.
6.2 – Glasschess
A tabela da próxima página exibe os resultados dos testes com o cálculo da eficiência e speedup
para cada conjunto de nós usados. O tempo do algoritmo seqüencial aparece em primeiro lugar
seguido dos tempos para o Crivo Mestre/Escravo e o Crivo de Raios. A secção esquerda da
tabela exibe os dados para a renderização sem anti-aliasing e a secção direita, com anti-aliasing.
C A P Í T U L O 6 . 2 – G L A S S C H E S S - 61
Glasschess.pov 1024x768
Sem anti-aliasing Com anti-aliasing
Segundos Speedup Eficiência Segundos Speedup Eficiência
Seqüencial Seqüencial
1 642 1 649
Crivo Crivo
Mestre/Escravo Mestre/Escravo
2 564 1,138 0,569 2 564 1,151 0,575
3 286 2,245 0,748 3 287 2,261 0,754
4 199 3,226 0,807 4 199 3,261 0,815
5 139 4,619 0,924 5 139 4,669 0,934
6 113 5,681 0,947 6 113 5,743 0,957
7 104 6,173 0,882 7 104 6,240 0,891
8 83 7,735 0,967 8 83 7,819 0,977
Crivo de Raios
2 331 1,940 0,970
3 215 2,986 0,995
4 161 3,988 0,997
5 129 4,977 0,995
6 107 6,000 1,000
7 92 6,978 0,997
8 80 8,025 1,003
8 8
Speedup
Speedup
6
6
4
4
2
2
0
0 2 3 4 5 6 7 8
2 3 4 5 6 7 8
Número de Máquinas
Speedup Linear
Speedup Linear Número de máquinas Crivo M estre/Escravo
Crivo de Raios
Crivo M estre/Escravo
62 - C A P Í T U L O V I – T E S T E S E RESULTADOS
600
Segundos 500
400
300
200
100
0
1 2 3 4 5 6 7 8
Crivo Mest re/ Escravo
Núm ero de Máquinas
Crivo de Raios
Esse terceiro gráfico dispõe a aproximação ocorrida entre os métodos quando se aumenta o
número de nós no cluster sem o uso de anti-aliasing.
6.3 – Skyvase
Essa imagem é utilizada oficialmente pelo POV-Ray para testes de velocidade de renderização
tanto para máquinas seqüências quanto para clusters.
A tabela da próxima página exibe os resultados dos testes com o cálculo da eficiência e
speedup para cada conjunto de nós usados. O tempo do algoritmo seqüencial aparece em
primeiro lugar seguido dos tempos para o Crivo Mestre/Escravo e o Crivo de Raios. A secção
esquerda da tabela exibe os dados para a renderização sem anti-aliasing e a secção direita, com
anti-aliasing.
C A P Í T U L O 6 . 3 – S K Y V A S E - 63
Skyvase.pov 4000x3000
Sem anti-aliasing Com anti-aliasing
Segundos Speedup Eficiência Segundos Speedup Eficiência
Seqüencial Seqüencial
1 246 1 252
Crivo Crivo
Mestre/Escravo Mestre/Escravo
2 216 1,139 0,569 2 215 1,172 0,586
3 108 2,278 0,759 3 108 2,333 0,778
4 73 3,370 0,842 4 72 3,500 0,875
5 54 4,556 0,911 5 53 4,755 0,951
6 44 5,591 0,932 6 44 5,727 0,955
7 36 6,833 0,976 7 37 6,811 0,973
8 31 7,935 0,992 8 32 7,875 0,984
Crivo de Raios
2 120 2,050 1,025
3 88 2,795 0,932
4 63 3,905 0,976
5 51 4,824 0,965
6 43 5,721 0,953
7 37 6,649 0,950
8 33 7,455 0,932
6
Speedup
5
5
4
3 4
2 3
1 2
0 1
2 3 4 5 6 7 8 0
Speedup Linear
Número de Máquinas 2 3 4 5 6 7 8
Crivo de Raios
Crivo Mest re/ Escravo
Speedup Linear Núm ero de Máquinas
Crivo Mest re/ Escravo
64 - C A P Í T U L O V I – T E S T E S E RESULTADOS
200
Segundos
150
100
50
0
1 2 3 4 5 6 7 8
Crivo de Raios
Núm ero de Máquinas
Crivo M estre/Escravo
O máximo de speedup foi alcançado em testes não registrados quando foram usadas todas
as máquinas excetuando a de identificação zero. Sete máquinas SMP, com dois processos em
cada uma, totalizando 14 processos renderizando a imagem exibida no sub-capítulo 6.1 sem anti-
aliasing pelo Crivo de Raios. O processo todo levou 19 segundos, comparando com o tempo
seqüencial de 273 segundos temos que o speedup foi de aproximadamente 14,37. A eficiência
calculada é de aproximadamente 1,02. Esse é o melhor resultado obtido nos testes e demonstra
uma aceleração super-linear do algoritmo dado pelo fato que menos mensagens são trocadas via
rede e a sincronização dos processos é mais rápida porque dois processos são iniciados por vez
ao invés de um só em cada máquina.
void Start_Tracing()
{
COLOUR unclippedColour;
int x;
int antialias_line = true;
int skip_lines;
int first_line;
int skip_odd_lines;
/* Set jitterscale. */
continue;
}
MosaicPreviewSize = 1;
Send_ProgressUpdate(PROGRESS_RENDERING);
Do_Cooperate(0);
Prune_Vista_Tree(Current_Line_Number);
if (opts.FrameSeq.Field_Render_Flag)
{
if (Current_Line_Number >= opts.First_Line)
{
antialias_line = ((Current_Line_Number % 2) ^ skip_odd_lines);
}
else
{
72 - A N E X O C
antialias_line = false;
}
}
Check_User_Abort(false);
/* Apply anti-aliasing. */
if ((opts.Options & ANTIALIAS) && antialias_line)
{
do_anti_aliasing(x, Current_Line_Number, Current_Line[x]);
}
/* Display pixel. */
plot_pixel(x, Current_Line_Number, Current_Line[x]);
POV_ASSIGN_PIXEL_UNCLIPPED (x, Current_Line_Number, unclippedColour)
POV_ASSIGN_PIXEL (x, Current_Line_Number, Current_Line [x])
}
output_prev_image_line_and_advance(Current_Line_Number);
}
Current_Line_Number = 0;
if (opts.Last_Line != opts.First_Line)
{
output_single_image_line_with_alpha_correction(Previous_Line,opts.Last_Line - 1);
}
A N E X O D - 73
Anexo D - Código da Radiosidade no POV-Ray
void Start_Tracing_Radiosity_Preview(int StartPixelSize, int EndPixelSize)
{
unsigned char Red, Green, Blue, Alpha;
unsigned char *thisr = NULL, *thisg = NULL, *thisb = NULL, *thisa = NULL;
unsigned char *upr = NULL, *upg = NULL, *upb = NULL, *upa = NULL;
int Smooth_Preview = 0;
int dx, dy, skip,
tr, tg, tb, ta,
lastr, lastg, lastb, lasta,
ulr, urr, llr, lrr,
ulg, urg, llg, lrg,
ulb, urb, llb, lrb,
ula, ura, lla, lra,
lor, log, lob, loa,
hir, hig, hib, hia,
tx, ty, jitter_range, jitter_offset, offset_x, offset_y, first_pass,
x, x2, y2;
DBL grey, gather_grey;
COLOUR Colour, avg_gather, unclippedColour;
int save_use_blur;
opts.Real_Radiosity_Error_Bound = opts.Radiosity_Error_Bound;
opts.Radiosity_Error_Bound *= opts.Radiosity_Low_Error_Factor;
firstRadiosityPass = true;
/* Initialize the accumulators which will allow us to set average amb Brightness */
Make_Colour(Radiosity_Gather_Total, 0.0, 0.0, 0.0);
Radiosity_Gather_Total_Count = 0;
/* if radiosity is on, you MUST use preview pass to get reasonable results.
* 8x8 is generally a good size to use if the user didn't specify anything.
*/
if ( StartPixelSize == 1 )
{
if (opts.radPretraceStart==0 || opts.radPretraceEnd==0)
{
StartPixelSize = EndPixelSize = 8;
}
else
{
/* lets use some percentages instead of the INI options!! */
StartPixelSize = max(Frame.Screen_Height,Frame.Screen_Width)*opts.radPretraceStart;
EndPixelSize = max(Frame.Screen_Height,Frame.Screen_Width)*opts.radPretraceEnd;
}
}
/* if there is no visible output, might as well just do one pass, it's faster.
* The last pass is the one which determines the values which get put into
* the radiosity tree, so just do the last (end) pass.
*/
/* NK rad - always do what the user asks for!
it WILL affect the final output
if ( !(opts.Options & DISPLAY)) StartPixelSize = EndPixelSize;
*/
/* Finally, end size must always be less than or equal to start size */
if ( EndPixelSize > StartPixelSize ) EndPixelSize = StartPixelSize;
skip = StartPixelSize;
first_pass = true;
jitter_range = 3;
jitter_offset = skip / 2 - 1; /* add a very small amount of jitter */
#if(ALLOW_SMOOT_RAD_PREVIEW == 1)
if(skip <= 8)
Smooth_Preview = 1;
#endif
Do_Cooperate(0);
Assign_Colour(Current_Line[x], Colour);
POV_ASSIGN_PIXEL (x, Current_Line_Number, Colour)
if (first_pass)
{
/* Ensure that the average ambient value returned by compute_ambient() is about
* the same as the average ambient value setting in the scene file
*/
if ( Radiosity_Gather_Total_Count )
{
VInverseScale(avg_gather, Radiosity_Gather_Total, (DBL)Radiosity_Gather_Total_Count);
gather_grey = avg_gather[pRED] + avg_gather[pGREEN] + avg_gather[pBLUE];
if ( gather_grey > 0. )
{
/* NK rad 1999 commented this out - we don't want to mess with the
'brightness' setting that the user chose */
/*opts.Radiosity_Brightness = 3. / gather_grey; */
if ( ot_fd != NULL)
{
ot_fd->printf("B%g\n", opts.Radiosity_Brightness);
}
}
}
first_pass = 0;
}
skip /= 2;
} /* end loop of different resolutions */…
}
A N E X O E - 75
Anexo E - Código da função parcial do Photon Mapping no POV-Ray
...
// global lights
photonOptions.Light_Is_Global = true;
for (Light = Frame.Light_Sources;
Light != NULL;
Light = Light->Next_Light_Source)
if (Light->Light_Type != FILL_LIGHT_SOURCE)
{
SearchThroughObjects(Frame.Objects, Light, true);
}
// light_group lights
photonOptions.Light_Is_Global = false;
for (Light_Group_Light = Frame.Light_Group_Lights;
Light_Group_Light != NULL;
Light_Group_Light = Light_Group_Light->Next)
{
Light = Light_Group_Light->Light;
if (Light->Light_Type != FILL_LIGHT_SOURCE)
{
SearchThroughObjects(Frame.Objects, Light, true);
}
}
factor = (DBL)photonCountEstimate/photonOptions.surfaceCount;
factor = sqrt(factor);
photonOptions.surfaceSeparation *= factor;
}
photonOptions.Light_Is_Global = true;
for (Light = Frame.Light_Sources;
Light != NULL;
Light = Light->Next_Light_Source)
if (Light->Light_Type != FILL_LIGHT_SOURCE)
{
ShootPhotonsAtObject(NULL, Light, true);
}
// light_group lights
photonOptions.Light_Is_Global = false;
for (Light_Group_Light = Frame.Light_Group_Lights;
Light_Group_Light != NULL;
Light_Group_Light = Light_Group_Light->Next)
{
Light = Light_Group_Light->Light;
if (Light->Light_Type != FILL_LIGHT_SOURCE)
{
ShootPhotonsAtObject(NULL, Light, true);
}
}
factor = (DBL)photonCountEstimate/photonOptions.globalCount;
factor = sqrt(factor);
photonOptions.globalSeparation *= factor;
Do_Cooperate(1);
}
/* do object-specific lighting */
SearchThroughObjects(Frame.Objects, Light, false);
}
/* do object-specific lighting */
SearchThroughObjects(Frame.Objects, Light, false);
}
#ifdef GLOBAL_PHOTONS
/* ----------- global photons ------------- */
if (photonOptions.globalPhotonMap.numPhotons>0)
{
buildTree(&photonOptions.globalPhotonMap);
setGatherOptions(&photonOptions.globalPhotonMap, false);
}
#endif
...