概述
SIMD是“Single Instruction/Multiple Data”的缩写,意为“单指令,多数据”。它是JavaScript操作CPU对应指令的接口,你可以看做这是一种不同的运算执行模式。与它相对的是SISD(“Single Instruction/Single Data”),即“单指令,单数据”。
SIMD的含义是使用一个指令,完成多个数据的运算;SISD的含义是使用一个指令,完成单个数据的运算,这是JavaScript的默认运算模式。显而易见,SIMD的执行效率要高于SISD,所以被广泛用于3D图形运算、物理模拟等运算量超大的项目之中。
为了理解SIMD,请看下面的例子。
|
|
上面代码中,数组a
和b
的对应成员相加,结果放入数组c
。它的运算模式是依次处理每个数组成员,一共有四个数组成员,所以需要运算4次。
如果采用SIMD模式,只要运算一次就够了。
|
|
上面代码之中,数组a
和b
的四个成员的各自相加,只用一条指令就完成了。因此,速度比上一种写法提高了4倍。
一次SIMD运算,可以处理多个数据,这些数据被称为“通道”(lane)。上面代码中,一次运算了四个数据,因此就是四个通道。
SIMD通常用于矢量运算。
|
|
上面代码中,v
和w
是两个多元矢量。它们的加运算,在SIMD下是一个指令、而不是n个指令完成的,这就大大提高了效率。这对于3D动画、图像处理、信号处理、数值处理、加密等运算是非常重要的。
总得来说,SIMD是数据并行处理(parallelism)的一种手段。
数据类型
SIMD提供多种数据类型。
- Float32x4:四个32位浮点数
- Float64x2:两个64位浮点数
- Int32x4:四个32位整数
- Int16x8:八个16位整数
- Int8x16:十六个8位整数
- Uint32x4:四个无符号的32位整数
- Uint16x8:八个无符号的16位整数
- Uint8x16:十六个无符号的8位整数
- Bool32x4:四个32位布尔值
- Bool16x8:八个16位布尔值
- Bool8x16:十六个8位布尔值
- Bool64x2:两个64位布尔值
每种数据类型都是一个方法,可以传入参数,生成对应的值。
|
|
上面代码中,变量a
就是一个128位、包含四个32位浮点数的值。
注意,这些数据类型方法都不是构造函数,前面不能加new
,否则会报错。
|
|
每种数据类型都有一系列运算符,下面是其中的一些。
- float32x4.abs(v):返回
v
的绝对值 - float32x4.neg(v):返回
v
的绝对值的负值 - float32x4.sqrt(v):返回
v
的平方根 - float32x4.add(v, w):
v
和w
对应项的相加 - float32x4.mul(v, w):
v
和w
对应项的相乘 - float32x4.equal(v, w):比较
v
和w
对应项是否相等,返回的布尔值组成一个uint32x4
的值
下面是一个add
运算符的例子。
|
|
此外,每种数据类型还有操作方法。
getAt
方法返回指定位置的值。
|
|
zero
方法可以将SIMD值清零。
|
|
上面代码中,变量b
包含的四个32位浮点数全部是0.0。
shuffle
方法根据指定模式,重新生成一个SIMD值。
|
|
下面是一个求平均值的例子。
|
|
二进制数组
SIMD可以与二进制数组结合,生成数组实例。
|
|
下面是一些应用的例子。
|
|
参考链接
- MDN, SIMD
- TC39, ECMAScript SIMD
- Axel Rauschmayer, JavaScript gains support for SIMD