From 8f0a4f128a5b9b16e4ab115db2552ae8edb2047f Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 2 Sep 2020 09:00:13 -0400 Subject: [PATCH 01/13] test --- tfjs-backend-webgl/src/backend_webgl_test.ts | 10 ++++++++ tfjs-backend-webgl/src/kernel_utils/reduce.ts | 25 ++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/tfjs-backend-webgl/src/backend_webgl_test.ts b/tfjs-backend-webgl/src/backend_webgl_test.ts index 6d13cd2d189..329c02ea5d0 100644 --- a/tfjs-backend-webgl/src/backend_webgl_test.ts +++ b/tfjs-backend-webgl/src/backend_webgl_test.ts @@ -552,6 +552,16 @@ describeWithFlags('memory webgl', WEBGL_ENVS, () => { expect(mem.numBytes).toBe(4); expect(mem.unreliable).toBeFalsy(); }); + + fit('max', async () => { + console.log( + 'memory before', (tf.memory() as WebGLMemoryInfo).numBytesInGPU); + const img = tf.ones([300, 300]); + const fbmx = img.max(); + img.dispose(); + fbmx.dispose(); + console.log('memory after', (tf.memory() as WebGLMemoryInfo).numBytesInGPU); + }); }); // We do not yet fully support half float backends. These tests are a starting diff --git a/tfjs-backend-webgl/src/kernel_utils/reduce.ts b/tfjs-backend-webgl/src/kernel_utils/reduce.ts index edf6df8db73..ce53ae7c362 100644 --- a/tfjs-backend-webgl/src/kernel_utils/reduce.ts +++ b/tfjs-backend-webgl/src/kernel_utils/reduce.ts @@ -22,6 +22,23 @@ import {ReduceProgram} from '../reduce_gpu'; type ReduceTypes = 'all'|'any'|'max'|'min'|'sum'|'prod'; +function reduceImpl( + x: TensorInfo, dtype: DataType, reductionType: ReduceTypes, + backend: MathBackendWebGL): TensorInfo { + const [batchSize, inSize] = x.shape; + const windowSize = backend_util.computeOptimalWindowSize(inSize); + const reduceInfo = {windowSize, inSize, batchSize}; + const program = new ReduceProgram(reduceInfo, reductionType); + const output = backend.runWebGLProgram(program, [x], dtype); + + if (output.shape[1] === 1) { + backend.disposeData(x.dataId); + return output; + } + + return reduceImpl(output, dtype, reductionType, backend); +} + export function reduce( x: TensorInfo, dtype: DataType, reductionType: ReduceTypes, backend: MathBackendWebGL): TensorInfo { @@ -35,5 +52,11 @@ export function reduce( return output; } - return reduce(output, dtype, reductionType, backend); + const final = reduceImpl(output, dtype, reductionType, backend); + + if (final.dataId !== output.dataId) { + backend.disposeData(output.dataId); + } + + return final; } From a5b4ec0f735a1d5e1be915b155cbc939b2ce393c Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 2 Sep 2020 09:48:09 -0400 Subject: [PATCH 02/13] fix --- tfjs-backend-webgl/src/kernel_utils/reduce.ts | 64 +++++++++++-------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/tfjs-backend-webgl/src/kernel_utils/reduce.ts b/tfjs-backend-webgl/src/kernel_utils/reduce.ts index ce53ae7c362..c5e0c41ea2e 100644 --- a/tfjs-backend-webgl/src/kernel_utils/reduce.ts +++ b/tfjs-backend-webgl/src/kernel_utils/reduce.ts @@ -15,48 +15,58 @@ * ============================================================================= */ -import {backend_util, DataType, TensorInfo} from '@tensorflow/tfjs-core'; +import {DataType, TensorInfo} from '@tensorflow/tfjs-core'; +import {computeOptimalWindowSize} from '@tensorflow/tfjs-core/dist/ops/reduce_util'; import {MathBackendWebGL} from '../backend_webgl'; import {ReduceProgram} from '../reduce_gpu'; type ReduceTypes = 'all'|'any'|'max'|'min'|'sum'|'prod'; -function reduceImpl( - x: TensorInfo, dtype: DataType, reductionType: ReduceTypes, - backend: MathBackendWebGL): TensorInfo { - const [batchSize, inSize] = x.shape; - const windowSize = backend_util.computeOptimalWindowSize(inSize); - const reduceInfo = {windowSize, inSize, batchSize}; - const program = new ReduceProgram(reduceInfo, reductionType); - const output = backend.runWebGLProgram(program, [x], dtype); - - if (output.shape[1] === 1) { - backend.disposeData(x.dataId); - return output; +function getSizes(inShape: number[]): + Array<{inSize: number, windowSize: number, outSize: number}> { + const sizes = [{ + inSize: inShape[1], + windowSize: computeOptimalWindowSize(inShape[1]), + outSize: Math.ceil(inShape[1] / computeOptimalWindowSize(inShape[1])) + }]; + + while (sizes[sizes.length - 1].outSize !== 1) { + const outSize = sizes[sizes.length - 1].outSize; + const windowSize = computeOptimalWindowSize(outSize); + sizes.push({ + inSize: outSize, + windowSize, + outSize: Math.ceil(outSize / windowSize) + }); } - return reduceImpl(output, dtype, reductionType, backend); + return sizes; } export function reduce( x: TensorInfo, dtype: DataType, reductionType: ReduceTypes, backend: MathBackendWebGL): TensorInfo { - const [batchSize, inSize] = x.shape; - const windowSize = backend_util.computeOptimalWindowSize(inSize); - const reduceInfo = {windowSize, inSize, batchSize}; - const program = new ReduceProgram(reduceInfo, reductionType); - const output = backend.runWebGLProgram(program, [x], dtype); - - if (output.shape[1] === 1) { - return output; - } + const sizes = getSizes(x.shape); + console.log('REDUCE BEGIN'); + console.log(backend.numDataIds()); + + let result = x; + for (let i = 0; i < sizes.length; i++) { + const {inSize, windowSize} = sizes[i]; - const final = reduceImpl(output, dtype, reductionType, backend); + const program = new ReduceProgram( + {windowSize, inSize, batchSize: x.shape[0]}, reductionType); + const previousResult = result; + result = backend.runWebGLProgram(program, [result], dtype); - if (final.dataId !== output.dataId) { - backend.disposeData(output.dataId); + if (i > 0) { + backend.disposeData(previousResult.dataId); + } } - return final; + console.log('REDUCE END'); + console.log(backend.numDataIds()); + + return result; } From 272a6319140cbac938be62edead7f70509515b02 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 2 Sep 2020 09:52:13 -0400 Subject: [PATCH 03/13] fix --- tfjs-backend-webgl/src/kernel_utils/reduce.ts | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/tfjs-backend-webgl/src/kernel_utils/reduce.ts b/tfjs-backend-webgl/src/kernel_utils/reduce.ts index c5e0c41ea2e..cc2e610c7e1 100644 --- a/tfjs-backend-webgl/src/kernel_utils/reduce.ts +++ b/tfjs-backend-webgl/src/kernel_utils/reduce.ts @@ -15,25 +15,21 @@ * ============================================================================= */ -import {DataType, TensorInfo} from '@tensorflow/tfjs-core'; -import {computeOptimalWindowSize} from '@tensorflow/tfjs-core/dist/ops/reduce_util'; +import {backend_util, DataType, TensorInfo} from '@tensorflow/tfjs-core'; import {MathBackendWebGL} from '../backend_webgl'; import {ReduceProgram} from '../reduce_gpu'; type ReduceTypes = 'all'|'any'|'max'|'min'|'sum'|'prod'; -function getSizes(inShape: number[]): +function getReductionSizes(inShape: number[]): Array<{inSize: number, windowSize: number, outSize: number}> { - const sizes = [{ - inSize: inShape[1], - windowSize: computeOptimalWindowSize(inShape[1]), - outSize: Math.ceil(inShape[1] / computeOptimalWindowSize(inShape[1])) - }]; + const sizes = []; - while (sizes[sizes.length - 1].outSize !== 1) { - const outSize = sizes[sizes.length - 1].outSize; - const windowSize = computeOptimalWindowSize(outSize); + while (sizes.length === 0 || sizes[sizes.length - 1].outSize !== 1) { + const outSize: number = + sizes.length ? sizes[sizes.length - 1].outSize : inShape[1]; + const windowSize = backend_util.computeOptimalWindowSize(outSize); sizes.push({ inSize: outSize, windowSize, @@ -47,9 +43,7 @@ function getSizes(inShape: number[]): export function reduce( x: TensorInfo, dtype: DataType, reductionType: ReduceTypes, backend: MathBackendWebGL): TensorInfo { - const sizes = getSizes(x.shape); - console.log('REDUCE BEGIN'); - console.log(backend.numDataIds()); + const sizes = getReductionSizes(x.shape); let result = x; for (let i = 0; i < sizes.length; i++) { @@ -65,8 +59,5 @@ export function reduce( } } - console.log('REDUCE END'); - console.log(backend.numDataIds()); - return result; } From da6ccc9a89ebb7e6ce7fce6e905929e6f8f0a246 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 2 Sep 2020 09:56:43 -0400 Subject: [PATCH 04/13] remove fit --- tfjs-backend-webgl/src/backend_webgl_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tfjs-backend-webgl/src/backend_webgl_test.ts b/tfjs-backend-webgl/src/backend_webgl_test.ts index 329c02ea5d0..80a5245ea24 100644 --- a/tfjs-backend-webgl/src/backend_webgl_test.ts +++ b/tfjs-backend-webgl/src/backend_webgl_test.ts @@ -553,7 +553,7 @@ describeWithFlags('memory webgl', WEBGL_ENVS, () => { expect(mem.unreliable).toBeFalsy(); }); - fit('max', async () => { + it('max', async () => { console.log( 'memory before', (tf.memory() as WebGLMemoryInfo).numBytesInGPU); const img = tf.ones([300, 300]); From ed6a5965dacb70c85fbd110be371b9d16e976986 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 2 Sep 2020 10:04:23 -0400 Subject: [PATCH 05/13] fix --- tfjs-backend-webgl/src/backend_webgl.ts | 3 ++- tfjs-backend-webgl/src/kernel_utils/reduce.ts | 4 ++-- tfjs-backend-webgl/src/reduce_gpu.ts | 5 +---- tfjs-core/src/ops/reduce_util.ts | 1 + 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tfjs-backend-webgl/src/backend_webgl.ts b/tfjs-backend-webgl/src/backend_webgl.ts index a939a659304..87a5317a612 100644 --- a/tfjs-backend-webgl/src/backend_webgl.ts +++ b/tfjs-backend-webgl/src/backend_webgl.ts @@ -1043,7 +1043,8 @@ export class MathBackendWebGL extends KernelBackend { const batchSize = x.shape[0]; const inSize = x.shape[1]; const windowSize = backend_util.computeOptimalWindowSize(inSize); - const reduceInfo = {windowSize, inSize, batchSize}; + const outSize = Math.ceil(inSize / windowSize); + const reduceInfo = {windowSize, inSize, batchSize, outSize}; const program = new ReduceProgram(reduceInfo, reduceType); const output = this.compileAndRun(program, [x], dtype); // No need to run another GPGPU program. diff --git a/tfjs-backend-webgl/src/kernel_utils/reduce.ts b/tfjs-backend-webgl/src/kernel_utils/reduce.ts index cc2e610c7e1..cde1aa527b6 100644 --- a/tfjs-backend-webgl/src/kernel_utils/reduce.ts +++ b/tfjs-backend-webgl/src/kernel_utils/reduce.ts @@ -47,10 +47,10 @@ export function reduce( let result = x; for (let i = 0; i < sizes.length; i++) { - const {inSize, windowSize} = sizes[i]; + const {inSize, windowSize, outSize} = sizes[i]; const program = new ReduceProgram( - {windowSize, inSize, batchSize: x.shape[0]}, reductionType); + {windowSize, inSize, batchSize: x.shape[0], outSize}, reductionType); const previousResult = result; result = backend.runWebGLProgram(program, [result], dtype); diff --git a/tfjs-backend-webgl/src/reduce_gpu.ts b/tfjs-backend-webgl/src/reduce_gpu.ts index 553639965ac..ff9541a39a9 100644 --- a/tfjs-backend-webgl/src/reduce_gpu.ts +++ b/tfjs-backend-webgl/src/reduce_gpu.ts @@ -26,10 +26,7 @@ export class ReduceProgram implements GPGPUProgram { constructor( reduceInfo: backend_util.ReduceInfo, reduceType: 'all'|'any'|'max'|'min'|'sum'|'prod') { - const windowSize = reduceInfo.windowSize; - const batchSize = reduceInfo.batchSize; - const inSize = reduceInfo.inSize; - const outSize = Math.ceil(inSize / windowSize); + const {windowSize, batchSize, inSize, outSize} = reduceInfo; this.outputShape = [batchSize, outSize]; let initializationValue = '0.0'; diff --git a/tfjs-core/src/ops/reduce_util.ts b/tfjs-core/src/ops/reduce_util.ts index 275b42deaff..3a0290d68be 100644 --- a/tfjs-core/src/ops/reduce_util.ts +++ b/tfjs-core/src/ops/reduce_util.ts @@ -27,6 +27,7 @@ export interface ReduceInfo { windowSize: number; batchSize: number; inSize: number; + outSize: number; } export function computeOptimalWindowSize(inSize: number): number { From 9a04bf421a2df871fd6c5426fb214d27b22fbdcb Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 2 Sep 2020 10:55:12 -0400 Subject: [PATCH 06/13] add test --- tfjs-backend-webgl/src/argminmax_gpu.ts | 5 +-- tfjs-backend-webgl/src/backend_webgl.ts | 7 +++- tfjs-backend-webgl/src/backend_webgl_test.ts | 10 ------ tfjs-backend-webgl/src/kernels/Max_test.ts | 38 ++++++++++++++++++++ 4 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 tfjs-backend-webgl/src/kernels/Max_test.ts diff --git a/tfjs-backend-webgl/src/argminmax_gpu.ts b/tfjs-backend-webgl/src/argminmax_gpu.ts index cbaca78deee..d3e63c0e6a9 100644 --- a/tfjs-backend-webgl/src/argminmax_gpu.ts +++ b/tfjs-backend-webgl/src/argminmax_gpu.ts @@ -26,10 +26,7 @@ export class ArgMinMaxProgram implements GPGPUProgram { constructor( reduceInfo: backend_util.ReduceInfo, op: 'max'|'min', firstPass: boolean) { - const windowSize = reduceInfo.windowSize; - const batchSize = reduceInfo.batchSize; - const inSize = reduceInfo.inSize; - const outSize = Math.ceil(inSize / windowSize); + const {windowSize, batchSize, outSize} = reduceInfo; if (!firstPass) { this.variableNames.push('bestIndicesA'); } diff --git a/tfjs-backend-webgl/src/backend_webgl.ts b/tfjs-backend-webgl/src/backend_webgl.ts index 87a5317a612..30c2168e9c6 100644 --- a/tfjs-backend-webgl/src/backend_webgl.ts +++ b/tfjs-backend-webgl/src/backend_webgl.ts @@ -1064,7 +1064,12 @@ export class MathBackendWebGL extends KernelBackend { inSize = bestIndicesA.shape[1]; } const windowSize = backend_util.computeOptimalWindowSize(inSize); - const reduceInfo = {windowSize, inSize, batchSize}; + const reduceInfo = { + windowSize, + inSize, + batchSize, + outSize: Math.ceil(inSize / windowSize) + }; const program = new ArgMinMaxProgram(reduceInfo, reduceType, bestIndicesA == null); const inputs = [x]; diff --git a/tfjs-backend-webgl/src/backend_webgl_test.ts b/tfjs-backend-webgl/src/backend_webgl_test.ts index 80a5245ea24..6d13cd2d189 100644 --- a/tfjs-backend-webgl/src/backend_webgl_test.ts +++ b/tfjs-backend-webgl/src/backend_webgl_test.ts @@ -552,16 +552,6 @@ describeWithFlags('memory webgl', WEBGL_ENVS, () => { expect(mem.numBytes).toBe(4); expect(mem.unreliable).toBeFalsy(); }); - - it('max', async () => { - console.log( - 'memory before', (tf.memory() as WebGLMemoryInfo).numBytesInGPU); - const img = tf.ones([300, 300]); - const fbmx = img.max(); - img.dispose(); - fbmx.dispose(); - console.log('memory after', (tf.memory() as WebGLMemoryInfo).numBytesInGPU); - }); }); // We do not yet fully support half float backends. These tests are a starting diff --git a/tfjs-backend-webgl/src/kernels/Max_test.ts b/tfjs-backend-webgl/src/kernels/Max_test.ts new file mode 100644 index 00000000000..0f3c42237d4 --- /dev/null +++ b/tfjs-backend-webgl/src/kernels/Max_test.ts @@ -0,0 +1,38 @@ +/** + * @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 * as tf from '@tensorflow/tfjs-core'; +// tslint:disable-next-line: no-imports-from-dist +import {ALL_ENVS, describeWithFlags} from '@tensorflow/tfjs-core/dist/jasmine_util'; + +describeWithFlags('Max', ALL_ENVS, () => { + it('does not have memory leak.', async () => { + const beforeDataIds = tf.engine().backend.numDataIds(); + + const img = tf.ones([100, 100]); + const fbmx = img.max(); + + const afterResDataIds = tf.engine().backend.numDataIds(); + expect(afterResDataIds).toEqual(beforeDataIds + 2); + + img.dispose(); + fbmx.dispose(); + + const afterDisposeDataIds = tf.engine().backend.numDataIds(); + expect(afterDisposeDataIds).toEqual(beforeDataIds); + }); +}); From eb807e3d22017ec6ddc923f76022ac268c639196 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 2 Sep 2020 11:35:08 -0400 Subject: [PATCH 07/13] save From 83c5ae3a04dd0e7d3ea31f4213c96663eff928fd Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Thu, 3 Sep 2020 08:57:24 -0400 Subject: [PATCH 08/13] fix --- tfjs-backend-webgl/src/kernels/Max_test.ts | 8 ++++---- tfjs-core/src/ops/max_test.ts | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/tfjs-backend-webgl/src/kernels/Max_test.ts b/tfjs-backend-webgl/src/kernels/Max_test.ts index 0f3c42237d4..a522dd12b4e 100644 --- a/tfjs-backend-webgl/src/kernels/Max_test.ts +++ b/tfjs-backend-webgl/src/kernels/Max_test.ts @@ -23,14 +23,14 @@ describeWithFlags('Max', ALL_ENVS, () => { it('does not have memory leak.', async () => { const beforeDataIds = tf.engine().backend.numDataIds(); - const img = tf.ones([100, 100]); - const fbmx = img.max(); + const x = tf.ones([100, 100]); + const xMax = x.max(); const afterResDataIds = tf.engine().backend.numDataIds(); expect(afterResDataIds).toEqual(beforeDataIds + 2); - img.dispose(); - fbmx.dispose(); + x.dispose(); + xMax.dispose(); const afterDisposeDataIds = tf.engine().backend.numDataIds(); expect(afterDisposeDataIds).toEqual(beforeDataIds); diff --git a/tfjs-core/src/ops/max_test.ts b/tfjs-core/src/ops/max_test.ts index f48f4cf7567..20942a375b8 100644 --- a/tfjs-core/src/ops/max_test.ts +++ b/tfjs-core/src/ops/max_test.ts @@ -32,6 +32,14 @@ describeWithFlags('max', ALL_ENVS, () => { expectArraysClose(await r.data(), 3); }); + it('with a large dimension', async () => { + const aData = new Float32Array(100); + aData[0] = 1; + const a = tf.tensor1d(aData); + const r = tf.max(a); + expectArraysClose(await r.data(), 1); + }); + it('ignores NaNs', async () => { expectArraysClose(await tf.max([3, NaN, 2]).data(), 3); }); From f1b095b40770252ebe52d88e2f1b3e80aecdd92a Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Thu, 3 Sep 2020 11:38:03 -0400 Subject: [PATCH 09/13] pr comments --- tfjs-backend-webgl/src/kernel_utils/reduce.ts | 20 +++++++++------- tfjs-backend-webgl/src/kernels/Max_test.ts | 24 ++++++++++--------- tfjs-core/src/ops/max_test.ts | 2 +- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/tfjs-backend-webgl/src/kernel_utils/reduce.ts b/tfjs-backend-webgl/src/kernel_utils/reduce.ts index cde1aa527b6..a2f88c26129 100644 --- a/tfjs-backend-webgl/src/kernel_utils/reduce.ts +++ b/tfjs-backend-webgl/src/kernel_utils/reduce.ts @@ -22,32 +22,34 @@ import {ReduceProgram} from '../reduce_gpu'; type ReduceTypes = 'all'|'any'|'max'|'min'|'sum'|'prod'; -function getReductionSizes(inShape: number[]): +// Returns an array of configuration objects that describe each stage of the +// reduction. +function getReductionStages(inShape: number[]): Array<{inSize: number, windowSize: number, outSize: number}> { - const sizes = []; + const stages = []; - while (sizes.length === 0 || sizes[sizes.length - 1].outSize !== 1) { + while (stages.length === 0 || stages[stages.length - 1].outSize !== 1) { const outSize: number = - sizes.length ? sizes[sizes.length - 1].outSize : inShape[1]; + stages.length ? stages[stages.length - 1].outSize : inShape[1]; const windowSize = backend_util.computeOptimalWindowSize(outSize); - sizes.push({ + stages.push({ inSize: outSize, windowSize, outSize: Math.ceil(outSize / windowSize) }); } - return sizes; + return stages; } export function reduce( x: TensorInfo, dtype: DataType, reductionType: ReduceTypes, backend: MathBackendWebGL): TensorInfo { - const sizes = getReductionSizes(x.shape); + const reductionStages = getReductionStages(x.shape); let result = x; - for (let i = 0; i < sizes.length; i++) { - const {inSize, windowSize, outSize} = sizes[i]; + for (let i = 0; i < reductionStages.length; i++) { + const {inSize, windowSize, outSize} = reductionStages[i]; const program = new ReduceProgram( {windowSize, inSize, batchSize: x.shape[0], outSize}, reductionType); diff --git a/tfjs-backend-webgl/src/kernels/Max_test.ts b/tfjs-backend-webgl/src/kernels/Max_test.ts index a522dd12b4e..e323b3c8fae 100644 --- a/tfjs-backend-webgl/src/kernels/Max_test.ts +++ b/tfjs-backend-webgl/src/kernels/Max_test.ts @@ -20,19 +20,21 @@ import * as tf from '@tensorflow/tfjs-core'; import {ALL_ENVS, describeWithFlags} from '@tensorflow/tfjs-core/dist/jasmine_util'; describeWithFlags('Max', ALL_ENVS, () => { - it('does not have memory leak.', async () => { - const beforeDataIds = tf.engine().backend.numDataIds(); + it('does not have memory leak when calling reduce multiple times.', + async () => { + const beforeDataIds = tf.engine().backend.numDataIds(); - const x = tf.ones([100, 100]); - const xMax = x.max(); + // Input must be large enough to trigger multi-stage reduction. + const x = tf.ones([100, 100]); + const xMax = x.max(); - const afterResDataIds = tf.engine().backend.numDataIds(); - expect(afterResDataIds).toEqual(beforeDataIds + 2); + const afterResDataIds = tf.engine().backend.numDataIds(); + expect(afterResDataIds).toEqual(beforeDataIds + 2); - x.dispose(); - xMax.dispose(); + x.dispose(); + xMax.dispose(); - const afterDisposeDataIds = tf.engine().backend.numDataIds(); - expect(afterDisposeDataIds).toEqual(beforeDataIds); - }); + const afterDisposeDataIds = tf.engine().backend.numDataIds(); + expect(afterDisposeDataIds).toEqual(beforeDataIds); + }); }); diff --git a/tfjs-core/src/ops/max_test.ts b/tfjs-core/src/ops/max_test.ts index 20942a375b8..3da2c8568ac 100644 --- a/tfjs-core/src/ops/max_test.ts +++ b/tfjs-core/src/ops/max_test.ts @@ -33,7 +33,7 @@ describeWithFlags('max', ALL_ENVS, () => { }); it('with a large dimension', async () => { - const aData = new Float32Array(100); + const aData = new Float32Array(1000); aData[0] = 1; const a = tf.tensor1d(aData); const r = tf.max(a); From 19a194bdc13e1478f916fdee4514cd979605f7e0 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Thu, 3 Sep 2020 15:04:21 -0400 Subject: [PATCH 10/13] fix --- tfjs-backend-webgl/src/kernel_utils/reduce.ts | 5 +---- tfjs-backend-webgl/src/kernels/Max_test.ts | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/tfjs-backend-webgl/src/kernel_utils/reduce.ts b/tfjs-backend-webgl/src/kernel_utils/reduce.ts index a2f88c26129..7d897917bfe 100644 --- a/tfjs-backend-webgl/src/kernel_utils/reduce.ts +++ b/tfjs-backend-webgl/src/kernel_utils/reduce.ts @@ -55,10 +55,7 @@ export function reduce( {windowSize, inSize, batchSize: x.shape[0], outSize}, reductionType); const previousResult = result; result = backend.runWebGLProgram(program, [result], dtype); - - if (i > 0) { - backend.disposeData(previousResult.dataId); - } + backend.disposeData(previousResult.dataId); } return result; diff --git a/tfjs-backend-webgl/src/kernels/Max_test.ts b/tfjs-backend-webgl/src/kernels/Max_test.ts index e323b3c8fae..acb7ca18430 100644 --- a/tfjs-backend-webgl/src/kernels/Max_test.ts +++ b/tfjs-backend-webgl/src/kernels/Max_test.ts @@ -29,7 +29,7 @@ describeWithFlags('Max', ALL_ENVS, () => { const xMax = x.max(); const afterResDataIds = tf.engine().backend.numDataIds(); - expect(afterResDataIds).toEqual(beforeDataIds + 2); + expect(afterResDataIds).toEqual(beforeDataIds + 1); x.dispose(); xMax.dispose(); From 62541cd74997c3c20d7a690aa7a2d0d459ae86bb Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Thu, 3 Sep 2020 16:15:48 -0400 Subject: [PATCH 11/13] revert --- tfjs-backend-webgl/src/kernel_utils/reduce.ts | 5 ++++- tfjs-backend-webgl/src/kernels/Max_test.ts | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tfjs-backend-webgl/src/kernel_utils/reduce.ts b/tfjs-backend-webgl/src/kernel_utils/reduce.ts index 7d897917bfe..a2f88c26129 100644 --- a/tfjs-backend-webgl/src/kernel_utils/reduce.ts +++ b/tfjs-backend-webgl/src/kernel_utils/reduce.ts @@ -55,7 +55,10 @@ export function reduce( {windowSize, inSize, batchSize: x.shape[0], outSize}, reductionType); const previousResult = result; result = backend.runWebGLProgram(program, [result], dtype); - backend.disposeData(previousResult.dataId); + + if (i > 0) { + backend.disposeData(previousResult.dataId); + } } return result; diff --git a/tfjs-backend-webgl/src/kernels/Max_test.ts b/tfjs-backend-webgl/src/kernels/Max_test.ts index acb7ca18430..1ad425bd98e 100644 --- a/tfjs-backend-webgl/src/kernels/Max_test.ts +++ b/tfjs-backend-webgl/src/kernels/Max_test.ts @@ -29,7 +29,7 @@ describeWithFlags('Max', ALL_ENVS, () => { const xMax = x.max(); const afterResDataIds = tf.engine().backend.numDataIds(); - expect(afterResDataIds).toEqual(beforeDataIds + 1); + expect(afterResDataIds).toEqual(beforeDataIds); x.dispose(); xMax.dispose(); From a4f6970219dc046e23ef15e7a8c70382cba532e3 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Thu, 3 Sep 2020 16:48:11 -0400 Subject: [PATCH 12/13] fix --- tfjs-backend-webgl/src/kernels/Max_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tfjs-backend-webgl/src/kernels/Max_test.ts b/tfjs-backend-webgl/src/kernels/Max_test.ts index 1ad425bd98e..e323b3c8fae 100644 --- a/tfjs-backend-webgl/src/kernels/Max_test.ts +++ b/tfjs-backend-webgl/src/kernels/Max_test.ts @@ -29,7 +29,7 @@ describeWithFlags('Max', ALL_ENVS, () => { const xMax = x.max(); const afterResDataIds = tf.engine().backend.numDataIds(); - expect(afterResDataIds).toEqual(beforeDataIds); + expect(afterResDataIds).toEqual(beforeDataIds + 2); x.dispose(); xMax.dispose(); From 98d31f04be836c9535d1f0ae46a54191fcde147d Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Thu, 3 Sep 2020 16:56:34 -0400 Subject: [PATCH 13/13] fix --- tfjs-backend-webgl/src/kernel_utils/reduce.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tfjs-backend-webgl/src/kernel_utils/reduce.ts b/tfjs-backend-webgl/src/kernel_utils/reduce.ts index a2f88c26129..9198b7b60bc 100644 --- a/tfjs-backend-webgl/src/kernel_utils/reduce.ts +++ b/tfjs-backend-webgl/src/kernel_utils/reduce.ts @@ -56,7 +56,7 @@ export function reduce( const previousResult = result; result = backend.runWebGLProgram(program, [result], dtype); - if (i > 0) { + if (previousResult.dataId !== x.dataId) { backend.disposeData(previousResult.dataId); } }