-
Combine o aprendizado de máquina e os gráficos do Metal 4
Saiba como combinar perfeitamente o aprendizado de máquina em seus apps com recursos gráficos usando o Metal 4. Vamos apresentar o recurso de tensor e o codificador de ML para executar modelos na timeline da GPU, em paralelo às tarefas de renderização e computação. Descubra como o Shader ML permite incorporar redes neurais diretamente em seus sombreadores para criar efeitos avançados e melhorar o desempenho. Também mostraremos novas ferramentas de depuração para cargas de trabalho de ML no Metal 4 em ação usando um app de exemplo.
Capítulos
- 0:00 - Introdução
- 2:52 - O que são tensors
- 6:21 - Codificar redes de ML
- 12:51 - Incorporar ML no shader
- 20:26 - Depurar cargas de trabalho de ML
Recursos
Vídeos relacionados
WWDC25
- Aprimore jogos com o Metal 4
- Conheça o Metal 4
- Explore jogos feitos com o Metal 4
- Novidades na renderização no Metal para apps imersivos
WWDC24
-
Buscar neste vídeo...
-
-
8:13 - Exporting a Core ML package with PyTorch
import coremltools as ct # define model in PyTorch # export model to an mlpackage model_from_export = ct.convert( custom_traced_model, inputs=[...], outputs=[...], convert_to='mlprogram', minimum_deployment_target=ct.target.macOS16, ) model_from_export.save('model.mlpackage') -
9:10 - Identifying a network in a Metal package
library = [device newLibraryWithURL:@"myNetwork.mtlpackage"]; functionDescriptor = [MTL4LibraryFunctionDescriptor new] functionDescriptor.name = @"main"; functionDescriptor.library = library; -
9:21 - Creating a pipeline state
descriptor = [MTL4MachineLearningPipelineDescriptor new]; descriptor.machineLearningFunctionDescriptor = functionDescriptor; [descriptor setInputDimensions:dimensions atBufferIndex:1]; pipeline = [compiler newMachineLearningPipelineStateWithDescriptor:descriptor error:&error]; -
9:58 - Dispatching a network
commands = [device newCommandBuffer]; [commands beginCommandBufferWithAllocator:cmdAllocator]; [commands useResidencySet:residencySet]; /* Create intermediate heap */ /* Configure argument table */ encoder = [commands machineLearningCommandEncoder]; [encoder setPipelineState:pipeline]; [encoder setArgumentTable:argTable]; [encoder dispatchNetworkWithIntermediatesHeap:heap]; -
10:30 - Creating a heap for intermediate storage
heapDescriptor = [MTLHeapDescriptor new]; heapDescriptor.type = MTLHeapTypePlacement; heapDescriptor.size = pipeline.intermediatesHeapSize; heap = [device newHeapWithDescriptor:heapDescriptor]; -
10:46 - Submitting commands to the GPU timeline
commands = [device newCommandBuffer]; [commands beginCommandBufferWithAllocator:cmdAllocator]; [commands useResidencySet:residencySet]; /* Create intermediate heap */ /* Configure argument table */ encoder = [commands machineLearningCommandEncoder]; [encoder setPipelineState:pipeline]; [encoder setArgumentTable:argTable]; [encoder dispatchNetworkWithIntermediatesHeap:heap]; [commands endCommandBuffer]; [queue commit:&commands count:1]; -
11:18 - Synchronization
[encoder barrierAfterStages:MTLStageMachineLearning beforeQueueStages:MTLStageVertex visibilityOptions:MTL4VisibilityOptionDevice]; -
15:17 - Declaring a fragment shader with tensor inputs
// Metal Shading Language 4 #include <metal_tensor> using namespace metal; [[fragment]] float4 shade_frag(tensor<device half, dextents<int, 2>> layer0Weights [[ buffer(0) ]], tensor<device half, dextents<int, 2>> layer1Weights [[ buffer(1) ]], /* other bindings */) { // Creating input tensor half inputs[INPUT_WIDTH] = { /* four latent texture samples + UV data */ }; auto inputTensor = tensor(inputs, extents<int, INPUT_WIDTH, 1>()); ... } -
17:12 - Operating on tensors in shaders
// Metal Shading Language 4 #include <MetalPerformancePrimitives/MetalPerformancePrimitives.h> using namespace mpp; constexpr tensor_ops::matmul2d_descriptor desc( /* M, N, K */ 1, HIDDEN_WIDTH, INPUT_WIDTH, /* left transpose */ false, /* right transpose */ true, /* reduced precision */ true); tensor_ops::matmul2d<desc, execution_thread> op; op.run(inputTensor, layerN, intermediateN); for (auto intermediateIndex = 0; intermediateIndex < intermediateN(0); ++intermediateIndex) { intermediateN[intermediateIndex, 0] = max(0.0f, intermediateN[intermediateIndex, 0]); } -
18:38 - Render using network evaluation
half3 baseColor = half3(outputTensor[0,0], outputTensor[1,0], outputTensor[2,0]); half3 tangentSpaceNormal = half3(outputTensor[3,0], outputTensor[4,0], outputTensor[5,0]); half3 worldSpaceNormal = worldSpaceTBN * tangentSpaceNormal; return baseColor * saturate(dot(worldSpaceNormal, worldSpaceLightDir));
-
-
- 0:00 - Introdução
Apresentamos o Metal 4, que aprimora a integração de aprendizado de máquina em jogos e gráficos. O Metal 4 permite técnicas como redimensionamento, compactação de assets e mesclagem de animações usando redes de ML, o que melhora o desempenho e a fidelidade visual. Os principais recursos incluem 'MTLTensors' para fluxos de trabalho de ML, 'MTL4MachineLearningCommandEncoder' para executar redes na linha do tempo da GPU, Shader ML para incorporar operações de ML em shaders, além de ferramentas de depuração aprimoradas. O CoreML é ideal para a criação de modelos de ML, e você pode obter uma integração perfeita da ML aos apps com a ajuda do Metal Debugger.
- 2:52 - O que são tensors
O Metal 4 apresenta o 'MTLTensor', um recurso projetado especificamente para workloads de aprendizado de máquina. 'MTLTensors' são contêineres de dados multidimensionais, permitindo a representação eficiente dos layouts de dados complexos usados em aprendizado de máquina, como aqueles necessários para operações de convolução. Eles simplificam a indexação de dados multidimensionais em comparação com representações planas como 'MTLBuffers'. Um 'MTLTensor' é definido de acordo com a classificação (número de eixos), as extensões (número de pontos de dados ao longo de cada eixo), o tipo de dados e as propriedades de uso. Essas propriedades são especificadas em um objeto 'MTLTensorDescriptor'. É possível criar 'MTLTensors' a partir de um objeto 'MTLDevice', que oferece desempenho otimizado com um layout opaco, ou de um objeto 'MTLBuffer' existente, onde é preciso especificar as etapas a serem consideradas para o preenchimento potencial.
- 6:21 - Codificar redes de ML
O Metal mais recente também apresenta o 'MTL4MachineLearningCommandEncoder', permitindo que o trabalho de aprendizado de máquina seja integrado à linha do tempo da GPU junto com comandos de computação e renderização. Esse novo codificador permite que modelos completos de ML sejam executados na GPU, sincronizando com outros comandos do Metal usando primitivas de sincronização padrão, como barreiras e cercas. O fluxo de trabalho envolve duas partes principais: offline e tempo de execução. Offline, o sistema converte um pacote CoreML em um 'MTLPackage' otimizado usando a ferramenta de linha de comando 'metal-package-builder'. Em tempo de execução, o sistema compila 'MTLPackage' em um 'MTL4MachineLearningPipelineState' e cria o 'MTL4MachineLearningCommandEncoder' configurado com o estado do pipeline, entradas e saídas, e então envia comandos codificados para a GPU. O codificador utiliza um 'MTLHeap' para armazenar dados intermediários, otimizando o uso de recursos. Isso permite a execução paralela de tarefas não dependentes, melhorando o desempenho. Os recursos de sincronização do Metal 4 garantem que as saídas de ML que consomem trabalho aguardem a conclusão da rede, o que o torna adequado para várias aplicações em tempo real, não apenas jogos.
- 12:51 - Incorporar ML no shader
O Metal 4 apresenta o Shader ML, permitindo que desenvolvedores incorporem operações de aprendizado de máquina diretamente nos shaders. Isso melhora o desempenho e reduz o uso de memória ao eliminar a necessidade de sincronizar tensores entre a memória do dispositivo e os shaders. A compressão de material neural, uma técnica específica de ML, é um exemplo. Ela comprime texturas de material em até 50% em comparação com formatos tradicionais compactados em bloco. Com o Shader ML, todo o processo de avaliação de material neural, desde a inicialização dos tensores de entrada até a inferência e sombreamento, pode ser combinado em uma única execução de shader. O Metal Performance Primitives é integrado ao Shader ML, fornecendo APIs de alto desempenho, como multiplicação e convolução de matrizes. Isso permite implementar rotinas de avaliação de redes neurais de forma eficiente dentro de fragment shaders, resultando em aplicações em tempo real sem perda perceptível de qualidade, mas com uso significativamente menor de memória e espaço em disco.
- 20:26 - Depurar cargas de trabalho de ML
No exemplo dado, com as novas ferramentas de GPU no Xcode, é possível depurar um workload de aprendizado de máquina que está causando artefatos graves no cálculo da oclusão de ambiente de um app. Você pode capturar o rastreamento da GPU e utilizar o Visualizador de Dependências para inspecionar a sincronização dos buffers de comando, descartando qualquer problema. Pode, então, examinar os tensores de entrada e saída do 'MTL4MachineLearningCommandEncoder', confirmando que o problema está na própria rede de aprendizado de máquina. Depois, pode abrir a rede no novo Depurador de Rede de ML, uma ferramenta visual que representa a estrutura do modelo (escrita em PyTorch e convertida para CoreML e MTLPackage), o que permite identificar a operação responsável pela introdução dos artefatos. Ao inspecionar o gráfico, os artefatos estão presentes na saída e na entrada de uma operação anterior, indicando um problema dentro da rede. A função 'SignedSmoothstep' é identificada como a área do problema. Ao revisar o código Python, um bug é descoberto: um asterisco extra, que faz com que o sistema interprete uma operação de multiplicação como uma operação de energia. A correção desse erro resolve o problema e a implementação de oclusão de ambiente neural usando o 'MTL4MachineLearningCommandEncoder' do Metal 4 é depurada com êxito.