Tests de modèles d'IA Web dans Google Colab

François Beaufort
François Beaufort

Configurer un environnement de test cohérent avec des GPU peut s'avérer plus difficile que prévu. Voici la procédure à suivre pour tester des modèles d'IA côté client basés sur un navigateur dans de vrais environnements de navigateur, tout en étant évolutifs, automatisables et dans une configuration matérielle standardisée connue.

Dans ce cas, le navigateur Chrome est un vrai navigateur Chrome compatible avec le matériel, et non une émulation logicielle.

Que vous soyez un développeur d'IA Web, de jeux Web ou de graphismes, ou que vous soyez intéressé par le test de modèles d'IA Web, ce guide est pour vous.

Étape 1: Créez un notebook Google Colab

1. Accédez à colab.new pour créer un notebook Colab. Le résultat doit ressembler à la figure 1. 2. Suivez les instructions pour vous connecter à votre compte Google.
Capture d'écran d'un nouveau Colab
Figure 1: Nouveau notebook Colab

Étape 2: Connectez-vous à un serveur compatible GPU T4

  1. Cliquez sur Connect (Connecter) en haut à droite du notebook.
  2. Sélectionnez Modifier le type d'exécution :
    Capture d'écran en gros plan montrant les étapes à suivre pour modifier l'environnement d'exécution.
    Figure 2. Modifiez l'environnement d'exécution dans l'interface Colab.
  3. Dans la fenêtre modale, sélectionnez T4 GPU (GPU T4) comme accélérateur matériel. Lorsque vous vous connectez, Colab utilise une instance Linux avec un GPU NVIDIA T4 connecté.
    Capture d'écran du module "Modifier le type d'exécution"
    Figure 3: Sous "Accélérateur matériel", sélectionnez GPU T4.
  4. Cliquez sur Enregistrer.
  5. Cliquez sur le bouton Connecter pour vous connecter à votre environnement d'exécution. Après un certain temps, une coche verte s'affiche sur le bouton, ainsi que des graphiques d'utilisation de la RAM et du disque. Ce message indique qu'un serveur a bien été créé avec le matériel requis.

Bravo ! Vous venez de créer un serveur avec un GPU connecté.

Étape 3: Installez les pilotes et les dépendances appropriés

  1. Copiez et collez les deux lignes de code suivantes dans la première cellule de code du notebook. Dans un environnement Colab, un point d'exclamation est ajouté devant l'exécution de la ligne de commande.

    !git clone https://github.com/jasonmayes/headless-chrome-nvidia-t4-gpu-support.git
    !cd headless-chrome-nvidia-t4-gpu-support && chmod +x scriptyMcScriptFace.sh && ./scriptyMcScriptFace.sh
    
    # Update, install correct drivers, and remove the old ones.
    apt-get install -y vulkan-tools libnvidia-gl-525
    
    # Verify NVIDIA drivers can see the T4 GPU and that vulkan is working correctly.
    nvidia-smi
    vulkaninfo --summary
    
    # Now install latest version of Node.js
    npm install -g n
    n lts
    node --version
    npm --version
    
    # Next install Chrome stable
    curl -fsSL https://dl.google.com/linux/linux_signing_key.pub | sudo gpg --dearmor -o /usr/share/keyrings/googlechrom-keyring.gpg
    echo "deb [arch=amd64 signed-by=/usr/share/keyrings/googlechrom-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list
    sudo apt update
    sudo apt install -y google-chrome-stable
    
    # Start dbus to avoid warnings by Chrome later.
    export DBUS_SESSION_BUS_ADDRESS="unix:path=/var/run/dbus/system_bus_socket"
    /etc/init.d/dbus start
    
  2. Cliquez sur à côté de la cellule pour exécuter le code.

    Capture d'écran d'un nouveau Colab
    Figure 4.

  3. Une fois l'exécution du code terminée, vérifiez que nvidia-smi a imprimé un résultat semblable à la capture d'écran suivante pour vérifier qu'un GPU est bien associé et qu'il est reconnu sur votre serveur. Vous devrez peut-être faire défiler les journaux plus tôt pour afficher cette sortie.

    Figure 5: Recherchez le résultat commençant par "NVIDIA-SMI".

Étape 4: Utilisez et automatisez le mode sans interface graphique de Chrome

  1. Cliquez sur le bouton Code pour ajouter une cellule de code.
  2. Vous pouvez ensuite écrire votre code personnalisé pour appeler un projet Node.js avec les paramètres de votre choix (ou simplement appeler google-chrome-stable directement dans la ligne de commande). Nous avons des exemples pour les deux éléments suivants.

Partie A: Utiliser Chrome sans interface graphique directement dans la ligne de commande

# Directly call Chrome to dump a PDF of WebGPU testing page
# and store it in /content/gpu.pdf
!google-chrome-stable \
--no-sandbox \
--headless=new \
--use-angle=vulkan \
--enable-features=Vulkan \
--disable-vulkan-surface \
--enable-unsafe-webgpu \
--print-to-pdf=/content/gpu.pdf https://webgpureport.org

Dans l'exemple, nous avons stocké la capture PDF obtenue dans /content/gpu.pdf. Pour afficher ce fichier, développez le contenu . Cliquez ensuite sur pour télécharger le fichier PDF sur votre ordinateur local.

Capture d'écran d'un nouveau Colab
Figure 6: Regardez les étapes pour télécharger le fichier PDF dans cette capture d'écran de l'interface Colab.

Partie B: Commander Chrome avec Puppeteer

Nous avons fourni un exemple minimaliste utilisant Puppeteer pour contrôler Headless Chrome. Il peut être exécuté comme suit:

# Call example node.js project to perform any task you want by passing
# a URL as a parameter
!node headless-chrome-nvidia-t4-gpu-support/examples/puppeteer/jPuppet.js chrome://gpu

Dans l'exemple jPuppet, nous pouvons appeler un script Node.js pour créer une capture d'écran. Mais comment cela fonctionne-t-il ? Regardez cette présentation du code Node.js dans jPuppet.js.

Répartition du code de nœud jPuppet.js

Commencez par importer Puppeteer. Cela vous permet de contrôler à distance Chrome avec Node.js:

import puppeteer from 'puppeteer';

Vérifiez ensuite quels arguments de ligne de commande ont été transmis à l'application Node. Assurez-vous que le troisième argument est défini. Il représente une URL à laquelle accéder. Vous devez examiner le troisième argument ici, car les deux premiers arguments appellent Node lui-même et le script que nous exécutons. Le troisième élément contient en fait le premier paramètre transmis au programme Node.js:

const url = process.argv[2];
if (!url) {
  throw "Please provide a URL as the first argument";
}

Définissez maintenant une fonction asynchrone nommée runWebpage(). Cela crée un objet de navigateur configuré avec les arguments de ligne de commande pour exécuter le binaire Chrome de la manière dont nous avons besoin pour que WebGL et WebGPU fonctionnent, comme décrit dans la section Activer la prise en charge de WebGPU et WebGL.

async function runWebpage() {
  const browser = await puppeteer.launch({
    headless: 'new',
    args:  [
        '--no-sandbox',
        '--headless=new',
        '--use-angle=vulkan',
        '--enable-features=Vulkan',
        '--disable-vulkan-surface',
        '--enable-unsafe-webgpu'
      ]
  });

Créez un objet "page de navigateur" que vous pourrez ensuite utiliser pour accéder à n'importe quelle URL:

const page = await browser.newPage();

Ajoutez ensuite un écouteur d'événements pour écouter les événements console.log lorsque la page Web exécute JavaScript. Cela vous permet de consigner les messages sur la ligne de commande du nœud et d'inspecter le texte de la console à la recherche d'une expression spéciale (dans ce cas, captureAndEnd) qui déclenche une capture d'écran et met fin au processus du navigateur dans Node. Cela est utile pour les pages Web qui doivent effectuer une certaine quantité de travail avant de pouvoir effectuer une capture d'écran et dont la durée d'exécution n'est pas déterministe.

page.on('console', async function(msg) {
  console.log(msg.text());
  if (msg.text() === 'captureAndEnd') {
    await page.screenshot({ path: '/content/screenshotEnd.png' });
    await browser.close();
  }
});

Enfin, commandez la page pour accéder à l'URL spécifiée et récupérez une capture d'écran initiale une fois la page chargée.

Si vous choisissez de faire une capture d'écran de chrome://gpu, vous pouvez fermer immédiatement la session du navigateur au lieu d'attendre le résultat de la console, car cette page n'est pas contrôlée par votre propre code.

  await page.goto(url,  { waitUntil: 'networkidle2' });
  await page.screenshot({path: '/content/screenshot.png'});
  if (url === 'chrome://gpu') {
    await browser.close();
  }
}
runWebpage();

Modifier package.json

Vous avez peut-être remarqué que nous utilisions une instruction d'importation au début du fichier jPuppet.js. Votre package.json doit définir les valeurs de type sur module, sinon vous recevrez une erreur indiquant que le module n'est pas valide.

 {
    "dependencies":  {
      "puppeteer": "*"
    },
    "name": "content",
    "version": "1.0.0",
    "main": "jPuppet.js",
    "devDependencies": {},
    "keywords": [],
    "type": "module",
    "description": "Node.js Puppeteer application to interface with headless Chrome with GPU support to capture screenshots and get console output from target webpage"
}

C'est aussi simple que cela. L'utilisation de Puppeteer facilite l'interface avec Chrome de manière programmatique.

Réussi

Nous pouvons maintenant vérifier que le classificateur MNIST TensorFlow.js Fashion peut reconnaître correctement un pantalon dans une image, avec un traitement côté client dans le navigateur à l'aide du GPU.

Vous pouvez l'utiliser pour toutes les charges de travail basées sur des GPU côté client, des modèles de machine learning aux tests de graphismes et de jeux.

Capture d'écran d'un nouveau Colab
Figure 7: Capture réussie d'un modèle TensorFlow.js accéléré par GPU, capable de reconnaître le côté client de vêtements dans le navigateur en temps réel

Ressources

Ajoutez une étoile dans le dépôt GitHub pour recevoir les prochaines mises à jour.