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 cesar@v3d.com.br Luiz Gonzaga da Silveira Jr V3D Studios gonzaga@v3d.com.br 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

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 08 de novembro de 2010 cesar@v3d.com.br

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

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

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

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

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

Programação introdutória em OpenCL e aplicações em realidade virtual e aumentada V3D Programação introdutória em OpenCL e aplicações em realidade virtual e aumentada César Leonardo Blum Silveira Prof. Dr. Luiz Gonzaga da Silveira Jr. V3D 24 de maio de 2010 Soluções em visualização e visão

Leia mais

Persistência de Dados

Persistência de Dados Persistência de s Universidade do Estado de Santa Catarina - Udesc Centro de Ciências Tecnológicas - CCT Departamento de Ciência da Computação Tecnologia de Sistemas de Informação Estrutura de s II - DAD

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

ARQUITETURA DE COMPUTADORES - 1866

ARQUITETURA DE COMPUTADORES - 1866 7 Unidade Central de Processamento (UCP): O processador é o componente vital do sistema de computação, responsável pela realização das operações de processamento e de controle, durante a execução de um

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

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

Notas da Aula 17 - Fundamentos de Sistemas Operacionais

Notas da Aula 17 - Fundamentos de Sistemas Operacionais Notas da Aula 17 - Fundamentos de Sistemas Operacionais 1. Gerenciamento de Memória: Introdução O gerenciamento de memória é provavelmente a tarefa mais complexa de um sistema operacional multiprogramado.

Leia mais

UNIVERSIDADE FEDERAL DO RIO GRANDE DO SUL INSTITUTO DE INFORMÁTICA INFORMÁTICA APLICADA

UNIVERSIDADE FEDERAL DO RIO GRANDE DO SUL INSTITUTO DE INFORMÁTICA INFORMÁTICA APLICADA Responda 1) Quem desenvolveu a linguagem C? Quando? 2) Existe alguma norma sobre a sintaxe da linguagem C? 3) Quais são os tipos básicos de dados disponíveis na linguagem C? 4) Quais são as principais

Leia mais

Tabela de Símbolos. Análise Semântica A Tabela de Símbolos. Principais Operações. Estrutura da Tabela de Símbolos. Declarações 11/6/2008

Tabela de Símbolos. Análise Semântica A Tabela de Símbolos. Principais Operações. Estrutura da Tabela de Símbolos. Declarações 11/6/2008 Tabela de Símbolos Análise Semântica A Tabela de Símbolos Fabiano Baldo Após a árvore de derivação, a tabela de símbolos é o principal atributo herdado em um compilador. É possível, mas não necessário,

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

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

Para construção dos modelos físicos, será estudado o modelo Relacional como originalmente proposto por Codd.

Para construção dos modelos físicos, será estudado o modelo Relacional como originalmente proposto por Codd. Apresentação Este curso tem como objetivo, oferecer uma noção geral sobre a construção de sistemas de banco de dados. Para isto, é necessário estudar modelos para a construção de projetos lógicos de bancos

Leia mais

Armazenamento de Dados. Prof. Antonio Almeida de Barros Junior

Armazenamento de Dados. Prof. Antonio Almeida de Barros Junior Armazenamento de Dados Prof. Antonio Almeida de Barros Junior 1 Armazenamento de Dados Todos os dados que utilizamos até o momento, ficavam armazenados apenas na memória. Ao final da execução dos programas,

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

Sistemas Operacionais

Sistemas Operacionais Sistemas Operacionais Gerência de processos Controle e descrição de processos Edson Moreno edson.moreno@pucrs.br http://www.inf.pucrs.br/~emoreno Sumário Representação e controle de processos pelo SO Estrutura

Leia mais

SISTEMAS OPERACIONAIS CAPÍTULO 3 CONCORRÊNCIA

SISTEMAS OPERACIONAIS CAPÍTULO 3 CONCORRÊNCIA SISTEMAS OPERACIONAIS CAPÍTULO 3 CONCORRÊNCIA 1. INTRODUÇÃO O conceito de concorrência é o princípio básico para o projeto e a implementação dos sistemas operacionais multiprogramáveis. O sistemas multiprogramáveis

Leia mais

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com - Aula 2-1. PRINCÍPIOS DE SOFTWARE DE ENTRADA E SAÍDA (E/S) As metas gerais do software de entrada e saída é organizar o software como uma série de camadas, com as mais baixas preocupadas em esconder as

Leia mais

Gerenciamento de Entrada e Saída Hélio Crestana Guardia e Hermes Senger

Gerenciamento de Entrada e Saída Hélio Crestana Guardia e Hermes Senger Gerenciamento de Entrada e Saída Hélio Crestana Guardia e Hermes Senger O controle da entrada e saída (E/S ou I/O, input/output) de dados dos dispositivos é uma das funções principais de um sistema operacional.

Leia mais

BARRAMENTO DO SISTEMA

BARRAMENTO DO SISTEMA BARRAMENTO DO SISTEMA Memória Principal Processador Barramento local Memória cachê/ ponte Barramento de sistema SCSI FireWire Dispositivo gráfico Controlador de vídeo Rede Local Barramento de alta velocidade

Leia mais

Algoritmos e Programação (Prática) Profa. Andreza Leite andreza.leite@univasf.edu.br

Algoritmos e Programação (Prática) Profa. Andreza Leite andreza.leite@univasf.edu.br (Prática) Profa. Andreza Leite andreza.leite@univasf.edu.br Introdução O computador como ferramenta indispensável: Faz parte das nossas vidas; Por si só não faz nada de útil; Grande capacidade de resolução

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

7.Conclusão e Trabalhos Futuros

7.Conclusão e Trabalhos Futuros 7.Conclusão e Trabalhos Futuros 158 7.Conclusão e Trabalhos Futuros 7.1 Conclusões Finais Neste trabalho, foram apresentados novos métodos para aceleração, otimização e gerenciamento do processo de renderização

Leia mais

Prof. Marcos Ribeiro Quinet de Andrade Universidade Federal Fluminense - UFF Pólo Universitário de Rio das Ostras - PURO

Prof. Marcos Ribeiro Quinet de Andrade Universidade Federal Fluminense - UFF Pólo Universitário de Rio das Ostras - PURO Conceitos básicos e serviços do Sistema Operacional Prof. Marcos Ribeiro Quinet de Andrade Universidade Federal Fluminense - UFF Pólo Universitário de Rio das Ostras - PURO Tipos de serviço do S.O. O S.O.

Leia mais

Sistemas Operacionais Gerência de Dispositivos

Sistemas Operacionais Gerência de Dispositivos Universidade Estadual de Mato Grosso do Sul UEMS Curso de Licenciatura em Computação Sistemas Operacionais Gerência de Dispositivos Prof. José Gonçalves Dias Neto profneto_ti@hotmail.com Introdução A gerência

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

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

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

Manual SAGe Versão 1.2 (a partir da versão 12.08.01)

Manual SAGe Versão 1.2 (a partir da versão 12.08.01) Manual SAGe Versão 1.2 (a partir da versão 12.08.01) Submissão de Relatórios Científicos Sumário Introdução... 2 Elaboração do Relatório Científico... 3 Submissão do Relatório Científico... 14 Operação

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

1 http://www.google.com

1 http://www.google.com 1 Introdução A computação em grade se caracteriza pelo uso de recursos computacionais distribuídos em várias redes. Os diversos nós contribuem com capacidade de processamento, armazenamento de dados ou

Leia mais

AMBIENTE PARA AUXILIAR O DESENVOLVIMENTO DE PROGRAMAS MONOLÍTICOS

AMBIENTE PARA AUXILIAR O DESENVOLVIMENTO DE PROGRAMAS MONOLÍTICOS UNIVERSIDADE REGIONAL DE BLUMENAU CENTRO DE CIÊNCIAS EXATAS E NATURAIS CURSO DE CIÊNCIAS DA COMPUTAÇÃO BACHARELADO AMBIENTE PARA AUXILIAR O DESENVOLVIMENTO DE PROGRAMAS MONOLÍTICOS Orientando: Oliver Mário

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

Introdução a Java. Hélder Nunes

Introdução a Java. Hélder Nunes Introdução a Java Hélder Nunes 2 Exercício de Fixação Os 4 elementos básicos da OO são os objetos, as classes, os atributos e os métodos. A orientação a objetos consiste em considerar os sistemas computacionais

Leia mais

Aula 4 Pseudocódigo Tipos de Dados, Expressões e Variáveis

Aula 4 Pseudocódigo Tipos de Dados, Expressões e Variáveis 1. TIPOS DE DADOS Todo o trabalho realizado por um computador é baseado na manipulação das informações contidas em sua memória. Estas informações podem ser classificadas em dois tipos: As instruções, que

Leia mais

Arquiteturas RISC. (Reduced Instructions Set Computers)

Arquiteturas RISC. (Reduced Instructions Set Computers) Arquiteturas RISC (Reduced Instructions Set Computers) 1 INOVAÇÕES DESDE O SURGIMENTO DO COMPU- TADOR DE PROGRAMA ARMAZENADO (1950)! O conceito de família: desacoplamento da arquitetura de uma máquina

Leia mais

Engenharia de Software III

Engenharia de Software III Engenharia de Software III Casos de uso http://dl.dropbox.com/u/3025380/es3/aula6.pdf (flavio.ceci@unisul.br) 09/09/2010 O que são casos de uso? Um caso de uso procura documentar as ações necessárias,

Leia mais

Sistemas Operacionais

Sistemas Operacionais Sistemas Operacionais Aula 6 Estrutura de Sistemas Operacionais Prof.: Edilberto M. Silva http://www.edilms.eti.br Baseado no material disponibilizado por: SO - Prof. Edilberto Silva Prof. José Juan Espantoso

Leia mais

Sistemas Operacionais. Prof. André Y. Kusumoto andrekusumoto.unip@gmail.com

Sistemas Operacionais. Prof. André Y. Kusumoto andrekusumoto.unip@gmail.com Sistemas Operacionais Prof. André Y. Kusumoto andrekusumoto.unip@gmail.com Estruturas de Sistemas de Computação O sistema operacional precisa garantir a operação correta do sistema de computação. Operação

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

DAS5102 Fundamentos da Estrutura da Informação

DAS5102 Fundamentos da Estrutura da Informação Pilhas A estrutura de dados Pilha emula a forma de organização de objetos intuitiva que é utilizada diariamente nos mais diversos contextos da vida humana. Containeres são empilhados e desempilhados diariamente

Leia mais

Sistemas Operacionais

Sistemas Operacionais Sistemas Operacionais Gerência de Arquivos Edson Moreno edson.moreno@pucrs.br http://www.inf.pucrs.br/~emoreno Sumário Conceituação de arquivos Implementação do sistemas de arquivo Introdução Sistema de

Leia mais

1. NÍVEL CONVENCIONAL DE MÁQUINA

1. NÍVEL CONVENCIONAL DE MÁQUINA 1. NÍVEL CONVENCIONAL DE MÁQUINA Relembrando a nossa matéria de Arquitetura de Computadores, a arquitetura de Computadores se divide em vários níveis como já estudamos anteriormente. Ou seja: o Nível 0

Leia mais

CONVENÇÃO DE CÓDIGO JAVA

CONVENÇÃO DE CÓDIGO JAVA CONVENÇÃO DE CÓDIGO JAVA Eligiane Ceron - Abril de 2012 Versão 1.0 Conteúdo Considerações iniciais... 2 Introdução... 2 Extensão de arquivos... 2 Arquivos de código Java... 2 Comentários iniciais... 2

Leia mais

ESTUDO DE CASO WINDOWS VISTA

ESTUDO DE CASO WINDOWS VISTA ESTUDO DE CASO WINDOWS VISTA História Os sistemas operacionais da Microsoft para PCs desktop e portáteis e para servidores podem ser divididos em 3 famílias: MS-DOS Windows baseado em MS-DOS Windows baseado

Leia mais

IFPE. Disciplina: Sistemas Operacionais. Prof. Anderson Luiz Moreira

IFPE. Disciplina: Sistemas Operacionais. Prof. Anderson Luiz Moreira IFPE Disciplina: Sistemas Operacionais Prof. Anderson Luiz Moreira SERVIÇOS OFERECIDOS PELOS SOS 1 Introdução O SO é formado por um conjunto de rotinas (procedimentos) que oferecem serviços aos usuários

Leia mais

Desenvolvimento de um Simulador de Gerenciamento de Memória

Desenvolvimento de um Simulador de Gerenciamento de Memória Desenvolvimento de um Simulador de Gerenciamento de Memória Ricardo Mendes do Nascimento. Ciência da Computação Universidade Regional Integrada do Alto Uruguai e das Missões (URI) Santo Ângelo RS Brasil

Leia mais

3 Arquitetura do Sistema

3 Arquitetura do Sistema 3 Arquitetura do Sistema Este capítulo irá descrever a arquitetura geral do sistema, justificando as decisões de implementação tomadas. Na primeira seção iremos considerar um conjunto de nós interagindo

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

CAPÍTULO 7 NÍVEL DE LINGUAGEM DE MONTAGEM

CAPÍTULO 7 NÍVEL DE LINGUAGEM DE MONTAGEM CAPÍTULO 7 NÍVEL DE LINGUAGEM DE MONTAGEM 71 Introdução Difere dos níveis inferiores por ser implementado por tradução A tradução é usada quando um processador está disponível para uma mensagem fonte mas

Leia mais

Java. Marcio de Carvalho Victorino www.dominandoti.eng.br

Java. Marcio de Carvalho Victorino www.dominandoti.eng.br Java Marcio de Carvalho Victorino www.dominandoti.eng.br 3. Considere as instruções Java abaixo: int cont1 = 3; int cont2 = 2; int cont3 = 1; cont1 += cont3++; cont1 -= --cont2; cont3 = cont2++; Após a

Leia mais

Gerência de Memória RAM em Computadores com Mais de 4GB O sistema Windows x86 (32bits) não tem capacidade de reconhecer, fisicamente, mais que 3,X GB de RAM, a não ser que seja ativado, manualmente, o

Leia mais

Sistemas Operacionais. Prof. André Y. Kusumoto andrekusumoto.unip@gmail.com

Sistemas Operacionais. Prof. André Y. Kusumoto andrekusumoto.unip@gmail.com Sistemas Operacionais Prof. André Y. Kusumoto andrekusumoto.unip@gmail.com Estruturas de Sistemas Operacionais Um sistema operacional fornece o ambiente no qual os programas são executados. Internamente,

Leia mais

Google Drive. Passos. Configurando o Google Drive

Google Drive. Passos. Configurando o Google Drive Google Drive um sistema de armazenagem de arquivos ligado à sua conta Google e acessível via Internet, desta forma você pode acessar seus arquivos a partir de qualquer dispositivo que tenha acesso à Internet.

Leia mais

Sistemas Distribuídos

Sistemas Distribuídos Sistemas Distribuídos Modelo Cliente-Servidor: Introdução aos tipos de servidores e clientes Prof. MSc. Hugo Souza Iniciando o módulo 03 da primeira unidade, iremos abordar sobre o Modelo Cliente-Servidor

Leia mais

Tais operações podem utilizar um (operações unárias) ou dois (operações binárias) valores.

Tais operações podem utilizar um (operações unárias) ou dois (operações binárias) valores. Tais operações podem utilizar um (operações unárias) ou dois (operações binárias) valores. 7.3.1.2 Registradores: São pequenas unidades de memória, implementadas na CPU, com as seguintes características:

Leia mais

Criando um script simples

Criando um script simples Criando um script simples As ferramentas de script Diferente de muitas linguagens de programação, você não precisará de quaisquer softwares especiais para criar scripts de JavaScript. A primeira coisa

Leia mais

Programação Orientada a Objetos com PHP & MySQL Sistema Gerenciador de Banco de Dados: Introdução e configuração de bases de dados com Postgre e MySQL

Programação Orientada a Objetos com PHP & MySQL Sistema Gerenciador de Banco de Dados: Introdução e configuração de bases de dados com Postgre e MySQL Programação Orientada a Objetos com PHP & MySQL Sistema Gerenciador de Banco de Dados: Introdução e configuração de bases de dados com Postgre e MySQL Prof. MSc. Hugo Souza Iniciando nossas aulas sobre

Leia mais

ICORLI. INSTALAÇÃO, CONFIGURAÇÃO e OPERAÇÃO EM REDES LOCAIS e INTERNET

ICORLI. INSTALAÇÃO, CONFIGURAÇÃO e OPERAÇÃO EM REDES LOCAIS e INTERNET INSTALAÇÃO, CONFIGURAÇÃO e OPERAÇÃO EM REDES LOCAIS e INTERNET 2010/2011 1 Protocolo TCP/IP É um padrão de comunicação entre diferentes computadores e diferentes sistemas operativos. Cada computador deve

Leia mais

MÓDULO 7 Modelo OSI. 7.1 Serviços Versus Protocolos

MÓDULO 7 Modelo OSI. 7.1 Serviços Versus Protocolos MÓDULO 7 Modelo OSI A maioria das redes são organizadas como pilhas ou níveis de camadas, umas sobre as outras, sendo feito com o intuito de reduzir a complexidade do projeto da rede. O objetivo de cada

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

Sistema de Computação

Sistema de Computação Sistema de Computação Máquinas multinível Nível 0 verdadeiro hardware da máquina, executando os programas em linguagem de máquina de nível 1 (portas lógicas); Nível 1 Composto por registrados e pela ALU

Leia mais

Processos e Threads (partes I e II)

Processos e Threads (partes I e II) Processos e Threads (partes I e II) 1) O que é um processo? É qualquer aplicação executada no processador. Exe: Bloco de notas, ler um dado de um disco, mostrar um texto na tela. Um processo é um programa

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

Métodos Os métodos de uma classe podem ser classificados como construtores, destrutores, funções ou procedimentos.

Métodos Os métodos de uma classe podem ser classificados como construtores, destrutores, funções ou procedimentos. Métodos Os métodos de uma classe podem ser classificados como construtores, destrutores, funções ou procedimentos. Construtor: método executado por uma CLASSE (e não por um objeto, instância da classe)

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

Introdução. Manipulação de arquivos em C. Estrutura de Dados II Prof Jairo Francisco de Souza

Introdução. Manipulação de arquivos em C. Estrutura de Dados II Prof Jairo Francisco de Souza Introdução Manipulação de arquivos em C Estrutura de Dados II Prof Jairo Francisco de Souza Manipulação de Arquivo em C Existem dois tipos possíveis de acesso a arquivos na linguagem C : sequencial (lendo

Leia mais

CAPÍTULO 2 CARACTERÍSTICAS DE E/S E PORTA PARALELA

CAPÍTULO 2 CARACTERÍSTICAS DE E/S E PORTA PARALELA 8 CAPÍTULO 2 CARACTERÍSTICAS DE E/S E PORTA PARALELA A porta paralela, também conhecida por printer port ou Centronics e a porta serial (RS-232) são interfaces bastante comuns que, apesar de estarem praticamente

Leia mais

Banco de Dados Aula 1 Introdução a Banco de Dados Introdução Sistema Gerenciador de Banco de Dados

Banco de Dados Aula 1 Introdução a Banco de Dados Introdução Sistema Gerenciador de Banco de Dados Banco de Dados Aula 1 Introdução a Banco de Dados Introdução Um Sistema Gerenciador de Banco de Dados (SGBD) é constituído por um conjunto de dados associados a um conjunto de programas para acesso a esses

Leia mais

Curso: Técnico de Informática Disciplina: Redes de Computadores. 1- Apresentação Binária

Curso: Técnico de Informática Disciplina: Redes de Computadores. 1- Apresentação Binária 1- Apresentação Binária Os computadores funcionam e armazenam dados mediante a utilização de chaves eletrônicas que são LIGADAS ou DESLIGADAS. Os computadores só entendem e utilizam dados existentes neste

Leia mais

Um Driver NDIS Para Interceptação de Datagramas IP

Um Driver NDIS Para Interceptação de Datagramas IP Um Driver NDIS Para Interceptação de Datagramas IP Paulo Fernando da Silva psilva@senior.com.br Sérgio Stringari stringari@furb.br Resumo. Este artigo apresenta o desenvolvimento de um driver NDIS 1 para

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

5 Mecanismo de seleção de componentes

5 Mecanismo de seleção de componentes Mecanismo de seleção de componentes 50 5 Mecanismo de seleção de componentes O Kaluana Original, apresentado em detalhes no capítulo 3 deste trabalho, é um middleware que facilita a construção de aplicações

Leia mais

2. Representação Numérica

2. Representação Numérica 2. Representação Numérica 2.1 Introdução A fim se realizarmos de maneira prática qualquer operação com números, nós precisamos representa-los em uma determinada base numérica. O que isso significa? Vamos

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

ULA Sinais de Controle enviados pela UC

ULA Sinais de Controle enviados pela UC Solução - Exercícios Processadores 1- Qual as funções da Unidade Aritmética e Lógica (ULA)? A ULA é o dispositivo da CPU que executa operações tais como: Adição Subtração Multiplicação Divisão Incremento

Leia mais

Busca. Pesquisa sequencial

Busca. Pesquisa sequencial Busca Banco de dados existem para que, de tempos em tempos, um usuário possa localizar o dado de um registro, simplesmente digitando sua chave. Uma tabela ou um arquivo é um grupo de elementos, cada um

Leia mais

Manual do Publicador. Wordpress FATEA Sistema de Gerenciamento de Conteúdo Web

Manual do Publicador. Wordpress FATEA Sistema de Gerenciamento de Conteúdo Web Manual do Publicador Wordpress FATEA Sistema de Gerenciamento de Conteúdo Web Sumário Painel de Administração... 3 1 - Inserção de post... 5 2 Publicação de post com notícia na área headline (galeria de

Leia mais

5 Framework para coordenação e mediação de Web Services para ambientes de aprendizado à distância

5 Framework para coordenação e mediação de Web Services para ambientes de aprendizado à distância 5 Framework para coordenação e mediação de Web Services para ambientes de aprendizado à distância O capítulo anterior apresentou uma discussão sobre a inclusão dos chamados learning services no processo

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

Pesquisa e organização de informação

Pesquisa e organização de informação Pesquisa e organização de informação Capítulo 3 A capacidade e a variedade de dispositivos de armazenamento que qualquer computador atual possui, tornam a pesquisa de informação um desafio cada vez maior

Leia mais

BACHARELADO EM SISTEMAS DE INFORMAÇÃO EaD UAB/UFSCar Sistemas de Informação - prof. Dr. Hélio Crestana Guardia

BACHARELADO EM SISTEMAS DE INFORMAÇÃO EaD UAB/UFSCar Sistemas de Informação - prof. Dr. Hélio Crestana Guardia O Sistema Operacional que você usa é multitasking? Por multitasking, entende-se a capacidade do SO de ter mais de um processos em execução ao mesmo tempo. É claro que, num dado instante, o número de processos

Leia mais

FAÇA FÁCIL: DRIVER IGS PARA COMUNICAÇÃO DE PROTOCOLOS PROPRIETÁRIOS INTRODUÇÃO

FAÇA FÁCIL: DRIVER IGS PARA COMUNICAÇÃO DE PROTOCOLOS PROPRIETÁRIOS INTRODUÇÃO FAÇA FÁCIL: DRIVER IGS PARA COMUNICAÇÃO DE PROTOCOLOS PROPRIETÁRIOS INTRODUÇÃO O Driver IGS possui um módulo de configuração que possibilita a comunicação com protocolos proprietários. Trata-se do Driver

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

Prática da Disciplina de Sistemas Distribuídos Serviços Web IFMA DAI Professor Mauro Lopes C. Silva

Prática da Disciplina de Sistemas Distribuídos Serviços Web IFMA DAI Professor Mauro Lopes C. Silva 1. O que são Serviços Web (Web Services)? Prática da Disciplina de Sistemas Distribuídos Serviços Web IFMA DAI Professor Mauro Lopes C. Silva A ideia central dos Web Services parte da antiga necessidade

Leia mais

Programação Orientada a Objetos com PHP & MySQL Cookies e Sessões. Prof. MSc. Hugo Souza

Programação Orientada a Objetos com PHP & MySQL Cookies e Sessões. Prof. MSc. Hugo Souza Programação Orientada a Objetos com PHP & MySQL Cookies e Sessões Prof. MSc. Hugo Souza Se você precisar manter informações sobre seus usuários enquanto eles navegam pelo seu site, ou até quando eles saem

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

NOTAS DE AULA Prof. Antonio Carlos Schneider Beck Filho (UFSM) Prof. Júlio Carlos Balzano de Mattos (UFPel) Arquitetura de Von Neumann

NOTAS DE AULA Prof. Antonio Carlos Schneider Beck Filho (UFSM) Prof. Júlio Carlos Balzano de Mattos (UFPel) Arquitetura de Von Neumann Universidade Federal de Santa Maria NOTAS DE AULA Prof. Antonio Carlos Schneider Beck Filho (UFSM) Prof. Júlio Carlos Balzano de Mattos (UFPel) Arquitetura de Von Neumann O modelo (ou arquitetura) de von

Leia mais

TRABALHO COM GRANDES MONTAGENS

TRABALHO COM GRANDES MONTAGENS Texto Técnico 005/2013 TRABALHO COM GRANDES MONTAGENS Parte 05 0 Vamos finalizar o tema Trabalho com Grandes Montagens apresentando os melhores recursos e configurações de hardware para otimizar a abertura

Leia mais

5. EXPERIÊNCIAS E ANÁLISE DOS RESULTADOS. 5.1 - Os Programas de Avaliação

5. EXPERIÊNCIAS E ANÁLISE DOS RESULTADOS. 5.1 - Os Programas de Avaliação 36 5. EXPERIÊNCIAS E ANÁLISE DOS RESULTADOS 5.1 - Os Programas de Avaliação Programas de avaliação convencionais foram utilizados para análise de diversas configurações da arquitetura. Estes programas

Leia mais