JavaScript Parallel Computing APIs

TypedArrays, Web Workers, WebCL und WebGL

Thomas Bergwinkl

Über mich

  • Aktives Mitglied in der Read Write Web Community Group
  • Invited Expert in der WebID W3C Incubator Group
  • Verschiedene Multimedia Projekte (z.B. Wavelet Video Codec, Raw-Entwickler)

Wieso JavaScript?

  • Plattformübergreifend
  • Ressourcensparend durch asynchrone APIs
  • Gleiche Codebasis für Client und Server
  • Reduzierter Wartungsaufwand
  • Einfache Anbindung an Web 2.0 und Web 3.0 Anwendungen

HTML5 APIs vs nativen Applikationen

  • File API
  • Web sockets
  • Web storage
  • WebRTC
  • Offline Web applications
  • Indexed Database API

Node.js Module

Node Packaged Modules, kurz npm, stellt ca. 29000 Module zur Verfügung

Performance aktueller JavaScript Engines

  • JIT Kompilierung
  • Inline Ersetzung
  • Inline Caching

Welche Möglichkeiten gibt es Binäre Daten effizient zu verwalten?

Im ECMA-262 Standard sind folgende Datentypen definiert:

Null, Boolean, String, Number, Object

Number

Number ist als Float definiert:

The Number type has exactly 18437736874454810627 (that is, 2^64-2^53+3) values, representing the double-precision 64-bit format IEEE 754 values as specified in the IEEE Standard for Binary Floating-Point Arithmetic...

Array

  • Array Elemente sind untypisiert
  • Verwaltungsoverhead je Element

String

  • Wird im Unicode Zeichensatz abgelegt
  • Kann als "ByteArray" verwendet werden (charCodeAt())

Jedoch

  • Ineffizient bei Werten fixer Länge
  • UTF-8: 1 Byte für 0-127, 2 Bytes für 128-255
  • UTF-16: 2 Bytes
  • Erschwert Optimierungen in der JavaScript Engine

Typed Arrays

ArrayBuffer API

Reservierter Speicher

[ Constructor(unsigned long length) ]
interface ArrayBuffer {
  readonly attribute unsigned long byteLength;
  ArrayBuffer slice(long begin, optional long end);
};

ArrayBufferView API

Zeiger auf einen Bereich des ArrayBuffer mit typisiertem Zugriff

interface ArrayBufferView {
  readonly attribute ArrayBuffer buffer;
  readonly attribute unsigned long byteOffset;
  readonly attribute unsigned long byteLength;
};

TypedArray API

Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array

[
  Constructor(unsigned long length),
  Constructor(TypedArray array),
  Constructor(type[] array),
  Constructor(ArrayBuffer buffer, optional unsigned long byteOffset,
      optional unsigned long length)
]
interface TypedArray {
    const unsigned long BYTES_PER_ELEMENT = element size in bytes;

    readonly attribute unsigned long length;

    getter type get(unsigned long index);
    setter void set(unsigned long index, type value);
    void set(TypedArray array, optional unsigned long offset);
    void set(type[] array, optional unsigned long offset);
    TypedArray subarray(long begin, optional long end);
};
TypedArray implements ArrayBufferView;

Beispiel

// 8-byte ArrayBuffer erstellen
var b = new ArrayBuffer(8);

// View mit Referenz auf b vom Typ Int32 erstellen
// über die gesammte Länge des ArrayBuffer
// beginnend bei Byte-Index 0 (Default Wert)
var v1 = new Int32Array(b);

// View mit Referenz auf b vom Typ Uint8 erstellen
// über die gesammte Länge des ArrayBuffer
// beginnend bei Byte Index 2
var v2 = new Uint8Array(b, 2);

// View mit Referenz auf b vom Typ Int16 erstellen
// mit der Länge 2 (Array Elemente)
// beginnend bei Byte Index 2
var v3 = new Int16Array(b, 2, 2);

und so sieht's im Speicher aus

varindex
b = 01234567
v1 = 01
v2 = 012345
v3 = 01

RawDevJS

  • Raw-Entwickler basierend auf dem C++ Qt Projekt
  • Portierung des Tiff-Parsers, Lossless JPEG Decoder mit Canvas-Viewer in 8h
  • WebGL-Viewer mit Demosaicing in weiteren 8h

Was ist zu machen?

Tiff Parser und Lossess JPEG Decoder

Demosaicing

Farbtransformation

Transformation

Architektur

Filter Chain (Canvas)

Filter Chain (WebGL)

Implementierung

  • FilterChain Klasse ruft die asynchrone filter-Funktion der übergebenen Filter Objekte auf
  • filter-Funktion wird im Konstruktor dynamisch, je nach vorhandener APIs, zugewiesen
  • WebGL besteht nur aus einem Filter um die Bilddaten nicht aus dem Grafikspeicher exportieren zu müssen

RequireJS

RequireJS wurde als Module Loader gewählt weil:

  • Browser sowie Node.js unterstützt werden
  • mit r.js ein Build System vorhanden ist
  • auch ohne Build Module schnell geladen werden (asynchron)

require-worker

Light Version von RequireJS speziell für Web Worker

  • Kleinere Worker Files nach dem Build
  • Synchrones Laden bei der Entwicklung

Debugging

  • Chrome unterstüzt "Breakpoint on start" für Worker
  • WebGL Objekte können mit dem Chrome WebGL Inspector analysiert werden

Web Worker im Browser

Firefox kann ArrayBufferViews nicht serialisieren

  • Firefox kann nur Array Buffer über MessageChannels serialisieren
  • ArrayBufferViews und TypedArrays werden manuell serialisiert (inklusive Typ, Offset und Länge)

WebCL im Browser

API des Nokia Plugins nicht aktuell

  • API des Nokia WebCL-Plugins für Firefox basiert auf älterem Stand der Spec
  • Wrapper notwendig um aktuelle API verwenden zu können

WebGL im Browser

Keine Untersütztung für 16 Bit Farbkanäle

Uint16Array wird in zwei Uint8Arrays (low/high) verteilt und im Shader-Code wieder zusammengefügt

Auch 3D Texturen sind im Standard nicht vorgesehen

3D Textur wird "aufgeklappt" und in 2D abgebildet

Web Worker unter Node.js mit webworker Modul

Startet für jeden Worker einen neuen Node Prozess und kommuniziert über Unix Sockets mit Web Socket API

  • Großer Overhead durch separaten Prozess
  • Keine Typed Array Serialisierung
  • Kein Transfer von ArrayBuffern möglich
  • Fork mit folgenden Features auf Github:
    • Typed Array (ohne Serialisierung)
    • Buffer (Node.js Datentyp für größere Binärdaten)
    • BSON Serialisierung via buffalo Modul

Web Worker unter Node.js mit webworker-threads Modul

Web Worker Modul implementiert als C++ Node.js Erweiterung

  • Worker laufen als Thread
  • Typed Array Unterstützung fehlt (Serialisierung, Transfer sowie Datentyp)

WebCL unter Node.js mit node-webcl und webcl-nodep

  • createContext Funktions benötigt Platform und DeviceType
  • Buffer erlaubt keine Offsets != 0
  • Module müssen unterschiedlich angesprochen werden

Ausblick - Verteilte Filterketten

Ausblick -Semantic Web Einbindung

Ausblick

ParallelArray

Links

http://rawdev.bergnet.org

Spezifikationen

Sonstiges