/** * @license * Copyright 2020 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 { backend_util, env, util } from '@tensorflow/tfjs-core'; import { ArgMinMaxProgram } from '../argminmax_gpu'; import { ArgMinMaxPackedProgram } from '../argminmax_packed_gpu'; import { reshape } from '../kernels/Reshape'; function argReduce(backend, x, reduceType, bestIndicesA = null) { let batchSize = x.shape[0]; let inSize = x.shape[1]; if (bestIndicesA != null) { batchSize = bestIndicesA.shape[0]; inSize = bestIndicesA.shape[1]; } const windowSize = backend_util.computeOptimalWindowSize(inSize); const reduceInfo = { windowSize, inSize, batchSize, outSize: Math.ceil(inSize / windowSize) }; const program = new ArgMinMaxProgram(reduceInfo, reduceType, bestIndicesA == null); const inputs = [x]; if (bestIndicesA != null) { inputs.push(bestIndicesA); } const output = backend.runWebGLProgram(program, inputs, 'int32'); // No need to run another GPGPU program. if (output.shape[1] === 1) { return output; } const result = argReduce(backend, x, reduceType, output); backend.disposeIntermediateTensorInfo(output); return result; } function argReducePacked(backend, x, reduceType, bestIndicesA = null) { const inShape = bestIndicesA != null ? bestIndicesA.shape : x.shape; const inSize = inShape[inShape.length - 1]; const windowSize = backend_util.computeOptimalWindowSize(inSize); const program = new ArgMinMaxPackedProgram(inShape, windowSize, reduceType, bestIndicesA == null); const inputs = bestIndicesA == null ? [x] : [x, bestIndicesA]; const output = backend.runWebGLProgram(program, inputs, 'int32'); if (output.shape.length === x.shape.length) { const result = argReducePacked(backend, x, reduceType, output); backend.disposeIntermediateTensorInfo(output); return result; } return output; } export function argMinMaxReduce(backend, x, axis, reduceType) { const axes = [axis]; backend_util.assertAxesAreInnerMostDims('arg' + reduceType.charAt(0).toUpperCase() + reduceType.slice(1), axes, x.shape.length); if (!env().getBool('WEBGL_PACK_REDUCE') || x.shape.length <= 2) { const intermediateTensorInfos = []; // Eagerly unpack x input since it is passed in to all the shaders which // require unpacked inputs. const xtexData = backend.texData.get(x.dataId); const xIsPacked = xtexData !== null && xtexData.isPacked; let xUnPacked = x; if (xIsPacked) { xUnPacked = backend.unpackTensor(x); intermediateTensorInfos.push(xUnPacked); } const [outShape, reduceShape] = backend_util.computeOutAndReduceShapes(xUnPacked.shape, axes); const inSize = util.sizeFromShape(reduceShape); const a2D = reshape({ inputs: { x: xUnPacked }, backend, attrs: { shape: [-1, inSize] } }); intermediateTensorInfos.push(a2D); const reduced = argReduce(backend, a2D, reduceType); intermediateTensorInfos.push(reduced); const reshaped = reshape({ inputs: { x: reduced }, backend, attrs: { shape: outShape } }); intermediateTensorInfos.forEach(t => backend.disposeIntermediateTensorInfo(t)); return reshaped; } return argReducePacked(backend, x, reduceType); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJnX21pbl9tYXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi90ZmpzLWJhY2tlbmQtd2ViZ2wvc3JjL2tlcm5lbF91dGlscy9hcmdfbWluX21heC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEVBQUMsWUFBWSxFQUFFLEdBQUcsRUFBYyxJQUFJLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUUxRSxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUNsRCxPQUFPLEVBQUMsc0JBQXNCLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQztBQUUvRCxPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFFM0MsU0FBUyxTQUFTLENBQ2QsT0FBeUIsRUFBRSxDQUFhLEVBQUUsVUFBdUIsRUFDakUsZUFBMkIsSUFBSTtJQUNqQyxJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNCLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEIsSUFBSSxZQUFZLElBQUksSUFBSSxFQUFFO1FBQ3hCLFNBQVMsR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xDLE1BQU0sR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQ2hDO0lBQ0QsTUFBTSxVQUFVLEdBQUcsWUFBWSxDQUFDLHdCQUF3QixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2pFLE1BQU0sVUFBVSxHQUNaLEVBQUMsVUFBVSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxFQUFDLENBQUM7SUFDN0UsTUFBTSxPQUFPLEdBQ1QsSUFBSSxnQkFBZ0Is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LENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkQsT0FBTyxRQUFRLENBQUM7S0FDakI7SUFDRCxPQUFPLGVBQWUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0FBQ2pELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbmltcG9ydCB7YmFja2VuZF91dGlsLCBlbnYsIFRlbnNvckluZm8sIHV0aWx9IGZyb20gJ0B0ZW5zb3JmbG93L3RmanMtY29yZSc7XG5cbmltcG9ydCB7QXJnTWluTWF4UHJvZ3JhbX0gZnJvbSAnLi4vYXJnbWlubWF4X2dwdSc7XG5pbXBvcnQge0FyZ01pbk1heFBhY2tlZFByb2dyYW19IGZyb20gJy4uL2FyZ21pbm1heF9wYWNrZWRfZ3B1JztcbmltcG9ydCB7TWF0aEJhY2tlbmRXZWJHTH0gZnJvbSAnLi4vYmFja2VuZF93ZWJnbCc7XG5pbXBvcnQge3Jlc2hhcGV9IGZyb20gJy4uL2tlcm5lbHMvUmVzaGFwZSc7XG5cbmZ1bmN0aW9uIGFyZ1JlZHVjZShcbiAgICBiYWNrZW5kOiBNYXRoQmFja2VuZFdlYkdMLCB4OiBUZW5zb3JJbmZvLCByZWR1Y2VUeXBlOiAnbWF4J3wnbWluJyxcbiAgICBiZXN0SW5kaWNlc0E6IFRlbnNvckluZm8gPSBudWxsKTogVGVuc29ySW5mbyB7XG4gIGxldCBiYXRjaFNpemUgPSB4LnNoYXBlWzBdO1xuICBsZXQgaW5TaXplID0geC5zaGFwZVsxXTtcbiAgaWYgKGJlc3RJbmRpY2VzQSAhPSBudWxsKSB7XG4gICAgYmF0Y2hTaXplID0gYmVzdEluZGljZXNBLnNoYXBlWzBdO1xuICAgIGluU2l6ZSA9IGJlc3RJbmRpY2VzQS5zaGFwZVsxXTtcbiAgfVxuICBjb25zdCB3aW5kb3dTaXplID0gYmFja2VuZF91dGlsLmNvbXB1dGVPcHRpbWFsV2luZG93U2l6ZShpblNpemUpO1xuICBjb25zdCByZWR1Y2VJbmZvID1cbiAgICAgIHt3aW5kb3dTaXplLCBpblNpemUsIGJhdGNoU2l6ZSwgb3V0U2l6ZTogTWF0aC5jZWlsKGluU2l6ZSAvIHdpbmRvd1NpemUpfTtcbiAgY29uc3QgcHJvZ3JhbSA9XG4gICAgICBuZXcgQXJnTWluTWF4UHJvZ3JhbShyZWR1Y2VJbmZvLCByZWR1Y2VUeXBlLCBiZXN0SW5kaWNlc0EgPT0gbnVsbCk7XG4gIGNvbnN0IGlucHV0cyA9IFt4XTtcbiAgaWYgKGJlc3RJbmRpY2VzQSAhPSBudWxsKSB7XG4gICAgaW5wdXRzLnB1c2goYmVzdEluZGljZXNBKTtcbiAgfVxuICBjb25zdCBvdXRwdXQgPSBiYWNrZW5kLnJ1bldlYkdMUHJvZ3JhbShwcm9ncmFtLCBpbnB1dHMsICdpbnQzMicpO1xuICAvLyBObyBuZWVkIHRvIHJ1biBhbm90aGVyIEdQR1BVIHByb2dyYW0uXG4gIGlmIChvdXRwdXQuc2hhcGVbMV0gPT09IDEpIHtcbiAgICByZXR1cm4gb3V0cHV0O1xuICB9XG4gIGNvbnN0IHJlc3VsdCA9IGFyZ1JlZHVjZShiYWNrZW5kLCB4LCByZWR1Y2VUeXBlLCBvdXRwdXQpO1xuICBiYWNrZW5kLmRpc3Bvc2VJbnRlcm1lZGlhdGVUZW5zb3JJbmZvKG91dHB1dCk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIGFyZ1JlZHVjZVBhY2tlZChcbiAgICBiYWNrZW5kOiBNYXRoQmFja2VuZFdlYkdMLCB4OiBUZW5zb3JJbmZvLCByZWR1Y2VUeXBlOiAnbWF4J3wnbWluJyxcbiAgICBiZXN0SW5kaWNlc0E6IFRlbnNvckluZm8gPSBudWxsKTogVGVuc29ySW5mbyB7XG4gIGNvbnN0IGluU2hhcGUgPSBiZXN0SW5kaWNlc0EgIT0gbnVsbCA/IGJlc3RJbmRpY2VzQS5zaGFwZSA6IHguc2hhcGU7XG4gIGNvbnN0IGluU2l6ZSA9IGluU2hhcGVbaW5TaGFwZS5sZW5ndGggLSAxXTtcbiAgY29uc3Qgd2luZG93U2l6ZSA9IGJhY2tlbmRfdXRpbC5jb21wdXRlT3B0aW1hbFdpbmRvd1NpemUoaW5TaXplKTtcbiAgY29uc3QgcHJvZ3JhbSA9IG5ldyBBcmdNaW5NYXhQYWNrZWRQcm9ncmFtKFxuICAgICAgaW5TaGFwZSwgd2luZG93U2l6ZSwgcmVkdWNlVHlwZSwgYmVzdEluZGljZXNBID09IG51bGwpO1xuICBjb25zdCBpbnB1dHMgPSBiZXN0SW5kaWNlc0EgPT0gbnVsbCA/IFt4XSA6IFt4LCBiZXN0SW5kaWNlc0FdO1xuICBjb25zdCBvdXRwdXQgPSBiYWNrZW5kLnJ1bldlYkdMUHJvZ3JhbShwcm9ncmFtLCBpbnB1dHMsICdpbnQzMicpO1xuICBpZiAob3V0cHV0LnNoYXBlLmxlbmd0aCA9PT0geC5zaGFwZS5sZW5ndGgpIHtcbiAgICBjb25zdCByZXN1bHQgPSBhcmdSZWR1Y2VQYWNrZWQoYmFja2VuZCwgeCwgcmVkdWNlVHlwZSwgb3V0cHV0KTtcbiAgICBiYWNrZW5kLmRpc3Bvc2VJbnRlcm1lZGlhdGVUZW5zb3JJbmZvKG91dHB1dCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICByZXR1cm4gb3V0cHV0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYXJnTWluTWF4UmVkdWNlKFxuICAgIGJhY2tlbmQ6IE1hdGhCYWNrZW5kV2ViR0wsIHg6IFRlbnNvckluZm8sIGF4aXM6IG51bWJlcixcbiAgICByZWR1Y2VUeXBlOiAnbWluJ3wnbWF4Jyk6IFRlbnNvckluZm8ge1xuICBjb25zdCBheGVzID0gW2F4aXNdO1xuICBiYWNrZW5kX3V0aWwuYXNzZXJ0QXhlc0FyZUlubmVyTW9zdERpbXMoXG4gICAgICAnYXJnJyArIHJlZHVjZVR5cGUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyByZWR1Y2VUeXBlLnNsaWNlKDEpLCBheGVzLFxuICAgICAgeC5zaGFwZS5sZW5ndGgpO1xuICBpZiAoIWVudigpLmdldEJvb2woJ1dFQkdMX1BBQ0tfUkVEVUNFJykgfHwgeC5zaGFwZS5sZW5ndGggPD0gMikge1xuICAgIGNvbnN0IGludGVybWVkaWF0ZVRlbnNvckluZm9zID0gW107XG4gICAgLy8gRWFnZXJseSB1bnBhY2sgeCBpbnB1dCBzaW5jZSBpdCBpcyBwYXNzZWQgaW4gdG8gYWxsIHRoZSBzaGFkZXJzIHdoaWNoXG4gICAgLy8gcmVxdWlyZSB1bnBhY2tlZCBpbnB1dHMuXG4gICAgY29uc3QgeHRleERhdGEgPSBiYWNrZW5kLnRleERhdGEuZ2V0KHguZGF0YUlkKTtcbiAgICBjb25zdCB4SXNQYWNrZWQgPSB4dGV4RGF0YSAhPT0gbnVsbCAmJiB4dGV4RGF0YS5pc1BhY2tlZDtcbiAgICBsZXQgeFVuUGFja2VkID0geDtcbiAgICBpZiAoeElzUGFja2VkKSB7XG4gICAgICB4VW5QYWNrZWQgPSBiYWNrZW5kLnVucGFja1RlbnNvcih4KTtcbiAgICAgIGludGVybWVkaWF0ZVRlbnNvckluZm9zLnB1c2goeFVuUGFja2VkKTtcbiAgICB9XG5cbiAgICBjb25zdCBbb3V0U2hhcGUsIHJlZHVjZVNoYXBlXSA9XG4gICAgICAgIGJhY2tlbmRfdXRpbC5jb21wdXRlT3V0QW5kUmVkdWNlU2hhcGVzKHhVblBhY2tlZC5zaGFwZSwgYXhlcyk7XG4gICAgY29uc3QgaW5TaXplID0gdXRpbC5zaXplRnJvbVNoYXBlKHJlZHVjZVNoYXBlKTtcbiAgICBjb25zdCBhMkQgPSByZXNoYXBlKFxuICAgICAgICB7aW5wdXRzOiB7eDogeFVuUGFja2VkfSwgYmFja2VuZCwgYXR0cnM6IHtzaGFwZTogWy0xLCBpblNpemVdfX0pO1xuICAgIGludGVybWVkaWF0ZVRlbnNvckluZm9zLnB1c2goYTJEKTtcblxuICAgIGNvbnN0IHJlZHVjZWQgPSBhcmdSZWR1Y2UoYmFja2VuZCwgYTJELCByZWR1Y2VUeXBlKTtcbiAgICBpbnRlcm1lZGlhdGVUZW5zb3JJbmZvcy5wdXNoKHJlZHVjZWQpO1xuICAgIGNvbnN0IHJlc2hhcGVkID1cbiAgICAgICAgcmVzaGFwZSh7aW5wdXRzOiB7eDogcmVkdWNlZH0sIGJhY2tlbmQsIGF0dHJzOiB7c2hhcGU6IG91dFNoYXBlfX0pO1xuXG4gICAgaW50ZXJtZWRpYXRlVGVuc29ySW5mb3MuZm9yRWFjaChcbiAgICAgICAgdCA9PiBiYWNrZW5kLmRpc3Bvc2VJbnRlcm1lZGlhdGVUZW5zb3JJbmZvKHQpKTtcbiAgICByZXR1cm4gcmVzaGFwZWQ7XG4gIH1cbiAgcmV0dXJuIGFyZ1JlZHVjZVBhY2tlZChiYWNrZW5kLCB4LCByZWR1Y2VUeXBlKTtcbn1cbiJdfQ==