blob: d376b9183668dfcb2a8ff60428c6651365c9445e [file]
// 4x4 matrix multiplication
// Author: John McCutchan
(function () {
// Kernel configuration
var kernelConfig = {
kernelName: "MatrixMultiplication",
kernelInit: init,
kernelCleanup: cleanup,
kernelSimd: simdMultiply,
kernelNonSimd: multiply,
kernelIterations: 1000
};
// Hook up to the harness
benchmarks.add(new Benchmark(kernelConfig));
// Benchmark data, initialization and kernel functions
var T1 = new Float32Array(16);
var T2 = new Float32Array(16);
var Out = new Float32Array(16);
var T1x = new Float32Array(16);
var T2x = new Float32Array(16);
var Outx = new Float32Array(16);
function equals(A, b) {
return (A[0] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 0), 0)) &&
(A[1] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 0), 1)) &&
(A[2] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 0), 2)) &&
(A[3] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 0), 3)) &&
(A[4] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 4), 0)) &&
(A[5] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 4), 1)) &&
(A[6] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 4), 2)) &&
(A[7] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 4), 3)) &&
(A[8] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 8), 0)) &&
(A[9] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 8), 1)) &&
(A[10] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 8), 2)) &&
(A[11] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 8), 3)) &&
(A[12] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 12), 0)) &&
(A[13] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 12), 1)) &&
(A[14] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 12), 2)) &&
(A[15] == SIMD.Float32x4.extractLane(SIMD.Float32x4.load(b, 12), 3));
}
function init() {
T1[0] = 1.0;
T1[5] = 1.0;
T1[10] = 1.0;
T1[15] = 1.0;
T2[0] = 2.0;
T2[5] = 2.0;
T2[10] = 2.0;
T2[15] = 2.0;
SIMD.Float32x4.store(T1x, 0, SIMD.Float32x4(1.0, 0.0, 0.0, 0.0));
SIMD.Float32x4.store(T1x, 4, SIMD.Float32x4(0.0, 1.0, 0.0, 0.0));
SIMD.Float32x4.store(T1x, 8, SIMD.Float32x4(0.0, 0.0, 1.0, 0.0));
SIMD.Float32x4.store(T1x, 12, SIMD.Float32x4(0.0, 0.0, 0.0, 1.0));
SIMD.Float32x4.store(T2x, 0, SIMD.Float32x4(2.0, 0.0, 0.0, 0.0));
SIMD.Float32x4.store(T2x, 4, SIMD.Float32x4(0.0, 2.0, 0.0, 0.0));
SIMD.Float32x4.store(T2x, 8, SIMD.Float32x4(0.0, 0.0, 2.0, 0.0));
SIMD.Float32x4.store(T2x, 12, SIMD.Float32x4(0.0, 0.0, 0.0, 2.0));
multiply(1);
simdMultiply(1);
return equals(T1, T1x) && equals(T2, T2x) && equals(Out, Outx);
}
function cleanup() {
return init(); // Sanity checking before and after are the same
}
function multiply(n) {
for (var i = 0; i < n; i++) {
var a00 = T1[0];
var a01 = T1[1];
var a02 = T1[2];
var a03 = T1[3];
var a10 = T1[4];
var a11 = T1[5];
var a12 = T1[6];
var a13 = T1[7];
var a20 = T1[8];
var a21 = T1[9];
var a22 = T1[10];
var a23 = T1[11];
var a30 = T1[12];
var a31 = T1[13];
var a32 = T1[14];
var a33 = T1[15];
var b0 = T2[0];
var b1 = T2[1];
var b2 = T2[2];
var b3 = T2[3];
Out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
Out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
Out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
Out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = T2[4];
b1 = T2[5];
b2 = T2[6];
b3 = T2[7];
Out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
Out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
Out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
Out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = T2[8];
b1 = T2[9];
b2 = T2[10];
b3 = T2[11];
Out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
Out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
Out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
Out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = T2[12];
b1 = T2[13];
b2 = T2[14];
b3 = T2[15];
Out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
Out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
Out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
Out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
}
}
function simdMultiply(n) {
for (var i = 0; i < n; i++) {
var a0 = SIMD.Float32x4.load(T1x, 0);
var a1 = SIMD.Float32x4.load(T1x, 4);
var a2 = SIMD.Float32x4.load(T1x, 8);
var a3 = SIMD.Float32x4.load(T1x, 12);
var b0 = SIMD.Float32x4.load(T2x, 0);
SIMD.Float32x4.store(Outx, 0,
SIMD.Float32x4.add(
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b0, 0, 0, 0, 0), a0),
SIMD.Float32x4.add(
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b0, 1, 1, 1, 1), a1),
SIMD.Float32x4.add(
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b0, 2, 2, 2, 2), a2),
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b0, 3, 3, 3, 3), a3)))));
var b1 = SIMD.Float32x4.load(T2x, 4);
SIMD.Float32x4.store(Outx, 4,
SIMD.Float32x4.add(
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b1, 0, 0, 0, 0), a0),
SIMD.Float32x4.add(
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b1, 1, 1, 1, 1), a1),
SIMD.Float32x4.add(
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b1, 2, 2, 2, 2), a2),
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b1, 3, 3, 3, 3), a3)))));
var b2 = SIMD.Float32x4.load(T2x, 8);
SIMD.Float32x4.store(Outx, 8,
SIMD.Float32x4.add(
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b2, 0, 0, 0, 0), a0),
SIMD.Float32x4.add(
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b2, 1, 1, 1, 1), a1),
SIMD.Float32x4.add(
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b2, 2, 2, 2, 2), a2),
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b2, 3, 3, 3, 3), a3)))));
var b3 = SIMD.Float32x4.load(T2x, 12);
SIMD.Float32x4.store(Outx, 12,
SIMD.Float32x4.add(
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b3, 0, 0, 0, 0), a0),
SIMD.Float32x4.add(
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b3, 1, 1, 1, 1), a1),
SIMD.Float32x4.add(
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b3, 2, 2, 2, 2), a2),
SIMD.Float32x4.mul(SIMD.Float32x4.swizzle(b3, 3, 3, 3, 3), a3)))));
}
}
} ());