View in English

  • Apple Developer
    • Get Started

    Explore Get Started

    • Overview
    • Learn
    • Apple Developer Program

    Stay Updated

    • Latest News
    • Hello Developer
    • Platforms

    Explore Platforms

    • Apple Platforms
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    Featured

    • Design
    • Distribution
    • Games
    • Accessories
    • Web
    • Home
    • CarPlay
    • Technologies

    Explore Technologies

    • Overview
    • Xcode
    • Swift
    • SwiftUI

    Featured

    • Accessibility
    • App Intents
    • Apple Intelligence
    • Games
    • Machine Learning & AI
    • Security
    • Xcode Cloud
    • Community

    Explore Community

    • Overview
    • Meet with Apple events
    • Community-driven events
    • Developer Forums
    • Open Source

    Featured

    • WWDC
    • Swift Student Challenge
    • Developer Stories
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Centers
    • Documentation

    Explore Documentation

    • Documentation Library
    • Technology Overviews
    • Sample Code
    • Human Interface Guidelines
    • Videos

    Release Notes

    • Featured Updates
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • Downloads

    Explore Downloads

    • All Downloads
    • Operating Systems
    • Applications
    • Design Resources

    Featured

    • Xcode
    • TestFlight
    • Fonts
    • SF Symbols
    • Icon Composer
    • Support

    Explore Support

    • Overview
    • Help Guides
    • Developer Forums
    • Feedback Assistant
    • Contact Us

    Featured

    • Account Help
    • App Review Guidelines
    • App Store Connect Help
    • Upcoming Requirements
    • Agreements and Guidelines
    • System Status
  • Quick Links

    • Events
    • News
    • Forums
    • Sample Code
    • Videos
 

Vidéos

Ouvrir le menu Fermer le menu
  • Collections
  • Toutes les vidéos
  • À propos

Plus de vidéos

  • À propos
  • Résumé
  • Code
  • Quoi de neuf dans BNNS Graph

    L'API BNNS Graph Builder permet désormais aux développeurs d'écrire des graphiques d'opérations en utilisant le langage Swift familier pour générer des routines de pré et post-traitement et de petits modèles d'apprentissage automatique. BNNS compile des graphiques avant l'exécution et prend en charge les cas d'utilisation en temps réel et sensibles à la latence, tels que le traitement audio. Dans cette séance, nous reprenons l'exemple du bit-crusher de l'année dernière et simplifions le composant Swift en supprimant la dépendance à un fichier Python séparé et en implémentant l'effet audio entièrement dans Swift. L'API BNNS Graph Builder est également adaptée au prétraitement des données d'image avant de les transmettre à un modèle d'apprentissage automatique. La séance comprend également une démonstration du découpage des pixels transparents d'une image avec un canal alpha.

    Chapitres

    • 0:00 - Introduction
    • 3:12 - Récapitulatif BNNSGraph
    • 6:15 - BNNSGraphBuilder
    • 16:58 - Utilisation de BNNSGraphBuilder

    Ressources

    • vImage.PixelBuffer
    • BNNS
    • Supporting real-time ML inference on the CPU
      • Vidéo HD
      • Vidéo SD

    Vidéos connexes

    WWDC25

    • Découvrir les frameworks d’apprentissage automatique et d’IA sur les plates-formes Apple

    WWDC24

    • Support real-time ML inference on the CPU
  • Rechercher dans cette vidéo…
    • 8:31 - Introduction to BNNSGraphBuilder

      import Accelerate
      
      
      
      func demo() throws {
      
          let context = try BNNSGraph.makeContext {
              builder in
           
              let x = builder.argument(name: "x",
                                       dataType: Float.self,
                                       shape: [8])
              let y = builder.argument(name: "y",
                                       dataType: Float.self,
                                       shape: [8])
              
              let product = x * y
              let mean = product.mean(axes: [0], keepDimensions: true)
              
              // Prints "shape: [1] | stride: [1]".
              print("mean", mean)
              
              return [ product, mean]
          }
          
          var args = context.argumentNames().map {
              name in
              return context.tensor(argument: name,
                                    fillKnownDynamicShapes: false)!
          }
          
          // Output arguments
          args[0].allocate(as: Float.self, count: 8)
          args[1].allocate(as: Float.self, count: 1)
          
          // Input arguments
          args[2].allocate(
              initializingFrom: [1, 2, 3, 4, 5, 6, 7, 8] as [Float])
          args[3].allocate(
              initializingFrom: [8, 7, 6, 5, 4, 3, 2, 1] as [Float])
      
              try context.executeFunction(arguments: &args)
          
          // [8.0, 14.0, 18.0, 20.0, 20.0, 18.0, 14.0, 8.0]
          print(args[0].makeArray(of: Float.self))
          
          // [15.0]
          print(args[1].makeArray(of: Float.self))
          
          args.forEach {
              $0.deallocate()
          }
      }
    • 12:04 - Strong typing

      // Performs `result = mask0 .< mask1 ? bases.pow(exponents) : 0
      
      let context = try BNNSGraph.makeContext {
          builder in
          
          let mask0 = builder.argument(dataType: Float16.self,
                                       shape: [-1])
          let mask1 = builder.argument(dataType: Float16.self,
                                       shape: [-1])
          
          let bases = builder.argument(dataType: Float16.self,
                                       shape: [-1])
          let exponents = builder.argument(dataType: Int32.self,
                                           shape: [-1])
          
          // `mask` contains Boolean values.
          let mask = mask0 .< mask1
          
          // Cast integer exponents to FP16.
          var result = bases.pow(y: exponents.cast(to: Float16.self))
          result = result * mask.cast(to: Float16.self)
          
          return [result]
      }
    • 14:15 - Slicing

      let srcImage = #imageLiteral(resourceName: "squirrel.jpeg").cgImage(
          forProposedRect: nil,
          context: nil,
          hints: nil)!
      
      var cgImageFormat = vImage_CGImageFormat(
          bitsPerComponent: 32,
          bitsPerPixel: 32 * 3,
          colorSpace: CGColorSpaceCreateDeviceRGB(),
          bitmapInfo: CGBitmapInfo(alpha: .none,
                                   component: .float,
                                   byteOrder: .order32Host))!
      
      let source = try vImage.PixelBuffer(cgImage: srcImage,
                                          cgImageFormat: &cgImageFormat,
                                          pixelFormat: vImage.InterleavedFx3.self)
      
      let cropSize = 640
      let horizontalMargin = (source.width - cropSize) / 2
      let verticalMargin = (source.height - cropSize) / 2
      
      let destination = vImage.PixelBuffer(size: .init(width: cropSize,
                                                       height: cropSize),
                                           pixelFormat: vImage.InterleavedFx3.self)
      
      let context = try BNNSGraph.makeContext {
          builder in
          
          let src = builder.argument(name: "source",
                                     dataType: Float.self,
                                     shape: [ -1, -1, 3])
          
          let result = src [
              BNNSGraph.Builder.SliceRange(startIndex: verticalMargin,
                                           endIndex: -verticalMargin),
              BNNSGraph.Builder.SliceRange(startIndex: horizontalMargin,
                                           endIndex: -horizontalMargin),
              BNNSGraph.Builder.SliceRange.fillAll
          ]
          
          return [result]
      }
      
      source.withBNNSTensor { src in
          destination.withBNNSTensor { dst in
              
              var args = [dst, src]
              
              print(src)
              print(dst)
              
              try! context.executeFunction(arguments: &args)
          }
      }
      
      let result = destination.makeCGImage(cgImageFormat: cgImageFormat)
    • 17:31 - Preprocessing by thresholding on mean

      let srcImage = #imageLiteral(resourceName: "birds.jpeg").cgImage(
          forProposedRect: nil,
          context: nil,
          hints: nil)!
      
      var cgImageFormat = vImage_CGImageFormat(
          bitsPerComponent: 16,
          bitsPerPixel: 16,
          colorSpace: CGColorSpaceCreateDeviceGray(),
          bitmapInfo: CGBitmapInfo(rawValue: CGBitmapInfo.byteOrder16Little.rawValue |
                                   CGBitmapInfo.floatComponents.rawValue |
                                   CGImageAlphaInfo.none.rawValue))!
      
      let source = try! vImage.PixelBuffer<vImage.Planar16F>(cgImage: srcImage,
                                                             cgImageFormat: &cgImageFormat)
      let destination = vImage.PixelBuffer<vImage.Planar16F>(size: source.size)
      
      let context = try BNNSGraph.makeContext {
          builder in
          
          let src = builder.argument(name: "source",
                                     dataType: Float16.self,
                                     shape: [-1, -1, 1])
          
          let mean = src.mean(axes: [0, 1], keepDimensions: false)
          
          let thresholded = src .> mean
          
          let result = thresholded.cast(to: Float16.self)
          
          return [result]
      }
      
      source.withBNNSTensor { src in
          destination.withBNNSTensor { dst in
              
              var args = [dst, src]
              
              try! context.executeFunction(arguments: &args)
          }
      }
      
      let result = destination.makeCGImage(cgImageFormat: cgImageFormat)
    • 19:04 - Postprocessing

      func postProcess(result: BNNSTensor, k: Int) throws -> ([Float32], [Int32]) {
          
          let context = try BNNSGraph.makeContext {
              builder in
              
              let x = builder.argument(dataType: Float32.self,
                                       shape: [-1])
              
              let softmax = x.softmax(axis: 1)
              
              let topk = softmax.topK(k, axis: 1, findLargest: true)
              
              return [topk.values, topk.indices]
          }
          
          let indices = context.allocateTensor(argument: context.argumentNames()[0],
                                               fillKnownDynamicShapes: false)!
          let values = context.allocateTensor(argument: context.argumentNames()[1],
                                              fillKnownDynamicShapes: false)!
          
          var arguments = [values, indices, result]
          
          try context.executeFunction(arguments: &arguments)
          
          return (values.makeArray(of: Float32.self), indices.makeArray(of: Int32.self))
      }
    • 21:03 - Bitcrusher in PyTorch

      import coremltools as ct
      from coremltools.converters.mil import Builder as mb
      from coremltools.converters.mil.mil import (
          get_new_symbol
      )
      
      import torch
      import torch.nn as nn
      import torch.nn.functional as F
      
      class BitcrusherModel(nn.Module):
          def __init__(self):
              super(BitcrusherModel, self).__init__()
      
          def forward(self, source, resolution, saturationGain, dryWet):
              # saturation
              destination = source * saturationGain
              destination = F.tanh(destination)
      
              # quantization
              destination = destination * resolution
              destination = torch.round(destination)
              destination = destination / resolution
      
              # mix
              destination = destination * dryWet
              destination = 1.0 - dryWet
              source = source * dryWet
              
              destination = destination + source
              
              return destination
    • 21:03 - Bitcrusher in Swift

      typealias BITCRUSHER_PRECISION = Float16
          
      let context = try! BNNSGraph.makeContext {
          builder in
          
          var source = builder.argument(name: "source",
                                        dataType: BITCRUSHER_PRECISION.self,
                                        shape: [sampleCount, 1, 1])
          
          let resolution = builder.argument(name: "resolution",
                                            dataType: BITCRUSHER_PRECISION.self,
                                            shape: [1, 1, 1])
          
          let saturationGain = builder.argument(name: "saturationGain",
                                                dataType: BITCRUSHER_PRECISION.self,
                                                shape: [1, 1, 1])
          
          var dryWet = builder.argument(name: "dryWet",
                                        dataType: BITCRUSHER_PRECISION.self,
                                        shape: [1, 1, 1])
          
          // saturation
          var destination = source * saturationGain
          destination = destination.tanh()
          
          // quantization
          
          destination = destination * resolution
          destination = destination.round()
          destination = destination / resolution
          
          // mix
          destination = destination * dryWet
          dryWet = BITCRUSHER_PRECISION(1) - dryWet
          source = source * dryWet
          
          destination = destination + source
          
          return [destination]
      }
    • 22:34 - Changing precision

      typealias BITCRUSHER_PRECISION = Float16
          
      let context = try! BNNSGraph.makeContext {
          builder in
          
          var source = builder.argument(name: "source",
                                        dataType: BITCRUSHER_PRECISION.self,
                                        shape: [sampleCount, 1, 1])
          
          let resolution = builder.argument(name: "resolution",
                                            dataType: BITCRUSHER_PRECISION.self,
                                            shape: [1, 1, 1])
          
          let saturationGain = builder.argument(name: "saturationGain",
                                                dataType: BITCRUSHER_PRECISION.self,
                                                shape: [1, 1, 1])
          
          var dryWet = builder.argument(name: "dryWet",
                                        dataType: BITCRUSHER_PRECISION.self,
                                        shape: [1, 1, 1])
          
          // saturation
          var destination = source * saturationGain
          destination = destination.tanh()
          
          // quantization
          
          destination = destination * resolution
          destination = destination.round()
          destination = destination / resolution
          
          // mix
          destination = destination * dryWet
          dryWet = BITCRUSHER_PRECISION(1) - dryWet
          source = source * dryWet
          
          destination = destination + source
          
          return [destination]
      }
    • 0:00 - Introduction
    • Le groupe Vector and Numerics d’Apple a développé BNNS, une bibliothèque d’apprentissage automatique pour l’inférence basée sur le CPU dans les apps, particulièrement utile pour le traitement de l’audio et de l’image en temps réel. BNNSGraph, introduit l’année dernière, a amélioré la vitesse, l’efficacité et la facilité d’utilisation. BNNSGraphBuilder, qui permet de créer en Swift de petits modèles et graphiques pour le pré-traitement et le post-traitement, est maintenant ajouté. Ceci est démontré par le prétraitement d’image, le post-traitement des données et la mise à jour de l’échantillon d’unité audio Bitcrusher.

    • 3:12 - Récapitulatif BNNSGraph
    • BNNSGraph est recommandé pour les tâches audio et à faible latence avec des délais en temps réel, car il permet le contrôle de la mémoire et du multithreading, améliorant ainsi les performances en temps réel. Auparavant, BNNS nécessitait le codage manuel de chaque couche, mais BNNSGraph utilise maintenant des graphes entiers en tant qu’objets. Il optimise ainsi les performances et l’efficacité énergétique en combinant des transformations mathématiques, la fusion de couches, l’élision de copie et le partage de mémoire tensorielle. BNNSGraph propose deux flux de travail principaux : l’utilisation d’un package CoreML et d’une compilation Xcode ou la définition du graphe directement en Swift pour les petits modèles avec BNNSGraphBuilder.

    • 6:15 - BNNSGraphBuilder
    • Une nouvelle API appelée BNNSGraphBuilder permet aux développeurs de créer des graphes d’opérations directement en Swift. Cela permet de créer des routines de prétraitement et de post-traitement ainsi que de petits modèles d’apprentissage automatique dans le code Swift. Les avantages incluent l’utilisation d’un langage familier, la vérification de type pendant la compilation et la possibilité de partager les valeurs d’exécution entre Swift et le graphe, ce qui améliore les performances. L’API propose également des fonctionnalités de débogage, telles que l’interrogation de tenseurs intermédiaires pour des propriétés telles que la forme et le type de données, et active la saisie automatique Xcode. Une nouvelle méthode de type, 'makeContext', convertit le code Swift en contexte réutilisable pour l’exécution de graphes. Le contexte est créé une fois au démarrage de l’app et peut ensuite être exécuté plusieurs fois, en bénéficiant d’optimisations de graphes holistiques. L’API offre un large éventail d’opérations mathématiques et logiques, ainsi que la prise en charge des primitives courantes des réseaux neuronaux telles que les opérations de multiplication matricielle, de convolution et de réduction. L’API BNNSGraphBuilder de Swift exploite un typage fort pour détecter les erreurs au moment de la compilation, garantissant ainsi l’exactitude du type de données pour les opérations de tenseurs. Ceci est démontré par la conversion automatique des types de données, tels que les entiers en FP16, ce qui évite les erreurs de compilation et améliore la fiabilité de l’app. L’API traite également les tranches de tenseur comme des références à des données existantes, optimisant ainsi l’utilisation de la mémoire. Le slicing des tenseurs s’effectue à l’aide d’indices Swift et de la nouvelle structure SliceRange, ce qui le rend plus intuitif pour les développeurs Swift. Cela permet des opérations efficaces telles que le recadrage d’image, comme le montre un exemple où une région carrée est recadrée à partir d’une photographie d’un écureuil à l’aide de tampons de pixels vImage et de la méthode 'withBNNSTensor', qui partage la mémoire pour des performances améliorées.

    • 16:58 - Utilisation de BNNSGraphBuilder
    • BNNSGraphBuilder est une puissante API Swift qui vous aide à créer des graphes d’opérations pour un prétraitement et un post-traitement efficaces des données dans les applications d’apprentissage automatique utilisant de l’audio et des images. Pour le prétraitement, utilisez l’API pour chiffrer les images, en convertissant les images à tons continus en images binaires. Vous pouvez également l’utiliser pour des tâches de post-traitement telles que l’application de fonctions softmax et d’opérations topK aux résultats des modèles ML. L’API démontre sa polyvalence en s’appliquant également aux effets audio. Elle vous permet de créer des effets audio en temps réel, comme le bitcrushing, avec des améliorations significatives des performances en utilisant une précision de 16 bits par rapport à 32 bits. BNNSGraphBuilder offre une interface de programmation conviviale, ce qui la rend accessible à un large éventail d’applications, allant des cas d’utilisation en temps réel et sensibles à la latence aux tâches ML à usage général.

Developer Footer

  • Vidéos
  • WWDC25
  • Quoi de neuf dans BNNS Graph
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • Apple Intelligence
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Downloads
    • Sample Code
    • Videos
    Open Menu Close Menu
    • Help Guides & Articles
    • Contact Us
    • Forums
    • Feedback & Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • Mini Apps Partner Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Read the latest news.
    Get the Apple Developer app.
    Copyright © 2026 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines