@tensorflow/tfjs-backend-wasm
Version:
This package adds a WebAssembly backend to TensorFlow.js. It currently supports the following models from our [models](https://github.com/tensorflow/tfjs-models) repo: - BlazeFace - BodyPix - CocoSSD - Face landmarks detection - HandPose - KNN classifier
113 lines • 17.2 kB
JavaScript
/**
* @license
* Copyright 2019 Google LLC. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================================
*/
import { Slice, slice_util, util } from '@tensorflow/tfjs-core';
import { sliceImplCPU } from '../kernel_utils/shared';
export function slice(args) {
const { inputs: { x }, attrs: { begin, size }, backend } = args;
const [begin_, size_] = slice_util.parseSliceParams(x, begin, size);
const isContinous = slice_util.isSliceContinous(x.shape, begin_, size_);
const xVals = backend.readSync(x.dataId);
const out = backend.makeOutput(size_, x.dtype);
const xStrides = util.computeStrides(x.shape);
const outData = backend.dataIdMap.get(out.dataId);
if (isContinous) {
const flatOffset = slice_util.computeFlatOffset(begin_, xStrides);
if (x.dtype === 'string') {
outData.stringBytes =
xVals
.slice(flatOffset, flatOffset + util.sizeFromShape(size_));
}
else {
const outVals = backend.typedArrayFromHeap(out);
outVals.set(xVals
.subarray(flatOffset, flatOffset + util.sizeFromShape(size_)));
}
return out;
}
if (x.dtype === 'string') {
const res = sliceImplCPU(xVals, begin_, size_, x.shape, x.dtype);
outData.stringBytes = res;
return out;
}
const outVals = backend.typedArrayFromHeap(out);
const rank = x.shape.length;
if (rank === 2) {
slice2d(xVals, xStrides[0], outVals, begin_, size_);
}
else if (rank === 3) {
slice3d(xVals, xStrides[0], xStrides[1], outVals, begin_, size_);
}
else if (rank === 4) {
slice4d(xVals, xStrides[0], xStrides[1], xStrides[2], outVals, begin_, size_);
}
else {
const res = sliceImplCPU(xVals, begin_, size_, x.shape, x.dtype);
outVals.set(res);
}
return out;
}
function slice2d(xVals, xStride, outVals, begin, size) {
let outOffset = 0;
const beginI = begin[0];
const beginJ = begin[1];
const endI = beginI + size[0];
for (let i = beginI; i < endI; i++) {
const xOffset = i * xStride + beginJ;
outVals.set(xVals.subarray(xOffset, xOffset + size[1]), outOffset);
outOffset += size[1];
}
}
function slice3d(xVals, xStride1, xStride2, outVals, begin, size) {
let outOffset = 0;
const beginI = begin[0];
const beginJ = begin[1];
const beginK = begin[2];
const endI = beginI + size[0];
const endJ = beginJ + size[1];
for (let i = beginI; i < endI; i++) {
for (let j = beginJ; j < endJ; j++) {
const xOffset = i * xStride1 + j * xStride2 + beginK;
outVals.set(xVals.subarray(xOffset, xOffset + size[2]), outOffset);
outOffset += size[2];
}
}
}
function slice4d(xVals, xStride1, xStride2, xStride3, outVals, begin, size) {
let outOffset = 0;
const beginI = begin[0];
const beginJ = begin[1];
const beginK = begin[2];
const endI = beginI + size[0];
const endJ = beginJ + size[1];
const endK = beginK + size[2];
const beginL = begin[3];
for (let i = beginI; i < endI; i++) {
for (let j = beginJ; j < endJ; j++) {
for (let k = beginK; k < endK; k++) {
const xOffset = i * xStride1 + j * xStride2 + k * xStride3 + beginL;
outVals.set(xVals.subarray(xOffset, xOffset + size[3]), outOffset);
outOffset += size[3];
}
}
}
}
export const sliceConfig = {
kernelName: Slice,
backendName: 'wasm',
kernelFunc: slice,
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2xpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi90ZmpzLWJhY2tlbmQtd2FzbS9zcmMva2VybmVscy9TbGljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEVBQXlDLEtBQUssRUFBRSxVQUFVLEVBQXVDLElBQUksRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBRzNJLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQztBQUVwRCxNQUFNLFVBQVUsS0FBSyxDQUNqQixJQUFvRTtJQUN0RSxNQUFNLEVBQUMsTUFBTSxFQUFFLEVBQUMsQ0FBQyxFQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUMsS0FBSyxFQUFFLElBQUksRUFBQyxFQUFFLE9BQU8sRUFBQyxHQUFHLElBQUksQ0FBQztJQUUxRCxNQUFNLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxHQUFHLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBRXBFLE1BQU0sV0FBVyxHQUFHLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUN4RSxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QyxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0MsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDOUMsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRWxELElBQUksV0FB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QUksQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUN0QjtTQUNGO0tBQ0Y7QUFDSCxDQUFDO0FBRUQsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFpQjtJQUN2QyxVQUFVLEVBQUUsS0FBSztJQUNqQixXQUFXLEVBQUUsTUFBTTtJQUNuQixVQUFVLEVBQUUsS0FBOEI7Q0FDM0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuaW1wb3J0IHtiYWNrZW5kX3V0aWwsIEtlcm5lbENvbmZpZywgS2VybmVsRnVuYywgU2xpY2UsIHNsaWNlX3V0aWwsIFNsaWNlQXR0cnMsIFNsaWNlSW5wdXRzLCBUeXBlZEFycmF5LCB1dGlsfSBmcm9tICdAdGVuc29yZmxvdy90ZmpzLWNvcmUnO1xuXG5pbXBvcnQge0JhY2tlbmRXYXNtfSBmcm9tICcuLi9iYWNrZW5kX3dhc20nO1xuaW1wb3J0IHtzbGljZUltcGxDUFV9IGZyb20gJy4uL2tlcm5lbF91dGlscy9zaGFyZWQnO1xuXG5leHBvcnQgZnVuY3Rpb24gc2xpY2UoXG4gICAgYXJnczoge2lucHV0czogU2xpY2VJbnB1dHMsIGF0dHJzOiBTbGljZUF0dHJzLCBiYWNrZW5kOiBCYWNrZW5kV2FzbX0pIHtcbiAgY29uc3Qge2lucHV0czoge3h9LCBhdHRyczoge2JlZ2luLCBzaXplfSwgYmFja2VuZH0gPSBhcmdzO1xuXG4gIGNvbnN0IFtiZWdpbl8sIHNpemVfXSA9IHNsaWNlX3V0aWwucGFyc2VTbGljZVBhcmFtcyh4LCBiZWdpbiwgc2l6ZSk7XG5cbiAgY29uc3QgaXNDb250aW5vdXMgPSBzbGljZV91dGlsLmlzU2xpY2VDb250aW5vdXMoeC5zaGFwZSwgYmVnaW5fLCBzaXplXyk7XG4gIGNvbnN0IHhWYWxzID0gYmFja2VuZC5yZWFkU3luYyh4LmRhdGFJZCk7XG4gIGNvbnN0IG91dCA9IGJhY2tlbmQubWFrZU91dHB1dChzaXplXywgeC5kdHlwZSk7XG4gIGNvbnN0IHhTdHJpZGVzID0gdXRpbC5jb21wdXRlU3RyaWRlcyh4LnNoYXBlKTtcbiAgY29uc3Qgb3V0RGF0YSA9IGJhY2tlbmQuZGF0YUlkTWFwLmdldChvdXQuZGF0YUlkKTtcblxuICBpZiAoaXNDb250aW5vdXMpIHtcbiAgICBjb25zdCBmbGF0T2Zmc2V0ID0gc2xpY2VfdXRpbC5jb21wdXRlRmxhdE9mZnNldChiZWdpbl8sIHhTdHJpZGVzKTtcblxuICAgIGlmICh4LmR0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgb3V0RGF0YS5zdHJpbmdCeXRlcyA9XG4gICAgICAgICAgKHhWYWxzIGFzIFVpbnQ4QXJyYXlbXSlcbiAgICAgICAgICAgICAgLnNsaWNlKGZsYXRPZmZzZXQsIGZsYXRPZmZzZXQgKyB1dGlsLnNpemVGcm9tU2hhcGUoc2l6ZV8pKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgb3V0VmFscyA9IGJhY2tlbmQudHlwZWRBcnJheUZyb21IZWFwKG91dCk7XG4gICAgICBvdXRWYWxzLnNldChcbiAgICAgICAgICAoeFZhbHMgYXMgVHlwZWRBcnJheSlcbiAgICAgICAgICAgICAgLnN1YmFycmF5KGZsYXRPZmZzZXQsIGZsYXRPZmZzZXQgKyB1dGlsLnNpemVGcm9tU2hhcGUoc2l6ZV8pKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbiAgfVxuXG4gIGlmICh4LmR0eXBlID09PSAnc3RyaW5nJykge1xuICAgIGNvbnN0IHJlcyA9IHNsaWNlSW1wbENQVSh4VmFscywgYmVnaW5fLCBzaXplXywgeC5zaGFwZSwgeC5kdHlwZSk7XG4gICAgb3V0RGF0YS5zdHJpbmdCeXRlcyA9IHJlcyBhcyBVaW50OEFycmF5W107XG4gICAgcmV0dXJuIG91dDtcbiAgfVxuXG4gIGNvbnN0IG91dFZhbHMgPSBiYWNrZW5kLnR5cGVkQXJyYXlGcm9tSGVhcChvdXQpO1xuICBjb25zdCByYW5rID0geC5zaGFwZS5sZW5ndGg7XG4gIGlmIChyYW5rID09PSAyKSB7XG4gICAgc2xpY2UyZChcbiAgICAgICAgeFZhbHMgYXMgVHlwZWRBcnJheSwgeFN0cmlkZXNbMF0sIG91dFZhbHMsIGJlZ2luXyBhcyBbbnVtYmVyLCBudW1iZXJdLFxuICAgICAgICBzaXplXyBhcyBbbnVtYmVyLCBudW1iZXJdKTtcbiAgfSBlbHNlIGlmIChyYW5rID09PSAzKSB7XG4gICAgc2xpY2UzZChcbiAgICAgICAgeFZhbHMgYXMgVHlwZWRBcnJheSwgeFN0cmlkZXNbMF0sIHhTdHJpZGVzWzFdLCBvdXRWYWxzLFxuICAgICAgICBiZWdpbl8gYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXJdLCBzaXplXyBhcyBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pO1xuICB9IGVsc2UgaWYgKHJhbmsgPT09IDQpIHtcbiAgICBzbGljZTRkKFxuICAgICAgICB4VmFscyBhcyBUeXBlZEFycmF5LCB4U3RyaWRlc1swXSwgeFN0cmlkZXNbMV0sIHhTdHJpZGVzWzJdLCBvdXRWYWxzLFxuICAgICAgICBiZWdpbl8gYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICAgICAgIHNpemVfIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCByZXMgPVxuICAgICAgICBzbGljZUltcGxDUFUoeFZhbHMsIGJlZ2luXywgc2l6ZV8sIHguc2hhcGUsIHguZHR5cGUpIGFzIFR5cGVkQXJyYXk7XG4gICAgb3V0VmFscy5zZXQocmVzKTtcbiAgfVxuXG4gIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIHNsaWNlMmQoXG4gICAgeFZhbHM6IGJhY2tlbmRfdXRpbC5UeXBlZEFycmF5LCB4U3RyaWRlOiBudW1iZXIsXG4gICAgb3V0VmFsczogYmFja2VuZF91dGlsLlR5cGVkQXJyYXksIGJlZ2luOiBbbnVtYmVyLCBudW1iZXJdLFxuICAgIHNpemU6IFtudW1iZXIsIG51bWJlcl0pOiB2b2lkIHtcbiAgbGV0IG91dE9mZnNldCA9IDA7XG4gIGNvbnN0IGJlZ2luSSA9IGJlZ2luWzBdO1xuICBjb25zdCBiZWdpbkogPSBiZWdpblsxXTtcbiAgY29uc3QgZW5kSSA9IGJlZ2luSSArIHNpemVbMF07XG4gIGZvciAobGV0IGkgPSBiZWdpbkk7IGkgPCBlbmRJOyBpKyspIHtcbiAgICBjb25zdCB4T2Zmc2V0ID0gaSAqIHhTdHJpZGUgKyBiZWdpbko7XG4gICAgb3V0VmFscy5zZXQoeFZhbHMuc3ViYXJyYXkoeE9mZnNldCwgeE9mZnNldCArIHNpemVbMV0pLCBvdXRPZmZzZXQpO1xuICAgIG91dE9mZnNldCArPSBzaXplWzFdO1xuICB9XG59XG5cbmZ1bmN0aW9uIHNsaWNlM2QoXG4gICAgeFZhbHM6IGJhY2tlbmRfdXRpbC5UeXBlZEFycmF5LCB4U3RyaWRlMTogbnVtYmVyLCB4U3RyaWRlMjogbnVtYmVyLFxuICAgIG91dFZhbHM6IGJhY2tlbmRfdXRpbC5UeXBlZEFycmF5LCBiZWdpbjogW251bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICAgIHNpemU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSk6IHZvaWQge1xuICBsZXQgb3V0T2Zmc2V0ID0gMDtcbiAgY29uc3QgYmVnaW5JID0gYmVnaW5bMF07XG4gIGNvbnN0IGJlZ2luSiA9IGJlZ2luWzFdO1xuICBjb25zdCBiZWdpbksgPSBiZWdpblsyXTtcbiAgY29uc3QgZW5kSSA9IGJlZ2luSSArIHNpemVbMF07XG4gIGNvbnN0IGVuZEogPSBiZWdpbkogKyBzaXplWzFdO1xuICBmb3IgKGxldCBpID0gYmVnaW5JOyBpIDwgZW5kSTsgaSsrKSB7XG4gICAgZm9yIChsZXQgaiA9IGJlZ2luSjsgaiA8IGVuZEo7IGorKykge1xuICAgICAgY29uc3QgeE9mZnNldCA9IGkgKiB4U3RyaWRlMSArIGogKiB4U3RyaWRlMiArIGJlZ2luSztcbiAgICAgIG91dFZhbHMuc2V0KHhWYWxzLnN1YmFycmF5KHhPZmZzZXQsIHhPZmZzZXQgKyBzaXplWzJdKSwgb3V0T2Zmc2V0KTtcbiAgICAgIG91dE9mZnNldCArPSBzaXplWzJdO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBzbGljZTRkKFxuICAgIHhWYWxzOiBiYWNrZW5kX3V0aWwuVHlwZWRBcnJheSwgeFN0cmlkZTE6IG51bWJlciwgeFN0cmlkZTI6IG51bWJlcixcbiAgICB4U3RyaWRlMzogbnVtYmVyLCBvdXRWYWxzOiBiYWNrZW5kX3V0aWwuVHlwZWRBcnJheSxcbiAgICBiZWdpbjogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICAgc2l6ZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pOiB2b2lkIHtcbiAgbGV0IG91dE9mZnNldCA9IDA7XG4gIGNvbnN0IGJlZ2luSSA9IGJlZ2luWzBdO1xuICBjb25zdCBiZWdpbkogPSBiZWdpblsxXTtcbiAgY29uc3QgYmVnaW5LID0gYmVnaW5bMl07XG4gIGNvbnN0IGVuZEkgPSBiZWdpbkkgKyBzaXplWzBdO1xuICBjb25zdCBlbmRKID0gYmVnaW5KICsgc2l6ZVsxXTtcbiAgY29uc3QgZW5kSyA9IGJlZ2luSyArIHNpemVbMl07XG4gIGNvbnN0IGJlZ2luTCA9IGJlZ2luWzNdO1xuXG4gIGZvciAobGV0IGkgPSBiZWdpbkk7IGkgPCBlbmRJOyBpKyspIHtcbiAgICBmb3IgKGxldCBqID0gYmVnaW5KOyBqIDwgZW5kSjsgaisrKSB7XG4gICAgICBmb3IgKGxldCBrID0gYmVnaW5LOyBrIDwgZW5kSzsgaysrKSB7XG4gICAgICAgIGNvbnN0IHhPZmZzZXQgPSBpICogeFN0cmlkZTEgKyBqICogeFN0cmlkZTIgKyBrICogeFN0cmlkZTMgKyBiZWdpbkw7XG4gICAgICAgIG91dFZhbHMuc2V0KHhWYWxzLnN1YmFycmF5KHhPZmZzZXQsIHhPZmZzZXQgKyBzaXplWzNdKSwgb3V0T2Zmc2V0KTtcbiAgICAgICAgb3V0T2Zmc2V0ICs9IHNpemVbM107XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBzbGljZUNvbmZpZzogS2VybmVsQ29uZmlnID0ge1xuICBrZXJuZWxOYW1lOiBTbGljZSxcbiAgYmFja2VuZE5hbWU6ICd3YXNtJyxcbiAga2VybmVsRnVuYzogc2xpY2UgYXMgdW5rbm93biBhcyBLZXJuZWxGdW5jLFxufTtcbiJdfQ==