Web AI-Modelltests in Google Colab

François Beaufort
François Beaufort

Das Einrichten einer einheitlichen Testumgebung mit GPUs kann schwieriger sein als erwartet. Hier erfahren Sie, wie Sie clientseitige, browserbasierte KI-Modelle in echten Browserumgebungen testen, die skalierbar, automatisierbar und in einer bekannten standardisierten Hardwarekonfiguration sind.

In diesem Fall handelt es sich um einen echten Chrome-Browser mit Hardwareunterstützung, im Gegensatz zur Softwareemulation.

Dieser Leitfaden richtet sich an Web-KI-, Web-Gaming- oder Grafikentwickler sowie an alle, die sich für das Testen von Web-KI-Modellen interessieren.

Schritt 1: Neues Google Colab-Notebook erstellen

1. Rufen Sie colab.new auf, um ein neues Colab-Notebook zu erstellen. Sie sollte in etwa so aussehen wie in Abbildung 1. 2. Folgen Sie der Aufforderung, um sich in Ihrem Google-Konto anzumelden.
Screenshot eines neuen Colab-Notebooks
Abbildung 1: Ein neues Colab-Notebook

Schritt 2: Verbindung zu einem T4-GPU-fähigen Server herstellen

  1. Klicken Sie oben rechts im Notizbuch auf Verbinden .
  2. Wählen Sie Laufzeittyp ändern aus:
    Ein Nahaufnahme-Screenshot, der die Schritte zum Ändern der Laufzeit zeigt
    Abbildung 2. Ändern Sie die Laufzeit in der Colab-Benutzeroberfläche.
  3. Wählen Sie im modalen Fenster T4 GPU als Hardwarebeschleuniger aus. Wenn Sie eine Verbindung herstellen, verwendet Colab eine Linux-Instanz mit einer angeschlossenen NVIDIA T4-GPU.
    Screenshot des Moduls „Laufzeittyp ändern“
    Abbildung 3: Wählen Sie unter „Hardwarebeschleuniger“ die Option T4-GPU aus.
  4. Klicken Sie auf Speichern.
  5. Klicken Sie auf die Schaltfläche Verbinden, um eine Verbindung zu Ihrer Laufzeit herzustellen. Nach einiger Zeit wird die Schaltfläche mit einem grünen Häkchen und Grafiken zur RAM- und Laufwerknutzung angezeigt. Dies bedeutet, dass ein Server mit der erforderlichen Hardware erstellt wurde.

Sehr gut. Sie haben gerade einen Server mit einer angehängten GPU erstellt.

Schritt 3: Die richtigen Treiber und Abhängigkeiten installieren

  1. Kopieren Sie die folgenden beiden Codezeilen und fügen Sie sie in die erste Codezelle des Notebooks ein. In einer Colab-Umgebung wird der Befehlszeilenausführung ein Ausrufezeichen vorangestellt.

    !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. Klicken Sie neben der Zelle auf , um den Code auszuführen.

    Screenshot eines neuen Colab-Notebooks
    Abbildung 4

  3. Prüfen Sie nach Abschluss der Ausführung des Codes, ob nvidia-smi etwas Ähnliches wie den folgenden Screenshot ausgegeben hat. So können Sie bestätigen, dass tatsächlich eine GPU angeschlossen ist und auf Ihrem Server erkannt wird. Möglicherweise müssen Sie in den Protokollen nach oben scrollen, um diese Ausgabe zu sehen.

    Abbildung 5: Suchen Sie nach der Ausgabe, die mit „NVIDIA-SMI“ beginnt.

Schritt 4: Headless Chrome verwenden und automatisieren

  1. Klicken Sie auf die Schaltfläche Code, um eine neue Codezelle hinzuzufügen.
  2. Sie können dann benutzerdefinierten Code schreiben, um ein Node.js-Projekt mit Ihren bevorzugten Parametern aufzurufen, oder einfach google-chrome-stable direkt in der Befehlszeile aufrufen. Wir haben Beispiele für beides.

Teil A: Headless Chrome direkt in der Befehlszeile verwenden

# 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

Im Beispiel haben wir die resultierende PDF-Datei unter /content/gpu.pdf gespeichert. Maximieren Sie dazu die Inhalte . Klicken Sie dann auf , um die PDF-Datei auf Ihren lokalen Computer herunterzuladen.

Screenshot eines neuen Colab-Notebooks
Abbildung 6: In diesem Screenshot der Colab-Benutzeroberfläche sehen Sie, wie Sie die PDF-Datei herunterladen.

Teil B: Chrome mit Puppeteer steuern

Wir haben ein minimalistisches Beispiel zur Steuerung von Headless Chrome mit Puppeteer zusammengestellt, das so ausgeführt werden kann:

# 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

Im jPuppet-Beispiel können wir ein Node.js-Script aufrufen, um einen Screenshot zu erstellen. Aber wie funktioniert das? Sehen Sie sich diese Schritt-für-Schritt-Anleitung zum Node.js-Code in jPuppet.js an.

jPuppet.js-Node-Code – Aufschlüsselung

Importieren Sie zuerst Puppeteer. So können Sie Chrome per Node.js aus der Ferne steuern:

import puppeteer from 'puppeteer';

Prüfen Sie als Nächstes, welche Befehlszeilenargumente an die Node-Anwendung übergeben wurden. Das dritte Argument muss festgelegt sein. Es stellt eine URL dar, zu der Sie weitergeleitet werden sollen. Sie müssen hier das dritte Argument prüfen, da die ersten beiden Argumente Node selbst und das Script aufrufen, das wir ausführen. Das dritte Element enthält tatsächlich den ersten Parameter, der an das Node-Programm übergeben wird:

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

Definieren Sie nun eine asynchrone Funktion namens runWebpage(). Dadurch wird ein Browserobjekt erstellt, das mit den Befehlszeilenargumenten konfiguriert ist, um das Chrome-Binärprogramm so auszuführen, dass WebGL und WebGPU wie unter WebGPU- und WebGL-Unterstützung aktivieren beschrieben funktionieren.

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'
      ]
  });

Erstellen Sie ein neues Browserseitenobjekt, mit dem Sie später eine beliebige URL aufrufen können:

const page = await browser.newPage();

Fügen Sie dann einen Ereignis-Listener hinzu, der auf console.log-Ereignisse wartet, wenn auf der Webseite JavaScript ausgeführt wird. So können Sie Nachrichten in der Node-Befehlszeile protokollieren und den Konsolentext auf einen bestimmten Begriff (in diesem Fall captureAndEnd) prüfen, der einen Screenshot auslöst und dann den Browserprozess in Node beendet. Dies ist nützlich für Webseiten, auf denen einige Vorgänge ausgeführt werden müssen, bevor ein Screenshot aufgenommen werden kann, und die eine nicht deterministische Ausführungszeit haben.

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

Geben Sie der Seite dann den Befehl, die angegebene URL aufzurufen, und machen Sie einen ersten Screenshot, sobald die Seite geladen ist.

Wenn Sie einen Screenshot von chrome://gpu erstellen möchten, können Sie die Browsersitzung sofort schließen, anstatt auf eine Konsolenausgabe zu warten, da diese Seite nicht durch Ihren eigenen Code gesteuert wird.

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

package.json ändern

Sie haben vielleicht bemerkt, dass wir am Anfang der Datei jPuppet.js eine Importanweisung verwendet haben. In package.json müssen die Typwerte auf module festgelegt sein. Andernfalls erhalten Sie die Fehlermeldung, dass das Modul ungültig ist.

 {
    "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"
}

Das war schon alles. Mit Puppeteer können Sie Chrome programmatisch einfacher verknüpfen.

Erfolg

Wir können jetzt bestätigen, dass der TensorFlow.js Fashion MNIST-Klassifikator eine Hose in einem Bild korrekt erkennen kann, wobei die clientseitige Verarbeitung im Browser mit der GPU erfolgt.

Sie können sie für alle clientseitigen GPU-basierten Arbeitslasten verwenden, von Modellen für maschinelles Lernen bis hin zu Grafik- und Spieletests.

Screenshot eines neuen Colab-Notebooks
Abbildung 7: Erfolgreiche Erfassung eines GPU-beschleunigten TensorFlow.js-Modells, das Kleidung clientseitig im Browser in Echtzeit erkennen kann

Ressourcen

Setzen Sie ein Sternchen im GitHub-Repository, um zukünftige Updates zu erhalten.