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 être 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 des environnements de navigateurs réels, tout en étant évolutifs, automatisables et dans une configuration matérielle standardisée connue.

Dans ce cas, le navigateur est un véritable navigateur Chrome avec prise en charge matérielle, par opposition à l'émulation logicielle.

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

Étape 1: Créer un notebook Google Colab

1. Accédez à colab.new pour créer un notebook Colab. Il 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 avec GPU T4

  1. Cliquez sur Connecter en haut à droite du bloc-notes.
  2. Sélectionnez Modifier le type d'environnement d'exécution :
    Capture d'écran détaillée 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 GPU T4 comme accélérateur matériel. Lorsque vous vous connectez, Colab utilise une instance Linux avec un GPU NVIDIA T4 associé.
    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 Se connecter pour vous connecter à votre environnement d'exécution. Au bout d'un certain temps, une coche verte s'affiche sur le bouton, ainsi que des graphiques sur l'utilisation de la RAM et du disque. Cela signifie qu'un serveur a bien été créé avec le matériel requis.

Bravo, vous venez de créer un serveur avec un GPU associé.

É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, l'exécution de la ligne de commande est précédée d'un point d'exclamation.

    !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é quelque chose de semblable à la capture d'écran suivante pour vous assurer que vous avez bien un GPU connecté et qu'il est reconnu sur votre serveur. Vous devrez peut-être faire défiler les journaux vers le début pour afficher cette sortie.

    Figure 5: Recherchez la sortie commençant par "NVIDIA-SMI".

Étape 4: Utiliser et automatiser Chrome sans interface utilisateur

  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 vos paramètres préférés (ou simplement appeler google-chrome-stable directement dans la ligne de commande). Nous avons des exemples pour les deux cas suivants.

Partie A: Utiliser Chrome sans interface utilisateur 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: Suivez la procédure de téléchargement du 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 Chrome sans interface graphique que vous pouvez exécuter 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 ? Consultez ce tutoriel sur le code Node.js dans jPuppet.js.

Décomposition du code Node de jPuppet.js

Commencez par importer Puppeteer. Vous pouvez ainsi contrôler Chrome à distance avec Node.js:

import puppeteer from 'puppeteer';

Vérifiez ensuite les arguments de ligne de commande transmis à l'application Node. Assurez-vous que le troisième argument est défini, ce qui représente une URL à laquelle accéder. Vous devez inspecter 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 réalité le premier paramètre transmis au programme Node:

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 de page de navigateur que vous pourrez utiliser ultérieurement 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 des messages sur la ligne de commande Node et d'inspecter le texte de la console à la recherche d'une phrase spéciale (dans ce cas, captureAndEnd) qui déclenche une capture d'écran, puis met fin au processus du navigateur dans Node. Cette méthode est utile pour les pages Web qui doivent effectuer une certaine quantité de travail avant de pouvoir prendre 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, demandez à la page d'accéder à l'URL spécifiée et prenez une capture d'écran initiale une fois la page chargée.

Si vous choisissez de prendre une capture d'écran de chrome://gpu, vous pouvez fermer la session du navigateur immédiatement au lieu d'attendre une sortie de 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 avons utilisé 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 un message d'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 par programmation.

Opération réussie

Nous pouvons maintenant vérifier que le classificateur Fashion MNIST TensorFlow.js peut correctement reconnaître 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 côté client basées sur GPU, des modèles de machine learning aux tests de graphiques 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 des vêtements côté client dans le navigateur en temps réel

Ressources

Ajoutez une étoile au dépôt GitHub pour recevoir les futures mises à jour.