Quantos núcleos de processador Intel você possui no seu computador? Se você usa um sistema baseado na Intel, na grande maioria dos casos, precisará adicionar um à sua resposta. A composição de quase todos os processadores Intel - do Atom ao Xeon E3, é claro, sem perder o Core, já há muitos anos inclui o núcleo gráfico integrado Intel Graphics, que é essencialmente um processador completo e, portanto, capaz de não apenas mostrar fotos na tela e acelerar o vídeo, mas também realize cálculos de uso geral "comuns". Como isso pode ser usado efetivamente? Olhe por baixo do corte.

Primeiro, explicaremos brevemente por que vale a pena confiar em uma GPU Intel. Obviamente, o desempenho da CPU no sistema quase sempre excede significativamente a GPU, por isso também é o Processador Central.
Mas é interessante notar que o desempenho das GPUs integradas da Intel na última década cresceu muito mais do que o da CPU em termos percentuais, e essa tendência certamente continuará com o advento de novas placas gráficas Intel discretas. Além disso, a GPU, em virtude de sua arquitetura (muitos dispositivos de execução de vetores), é muito mais adequada para a execução de um certo tipo de tarefas - o processamento de imagens, que é, de fato, realizar quaisquer operações do mesmo tipo em matrizes de dados. A GPU faz isso com total paralelização interna, gasta menos energia do que a CPU e, em alguns casos, até supera em velocidade absoluta. Finalmente, a GPU e a CPU podem trabalhar em paralelo, cada uma em suas próprias tarefas, fornecendo desempenho máximo e / ou consumo mínimo de energia de todo o sistema.
Ok, Intel. Decidimos usar a GPU Intel para cálculos de uso geral, como fazer isso?
- A maneira mais simples que não requer nenhum conhecimento especial em gráficos (shaders Direct3D e OpenGL) é o OpenCL.
Os kernels OpenCL são independentes de plataforma e serão executados automaticamente em todos os dispositivos de computação disponíveis no sistema - CPU, GPU, FPGA, etc. Mas a taxa por essa versatilidade está longe do desempenho máximo possível em cada tipo de dispositivo, e especialmente na GPU Intel integrada. Aqui podemos dar um exemplo: ao executar código em qualquer GPU Intel que transponha uma matriz de 16x16 bytes, a vantagem de desempenho da programação direta da GPU Intel será 8 vezes maior do que na versão OpenCL!
Além disso, algumas das funcionalidades necessárias para implementar algoritmos comuns (por exemplo, "filtros amplos" que usam dados de um grande grupo de pixels em uma única transformação), o OpenCL simplesmente não suporta.
Portanto, se você precisar de velocidade máxima na GPU e / ou algo mais complicado do que trabalhar independentemente com cada elemento da matriz e seus vizinhos mais próximos, o Intel C for Metal (ICM) o ajudará - uma ferramenta para o desenvolvimento de aplicativos em execução nos gráficos Intel .
ICM - bem-vindo à forja!
Do ponto de vista de desempenho e funcionalidade, o ICM pode ser considerado "montador de placas gráficas Intel" e, em termos de circuitos e usabilidade - "análogo do OpenCL para placas gráficas Intel".
Por muitos anos, o ICM tem sido usado internamente pela Intel no desenvolvimento de produtos de processamento de mídia na GPU Intel. Mas em 2018, o ICM foi lançado ao público, e mesmo com código aberto!
O Intel C for Metal ganhou seu nome atual há alguns meses, antes de ser chamado Intel C for Media (o mesmo acrônimo ICM ou apenas CM ou mesmo Cm) e, ainda mais cedo - o Media Development Framework (MDF). Portanto, se em algum lugar no nome do componente, na documentação ou nos comentários de código aberto, os nomes antigos se encontrarem - não se assuste, esse é um valor histórico.
Portanto, o código do aplicativo ICM, assim como no OpenCL, contém duas partes: a “administrativa”, executada no processador, e o kernel, executado na GPU. Não é de surpreender que a primeira parte seja chamada de host e a segunda seja o kernel.
Os kernels são uma função do processamento de um determinado bloco de pixels (ou apenas dados), são escritos na linguagem Intel C for Metal e compilados no conjunto de instruções da GPU Intel (ISA) usando o compilador ICM.
O host é uma espécie de "gerenciador de equipe do kernel", administra o processo de transferência de dados entre a CPU e a GPU e realiza outros "trabalhos gerenciais" por meio da biblioteca de tempo de execução do ICM Runtime e do driver de mídia da GPU da Intel.
Um fluxo de trabalho detalhado do ICM se parece com isso:
- O código do host ICM é compilado por qualquer compilador x86 C / C ++ junto com o aplicativo inteiro;
- O código do kernel do ICM é compilado pelo compilador do ICM em um arquivo binário com algum conjunto de instruções comum (ISA comum);
- Em tempo de execução, esse conjunto geral de instruções JIT se traduz em uma GPU Intel específica;
- O host ICM chama a biblioteca de tempo de execução ICM para se comunicar com a GPU e o sistema operacional.
Mais alguns pontos importantes e úteis:
- As superfícies usadas no ICM para representar / armazenar dados podem ser compartilhadas com o DirectX 11 e 9 (DXVA no Linux).
- A GPU pode pegar e gravar dados da memória de vídeo e da memória do sistema compartilhada com a CPU. O ICM inclui funções especiais para ambos os casos de transferência de dados em ambas as direções. Ao mesmo tempo, a memória do sistema é exatamente compartilhada e a cópia real não é necessária - para isso, a chamada cópia zero é fornecida no ICM.
ICM - na abertura do vulcão!
Já a partir do nome "C for Iron", o dispositivo de idioma corresponde ao dispositivo gráfico interno da Intel. Ou seja, leva em consideração o fato de que o código será executado em várias dezenas de unidades de execução (Unidade de Execução) da placa de vídeo, cada uma delas um processador totalmente vetorial capaz de executar vários threads simultaneamente.
A linguagem ICM em si é C ++ com algumas limitações e extensões. Comparado ao C ++, o ICM não possui ... ponteiros, alocação de memória e variáveis estáticas. Sob a proibição também funções recursivas. Mas há uma programação de modelo vetorial explícito (SIMD): tipos de dados vetoriais - vetor, matriz e superfície; operações de vetor nesses tipos de dados, condições de vetor se / else, executadas independentemente para cada elemento do vetor; bem como funções internas para acessar a funcionalidade fixa do hardware da GPU Intel.
O trabalho com vetores, matrizes e superfícies em tarefas reais é facilitado por objetos de "subconjuntos" - a partir dos objetos básicos correspondentes, você pode escolher apenas os blocos de "referência" que lhe interessam ou, como um caso especial, elementos individuais por máscara.
Por exemplo, vejamos o código ICM que implementa um filtro linear - substituindo um valor
Cores RGB de cada pixel por seu valor médio e 8 vizinhos na imagem:
Se as cores (dados) na matriz estiverem localizadas como
R8G8B8 , o cálculo com a divisão da imagem de entrada em blocos de 6x8 pixels (elementos de dados de 6x24 bytes) será o seguinte:
_GENX_MAIN_ void linear(SurfaceIndex inBuf, SurfaceIndex outBuf, uint h_pos, uint v_pos){
- O tamanho das matrizes é definido no formato <tipo de dados, altura, largura>;
- o operador select <v_size, v_stride, h_size, h_stride> (i, j) retorna a submatriz começando com o elemento (i, j) , v_size mostra o número de linhas selecionadas, v_stride - a distância entre as linhas selecionadas h_size - o número de colunas selecionadas h_size - o número de colunas selecionadas, h_stride - a distância entre elas .
Observe que o tamanho da matriz de entrada 8x32 é escolhido porque, embora o bloco 8x30 seja algoritmicamente suficiente para calcular os valores de todos os pixels no bloco 6x24, o bloco de dados é lido no ICM, não em bytes, mas por elementos dword de 32 bits.
O código acima é, de fato, um núcleo completo do ICM. Como mencionado, ele será compilado pelo compilador ICM em dois estágios (pré-compilação e tradução posterior do JIT). O compilador ICM é construído com base no LLVM e, se desejado, pode ser
estudado nas fontes e construído por você .
Mas o que o host ICM faz? Invoca as funções da biblioteca de tempo de execução do ICM Runtime que:
- Crie, inicialize e exclua depois de usar o dispositivo GPU (CmDevice), bem como superfícies contendo dados do usuário usados nos kernels (CmSurface);
- Trabalhar com kernels - faça o download dos arquivos .isa pré-compilados, prepare seus argumentos, indicando a parte dos dados com os quais cada kernel trabalhará;
- Crie e gerencie a fila de execução do kernel;
- Eles controlam a operação dos threads que executam cada kernel na GPU;
- Gerenciar eventos (CmEvent) - objetos de sincronização da GPU e da CPU;
- Transfira dados entre a GPU e a CPU, ou melhor, entre o sistema e a memória de vídeo;
- Relatar erros, medir o tempo de operação dos kernels.
O código do host mais simples é assim:
Como você pode ver, não há nada complicado em criar e usar kernels e um host. Tudo é simples!
A única dificuldade a alertar para retornar ao mundo real: atualmente, na versão publicamente disponível do ICM, a única maneira de depurar kernels são as mensagens printf. Como usá-los corretamente pode ser visto no exemplo
Hello, World .
ICM - não metal pesado!
Agora vamos ver como isso funciona na prática. O ICM Developer Kit
está disponível para Windows e Linux e , para ambos os sistemas operacionais, contém os casos de uso do ICM Compiler, da documentação e do tutorial. Uma descrição detalhada desses exemplos de treinamento é
baixada separadamente .
Para Linux, o pacote também inclui um driver de mídia no modo usuário para VAAPI com uma biblioteca de tempo de execução ICM Runtime integrada. Para Windows, o driver de gráficos Intel usual para Windows funcionará com o ICM. A biblioteca de tempo de execução do ICM Runtime está incluída no conjunto de DLL deste driver. O pacote ICM inclui apenas o arquivo .lib do link para ele. Se o driver estiver ausente no sistema por algum motivo, ele será baixado do site da Intel e a operação correta do ICM nos drivers será garantida, a partir da versão 15.60 - 2017).
O código fonte dos componentes pode ser encontrado aqui:
O conteúdo adicional desta seção se aplica exclusivamente ao Windows, mas os princípios gerais de trabalho com o ICM também são aplicáveis ao Linux.
Para o trabalho "regular" com o pacote ICM, você precisará do Visual Studio a partir de 2015 e do Cmake a partir da versão 3.2. Ao mesmo tempo, os arquivos de configuração e script dos exemplos de treinamento foram projetados para o VS 2015. Para usar versões mais recentes dos arquivos do VS, você precisará estudar e editar os caminhos dos componentes do VS.
Então, conhecendo o ICM para Windows:
- Faça o download do arquivo ;
- Descompacte-o;
- Iniciamos (preferencialmente na linha de comando do VS) o script de configuração do ambiente setupenv.bat com três parâmetros - a geração da GPU Intel (correspondente ao processador no qual a GPU está integrada, pode ser deixada por padrão: gen9), a plataforma de compilação: x86 \ x64 e a versão DirectX para compartilhando com o ICM: dx9 / dx11.
Depois disso, você pode simplesmente criar todos os exemplos de treinamento - na pasta de exemplos, o script
build_all.bat fará
isso ou gerará projetos para o Microsoft Visual Studio - isso
criará o script
create_vs.bat com o nome de um exemplo específico como parâmetro.
Como você pode ver, o aplicativo ICM será um arquivo .exe com a parte do host e um arquivo .isa com a parte da GPU pré-compilada correspondente.
Vários exemplos estão incluídos no pacote ICM - do Hello, World, mais simples, que mostra os princípios básicos da operação do ICM, ao mais complicado - a implementação do algoritmo para encontrar o "fluxo máximo - corte mínimo" do gráfico (problema de corte mínimo do fluxo máximo) usado na segmentação e costura de imagens .
Todos os estudos de caso do ICM estão bem documentados no código e na
descrição separada já mencionada. Recomenda-se mergulhar no ICM com precisão - estudando e executando exemplos sequencialmente e depois modificando-os para atender às suas necessidades.
Para uma compreensão geral de todos os recursos existentes do ICM, é altamente recomendável que você estude a “especificação” - a descrição do ICM
cmlangspec.html na
pasta \ documents \ compiler \ html \ cmlangspec .
Em particular, descreve a API das funções ICM implementadas no hardware - acesso aos chamados sampler de textura (Sampler) - um mecanismo para filtrar imagens de diferentes formatos, bem como avaliar o movimento (estimativa de movimento) entre os quadros de vídeo e alguns recursos de análise de vídeo.
ICM - ataque enquanto está quente!
Falando sobre o desempenho dos aplicativos ICM, deve-se observar que os estudos de caso incluem a medição do tempo de seu trabalho, para executá-los no sistema de destino e compará-los com suas tarefas, você pode avaliar a adequação do uso do ICM para eles.
E considerações gerais sobre o desempenho do ICM são bastante simples:
- Ao descarregar cálculos em uma GPU, lembre-se da sobrecarga de transferência de dados da CPU <-> GPU e sincronização desses dispositivos. Portanto, um exemplo como Hello, World não é um bom candidato para uma implementação de ICM. Mas os algoritmos de visão computacional, IA e qualquer processamento não trivial de matrizes de dados, especialmente com uma alteração na ordem desses dados no processo ou na saída, é o que o ICM precisa.
- Além disso, ao projetar um código ICM, é necessário levar em consideração o dispositivo interno da GPU, ou seja, é recomendável criar um número suficiente (> 1000) de threads da GPU e carregá-los todos com trabalho. Nesse caso, é uma boa idéia dividir as imagens para processamento em pequenos blocos. Mas a maneira específica de particionar, bem como a escolha de um algoritmo de processamento específico para obter o máximo desempenho, não é uma tarefa trivial. No entanto, isso se aplica a qualquer maneira de trabalhar com qualquer GPU (e CPU).
Você tem código OpenCL, mas seu desempenho não lhe agrada? Ou código CUDA, mas você deseja trabalhar em um número muito maior de plataformas? Então vale a pena dar uma olhada no ICM.
O ICM é um produto vivo e em evolução. Você pode participar de seu uso e desenvolvimento - os repositórios correspondentes no github estão aguardando seus commits. Todas as informações necessárias para os dois processos estão neste artigo e nos arquivos leia-me no github. E se algo estiver faltando, ele aparecerá após suas perguntas nos comentários.