Programação introdutória em OpenCL e aplicações em realidade virtual e aumentada

Tamanho: px
Começar a partir da página:

Download "Programação introdutória em OpenCL e aplicações em realidade virtual e aumentada"

Transcrição

1 Capítulo 3 Programação introdutória em OpenCL e aplicações em realidade virtual e aumentada César Leonardo Blum Silveira V3D Studios Luiz Gonzaga da Silveira Jr V3D Studios Abstract OpenCL is an open standard for high-performance computing in heterogeneous computational environments composed of multicore CPUs and many-core GPUs. OpenCL makes it possible to write multi-platform code for such devices, without the need to use vendor-specific languages and tools, or to map problems to graphics APIs. Focused on parallelism, programming in OpenCL is based on writing functions that are executed in multiple simultaneous instances. This chapter aims to introduce key concepts and explore the architecture defined by the OpenCL standard, presenting practical examples in the fields of Virtual and Augmented Reality. Resumo OpenCL é um padrão aberto para programação de alto desempenho em ambientes computacionais heterogêneos equipados com CPUs multicore e GPUs many-core. OpenCL torna possível a escrita de código multi-plataforma para tais dispositivos, sem a necessidade do uso de linguagens e ferramentas específicas de fabricante ou do mapeamento 65

2 de problemas para APIs gráficas. Com foco no paralelismo, a programação em OpenCL baseia-se na escrita de funções que são executadas em múltiplas instâncias simultâneas. Este capítulo visa introduzir conceitos-chave e explorar a arquitetura definida no padrão OpenCL, apresentando exemplos práticos nas áreas de Realidade Virtual e Aumentada Introdução Os computadores pessoais, servidores e dispositivos móveis atuais podem ser equipados com placas gráfica capazes rodar aplicações gráficas 3-D de alta qualidade visual em tempo-real. Além disso, a cada aproximadamente um ano e meio, são lançadas novas placas gráficas ainda mais sofisticadas, capazes de processar grandes volumes de dados. A preços acessíveis e oferecendo alto desempenho 1, graças, sobretudo, à indústria de jogos digitais, estas placas atualmente podem ser utilizadas para a solução de problemas em diversas áreas do conhecimento que demandam alto poder de processamento, como processamento de imagens, visão computacional, simulações de processos físicos e químicos, problemas algébricos que manipulam grandes volumes de informação, entre outras. O foco deste capítulo é mostrar como tirar proveito do poder computacional provido pelas centenas de processadores das placas gráficas modernas. Aplicações que fazem uso da capacidade de processamento paralelo dos dispositivos gráficos geralmente o fazem através do mapeamento de problemas para as APIs gráficas OpenGL ou Direct3D, ou através de programas que executam diretamente nos processadores das placas gráficas, denominados shaders. Além disso, fabricantes de placas gráficas fornecem linguagens, APIs e ferramentas de desenvolvimento que permitem o acesso direto à memória e aos processadores destas placas; porém, o uso destes recursos de programação torna o código desenvolvido específico para uma determinada arquitetura. Neste contexto, surge o padrão OpenCL (Open Computing Language), criado pela Apple [Apple Inc. 2009] e padronizado pelo Khronos Group [Khronos Group 2010]. OpenCL é a primeira plataforma aberta e livre de royalties para computação de alto desempenho em sistemas heterogêneos compostos por CPUs, GPUs, arquiteturas tipo Cell e outros processadores paralelos. OpenCL oferece aos desenvolvedores um ambiente uniforme de programação paralela para escrever códigos portáveis para estes sistemas heterogêneos, a fim de tirarem proveito do poder de processamento dos dispositivos gráficos e processadores e usá-los para diversas aplicações em múltiplas plataformas computacionais. A especificação OpenCL 1.0 é realizada em três partes: uma linguagem, uma camada de plataforma e um runtime. A especificação da linguagem descreve a sintaxe e a API para escrita de código em OpenCL, que executa nos aceleradores suportados, CPUs multicore e GPUs many-core. A linguagem é baseada na especificação C99 linguagem C [ISO 2005]. A camada de plataforma fornece ao desenvolvedor acesso às rotinas que buscam o número e os tipos de dispositivos no sistema. Assim, o desenvolvedor pode escolher e inicializar os dispositivos adequados para o processamento. O runtime permite 1 Os modelos de topo tem desempenho na ordem de teraflops, fornecidos por centenas de stream processors. 66

3 ao desenvolvedor enfileirar comandos para execução nos dispositivos, sendo também é responsável por gerenciar os recursos de memória e computação disponíveis. Na prática, aplicações OpenCL são estruturadas em uma série de camadas, como mostra a Figura 3.1. Kernels correspondem às entidades que são escritas pelo desenvolvedor na linguagem OpenCL C. A aplicação faz uso da API C do padrão para comunicar-se com a camada de plataforma (Platform Layer), enviando comandos ao runtime, que gerencia diversos aspectos da execução. Aplicação Kernels API OpenCL C OpenCL Platform Layer OpenCL runtime Driver Hardware (GPU,CPU,...) Figura 3.1. Arquitetura da OpenCL Uma breve ilustração A fim de evitar que o leitor tenha que passar por muitos conceitos teóricos antes de ter uma ideia de como ocorre a programação em OpenCL na prática, será apresentado aqui um exemplo simples de código. O trecho de código a seguir corresponde a um kernel que calcula a diferença entre os elementos de dois arrays e os armazena em um terceiro: kernel void ArrayDiff( global const int* a, global const int* b, global int* c) { int id = get_global_id(0); c[id] = a[id] - b[id]; Por ora, os detalhes a respeito de palavras-chave da linguagem, como kernel e global serão deixados de lado, pois serão introduzidos mais adiante. O que é 67

4 importante observar no código é que não há um laço para iterar sobre os arrays. Em OpenCL, o código escrito corresponde a uma unidade do resultado desejado. O runtime cria várias instâncias do mesmo código no momento da execução, e cada uma delas recebe um ID que pode ser usado para determinar a porção dos dados que devem ser acessada por uma instância em particular. Isto viabiliza o processamento paralelo dos dados. A título de comparação, o código abaixo realizaria a mesma tarefa, porém de forma sequencial (considere que ARRAY_LENGTH é uma constante que contém o número de elementos nos arrays): void ArrayDiff( const int* a, const int* b, int* c) { for (int i = 0; i < ARRAY_LENGTH; ++i) { c[i] = a[i] - b[i]; O uso de OpenCL é, portanto, recomendado para aplicações que realizam operações computacionalmente custosas, porém paralelizáveis por permitirem o cálculo independente de diferentes porções do resultado Organização do texto O restante do texto está organizado como segue. A Seção 3.2 apresenta um histórico da programação em GPUs. A Seção 3.3 introduz os conceitos da arquitetura OpenCL. As Seções 3.4 e 3.5 discutem alguns aspectos da linguagem OpenCL C e da sua API, respectivamente. A Seção 3.6 apresenta passo-a-passo a construção de uma aplicação OpenCL completa. As Seções 3.7 e 3.8 ilustram possibilidades de uso de OpenCL em Realidade Virtual e Aumentada através de exemplos. A Seção 3.9 discute aspectos relativos à otimização de aplicações com OpenCL. Finalmente, a Seção 3.10 apresenta algumas considerações finais Programação em GPU Antes de mais nada, é importante recordar a evolução das tecnologias destes dispositivos gráficos e das APIs de suporte à programação. Sabemos que sobretudo a indústria dos jogos tem impulsionado de forma decisiva esta evolução, através do desenvolvimento de jogos visual ricos e que exigem cada vez mais enorme poder computacional para serem executados em tempo-real. Para entender este caminho retrocedendo no tempo e observamos que as placas gráficas começaram como simples controladoras de vídeo e gradativamente incorporaram funções de aceleração 3-D, bem como modificaram o modelo de programação. Neste entremeio, o termo GPU (Graphics Processing Unit) foi 68

5 cunhado para denotar que o dispositivo gráfico tinha se tornado um processador. Esta evolução alavancou inúmeras possibilidades para a computação gráfica, em especial para a renderização em tempo-real, pois se dispunha de um dispositivo dedicado para para processamento gráfico 3-D. A evolução dos dispositivos gráficos foi acompanhada por softwares, abstraem os detalhes de hardware de cada fabricante e oferecem APIs para programação. Os grandes representantes deste seguimento são o padrão aberto OpenGL e a tecnologia Direct3D (parte da DirectX) da Microsoft. Ambas as tecnologias implementam o processo de renderização usando como base um pipeline gráfico, que descreve todo o fluxo de dados do processo de renderização. As APIs da OpenGL e do Direct3D fornecem um conjuntos de funções para a programação do pipeline gráfico, e ainda provêm mecanismos transparentes de acionamento do dispositivo gráfico e comunicação com o sistema computacional principal, Figura 3.2. Processamento de primitivas Transformações & Iluminação (T&L) Montagem de primitivas Rasterizador API VBO Texturas... Fog Stencil... Color Buffer Blending FRAMEBUFFER Figura 3.2. Pipeline gráfico da OpenGL Durante o processo evolutivo, as placas gráficas 3-D tornaram-se passíveis de serem programadas diretamente através do pipeline gráfico. Os programas, denominados shaders, são escritos através de linguagens específicas (GLSL, HLSL, Cg e outras), compilados para o hardware gráfico. Desta forma, as GPUs oferecem mecanismos para permutar funções fixas por códigos desenvolvidos externamente, porém limitados a hot spots definidos pipeline gráfico, Figura 3.3. A possibilidade de se programar os processadores das GPUs através de shaders, provocou uma explosão de pesquisas e experimentação no sentido de empregar estes dispositivos na solução de problemas em diversas outras áreas. Para viabilizar o uso dos processadores do dispositivo gráfico bastava codificar o problema e os dados em estruturas processáveis pelos shaders e representadas pelo pipeline gráfico. Nascia assim a GPGPU (General Purpose computation on GPU), programação em GPU para propósito general. Recentemente ocorreu uma grande inovação nos dispositivos gráficos, instruções 69

6 Processamento de primitivas Vertex Shader Geometry Shader Montagem de primitivas Rasterizador API VBO Stream buffer Fragment Shader Stencil... Color Buffer Blending FRAMEBUFFER Figura 3.3. Pipeline gráfico programável da OpenGL de processador e hardware de memória foram adicionados a GPU, para dar suporte às linguagens de programação de propósito geral. Concomitantemente, foram criados ambientes de programação para permitir que as GPUs possam ser programadas com linguagens de programação familiares, como C e C++. Esta inovação torna as GPU processadores many-core, paralelos, completamente programáveis para aplicações de propósito geral. Nascia assim o termo GPU Computing, cunhado para denotar o uso de GPU para computação via uma API e linguagem de programação paralela, sem necessariamente ficar preso à estrutura do pipeline gráfico, a menos que seja conveniente. Duas soluções tecnológicas proprietárias dão suporte a GPU Computing, CUDA da NVIDIA e Stream da AMD/ATI e a OpenCL, um padrão aberto com suporte aos dispositivos gráficos de diversos fabricantes, preservando-se a interface de programação. Tanto a NVIDIA [NVIDIA Corporation 2010], quanto a AMD/ATI [ATI 2010] são fontes de excelentes materiais sobre OpenCL e também provedoras das implementações da OpenCL para seus respectivos hardwares. O restante deste capítulo será destinado exclusivamente a OpenCL e por vezes, uma comparação com CUDA e Stream. A sinergia entre OpenCL e OpenGL será abordada com mais detalhes, pois são mais e mais comuns aplicações que utilizam tanto os recursos gráficos para renderização e outras tarefas não-gráficas, como áudio, simulação física, inteligência artificial, sistemas financeiros, diversas áreas da matemática em si e em qualquer problema que demande alto desempenho e seja computacionalmente paralelizável A arquitetura OpenCL A arquitetura OpenCL é composta por um conjunto de entidades que definem uma camada de abstração de baixo nível para os dispositivos que suportam o padrão. A arquitetura também pode ser vista na forma de quatro modelos: modelo de plataforma, modelo de execução, modelo de programação e modelo de memória. As seções a seguir introduzem os conceitos da arquitetura OpenCL. Os modelos de 70

7 plataforma, execução e programação são introduzidos junto à discussão de alguns destes conceitos. O modelo de memória é detalhado em uma seção separada. Os nomes dos conceitos foram mantidos na sua forma original em inglês, deixando o leitor familiarizado com a terminologia encontrada na literatura Devices Um device OpenCL é qualquer dispositivo computacional acessível pelo runtime OpenCL para o envio de tarefas a serem executadas. Uma GPU ou uma CPU são consideradas devices segundo esta definição. Cada device possui uma ou mais compute units capazes de executar instruções em paralelo. Uma compute unit comporta um ou mais processing elements, que efetivamente realizam o processamento. O sistema computacional responsável pela agregação, inicialização e submissão de tarefas a diferentes devices OpenCL é denominado host. Host, devices, compute units e processing elements compõem o modelo de plataforma da arquitetura OpenCL. As entidades representadas por retângulos na Figura 3.4 correspondem ao modelo de plataforma. Device Computer Unit Computer Unit Processing Element Memória local Processing Element Memória local Memória privada Memória privada Memória global e memória constante Device Figura 3.4. Modelos de plataforma e de memória da arquitetura OpenCL Kernels Um kernel (também chamado de kernel function ou compute kernel) é um conjunto de instruções que podem ser executadas em um device OpenCL. Kernels são compilados a partir de funções escritas na linguagem OpenCL C (ver Seção 3.4) e constituem a unidade básica de desenvolvimento em OpenCL. Durante a execução, podem existir uma ou mais instâncias de um mesmo kernel, 71

8 sendo cada instância denominada um work-item. O padrão OpenCL define em seu modelo de programação dois modos de uso para um kernel: No modo data parallel, múltiplos work-items operam sobre porções diferentes de um conjunto de dados. Diversos work-items podem ser executados em paralelo, de acordo com o número de compute units e de processing elements do device em uso. Neste modo, work-items são combinados em work-groups. No modo task parallel, um único work-item é executado sobre um único processing element do device, designando uma tarefa sequencial. Este modo é assim denominado porque permite a execução de tarefas distintas em paralelo, de acordo com o número de compute units e de processing elements do device em uso. Um kernel tem seus work-items executados sobre um espaço de índices denominado NDRange (N-dimensional range). São suportados espaços de índices de 1, 2 e 3 dimensões. Quando o host encaminha a execução de um kernel para um device, ele informa também o número de dimensões, bem como o tamanho de cada uma destas, do espaço de índices sobre o qual o kernel deve ser executado. O runtime encarrega-se de criar um work-item para cada ponto neste espaço. Em cada dimensão, os índices são inteiros que variam de 0 até o tamanho da respectiva dimensão menos um. A definição do espaço de índices e a criação de work-items para os pontos do espaço de índices constituem o modelo de execução da arquitetura OpenCL. Cada work-item de um kernel é identificado por uma tupla de IDs globais, com um ID para cada dimensão do espaço de índices, e por uma tupla de IDs locais dentro do work-group. Da mesma forma, cada work-group é identificado por uma tupla de IDs, com um ID pra cada dimensão do espaço de índices. Assim, um work-item pode ser identificado pelos seus IDs globais ou pela combinação dos IDs do seu work-group com seus IDs locais. A Figura 3.5 ilustra a organização de IDs em um espaço de índices de duas dimensões. Aplicações que realizam processamento paralelo muitas vezes requerem a presença de algum mecanismo de sincronização. OpenCL permite que work-items em um mesmo work-group definam barreiras onde a execução é suspendida até que todos os work-items atinjam a barreira. No entanto, não existe nenhuma forma de sincronizar as atividades entre diferentes work-groups Program objects Um (program object) é utilizado pelo host para encapsular um programa OpenCL, isto é, o código de um ou mais kernels, na forma de código-fonte ou binária. Program objects também encapsulam uma referência para um context (ver Seção 3.3.6), o último executável compilado com sucesso e uma lista de devices para os quais o programa foi compilado. 72

9 Figura 3.5. Exemplo de espaço de índices de duas dimensões. Os identificadores externos correspondem aos identificadores dos work-groups, representados pelas caixas maiores. As caixas menores correspondem aos work-items. Os identificadores na parte superior das caixas menores correspondem aos IDs globais, enquanto os identificadores na parte inferior correspondem aos IDs locais Memory objects Um memory object permite ao host alocar e acessar a memória global (ver Seção 3.3.7) dos devices OpenCL utilizados pela aplicação. Existem duas categorias de memory objects: buffer objects (ou simplesmente buffers) e image objects. Buffers armazenam coleções de tamanho fixo de valores de um determinado tipo de dados, isto é, correspondem a arrays comumente usados na programação. Image objects armazenam texturas bi- ou tri-dimensionais, frame-buffers ou imagens. Enquanto buffers são sempre suportados por devices OpenCL, estes podem não oferecer suporte a image objects. É necessário que o host verifique o suporte antes do envio de um kernel que utiliza image objects para execução. A principal diferença entre as duas categorias de memory objects reside na forma como os dados armazenados por estes são acessados. Buffers são acessados por meio de índices inteiros. Imagens são acessadas através de sampler objects, que possuem parâmetros relativos à representação binária dos valores dos pixels e métodos de interpolação, entre outros Command queues Uma command queue é a entidade que permite que o host comunique-se com um device OpenCL, através do envio de comandos para este. Tais comandos possibilitam o envio de kernels para execução, comunicação com a memória global dos devices e sincronização de tarefas. Os comandos inseridos em uma command queue sempre são iniciados em ordem, porém o término da sua execução pode ocorrer fora de ordem. No entanto, também é possível fazer com que a execução seja totalmente em ordem, isto é, um comando só 73

10 começará a ser executado quando o comando anterior houver finalizado sua execução. Sempre que um comando é enfileirado, é possível solicitar o retorno de um event object para o comando, que permite o aguardo pelo evento do término da execução do comando antes que a execução prossiga Contexts Um context constitui um ambiente para execução de kernels OpenCL, agregando um ou mais devices, memory objects e command queues. A criação e configuração de um context estão entre as primeiras tarefas que o host deve realizar em uma aplicação OpenCL Modelo de memória A arquitetura OpenCL define um modelo de memória que divide a memória dos devices em quatro categorias. Estas categorias determinam a forma como os work-items compartilham diferentes regiões de memória: Memória global (global memory): compartilhada por todos os work-items de um kernel em execução, sendo permitido o acesso de escrita e leitura. Os work-items de um determinado work-group podem perceber mudanças na memória global realizadas pelos work-items de outros work-groups (no entanto, como explicado na Seção 3.3.2, não há mecanismo de sincronização entre work-groups, portanto a memória global não é um meio confiável de comunicação entre work-groups distintos). Memória local (local memory): compartilhada apenas entre os work-items de um mesmo work-group, sendo permitido o acesso para escrita e leitura. Memória privada (private memory): não-compartilhada, restrita a cada work-item, para leitura e escrita. Memória constante (constant memory): compartilhada por todos os work-items, mas é permitido somente o acesso para leitura durante a execução de um kernel. As entidades elípticas na Figura 3.4 correspondem às diferentes categorias de memória encontradas em um device da arquitetura OpenCL. Na figura, também pode ser observada a relação do modelo de plataforma com o modelo de memória Consistência de memória O estado visível da memória a um work-item pode não ser o mesmo para outros workitems durante a execução de um kernel, sendo isto dependente de implementação. Porém, as seguintes garantias são feitas quanto à consistência do acesso à memória: 1. Para um único work-item, há consistência de leitura e escrita. Se um work-item escrever em uma região de memória e a seguir ler a mesma região, o valor lido será aquele que foi escrito. 74

11 2. As memórias global e local são consistentes entre work-items de um mesmo workgroup em uma barreira (ver Seção 3.5.2) A linguagem OpenCL A linguagem utilizada para a escrita kernels OpenCL, chamada OpenCL C, é baseada na especificação C99 da linguagem C, com algumas extensões e um conjunto de restrições. As seções a seguir detalham os aspectos mais relevantes da linguagem OpenCL C Tipos de dados A linguagem OpenCL C oferece tipos de dados divididos em duas categorias: tipos escalares e tipos vetoriais. Tipos escalares permitem o armazenamento de informações numéricas com diferentes níveis de precisão e em diversos intervalos. Tipos vetoriais permitem o armazenamento de múltiplos dados escalares em uma única estrutura. Além disso, tipos definidos através de struct ou union, além de arrays, funções e ponteiros, também são suportados. Há também tipos especiais para imagens (image2d_t e image3d_t), samplers de imagens (sampler_t) e eventos (event_t). A Tabela 3.1 apresenta os principais tipos escalares da linguagem OpenCL C. Tipos vetoriais são nomeados de acordo com os tipos escalares, sendo sua forma geral tipon. tipo corresponde a um dos tipos listados na Tabela 3.1, enquanto n especifica o número de componentes do vetor, o qual pode ser 2, 4, 8 ou 16. Por exemplo, um vetor com 4 componentes do tipo int possui tipo int4. Tipos vetoriais com componentes sem sinal sempre são declarados seguindo a forma abreviada do tipo escalar, isto é, com o prefixo u no início do nome do tipo, ao invés do modificador unsigned. Não são suportados vetores de bool, half, size_t e void, nem de tipos definidos pelo usuário. As componentes de uma variável de tipo vetorial são acessadas por meio do operador.. As componentes são identificadas pelos caracteres x, y, z e w, ou por índices numéricos de 0 a F (notação hexadecimal). Mais de uma componente pode ser informada em um único acesso, em qualquer ordem, ou mesmo de forma repetida, para formar outro vetor, contanto que sejam respeitadas as quantidades de componentes permitidas. Os exemplos abaixo ilustram alguns acessos a vetores: float4 vec1; float4 vec2; float16 vec3; // Acesso à primeira componente de vec1 vec1.x = 1.0f; // Acesso simultâneo às componentes x e z de vec2 vec2.xz = (float2)(2.0f, 3.0f); // Acesso com componentes misturadas 75

12 Tipo bool uchar / char ushort / short uint / int ulong / long float half size_t void Descrição Booleano; assume os valores true ou false. Inteiro de 8 bits sem/com sinal. Inteiro de 16 bits sem/com sinal. Inteiro de 32 bits sem/com sinal. Inteiro de 64 bits sem/com sinal. Ponto-flutuante de 32 bits. Ponto-flutuante de 16 bits. Equivalente a uint ou ulong, dependendo da implementação. Tipo vazio. Tabela 3.1. Tipos de dados escalares da linguagem OpenCL C. Tipos sem sinal também podem ser nomeados na forma unsigned [nome do tipo com sinal]. vec1.zw = vec2.yx; // Acesso com componentes repetidas vec2.yz = vec1.ww; // Acesso às componentes 0, 5, 10 e 15 de vec3 vec3.s05af = vec1; Qualificadores A linguagem OpenCL C oferece um único qualificador de função, kernel, cujo propósito é indicar que a função qualificada é um kernel. Dentro de um código OpenCL, uma chamada a uma função definida com o qualificador kernel comporta-se de forma similar a qualquer outra chamada. Deve-se atentar, no entanto, a chamadas a funções kernel que tenham no seu código variáveis declaradas com o qualificador local (ver texto a seguir), pois o comportamento é definido pela implementação. Os qualificadores de espaço de endereçamento da linguagem OpenCL C, global, local, constant e private 2 indicam o tipo de região de memória onde uma variável ou buffer está alocado, de acordo com o modelo de memória descrito na seção As seguintes regras se aplicam ao uso de qualificadores de espaço de endereçamento: 1. Variáveis declaradas sem um qualificador de espaço de endereçamento são automaticamente tratadas como private. 2 Estes qualificadores podem também ser usados sem o prefixo. 76

13 2. Em um kernel, argumentos declarados como ponteiros devem ser global, local ou constant. O uso de um destes qualificadores é obrigatório para tais argumentos. 3. Um ponteiro de um espaço de endereçamento só pode ser atribuído a outro ponteiro do mesmo espaço de endereçamento. Por exemplo, tentar atribuir o valor de um ponteiro local a outro declarado com o qualificador global constitui uma operação ilegal. 4. Variáveis cujo escopo seja o programa inteiro devem ser declaradas com o qualificador constant. A seguir estão ilustradas algumas declarações de variáveis com os qualificadores de espaço de endereçamento apresentados: // Array de inteiros alocado na memória global global int* arr; // Vetor com 4 componentes ponto-flutuante alocado // na memória local local float4 vec; // Inteiro de 64 bits alocado na memória privada long n; Operadores A linguagem OpenCL C oferece um conjunto de operadores que trabalham tanto com tipos escalares quanto vetoriais, permitindo a construção de expressões aritméticas, lógicas e relacionais com tais tipos. A Tabela 3.2 apresenta os principais operadores da linguagem, divididos de acordo com a sua categoria. A seguir são listadas algumas observações importantes sobre o uso dos operadores da linguagem OpenCL C: 1. Uma operação entre um vetor e um escalar converte o escalar para o tipo do vetor 3 e aplica a operação sobre cada componente do vetor. Por exemplo, uma soma entre um vetor e um escalar resultará em um vetor cujas componentes foram acrescidas da quantidade escalar. Da mesma forma, os operadores unários retornam resultados vetoriais onde a operação foi aplicada individualmente sobre cada componente do vetor. 3 O escalar deve possuir o mesmo número de bits ou menos que o tipo das componentes do vetor; caso contrário, a tentativa de conversão para um tipo menor resultará em um erro de compilação. 77

14 Categoria Operadores Operadores aritméticos binários +, -, *, /, % Operadores aritméticos unários +, -, ++, - Operadores relacionais >, >=, <, <=, ==,!= Operadores lógicos binários &&, Operadores lógicos unários! Operadores bit-a-bit &,, ˆ,, <<, >> Operadores de atribuição =, +=, -=, *=, /=, %=, &=, =, ^=, <<=, >>= Tabela 3.2. Principais operadores da linguagem OpenCL C. 2. Operações entre vetores requerem que estes sejam do mesmo tamanho, isto é, contenham o mesmo número de componentes. Caso contrário, ocorrerá um erro de compilação. Tais operações são aplicadas componente-a-componente sobre o vetor, por isso a necessidade de estes possuírem o mesmo número de componentes. 3. Operações lógicas e relacionais com pelo menos um operando vetorial retornam um vetor do mesmo tipo deste, porém sempre com sinal. Cada componente pode conter o valor 0 para um resultado falso e -1 (todos os bits configurados em 1) para um resultado verdadeiro. 4. Os operadores aritméticos %, ++, -, operadores lógicos e operadores bit-a-bit não suportam tipos ponto-flutuante Restrições A linguagem OpenCL C estende a linguagem da especificação C99 com alguns tipos novos e outros elementos, mas também acrescenta uma série de restrições. A lista a seguir enumera algumas das principais destas restrições: 1. Ponteiros para função não são permitidos. 2. Argumentos para kernels não podem ser ponteiros para ponteiros. 3. Variáveis do tipo image2d_t e image3d_t podem ser declaradas apenas como argumentos para funções. 4. Não são permitidos arrays nem ponteiros para variáveis do tipo sampler_t. Variáveis deste tipo não podem ser usadas como variáveis locais em uma função, retornadas por uma função nem passadas como argumento para funções chamadas por um kernel (exceto as funções da API OpenCL). Finalmente, uma variável sampler_t passada como argumento para um kernel não pode ser modificada. 78

15 5. Funções e macros com número variável de argumentos não são suportados. 6. Os qualificadores extern, static e auto não são suportados. 7. Não há suporte a recursão. 8. A escrita em ponteiros ou arrays com tipos de tamanho inferior a 32 bits (inclusive os os tipos vetoriais char2 e uchar2) não é permitida. 9. Não são permitidos argumentos do tipo event_t para kernels. 10. Os elementos de uma struct ou union devem pertencer ao mesmo espaço de endereçamento, de acordo com os qualificadores discutidos em A API OpenCL Além da linguagem OpenCL C, o padrão OpenCL define uma API para uso em conjunto com estas linguagem, provendo diversas funções que podem ser usadas pelos kernels durante a computação das suas tarefas. Estas funções permitem a a identificação de work-items e work-groups, a realização de operações matemáticas diversas (livrando o programador da tarefa de implementá-las), sincronização, e ainda outras funcionalidades. Esta fora do escopo deste material realizar uma listagem exaustiva de toda a API OpenCL. Caso esteja interessado em ter acesso à todas as funções disponíveis, o leitor deve referir-se ao documento da especificação OpenCL 1.0 [Khronos Group 2009]. As seções a seguir apresentam as funções de identificação e sincronização da API OpenCL Identificação Funções de identificação permitem que cada work-item adquira conhecimento sobre a sua localização no espaço de índices sobre o qual o kernel é executado get_global_id size_t get_global_id(uint dimindx) Retorna o índice global do work-item no espaço de índices, na dimensão identificada por dimindx get_local_id size_t get_local_id(uint dimindx) 79

16 Retorna o índice local do work-item no seu work-group, na dimensão identificada por dimindx get_group_id size_t get_group_id(uint dimindx) Retorna o índice do work-group ao qual o work-item pertence, na dimensão identificada por dimindx get_global_size size_t get_global_size(uint dimindx) Retorna o número total de work-items na dimensão identificada por dimindx get_local_size size_t get_local_size(uint dimindx) Retorna o número de work-items em um work-group na dimensão identificada por dimindx get_num_groups size_ get_num_groups(uint dimindx) Retorna o número de work-groups na dimensão identificada por dimindx get_work_dim uint get_work_dim() 80

17 Retorna o número de dimensões do espaço de índices sobre o qual o kernel está sendo executado Sincronização A API de sincronização permite a especificação de pontos de sincronização que garantem a consistência de memória, devendo ser atingidos por todos os work-items em um workgroup antes que a execução prossiga barrier void barrier(cl_mem_fence_flags flags) Cria uma barreira de sincronização. A execução só continuará após todos os workitems pertencentes ao work-group do work-item que atingiu a barreiram também a atinjam. Do contrário, o work-item, ou os work-items, que chegarem à barreira terão sua execução bloqueada indefinidamente, e o host não será notificado do término da execução do kernel em momento algum. Uma barreira permite a criação de uma memory fence, que garante que todas as escritas na memória anteriores à barreira terão sido realmente efetuadas. O parâmetro flags permite controlar a memory fence. Seu valor pode ser CLK_LOCAL_MEM_FENCE, garantindo a consistência da memória local, CLK_GLOBAL_MEM_FENCE, garantindo a consistência da memória global, ou a combinação de ambos os valores através do operador (or bit-a-bit) OpenCL na prática Uma vez discutidos os principais conceitos referentes à arquitetura e ao padrão OpenCL, é interessante ilustrar o seu uso de forma prática, através da apresentação de um exemplo simples. As seções a seguir demonstram a construção de uma aplicação OpenCL simples, para o cálculo da diferença entre os elementos de dois arrays. O kernel utilizado é o mesmo apresentado na Seção A execução do kernel é bastante simples. Após obter o seu ID global no espaço de índices, este é utilizado para endereçar a posição correspondente nos arrays de entrada e saída. A atribuição de IDs aos work-items é feita pelo runtime, cabendo ao desenvolvedor informar apenas o número de work-items desejados através da especificação das dimensões do espaço de índices. Os work-items, então, acessam as regiões de memória que lhes interessam de acordo com seus IDs. Estes work-items executam de forma paralela, de acordo com a quantidade de compute units e processing elements do device em uso. Os trechos de código das seções seguintes ilustram em sequência todos os passos 81

18 necessários para a criação de uma aplicação OpenCL simples. Se inseridos em um arquivo de código-fonte, com os devidos cuidados de ligação e localização de cabeçalhos, este código gera um executável funcional em plataformas que suportam o padrão OpenCL. As explicações para o propósito e os argumentos de cada função estão incluídas nos comentários junto aos trechos de código. Detalhes de menor relevância para a discussão são deixados de lado, sendo solicitado que o leitor busque mais informações na especificação do padrão OpenCL, onde há uma listagem exaustiva de todas as funções e possíveis valores para seus argumentos Inclusão de cabeçalhos e definições A inclusão do cabeçalho contendo as declarações de funções e outros símbolos da OpenCL é diferente de acordo com o sistema operacional. Em sistemas Mac OS X, o cabeçalho é incluído da seguinte maneira: #include <OpenCL/opencl.h> Nos demais sistemas, da seguinte forma: #include <CL/opencl.h> Neste exemplo, também é incluído o cabeçalho padrão para entrada e saída padrão na linguagem C++, e é definida uma macro para controlar o tamanho dos arrays: #include <iostream> #define ARRAY_LENGTH Declaração de variáveis Os conceitos apresentados na Seção 3.3 possuem, em sua maior parte, tipos de dados associados a si no momento da programação. Variáveis destes tipos são declaradas pelo host para serem utilizadas pelo runtime. O código abaixo apresenta as declarações necessárias para este exemplo: int main(int argc, char** argv) { // Identificador de device cl_device_id deviceid; // Context OpenCL cl_context context; // Command queue 82

19 cl_command_queue queue; // Program object cl_program program; // Kernel cl_kernel kernel; // Event object cl_event event; // Memory objects (para buffers) cl_mem bufa; cl_mem bufb; cl_mem bufc; Além das variáveis relacionadas ao ambiente OpenCL, também são declaradas variáveis que o host utiliza para o armazenamento de dados de entrada e saída para o kernel, para a determinação das dimensões do espaço de índices e para o armazenamento de códigos de erro: // Arrays no lado host int* hosta; int* hostb; int* hostc; // Array de um único elemento contendo o número de // work-items que serão criados na única dimensão (0) // usada neste exemplo size_t globalsize[1] = { ARRAY_LENGTH ; // Variável para armazenamento de códigos de erro int err; Código-fonte do kernel O código-fonte do kernel é armazenado em uma string embutida no código-fonte do programa executado pelo host. Uma possível alternativa seria realizar a carga do códigofonte a partir de um arquivo texto durante a execução. Esta código-fonte é passado para a camada de plataforma para ser compilado para a placa gráfica usada usada para o processamento. const char* source = " kernel void ArrayDiff( \ global const int* a, \ global const int* b, \ global int* c) \ { \ 83

20 " ; int id = get_global_id(0); \ c[id] = a[id] - b[id]; \ Inicialização do context Para tornar possível o acesso a devices OpenCL, é necessário que o host primeiro inicialize e configure um context. Nesta discussão, a inicialização do context OpenCL não se refere somente à alocação do context em si, mas também à criação do ambiente mínimo necessário para a execução de kernels OpenCL. No exemplo, é criado um context para um único device, uma GPU, com uma única command queue: // A função clgetdeviceids permite a obtenção de // um ou mais identificadores para devices do // host que suportem o padrão OpenCL. // Aqui, é obtido um ID para uma única GPU. err = clgetdeviceids( // (cl_platform_id) Ver especificação. NULL, // (cl_device_type) Tipo de device desejado. // Aqui, uma GPU. Outras opções comuns são // CL_DEVICE_TYPE_CPU, para uma CPU, e // CL_DEVICE_TYPE_ALL, para obter todos os // devices disponíveis. CL_DEVICE_TYPE_GPU, // (cl_uint) Número de devices desejados. 1, // (cl_device_id*) Ponteiro para o local onde a // lista de IDs de devices deverá ser armazenada. &deviceid, // (cl_uint*) Retorna o número de devices // encontrados. NULL ); if (err!= CL_SUCCESS) { std::cerr << "Falha ao obter ID para o device.\n"; exit(exit_failure); // A função clcreatecontext permite a criação de um // context OpenCL. context = clcreatecontext( // (const cl_context_properties*) Ver especificação. 0, // (cl_uint) Número de devices no context. 1, // (const cl_device_id*) Lista de IDs de devices // para o context. 84

21 ); &deviceid, // Ponteiro para uma função de notificação chamada // sempre que houver um erro no context. Ver // especificação para detalhes sobre a assinatura da // função. NULL, // (void*) Ponteiro para dados arbitrários passados // para a função apontada pelo argumento anterior. NULL, // (cl_int*) Retorna código de erro. &err if (!context err!= CL_SUCCESS) { std::cerr << "Falha ao criar context.\n"; exit(exit_failure); // A função clcreatecommandqueue cria uma command queue // para um determinado device em um context. queue = clcreatecommandqueue( // (cl_context) Context. context, // (cl_device_id) Identificador do device. deviceid, // (cl_command_queue_properties) Propriedades da command // queue. Ver especificação. 0, // (cl_int*) Retorna código de erro. &err ); if (!queue err!= CL_SUCCESS) { std::cerr << "Falha ao criar command queue.\n"; exit(exit_failure); Compilação do kernel A compilação do kernel ocorre em três passos: 1. Criação de um program object no context. 2. Compilação do programa para os devices do context. 3. Criação de um kernel a partir do programa compilado. O código a seguir demonstra a realização destes passos: 85

22 // A função clcreateprogramwithsource cria um program // object a partir do código-fonte de um kernel, // estando este código-fonte representado em um array // de strings. program = clcreateprogramwithsource( // (cl_context) Context. context, // (cl_uint) Número de strings no array do // código-fonte. 1, // (const char**) Array de strings do código-fonte. &source, // (const size_t*) Array de tamanhos de string para // cada string do array do código-fonte. NULL, // (cl_int*) Retorna código de erro. &err ); if (!program err!= CL_SUCCESS) { std::cerr << "Falha ao criar program object.\n"; exit(exit_failure); // A função clbuildprogram compila o código-fonte de um // program object para um ou mais devices do // context. err = clbuildprogram( // (cl_program) Program object. program, // (cl_uint) Número de devices para o qual o // programa deve ser compilado. 0 indica que o // programa deve ser compilado para todos os // devices do context. 0, // (const cl_device_id*) Lista de devices para // o qual o programa deve ser compilado. NULL indica // que o programa deve ser compilado para todos os // devices do context. NULL, // (const char*) Opções para o compilador OpenCL. NULL, // Ponteiro para função que será chamada após a // compilação. Ver especificação para mais detalhes. NULL, // (void*) Ponteiro para dados arbitrários passados // para a função apontada pelo argumento anterior. NULL ); // Caso a compilação tenha falhado, imprime as mensagens 86

23 // de erro do compilador if (err!= CL_SUCCESS) { size_t len; char info[2048]; // A função clgetprogrambuildinfo permite a obtenção // de dados sobre a compilação de um programa para um // determinado device. clgetprogrambuildinfo( // (cl_program) Program object. program, // (cl_device_id) ID do device para o qual se // deseja obter dados a respeito da compilação. deviceid, // (cl_program_build_info) Nome do parâmetro que // indica a informação desejada sobre a compilação. // Ver especificação para outros parâmetros. CL_PROGRAM_BUILD_LOG, // (size_t) Tamanho do array onde os dados // retornados serão armazenados. sizeof(info), // (void*) Array onde os dados serão armazenados. info, // (size_t*) Retorna o tamanho em bytes dos dados // obtidos. &len ); std::cerr << info << std::endl; exit(exit_failure); // A função clcreatekernel cria um kernel a partir // de um program object que passou pela etapa de // compilação. kernel = clcreatekernel( // (cl_program) Program object, após compilação. program, // (const char*) Nome da função kernel declarada // no código-fonte do programa. "ArrayAbsDiff", // Retorna código de erro. &err ); if (!kernel err!= CL_SUCCESS) { std::cerr << "Falha ao criar kernel.\n"; exit(exit_failure); 87

24 Criação dos arrays no host Neste exemplo, os arrays de entrada são criados pelo host e inicializados com valores aleatórios de -50 a +50. Também é criado um array onde são armazenados os resultados da execução do kernel: // Cria os arrays no host, para armazenamento dos // dados de entrada e saída do kernel. hosta = new int[array_length]; hostb = new int[array_length]; hostc = new int[array_length]; // Inicializa os arrays hosta e hostb com valores // aleatórios entre -50 e +50. for (int i = 0; i < ARRAY_LENGTH; ++i) { hosta[i] = rand() % ; hostb[i] = rand() % ; Criação dos buffers OpenCL Após a criação do context e da obtenção dos dados de entrada, estes devem ser transferidos para a memória do device que será usado para a computação (neste caso, a GPU). No entanto, é necessário que antes sejam alocados memory objects do tamanho adequado no context, que permitem a transferência dos dados para a memória do device: // A função clcreatebuffer permite a criação de // buffers em um determinado context. Estes buffers // permitem a posterior entrada e saída de dados // para a memória global dos devices do context. bufa = clcreatebuffer( // (cl_context) Context. context, // (cl_mem_flags) Flags de especificação de // informações sobre a alocação e o uso da // memória associada ao buffer. A flag // CL_MEM_READ_ONLY cria um buffer somente-leitura. // Outra flags comum é CL_MEM_READ_WRITE, para // a criação de buffers que permitem leitura e // escrita da memória. Ver especificação para demais // flags permitidas. CL_MEM_READ_ONLY, // (size_t) Tamanho em bytes do memory object // a ser alocado. ARRAY_LENGTH * sizeof(int), // (void*) Ponteiro para dados de inicialização // do buffer. NULL, // Retorna código de erro. 88

25 ); &err if (!bufa err!= CL_SUCCESS) { std::cerr << "Falha ao criar buffer bufa.\n"; exit(exit_failure); bufb = clcreatebuffer( context, CL_MEM_READ_ONLY, ARRAY_LENGTH * sizeof(int), NULL, &err ); if (!bufa err!= CL_SUCCESS) { std::cerr << "Falha ao criar buffer bufb.\n"; exit(exit_failure); bufc = clcreatebuffer( context, CL_MEM_READ_WRITE, ARRAY_LENGTH * sizeof(int), NULL, &err ); if (!bufa err!= CL_SUCCESS) { std::cerr << "Falha ao criar buffer bufc.\n"; exit(exit_failure); Escrita dos buffers de entrada Após a criação dos memory objects, é possível transferir os dados para o device. Isto é feito através do envio de comandos de escrita de buffers para a sua command queue: // A função clenqueuewritebuffer insere em uma command // queue um comando para escrita de dados do // host na memória do device associado à // command queue, por meio de um memory object. err = clenqueuewritebuffer( // (cl_queue) Command queue. queue, // (cl_mem) Memory object. 89

26 bufa, // (cl_bool) Determina se o host deve // bloquear até o término da escrita dos dados. CL_TRUE, // (size_t) Offset a partir do qual os dados // devem ser transferidos. 0, // (size_t) Comprimento em bytes dos dados a // serem transferidos. ARRAY_LENGTH * sizeof(int), // (const void*) Ponteiro para a região de memória // do host onde os dados se localizam. hosta, // (cl_uint) Número de eventos na lista de eventos // que devem ser aguardados antes do início da // transferência dos dados. 0, // (const cl_event*) Lista de eventos que devem ser // aguardados antes do início da transferência dos // dados. NULL, // (cl_event*) Retorna um event object para // aguardar pelo término da transferência dos dados, // caso a chamada seja não-bloqueante. NULL); err = clenqueuewritebuffer( queue, bufb, CL_TRUE, 0, ARRAY_LENGTH * sizeof(int), hostb, 0, NULL, NULL ); if (err!= CL_SUCCESS) { std::cerr << "Falha ao transferir dados para o device.\n"; exit(exit_failure); É interessante observar que os memory objects em si, no momento da sua criação, estão associados ao context, e não a um device específico. A associação com um device ocorre no momento do enfileiramento de um comando de escrita (ou leitura), dado que cada command queue é específica de um único device. 90

27 Configuração dos argumentos do kernel Antes do envio do kernel para execução, é necessário que seu argumentos sejam configurados com os valores adequados. A configuração dos argumentos se dá pela informação das regiões de memória do host onde seus valores se encontram. // A função clsetkernelarg é utilizada para configurar os // argumentos para um kernel. err = clsetkernelarg( // (cl_kernel) Kernel. kernel, // (cl_uint) Posição (índice) do argumento, de acordo // com a ordem em que os argumentos foram declarados // no código-fonte OpenCL C. 0, // (size_t) Tamanho dos dados apontados pelo argumento // seguinte. sizeof(cl_mem), // (const void*) Dados a serem passados como argumento. &bufa); err = clsetkernelarg(kernel, 1, sizeof(cl_mem), &bufb); err = clsetkernelarg(kernel, 2, sizeof(cl_mem), &bufc); if (err!= CL_SUCCESS) { std::cerr << "Falha ao configurar argumentos do kernel.\n"; exit(exit_failure); Envio do kernel para execução Após a configuração dos argumentos, o kernel pode ser enviado para execução no device. É importante observar que a chamada que enfileira o comando de execução do kernel é sempre não-bloqueante. O término da execução deve ser aguardado a partir do evento retornado pelo enfileiramento. // A função clenqueuendrangekernel insere em uma // command queue um kernel para execução em um // device. A função permite também a // especificação das dimensões do espaço de índices // sobre o qual o kernel será executado. err = clenqueuendrangekernel( // (cl_queue) Command queue. queue, // (cl_kernel) Kernel. kernel, // (cl_uint) Número de dimensões do espaço de // índices. 1, // (const size_t*) Ver especificação. 91

28 ); NULL, // (const size_t*) Array de tamanhos das dimensões // globais do espaço de índices. globalsize, // (const size_t*) Array de tamanhos das dimensões // locais do espaço de índices (dimensões dos // work-groups). Quando NULL, o runtime determina // o tamanho das dimensões. NULL, // (cl_uint) Número de eventos na lista de eventos // que devem ser aguardados antes do início da // execução do kernel. 0, // (const cl_event*) Lista de eventos que devem ser // aguardados antes do início da execução do kernel. NULL, // (cl_event*) Retorna um event object para // aguardar pelo término da execução do kernel. &event if (err!= CL_SUCCESS) { std::cerr << "Falha ao enviar kernel para execução.\n"; exit(exit_failure); Quando o array de tamanhos de dimensões locais é especificado pelo desenvolvedor, é necessário que a divisão das dimensões globais pelas dimensões locais seja exata, sem resto. Caso contrário, um erro ocorrerá e o kernel não será enviado para execução Sincronização: espera pelo término da execução do kernel Sincronização no host consiste no aguardo pelo término de um ou mais comandos submetidos a uma command queue, ou mesmo de todos estes. Aqui, o evento retornado pelo comando de enfileiramento do kernel é usado para aguardar o término da execução do mesmo: // A função clwaitforevents aguarda o término de todos // os eventos em um array de eventos. // Aqui, como há apenas um evento, o endereço do "array" // corresponde ao próprio endereço da variável event. clwaitforevents( // Número de eventos no array. 1, // Array de eventos. &event ); 92

29 Leitura dos resultados A leitura de dados da memória do device é efetuada de forma praticamente idêntica à escrita de dados, porém com a invocação de uma função diferente: // A função clenqueuereadbuffer insere em uma command // queue um comando para leitura de dados de um // device para a memória do host. Os // argumentos são os mesmos de clenqueuewritebuffer, // porém o conteúdo do array apontado pelo 6o. argumento // é sobrescrito com os dados lidos do device. // Aqui, o terceiro argumento é CL_FALSE, portanto // a chamada é não-bloqueante. err = clenqueuereadbuffer( queue, bufc, CL_FALSE, 0, ARRAY_LENGTH * sizeof(int), hostc, 0, NULL, NULL ); if (err!= CL_SUCCESS) { std::cerr << "Falha ao ler resultados.\n"; exit(exit_failure); Sincronização: espera pelo término da leitura dos resultados A leitura dos resultados foi feita de forma não-bloqueante na seção anterior para ilustrar uma forma de sincronização alternativa ao uso de clwaitforevents: // A função clfinish bloqueia a execução no host // até o término da execução de todos os comandos na command // queue de comandos passada como argumento. Neste caso, o // o único comando na command queue é o comando de leitura do // buffer que contém os resultados da computação. clfinish(queue); Apresentação dos resultados O código a seguir imprime os dados de entrada gerados, bem como da saída calculada, para verificação dos resultados da execução: // Imprime os arrays gerados e os resultados na tela #define PRINT_ARRAY(name, array) \ 93

30 std::cout << name << ":"; \ for (int i = 0; i < ARRAY_LENGTH; ++i) { \ std::cout << " " << array[i]; \ \ std::cout << "\n"; PRINT_ARRAY("A", hosta) PRINT_ARRAY("B", hostb) PRINT_ARRAY("C", hostc) Liberação de recursos Após a execução do kernel, os recursos alocados devem ser liberados através de funções especiais disponibilizadas pela OpenCL. Existe uma função de liberação para cada tipo de objeto utilizado: clreleasememobject(bufa); clreleasememobject(bufb); clreleasememobject(bufc); clreleasekernel(kernel); clreleaseprogram(program); clreleasecommandqueue(queue); clreleasecontext(context); Finalmente, os demais recursos são liberados pela aplicação e esta é encerrada: delete hosta; delete hostb; delete hostc; return 0; 3.7. Aplicações em Realidade Virtual Em Realidade Virtual, um ambiente computacional imaginário ou simulando o mundo real é o cenário no qual usuários podem interagir com objetos, controlá-los ou simplesmente visualizá-los em um tela de computador ou utilizando sistemas estereoscópicos, que permitem a imersão naquele mundo virtual. Para tornar o ambiente atrativo, o sistema deve ser visualmente rico, dinâmico e ser processado em tempo-real. Neste contexto, a exigência de placa gráfica é inevitável para a execução e o desenvolvimento destes aplicativos. Como descrito na Seção 3.2, para a programação de aplicativos gráficos, a escolha por APIs gráficas como OpenGL e Direct3D é o caminho natural para a realização da tarefa APIs que fornecem um nível de abstração de acima destas, como OpenSceneGraph, OpenSG e outras auxiliam no desenvolvimento, porém ainda utilizam as APIs OpenGL ou Direct3D como base. 94

31 A possibilidade de interação entre OpenCL e OpenGL permite que além da renderização em tempo-real, outros algoritmos paralelizáveis tirem proveito do poder de processamento do dispositivo gráfico. Para ilustrar esta sinergia entre OpenCL e OpenGL, é mostrado que object buffers OpenGL podem ser mapeados no espaço de endereçamento de objetos OpenCL, permitindo que um kernel OpenCL leia dados escritos por meio da API OpenGL. O contrário também é possível, isto é, kernels OpenCL podem escrever dados que são consumidos pelo código OpenGL. O exemplo a seguir demonstra como explorar a interoperabilidade entre OpenGL e OpenCL, modificando-se dinamicamente um vertex buffer através de um kernel OpenCL. Neste exemplo, os vértices de uma malha (mesh), são armazenados em um VBO, sendo suas posições modificadas via OpenCL. Objetivamente, os seguintes passos devem ser executados: 1. Criar um VBO (vazio): // Cria o buffer object glgenbuffers(1, vbo); glbindbuffer(gl_array_buffer, *vbo); // Inicia o buffer object com o tamanho total da malha (vazia) unsigned int size = mesh_width * mesh_height * 4 * sizeof(float); glbufferdata(gl_array_buffer, size, 0, GL_DYNAMIC_DRAW); 2. Criar um memory object de um VBO na memória globa, para que a OpenCL tenha acesso ao VBO: // cria buffer OpenCL do VBO vbo_cl = clcreatefromglbuffer( cxgpucontext, CL_MEM_WRITE_ONLY, *vbo, NULL); 3. Obter o VBO para escrita a partir da OpenCL; // mapeia o buffer object para escrita pela OpenCL cierrnum = clenqueueacquireglobjects( cqcommandqueue, 1, &vbo_cl, 0,0,0); 4. Executar o seguinte kernel para modificar as posições dos vértices: kernel void seno( global float4* pos, unsigned int width, unsigned int height, float time) { unsigned int x = get_global_id(0); unsigned int y = get_global_id(1); // Calcula coordenadas u,v. float u = x / (float) width; 95

32 float v = y / (float) height; u = u*2.0f - 1.0f; v = v*2.0f - 1.0f; // Calcular um padrão de onda senoidal float freq = 4.0f; float w = sin(u*freq + time) * cos(v*freq + time) * 0.5f; // Escreve vértice de saída pos[y*width+x] = (float4)(u, w, v, 1.0f); 5. Liberar o VBO para retornar a posse para OpenGL: // liberar o buffer object para a OpenGL cierrnum = clenqueuereleaseglobjects( cqcommandqueue, 1, &vbo_cl, 0,0,0); 6. Renderizar o resultado usando OpenGL: glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glbindbuffer(gl_array_buffer, vbo); glvertexpointer(4, GL_FLOAT, 0, 0); glenableclientstate(gl_vertex_array); glcolor3f(1.0, 0.0, 0.0); gldrawarrays(gl_points, 0, mesh_width * mesh_height); gldisableclientstate(gl_vertex_array); A Figura 3.6 mostra telas da aplicação em execução, destacando as diferentes formas da malha, obtidas pelo deslocamento dos vértices. Figura 3.6. Malha renderizada em OpenGL, com forma modificada via OpenCL. 96

33 Em termos de aplicações, pode-se ainda enumerar algumas que poderiam fazer empregar OpenGL e OpenCL em conjunto: simulação de fluidos, sistemas de partículas, manipulação de texturas, visualização de imagens, entre outras. Em todos estes casos, OpenGL é responsável pela renderização (ou simplesmente visualização, no caso de imagens), enquanto a simulação é realizada por meio de kernels OpenCL. Resultados semelhantes aos do exemplo apresentado podem ser obtidos através da OpenGL e do uso shaders. OpenCL pode ser mais interessante para a solução de determinados problemas, enquanto shaders para outros. O mecanismo de gerenciamento de shaders na GPU fica completamente a cargo da API gráfica. Por outro lado, OpenCL pode ser mais flexível e oferecer mais recursos do que shaders. Para desenvolvedores de aplicações genéricas, empregar shaders torna necessário estudar mais uma linguagem (GLSL, HLSL, Cg, etc.), com uma curva de aprendizagem mais longa, dada a necessidade de se conhecer o pipeline gráfico. A falta de comunicação entre processos pode ser limitante no uso de shaders. OpenCL oferece um modelo de memória mais flexível e com capacidade de sincronização entre work-items; no entanto, exige um conhecimento mais detalhado do modelo de programação, gerenciamento de memória e controle de concorrência. A escalabilidade na instanciação dos shaders está limitada ao dispositivo gráfico de saída, enquanto OpenCL limita-se apenas à capacidade da placa gráfica. No entanto, alguns acessos ao hardware só podem ser realizados por meio de shaders, como, por exemplo, mipmapping e cubemaps. No que concerne a depuração, shaders tem evoluído, enquanto a OpenCL ainda carece de ferramentas, apesar de permitir a execução de kernels em devices emulados e suportar breakpoints Aplicações em Realidade Aumentada Aplicações de Realidade Aumentada dependem de bons algoritmos de visão computacional para a correta detecção dos pontos de interesse na cena, como marcadores. Além de uma boa capacidade de detecção, tais algoritmos devem possuir bom desempenho computacional, para proporcionar uma experiência adequada e contínua ao usuário. Muitos algoritmos de visão computacional baseiam-se na informação de bordas (grandes variações de intensidade entre pixels adjacentes) das imagens para a detecção de pontos ou características de interesse. O operador de Laplace é utilizado para a detecção das bordas de uma imagem, tendo a vantagem de seus resultados serem invariantes a rotação e de permitir implementações eficientes, uma vez que sua aplicação se dá de forma independente sobre cada ponto da imagem. Computações deste tipo são adequadas ao modelo de paralelismo oferecido pela arquitetura OpenCL. O operador de Laplace é aplicado sobre uma imagem realizando-se a convolução desta com a máscara apresentada na Figura 3.7(a). O resultado é uma imagem com valores próximos de zero nas regiões mais homogêneas, e com valores muito baixos ou muito altos onde há bordas. As Figuras 3.7(b) e 3.7(c) apresentam uma imagem de entrada e o resultado da aplicação do operador sobre esta, respectivamente. 97

34 (a) (b) (c) Figura 3.7. (a) Operador de Laplace. (b) Imagem original. (c) Resultado da convolução, escalado para o intervalo de valores de 0 a 255. O kernel OpenCL a seguir implementa o operador de Laplace: kernel void Laplacian( global const int* image, global int* laplacian) { int x = get_global_id(0); int y = get_global_id(1); int width = get_global_size(0); int height = get_global_size(1); if (x > 0 && x < width - 1 && y > 0 && y < height - 1) { laplacian[y * width + x] = -4 * image[y * width + x] + image[(y - 1) * width + x] + image[(y + 1) * width + x] + image[y * width + (x - 1)] + image[y * width + x + 1]; 98

Programação Paralela em OpenCL

Programação Paralela em OpenCL Programação Paralela em OpenCL César L. B. Silveira cesar@v3d.com.br 19 de novembro de 2010 Introdução Open CompuDng Language (OpenCL) Padrão aberto, livre de royal&es, para programação paralela em ambientes

Leia mais

Programação Paralela em Ambientes Computacionais Heterogêneos com OpenCL

Programação Paralela em Ambientes Computacionais Heterogêneos com OpenCL Programação Paralela em Ambientes Computacionais Heterogêneos com OpenCL César L. B. Silveira Prof. Dr. Luiz G. da Silveira Jr. Prof. Dr. Gerson Geraldo H. Cavalheiro 28 de outubro de 2010 contato@v3d.com.br

Leia mais

Programação Paralela em Ambientes Computacionais Heterogêneos com OpenCL

Programação Paralela em Ambientes Computacionais Heterogêneos com OpenCL Programação Paralela em Ambientes Computacionais Heterogêneos com OpenCL César L. B. Silveira 1, Luiz G. da Silveira Jr. 1, Gerson Geraldo H. Cavalheiro 2 1 V3D Labs Av. Unisinos, 950, Prédio Unitec, Sala

Leia mais

Programação em OpenCL: Uma introdução prática

Programação em OpenCL: Uma introdução prática Programação em OpenCL: Uma introdução prática César L. B. Silveira 1, Luiz G. da Silveira Jr. 2, Gerson Geraldo H. Cavalheiro 3 1 V3D Labs São Leopoldo, RS, Brasil 2 Universidade do Vale do Rio dos Sinos

Leia mais

OpenGL. Uma Abordagem Prática e Objetiva. Marcelo Cohen Isabel Harb Manssour. Novatec Editora

OpenGL. Uma Abordagem Prática e Objetiva. Marcelo Cohen Isabel Harb Manssour. Novatec Editora OpenGL Uma Abordagem Prática e Objetiva Marcelo Cohen Isabel Harb Manssour Novatec Editora Capítulo 1 Introdução A Computação Gráfica é uma área da Ciência da Computação que se dedica ao estudo e ao desenvolvimento

Leia mais

Estrutura da linguagem de programação C Prof. Tiago Eugenio de Melo tiago@comunidadesol.org

Estrutura da linguagem de programação C Prof. Tiago Eugenio de Melo tiago@comunidadesol.org Estrutura da linguagem de programação C Prof. Tiago Eugenio de Melo tiago@comunidadesol.org Breve Histórico A linguagem de programação C foi criada na década de 70, por Dennis Ritchie, que a implementou,

Leia mais

APLICAÇÕES EM SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com

APLICAÇÕES EM SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com - Aula 6 - ALGORÍTIMOS PARALELOS MPI - Parallel Virtual Machine e PVM - Parallel Virtual Machine 1. INTRODUÇÃO Inicialmente é necessário conceber alguns conceitos para entendimento dos algoritmos paralelos:

Leia mais

INTRODUÇÃO AO C++ SISTEMAS DE INFORMAÇÃO DR. EDNALDO B. PIZZOLATO

INTRODUÇÃO AO C++ SISTEMAS DE INFORMAÇÃO DR. EDNALDO B. PIZZOLATO INTRODUÇÃO AO C++ SISTEMAS DE INFORMAÇÃO DR. EDNALDO B. PIZZOLATO Tópicos Estrutura Básica B de Programas C e C++ Tipos de Dados Variáveis Strings Entrada e Saída de Dados no C e C++ INTRODUÇÃO O C++ aceita

Leia mais

Utilização. de Shaders de efeitos realistas para jogos. Bruno Pereira Evangelista. Pontifícia Universidade Católica de Minas Gerais

Utilização. de Shaders de efeitos realistas para jogos. Bruno Pereira Evangelista. Pontifícia Universidade Católica de Minas Gerais Utilização de Shaders para criação de efeitos realistas para jogos Bruno Pereira Evangelista Pontifícia Universidade Católica de Minas Gerais Sumário 2/48 Apresentação pessoal Introdução Pipeline de renderização

Leia mais

Bruno Pereira Evangelista. www.brunoevangelista.com

Bruno Pereira Evangelista. www.brunoevangelista.com Bruno Pereira Evangelista www.brunoevangelista.com 2 Introdução Shaders Pipeline de Renderização Evolução dos Shaders Como Programar Shaders Programando Shaders com XNA Ferramentas Conclusões 3 Durante

Leia mais

Vetores. Vetores. Figura 1 Exemplo de vetor com 10 elementos

Vetores. Vetores. Figura 1 Exemplo de vetor com 10 elementos Vetores Nos capítulos anteriores estudamos as opções disponíveis na linguagem C para representar: Números inteiros em diversos intervalos. Números fracionários com várias alternativas de precisão e magnitude.

Leia mais

Resumo da Introdução de Prática de Programação com C. A Linguagem C

Resumo da Introdução de Prática de Programação com C. A Linguagem C Resumo da Introdução de Prática de Programação com C A Linguagem C O C nasceu na década de 70. Seu inventor, Dennis Ritchie, implementou-o pela primeira vez usando um DEC PDP-11 rodando o sistema operacional

Leia mais

Alocação dinâmica de memória

Alocação dinâmica de memória Alocação dinâmica de memória Jander Moreira 1 Primeiras palavras Na solução de problemas por meio algoritmos ou programas, é comum surgir a necessidade de manter todo o conjunto de dados a ser processado

Leia mais

Computação Heterogênea Programação paralela, clusters e GPUs

Computação Heterogênea Programação paralela, clusters e GPUs Computação Heterogênea Programação paralela, clusters e GPUs Profa. Dra. Denise Stringhini (ICT- Unifesp) Primeiro Encontro do Khronos Chapters Brasil Belo Horizonte, 20/09/2013 Conteúdo Computação heterogênea:

Leia mais

Capítulo 8 Arquitetura de Computadores Paralelos

Capítulo 8 Arquitetura de Computadores Paralelos Capítulo 8 Arquitetura de Computadores Paralelos Necessidade de máquinas com alta capacidade de computação Aumento do clock => alta dissipação de calor Velocidade limitada dos circuitos => velocidade da

Leia mais

Sistemas Operacionais Aula 03: Estruturas dos SOs. Ezequiel R. Zorzal ezorzal@unifesp.br www.ezequielzorzal.com

Sistemas Operacionais Aula 03: Estruturas dos SOs. Ezequiel R. Zorzal ezorzal@unifesp.br www.ezequielzorzal.com Sistemas Operacionais Aula 03: Estruturas dos SOs Ezequiel R. Zorzal ezorzal@unifesp.br www.ezequielzorzal.com OBJETIVOS Descrever os serviços que um sistema operacional oferece aos usuários e outros sistemas

Leia mais

PARALELIZAÇÃO DE APLICAÇÕES NA ARQUITETURA CUDA: UM ESTUDO SOBRE VETORES 1

PARALELIZAÇÃO DE APLICAÇÕES NA ARQUITETURA CUDA: UM ESTUDO SOBRE VETORES 1 PARALELIZAÇÃO DE APLICAÇÕES NA ARQUITETURA CUDA: UM ESTUDO SOBRE VETORES 1 DUTRA, Evandro Rogério Fruhling 2 ; VARINI, Andre Luis 2 ; CANAL, Ana Paula 2 1 Trabalho de Iniciação Científica _UNIFRA 2 Ciência

Leia mais

Curso de Linguagem C

Curso de Linguagem C Curso de Linguagem C 1 Aula 1 - INTRODUÇÃO...4 AULA 2 - Primeiros Passos...5 O C é "Case Sensitive"...5 Dois Primeiros Programas...6 Introdução às Funções...7 Introdução Básica às Entradas e Saídas...

Leia mais

Hardware (Nível 0) Organização. Interface de Máquina (IM) Interface Interna de Microprogramação (IIMP)

Hardware (Nível 0) Organização. Interface de Máquina (IM) Interface Interna de Microprogramação (IIMP) Hardware (Nível 0) Organização O AS/400 isola os usuários das características do hardware através de uma arquitetura de camadas. Vários modelos da família AS/400 de computadores de médio porte estão disponíveis,

Leia mais

Universidade da Beira Interior Cursos: Matemática /Informática e Ensino da Informática

Universidade da Beira Interior Cursos: Matemática /Informática e Ensino da Informática Folha 1-1 Introdução à Linguagem de Programação JAVA 1 Usando o editor do ambiente de desenvolvimento JBUILDER pretende-se construir e executar o programa abaixo. class Primeiro { public static void main(string[]

Leia mais

MC102 Algoritmos e programação de computadores Aula 3: Variáveis

MC102 Algoritmos e programação de computadores Aula 3: Variáveis MC102 Algoritmos e programação de computadores Aula 3: Variáveis Variáveis Variáveis são locais onde armazenamos valores na memória. Toda variável é caracterizada por um nome, que a identifica em um programa,

Leia mais

Conceitos de Linguagens de Programação

Conceitos de Linguagens de Programação Conceitos de Linguagens de Programação Aula 07 Nomes, Vinculações, Escopos e Tipos de Dados Edirlei Soares de Lima Introdução Linguagens de programação imperativas são abstrações

Leia mais

Um sistema é constituído de um conjunto de processos que executam seus respectivos códigos do sistema operacional e processos e códigos de usuários.

Um sistema é constituído de um conjunto de processos que executam seus respectivos códigos do sistema operacional e processos e códigos de usuários. Os sistemas computacionais atuais permitem que diversos programas sejam carregados na memória e executados simultaneamente. Essa evolução tornou necessário um controle maior na divisão de tarefas entre

Leia mais

PROGRAMA DE DISCIPLINA

PROGRAMA DE DISCIPLINA PROGRAMA DE DISCIPLINA Disciplina: Introdução à Programação Carga horária total: 60 Carga horária teórica: 0 Carga horária prática: 60 Código da Disciplina: CCMP0041 Período de oferta: 2010.2 Turma: CA

Leia mais

Paradigmas de Programação

Paradigmas de Programação Paradigmas de Programação Tipos de Dados Aula 5 Prof.: Edilberto M. Silva http://www.edilms.eti.br Prof. Edilberto Silva / edilms.eti.br Tipos de Dados Sistema de tipos Tipos de Dados e Domínios Métodos

Leia mais

Point Based Graphics e Aplicações em Jogos

Point Based Graphics e Aplicações em Jogos Point Based Graphics e Aplicações em Jogos Luciano Silva Laboratório de Processamento Gráfico e Mídias Digitais Faculdade de Computação e Informática, Universidade Presbiteriana Mackenzie Abstract Point

Leia mais

Computação II Orientação a Objetos

Computação II Orientação a Objetos Computação II Orientação a Objetos Fabio Mascarenhas - 2014.1 http://www.dcc.ufrj.br/~fabiom/java Introdução Esse não é um curso de Java! O objetivo é aprender os conceitos da programação orientada a objetos,

Leia mais

6 - Gerência de Dispositivos

6 - Gerência de Dispositivos 1 6 - Gerência de Dispositivos 6.1 Introdução A gerência de dispositivos de entrada/saída é uma das principais e mais complexas funções do sistema operacional. Sua implementação é estruturada através de

Leia mais

Capítulo 2: Introdução à Linguagem C

Capítulo 2: Introdução à Linguagem C Capítulo 2: Introdução à Linguagem C INF1005 Programação 1 Pontifícia Universidade Católica Departamento de Informática Programa Programa é um algoritmo escrito em uma linguagem de programação. No nosso

Leia mais

Programando em C# Orientado a Objetos. By: Maromo

Programando em C# Orientado a Objetos. By: Maromo Programando em C# Orientado a Objetos By: Maromo Agenda Módulo 1 Plataforma.Net. Linguagem de Programação C#. Tipos primitivos, comandos de controle. Exercícios de Fixação. Introdução O modelo de programação

Leia mais

clopencl - OpenCL para ambiente cluster

clopencl - OpenCL para ambiente cluster clopencl - OpenCL para ambiente cluster Mário João da Costa Afonso Relatório Final do Trabalho de Projecto apresentado à Escola Superior de Tecnologia e Gestão Instituto Politécnico de Bragança para obtenção

Leia mais

INF 1005 Programação I

INF 1005 Programação I INF 1005 Programação I Aula 03 Introdução a Linguagem C Edirlei Soares de Lima Estrutura de um Programa C Inclusão de bibliotecas auxiliares: #include Definição de constantes:

Leia mais

Programação de Computadores I. Ponteiros

Programação de Computadores I. Ponteiros Ponteiros Prof. Edwar Saliba Júnior Outubro de 2012 Unidade 13 Ponteiros 1 Identificadores e Endereços Na linguagem C, uma declaração de variável faz associação entre um identificador e endereços de memória;

Leia mais

Notas da Aula 4 - Fundamentos de Sistemas Operacionais

Notas da Aula 4 - Fundamentos de Sistemas Operacionais Notas da Aula 4 - Fundamentos de Sistemas Operacionais 1. Threads Threads são linhas de execução dentro de um processo. Quando um processo é criado, ele tem uma única linha de execução, ou thread. Esta

Leia mais

Tipos de Dados Simples

Tipos de Dados Simples Programação 11543: Engenharia Informática 6638: Tecnologias e Sistemas de Informação Cap. 3 Tipos de Dados Simples Tipos de Dados Simples Objectivos: Hierarquia de tipos de dados Tipos de dados simples

Leia mais

Introdução à Programação

Introdução à Programação Introdução à Programação Introdução a Linguagem C Construções Básicas Programa em C #include int main ( ) { Palavras Reservadas } float celsius ; float farenheit ; celsius = 30; farenheit = 9.0/5

Leia mais

Arquitetura e Programação de GPU. Leandro Zanotto RA: 001962 Anselmo Ferreira RA: 023169 Marcelo Matsumoto RA: 085973

Arquitetura e Programação de GPU. Leandro Zanotto RA: 001962 Anselmo Ferreira RA: 023169 Marcelo Matsumoto RA: 085973 Arquitetura e Programação de GPU Leandro Zanotto RA: 001962 Anselmo Ferreira RA: 023169 Marcelo Matsumoto RA: 085973 Agenda Primeiras Placas de Vídeo Primeira GPU Arquitetura da GPU NVIDIA Arquitetura

Leia mais

JSP - ORIENTADO A OBJETOS

JSP - ORIENTADO A OBJETOS JSP Orientação a Objetos... 2 CLASSE:... 2 MÉTODOS:... 2 Método de Retorno... 2 Método de Execução... 2 Tipos de Dados... 3 Boolean... 3 Float... 3 Integer... 4 String... 4 Array... 4 Primeira:... 4 Segunda:...

Leia mais

Componentes da linguagem C++

Componentes da linguagem C++ Componentes da linguagem C++ C++ é uma linguagem de programação orientada a objetos (OO) que oferece suporte às características OO, além de permitir você realizar outras tarefas, similarmente a outras

Leia mais

Notas da Aula 15 - Fundamentos de Sistemas Operacionais

Notas da Aula 15 - Fundamentos de Sistemas Operacionais Notas da Aula 15 - Fundamentos de Sistemas Operacionais 1. Software de Entrada e Saída: Visão Geral Uma das tarefas do Sistema Operacional é simplificar o acesso aos dispositivos de hardware pelos processos

Leia mais

Orientação a Objetos

Orientação a Objetos 1. Domínio e Aplicação Orientação a Objetos Um domínio é composto pelas entidades, informações e processos relacionados a um determinado contexto. Uma aplicação pode ser desenvolvida para automatizar ou

Leia mais

Formação em game programming: 01 - Introdução à programação

Formação em game programming: 01 - Introdução à programação Formação em game programming: Para que um jogo eletrônico funcione adequadamente como foi projetado, é necessário que ele esteja corretamente programado. Todas as funções de controle de personagens e objetos

Leia mais

GUILHERME STUTZ TÖWS ANIMAÇÃO DE ALGORITMOS

GUILHERME STUTZ TÖWS ANIMAÇÃO DE ALGORITMOS GUILHERME STUTZ TÖWS ANIMAÇÃO DE ALGORITMOS Trabalho de graduação do Curso de Ciência da Computação do Setor de Ciências Exatas da Universidade Federal do Paraná. Professor: André Luiz Pires Guedes CURITIBA

Leia mais

LP II Estrutura de Dados. Introdução e Linguagem C. Prof. José Honorato F. Nunes honorato.nunes@ifbaiano.bonfim.edu.br

LP II Estrutura de Dados. Introdução e Linguagem C. Prof. José Honorato F. Nunes honorato.nunes@ifbaiano.bonfim.edu.br LP II Estrutura de Dados Introdução e Linguagem C Prof. José Honorato F. Nunes honorato.nunes@ifbaiano.bonfim.edu.br Resumo da aula Considerações Gerais Introdução a Linguagem C Variáveis e C Tipos de

Leia mais

Sistemas Operacionais

Sistemas Operacionais Sistemas Operacionais Sistemas de Entrada/Saída Princípios de Hardware Sistema de Entrada/Saída Visão Geral Princípios de Hardware Dispositivos de E/S Estrutura Típica do Barramento de um PC Interrupções

Leia mais

Programação em C++: Introdução

Programação em C++: Introdução Programação em C++: Introdução J. Barbosa J. Tavares Visualização Científica Conceitos básicos de programação Algoritmo Conjunto finito de regras sobre as quais se pode dar execução a um dado processo

Leia mais

Auditoria de senhas em hardware paralelo com o John the Ripper O impacto das tecnologias de processamento paralelo na quebra de senhas

Auditoria de senhas em hardware paralelo com o John the Ripper O impacto das tecnologias de processamento paralelo na quebra de senhas Auditoria de senhas em hardware paralelo com o John the Ripper O impacto das tecnologias de processamento paralelo na quebra de senhas Claudio André claudio.andre@correios.net.br Motivação Seu computador

Leia mais

OpenGL Shading Language

OpenGL Shading Language OpenGL Shading Language Guilherme S. Moura (gsm@cin.ufpe.br) Saulo A. Pessoa (sap@cin.ufpe.br) Vladimir Alves (vap2@cin.ufpe.br) Felipe Maia O que é? High Level Shading Language para OpenGL Descreve shaders

Leia mais

4 Criação de macros e introdução à linguagem VBA

4 Criação de macros e introdução à linguagem VBA 4 Criação de macros e introdução à linguagem VBA Vinicius A. de Souza va.vinicius@gmail.com São José dos Campos, 2011. 1 Sumário Tópicos em Microsoft Excel 2007 Introdução à criação de macros...3 Gravação

Leia mais

PROGRAMA DE DISCIPLINA

PROGRAMA DE DISCIPLINA PROGRAMA DE DISCIPLINA Disciplina: INTRODUÇÃO À PROGRAMAÇÃO Carga horária total: 60 h Carga horária teórica: 30 h Carga horária prática: 30 h Código da Disciplina: CCMP0041 Período de oferta: 2015.2 Turma:

Leia mais

1. CAPÍTULO COMPUTADORES

1. CAPÍTULO COMPUTADORES 1. CAPÍTULO COMPUTADORES 1.1. Computadores Denomina-se computador uma máquina capaz de executar variados tipos de tratamento automático de informações ou processamento de dados. Os primeiros eram capazes

Leia mais

Programação Orientada a Objetos Prof. Rone Ilídio UFSJ/CAP

Programação Orientada a Objetos Prof. Rone Ilídio UFSJ/CAP Programação Orientada a Objetos Prof. Rone Ilídio UFSJ/CAP 1) Introdução Programação Orientada a Objetos é um paradigma de programação bastante antigo. Entretanto somente nos últimos anos foi aceito realmente

Leia mais

Programação Paralela Híbrida em CPU e GPU: Uma Alternativa na Busca por Desempenho

Programação Paralela Híbrida em CPU e GPU: Uma Alternativa na Busca por Desempenho 124 - Encontro Anual de Tecnologia da Informação Programação Paralela Híbrida em CPU e GPU: Uma Alternativa na Busca por Desempenho André Luís Stefanello¹, Crístian Cleder Machado1, Dioni da Rosa¹, Maurício

Leia mais

2. OPERADORES... 6 3. ALGORITMOS, FLUXOGRAMAS E PROGRAMAS... 8 4. FUNÇÕES... 10

2. OPERADORES... 6 3. ALGORITMOS, FLUXOGRAMAS E PROGRAMAS... 8 4. FUNÇÕES... 10 1. TIPOS DE DADOS... 3 1.1 DEFINIÇÃO DE DADOS... 3 1.2 - DEFINIÇÃO DE VARIÁVEIS... 3 1.3 - VARIÁVEIS EM C... 3 1.3.1. NOME DAS VARIÁVEIS... 3 1.3.2 - TIPOS BÁSICOS... 3 1.3.3 DECLARAÇÃO DE VARIÁVEIS...

Leia mais

COMPARAÇÃO DE DESEMPENHO ENTRE DIFERENTES IMPLEMENTAÇÕES DO ALGORITMO KECCAK PARA PLATAFORMAS GPGPUS UTILIZANDO OPENCL

COMPARAÇÃO DE DESEMPENHO ENTRE DIFERENTES IMPLEMENTAÇÕES DO ALGORITMO KECCAK PARA PLATAFORMAS GPGPUS UTILIZANDO OPENCL CENTRO UNIVERSITÁRIO EURÍPIDES DE MARÍLIA FUNDAÇÃO DE ENSINO EURÍPIDES SOARES DA ROCHA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO COMPARAÇÃO DE DESEMPENHO ENTRE DIFERENTES IMPLEMENTAÇÕES DO ALGORITMO KECCAK

Leia mais

Curso de C: uma breve introdução

Curso de C: uma breve introdução V Semana de Engenharia Elétrica - UFBA Licença de uso e distribuição Todo o material aqui disponível pode, posteriormente, ser utilizado sobre os termos da: Creative Commons License:

Leia mais

AULA 02. 1. Uma linguagem de programação orientada a objetos

AULA 02. 1. Uma linguagem de programação orientada a objetos AULA 02 TECNOLOGIA JAVA O nome "Java" é usado para referir-se a 1. Uma linguagem de programação orientada a objetos 2. Uma coleção de APIs (classes, componentes, frameworks) para o desenvolvimento de aplicações

Leia mais

- Aula 1 - ARQUITETURA DE COMPUTADORES

- Aula 1 - ARQUITETURA DE COMPUTADORES - Aula 1 - ARQUITETURA DE COMPUTADORES Em arquitetura de computadores serão estudados aspectos da estrutura e do funcionamento dos computadores. O objetivo é apresentar de forma clara e abrangente a natureza

Leia mais

PROJETO LÓGICO DE COMPUTADORES Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br

PROJETO LÓGICO DE COMPUTADORES Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br - Aula 6 - ARQUITETURAS AVANÇADAS DE COMPUTADORES 1. INTRODUÇÃO As arquiteturas dos processadores têm evoluído ao longo dos anos, e junto com ela o conceito de arquitetura avançada tem se modificado. Nos

Leia mais

DESENVOLVIMENTO DE SOFTWARE

DESENVOLVIMENTO DE SOFTWARE VARIAÁ VEL Antes de iniciarmos os comandos referentes a Banco de Dados, precisamos de uma breve descrição técnica sobre Variáveis que serão uma constante em programação seja qual for sua forma de leitura.

Leia mais

ARRAYS. Um array é um OBJETO que referencia (aponta) mais de um objeto ou armazena mais de um dado primitivo.

ARRAYS. Um array é um OBJETO que referencia (aponta) mais de um objeto ou armazena mais de um dado primitivo. Cursos: Análise, Ciência da Computação e Sistemas de Informação Programação I - Prof. Aníbal Notas de aula 8 ARRAYS Introdução Até agora, utilizamos variáveis individuais. Significa que uma variável objeto

Leia mais

Arquivos. Estruturas de Dados II Vanessa Braganholo

Arquivos. Estruturas de Dados II Vanessa Braganholo Arquivos Estruturas de Dados II Vanessa Braganholo Entidades } Aplicações precisam armazenar dados sobre as mais diversas entidades, que podem ser concretas ou abstratas } Funcionário de uma empresa (concreto)

Leia mais

4 Conversor EDTV Raw. 4.1 Arquitetura

4 Conversor EDTV Raw. 4.1 Arquitetura 4 Conversor EDTV Raw O conversor EDTV Raw é o programa que lê um documento escrito no perfil NCL EDTV e gera um documento Raw equivalente, i.e. que define a mesma apresentação. Este capítulo, apresenta

Leia mais

Algoritmos em Javascript

Algoritmos em Javascript Algoritmos em Javascript Sumário Algoritmos 1 O que é um programa? 1 Entrada e Saída de Dados 3 Programando 4 O que é necessário para programar 4 em JavaScript? Variáveis 5 Tipos de Variáveis 6 Arrays

Leia mais

Aula 10 - Streams (Parte I)

Aula 10 - Streams (Parte I) Disciplina de TICs 1 - Introdução a Programação em GPGPU Aula 10 - Streams (Parte I) Introdução Até então foi visto como engenho de processamento paralelo massivo de dados nas GPUs pode aumentar assombrosamente

Leia mais

Representação de Dados (inteiros não negativos)

Representação de Dados (inteiros não negativos) Representação de Dados (inteiros não negativos) 1 Memória Armazena instruções e dados durante a execução de um programa A memória principal pode ser vista como um array de bytes, cada um com seu endereço

Leia mais

e à Linguagem de Programação Python

e à Linguagem de Programação Python Introdução a Algoritmos, Computação Algébrica e à Linguagem de Programação Python Curso de Números Inteiros e Criptografia Prof. Luis Menasché Schechter Departamento de Ciência da Computação UFRJ Agosto

Leia mais

ESTRUTURAS DE DADOS I. Notas de Aula. Prof. Dr. Gilberto Nakamiti

ESTRUTURAS DE DADOS I. Notas de Aula. Prof. Dr. Gilberto Nakamiti ESTRUTURAS DE DADOS I Notas de Aula 1 SUMÁRIO 1. INTRODUÇÃO... 2 1.1 Array (vetores)... 2 2. BUSCA DE ELEMENTOS... 3 2.1 Busca Seqüencial... 3 2.2 Busca Binária... 3 2.3 Busca Indexada... 3 2.4 Busca Hash...

Leia mais

Computação Gráfica. Renderização em Tempo Real. Erivaldo Xavier de Lima Filho desadoc@gmail.com

Computação Gráfica. Renderização em Tempo Real. Erivaldo Xavier de Lima Filho desadoc@gmail.com Computação Gráfica Renderização em Tempo Real Erivaldo Xavier de Lima Filho desadoc@gmail.com Computação Gráfica É a síntese de imagens por computador Consiste de vários passos: o Modelagem o Renderização

Leia mais

Figura 13.1: Um exemplo de árvore de diretório.

Figura 13.1: Um exemplo de árvore de diretório. 13. Árvores W. Celes e J. L. Rangel Nos capítulos anteriores examinamos as estruturas de dados que podem ser chamadas de unidimensionais ou lineares, como vetores e listas. A importância dessas estruturas

Leia mais

Programação Básica em Arduino Aula 2

Programação Básica em Arduino Aula 2 Programação Básica em Arduino Aula 2 Execução: Laboratório de Automação e Robótica Móvel Variáveis são lugares (posições) na memória principal que servem para armazenar dados. As variáveis são acessadas

Leia mais

Linguagens de programação

Linguagens de programação Prof. André Backes Linguagens de programação Linguagem de Máquina Computador entende apenas pulsos elétricos Presença ou não de pulso 1 ou 0 Tudo no computador deve ser descrito em termos de 1 s ou 0 s

Leia mais

1 - Processamento de dados

1 - Processamento de dados Conceitos básicos sobre organização de computadores 2 1 - Processamento de dados O que é processamento? O que é dado? Dado é informação? Processamento é a manipulação das informações coletadas (dados).

Leia mais

Java Como Programar, 8/E

Java Como Programar, 8/E Capítulo 2 Introdução aos aplicativos Java Java Como Programar, 8/E (C) 2010 Pearson Education, Inc. Todos os 2.1 Introdução Programação de aplicativo Java. Utilize as ferramentas do JDK para compilar

Leia mais

14. Arquivos. W. Celes e J. L. Rangel. Estruturas de Dados PUC-Rio 13-1

14. Arquivos. W. Celes e J. L. Rangel. Estruturas de Dados PUC-Rio 13-1 14. Arquivos W. Celes e J. L. Rangel Neste capítulo, apresentaremos alguns conceitos básicos sobre arquivos, e alguns detalhes da forma de tratamento de arquivos em disco na linguagem C. A finalidade desta

Leia mais

Programação para Dispositivos Móveis Aula 1. Prof. William Yamamoto

Programação para Dispositivos Móveis Aula 1. Prof. William Yamamoto Programação para Dispositivos Móveis Aula 1 Prof. William Yamamoto Visual Studio É uma ferramenta de desenvolvimento completa que atende praticamente a todas as plataformas de desenvolvimento, como: Web

Leia mais

Arquitetura de Computadores. Introdução aos Sistemas Operacionais

Arquitetura de Computadores. Introdução aos Sistemas Operacionais Arquitetura de Computadores Introdução aos Sistemas Operacionais O que é um Sistema Operacional? Programa que atua como um intermediário entre um usuário do computador ou um programa e o hardware. Os 4

Leia mais

Programação Básica em STEP 7 Blocos de Dados. SITRAIN Training for Automation and Drives. Página 8-1

Programação Básica em STEP 7 Blocos de Dados. SITRAIN Training for Automation and Drives. Página 8-1 Conteúdo Página Áreas de Armazenamento para Dados... 2 (DBs)... 3 Visão Geral dos Tipos de Dados no STEP 7... 4 Tipos de Dados Elementares no STEP 7... 5 Criando um Novo Bloco de Dados... 6 Editando, Salvando,

Leia mais

Manual do Desenvolvedor Criptografia de Arquivos do WebTA

Manual do Desenvolvedor Criptografia de Arquivos do WebTA Manual do Desenvolvedor Criptografia de Arquivos do WebTA Versão 1.4 Índice 1. Objetivo..3 2. Processo..3 3. API de Criptografia - Biblioteca Java..4 3.1 WEBTACryptoUtil..4 3.1.1 decodekeyfile..4 3.1.2

Leia mais

Linguagens de. Aula 02. Profa Cristiane Koehler cristiane.koehler@canoas.ifrs.edu.br

Linguagens de. Aula 02. Profa Cristiane Koehler cristiane.koehler@canoas.ifrs.edu.br Linguagens de Programação III Aula 02 Profa Cristiane Koehler cristiane.koehler@canoas.ifrs.edu.br Linguagens de Programação Técnica de comunicação padronizada para enviar instruções a um computador. Assim

Leia mais

Sistemas Operacionais

Sistemas Operacionais Sistemas Operacionais Sistemas de Entrada/Saída Princípios de Software Sistema de Entrada/Saída Princípios de Software Tratadores (Manipuladores) de Interrupções Acionadores de Dispositivos (Device Drivers)

Leia mais

Italo Valcy

Italo Valcy <italo@dcc.ufba.br> Programação C Módulo 01 Introdução à linguagem C Italo Valcy www.ieee.org/ufba Italo Valcy Programação em C Licença de uso e distribuição Todo o material aqui disponível pode, posteriormente,

Leia mais

PADI 2015/16. Aula 1 Introdução à Plataforma.NET

PADI 2015/16. Aula 1 Introdução à Plataforma.NET PADI 2015/16 Aula 1 Introdução à Plataforma.NET 1 Sumário 1. Framework.NET Arquitectura 2. Linguagem C# 2.0 Sintaxe C# vs. Java vs. C++ 3. IDE: MS Visual Studio 2005 ou superior Ferramentas Console/Win

Leia mais

Experimentos com a memória cache do CPU

Experimentos com a memória cache do CPU Experimentos com a memória cache do CPU Alberto Bueno Júnior & Andre Henrique Serafim Casimiro Setembro de 2010 1 Contents 1 Introdução 3 2 Desvendando o cache 3 2.1 Para que serve o cache?.....................

Leia mais

2. Constantes e Variáveis

2. Constantes e Variáveis 2. Constantes e Variáveis Neste capitulo veremos como os dados constantes e variáveis são manipulados pela linguagem C. O que são constantes inteiras, reais, caracteres e strings. Quais são as regras de

Leia mais

Algoritmos e Programação Estruturada

Algoritmos e Programação Estruturada Algoritmos e Programação Estruturada Virgínia M. Cardoso Linguagem C Criada por Dennis M. Ritchie e Ken Thompson no Laboratório Bell em 1972. A Linguagem C foi baseada na Linguagem B criada por Thompson.

Leia mais

Programação: Tipos, Variáveis e Expressões

Programação: Tipos, Variáveis e Expressões Programação de Computadores I Aula 05 Programação: Tipos, Variáveis e Expressões José Romildo Malaquias Departamento de Computação Universidade Federal de Ouro Preto 2011-1 1/56 Valores Valor é uma entidade

Leia mais

Aula 1 - Introdução e configuração de ambiente de desenvolvimento

Aula 1 - Introdução e configuração de ambiente de desenvolvimento Aula 1 - Introdução e configuração de ambiente de desenvolvimento Olá, seja bem-vindo à primeira aula do curso para desenvolvedor de Android, neste curso você irá aprender a criar aplicativos para dispositivos

Leia mais

ENG1000 Introdução à Engenharia

ENG1000 Introdução à Engenharia ENG1000 Introdução à Engenharia Aula 04 Introdução a Linguagem Lua Edirlei Soares de Lima Linguagem Lua Lua é uma linguagem de programação projetada para dar suporte à programação

Leia mais

Capacidade = 512 x 300 x 20000 x 2 x 5 = 30.720.000.000 30,72 GB

Capacidade = 512 x 300 x 20000 x 2 x 5 = 30.720.000.000 30,72 GB Calculando a capacidade de disco: Capacidade = (# bytes/setor) x (méd. # setores/trilha) x (# trilhas/superfície) x (# superfícies/prato) x (# pratos/disco) Exemplo 01: 512 bytes/setor 300 setores/trilha

Leia mais

Edison Gustavo Muenz. Estudo e implementação de um algoritmo de processamento de imagens com técnicas GPGPU

Edison Gustavo Muenz. Estudo e implementação de um algoritmo de processamento de imagens com técnicas GPGPU Edison Gustavo Muenz Estudo e implementação de um algoritmo de processamento de imagens com técnicas GPGPU Florianópolis SC Agosto / 2008 Edison Gustavo Muenz Estudo e implementação de um algoritmo de

Leia mais

Programação Elementar de Computadores Jurandy Soares

Programação Elementar de Computadores Jurandy Soares Programação Elementar de Computadores Jurandy Soares Básico de Computadores Computador: dispositivos físicos + programas Dispositivos físicos: hardware Programas: as instruções que dizem aos dispositivos

Leia mais

Capítulo 2. Charm++ 16

Capítulo 2. Charm++ 16 2 Charm++ O Charm++ é uma linguagem orientada a objetos para programação paralela baseada em C++ (34). Ela possui uma biblioteca de execução para suporte a computação paralela que se chama Kernel do Charm

Leia mais

UNIVERSIDADE FEDERAL DE SANTA MARIA DEPARTAMENTO DE ELETRÔNICA E COMPUTAÇÃO PROGRAMA DE PÓS-GRADUAÇÃO EM INFORMÁTICA

UNIVERSIDADE FEDERAL DE SANTA MARIA DEPARTAMENTO DE ELETRÔNICA E COMPUTAÇÃO PROGRAMA DE PÓS-GRADUAÇÃO EM INFORMÁTICA UNIVERSIDADE FEDERAL DE SANTA MARIA DEPARTAMENTO DE ELETRÔNICA E COMPUTAÇÃO PROGRAMA DE PÓS-GRADUAÇÃO EM INFORMÁTICA Estudo e aperfeiçoamento da técnica de Steering Behaviors na simulação física de fluidos

Leia mais

Sistema Operacional. Processo e Threads. Prof. Dr. Márcio Andrey Teixeira Sistemas Operacionais

Sistema Operacional. Processo e Threads. Prof. Dr. Márcio Andrey Teixeira Sistemas Operacionais Sistema Operacional Processo e Threads Introdução a Processos Todos os computadores modernos são capazes de fazer várias coisas ao mesmo tempo. Enquanto executa um programa do usuário, um computador pode

Leia mais

Java - Introdução. Professor: Vilson Heck Junior. vilson.junior@ifsc.edu.br

Java - Introdução. Professor: Vilson Heck Junior. vilson.junior@ifsc.edu.br Java - Introdução Professor: Vilson Heck Junior vilson.junior@ifsc.edu.br Agenda O que é Java? Sun / Oracle. IDE - NetBeans. Linguagem Java; Maquina Virtual; Atividade Prática. Identificando Elementos

Leia mais

Conceito de classe em C++

Conceito de classe em C++ Introdução à Programação com Classes em C++ Ana Paula Rocha, Luís Paulo Reis, João Pascoal Faria FEUP - MIEEC Programação 2-2008/2009 Conceito de classe em C++ Classe em sentido lato: tipo de dados definido

Leia mais

Sintaxe Básica de Java Parte 1

Sintaxe Básica de Java Parte 1 Sintaxe Básica de Java Parte 1 Universidade Católica de Pernambuco Ciência da Computação Prof. Márcio Bueno poonoite@marcioubeno.com Fonte: Material da Profª Karina Oliveira Estrutura de Programa Um programa

Leia mais

Sistemas Operacionais 2014 Introdução. Alexandre Augusto Giron alexandre.a.giron@gmail.com

Sistemas Operacionais 2014 Introdução. Alexandre Augusto Giron alexandre.a.giron@gmail.com Sistemas Operacionais 2014 Introdução Alexandre Augusto Giron alexandre.a.giron@gmail.com Roteiro Sistemas Operacionais Histórico Estrutura de SO Principais Funções do SO Interrupções Chamadas de Sistema

Leia mais