By Ivan Jibaja, Senior Software Engineer, Intel Corporation

Executive Summary

This paper introduces JavaScript language extensions, which enable SIMD programming. First, it explains SIMD, its uses, and the currently implemented types and operations made available. Second, it shows some common techniques used when writing SIMD programs and an example. The SIMD extensions run everywhere JS runs without the need for any external plugins.

Introduction

Modern microprocessors utilize parallelism to deliver high performance within a constrained power budget. Through the class of Single Instruction, Multiple Data (SIMD) instructions, processors exploit data parallelism in applications by simultaneous processing the same operation on multiple data items, delivering major performance improvements at high power-efficiency. SIMD is particularly applicable to computations in image/audio/video processing including computer vision and perceptual computing. Thanks to its superior power efficiency and excellent performance boost, SIMD plays an increasing role in modern systems. However, it wasn’t possible to utilize these powerful SIMD instructions directly from JavaScript.

JavaScript is the programming language used for programs running in web browsers and for hybrid HTML5 applications running on top of a web-runtime. JavaScript has been called the assembly language of the web platform, and as such it should enable use of SIMD instructions in the underlying hardware.

Through collaboration with Mozilla and Google, Intel is bringing SIMD to JavaScript by expanding the language specification. By using the SIMD numeric types that we are proposing, it is now possible to develop a whole new class of compute-intensive applications such as games and image/video processing in plain JavaScript without the need of additional plugins or non-portable native code. If any of the proposed SIMD types are used, your application will run a lot faster and more power efficiently on the platforms that have SIMD support.

SIMD

What is SIMD?

As mentioned above, SIMD stands for Single Instruction, Multiple Data. SIMD allows the same operations to be performed on multiple data points simultaneously, which exploits data level parallelism. Today, a large number of processors have instructions for SIMD operations. SIMD operations can largely benefit applications in fields like 3D graphics and audio/video processing in multimedia applications.

SIMD programming

A SIMD value has multiple lanes; for this example we are using a SIMD vector of length 4. For a SIMD vector of length 4, the lanes are named x, y, z, and w. The figure below shows a use example for a SIMD addition operation. Instead of having to perform 4 separate addition operations on pairs of 4 separate scalars, SIMD allows you to add all of them at the same time by performing the operation on all 4 lanes simultaneously. By requiring fewer operations to process a particular data set use of SIMD instructions yields higher performance and energy efficiency compared to scalar operations.

SIMD in JavaScript

Application Programming Interface (API)

The SIMD extensions are implemented in the SIMD object. Here’s a simple example performing an addition of 2 float32x4 values:

These lines of code result in the variable c being a SIMD vector that holds the values [6.0, 8.0, 10.0, 12.0]

Types

SIMD.float32x4: vector with length 4 where each lane holds a IEEE-754 32-bit single-precision floating point value

SIMD.int32x4: vector with length 4 where each lane holds a 32-bit signed integer value

Float32x4Array: A typed array holding SIMD.float32x4 values as packed binary data

Int32x4Array: A typed array holding SIMD.int32x4 values as packed binary data

SIMD data types in JavaScript are immutable; this means that it is not possible to alter an instance directly. Despite the fact that a SIMD data type is organized as having 4 lanes holding distinct values, a SIMD data type should not be used as a list of the mentioned 4 values. Instead, the code should perform operations on multiple immutable SIMD data types that would create new immutable SIMD objects. The arrays can be aliased using other typed arrays and the values can be interpreted differently by changing a DataView.

Constructors

splat creates instances of the specified SIMD data type with all lanes set to s

Lane Accessors

The following accessors are used to read values of the individual lanes:

Individual values are read using the getters x, y, z, and w. For example:

Lane Mutators

All SIMD vectors in JavaScript are immutable so you cannot change the value in a particular lane. However, the following mutators are used to create a new instance of a SIMD vector with an individual value changed:



For example:

Operations

For the complete and up to date API see the current polyfill source listed in the reference section.

Performance analysis

The following figure presents measurements of benchmark applications whose core computation is amenable to SIMD optimizations.

A consistent 3.5x speedup of these JavaScript applications is achieved by the use of SIMD. For a more visual demo, the following screenshots use the Mandelbrot kernel in our benchmark to calculate the Mandelbrot set dynamically as we zoom in and out. In this scenario, JavaScript performance is critical as it is a limiting factor to the frames per second that can be computed.

Speedup in Firefox browser

Speedup in Chromium browser

Sample Code

The following code is extracted from the visual Mandelbrot benchmark shown above. It computes the iteration count associated with a pixel. That iteration count is mapped to a color visualization.

Scalar version

SIMD version

References