From bcf7f9dbc592783313d7820fdbc804f1f5535edc Mon Sep 17 00:00:00 2001 From: Linchenn <40653845+Linchenn@users.noreply.github.com> Date: Tue, 14 Jul 2020 10:49:05 -0700 Subject: [PATCH 01/10] add tests for Profiler --- tfjs-core/src/profiler_test.ts | 120 ++++++++++++++++++++++++++------- 1 file changed, 94 insertions(+), 26 deletions(-) diff --git a/tfjs-core/src/profiler_test.ts b/tfjs-core/src/profiler_test.ts index 7d49cfedcaa..3747984236c 100644 --- a/tfjs-core/src/profiler_test.ts +++ b/tfjs-core/src/profiler_test.ts @@ -18,8 +18,9 @@ import {BackendTimer, BackendTimingInfo} from './backends/backend'; import * as tf from './index'; import {describeWithFlags, SYNC_BACKEND_ENVS} from './jasmine_util'; -import {checkComputationForErrors, Logger, Profiler} from './profiler'; +import {checkComputationForErrors, KernelProfile, Logger, Profiler} from './profiler'; import {Tensor} from './tensor'; +import {NamedTensorMap} from './tensor_types'; import {TypedArray} from './types'; class TestBackendTimer implements BackendTimer { @@ -42,6 +43,32 @@ class TestLogger extends Logger { name: string, result: Tensor, vals: TypedArray, timeMs: number) {} } +async function promiseCheckWrapper( + acturalValPromise: Promise<{}>, truthVal: {}) { + return acturalValPromise.then(acturalVal => { + expect(acturalVal).toEqual(truthVal); + }); +} + +async function checkKernelProfile(acturalVal: KernelProfile, truthVal: { + kernelName: string, + result: Tensor, + vals: TypedArray, + timeMs: number|{error: string}, + inputs: NamedTensorMap, + extraInfo: string +}) { + expect(acturalVal.kernelName).toBe(truthVal.kernelName); + expect(acturalVal.result).toBe(truthVal.result); + expect(acturalVal.inputs).toBe(truthVal.inputs); + + return Promise.all([ + promiseCheckWrapper(acturalVal.vals, truthVal.vals), + promiseCheckWrapper(acturalVal.timeMs, truthVal.timeMs), + promiseCheckWrapper(acturalVal.extraInfo, truthVal.extraInfo), + ]); +} + describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { it('profiles simple function', doneFn => { const delayMs = 5; @@ -56,29 +83,28 @@ describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { spyOn(logger, 'logKernelProfile').and.callThrough(); const timeSpy = timer.time as jasmine.Spy; - const logKernelProfileSpy = logger.logKernelProfile as jasmine.Spy; let kernelCalled = false; const result = 1; const resultScalar = tf.scalar(result); - profiler.profileKernel('MatMul', inputs, () => { + const kernelProfiles = profiler.profileKernel('MatMul', inputs, () => { kernelCalled = true; return [resultScalar]; }); - setTimeout(() => { expect(timeSpy.calls.count()).toBe(1); - - expect(logKernelProfileSpy.calls.count()).toBe(1); - - expect(logKernelProfileSpy.calls.first().args).toEqual([ - 'MatMul', resultScalar, new Float32Array([result]), queryTimeMs, inputs, - extraInfo - ]); - expect(kernelCalled).toBe(true); - doneFn(); + expect(kernelProfiles.length).toBe(1); + + checkKernelProfile(kernelProfiles[0], { + kernelName: 'MatMul', + result: resultScalar, + vals: new Float32Array([result]), + timeMs: queryTimeMs, + inputs, + extraInfo, + }).then(() => doneFn()); }, delayMs * 2); }); @@ -94,37 +120,79 @@ describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { spyOn(timer, 'time').and.callThrough(); spyOn(logger, 'logKernelProfile').and.callThrough(); const timeSpy = timer.time as jasmine.Spy; - const logKernelProfileSpy = logger.logKernelProfile as jasmine.Spy; let matmulKernelCalled = false; let maxKernelCalled = false; const result = 1; const resultScalar = tf.scalar(result); - profiler.profileKernel('MatMul', inputs, () => { - const result = profiler.profileKernel('Max', inputs, () => { + let innerKernelProfile: KernelProfile[]; + const outerKernelProfile = profiler.profileKernel('MatMul', inputs, () => { + innerKernelProfile = profiler.profileKernel('Max', inputs, () => { maxKernelCalled = true; return [resultScalar]; }); matmulKernelCalled = true; - return result; + return innerKernelProfile.map(kernelProfile => kernelProfile.result); }); setTimeout(() => { expect(timeSpy.calls.count()).toBe(2); + expect(matmulKernelCalled).toBe(true); + expect(maxKernelCalled).toBe(true); + expect(innerKernelProfile.length).toBe(1); + expect(outerKernelProfile.length).toBe(1); + + const checkInnerKernelProfile = + checkKernelProfile(innerKernelProfile[0], { + kernelName: 'Max', + result: resultScalar, + vals: new Float32Array([result]), + timeMs: queryTimeMs, + inputs, + extraInfo + }); + const checkOuterKernelProfile = + checkKernelProfile(outerKernelProfile[0], { + kernelName: 'MatMul', + result: resultScalar, + vals: new Float32Array([result]), + timeMs: queryTimeMs * 2, + inputs, + extraInfo + }); + Promise.all([checkInnerKernelProfile, checkOuterKernelProfile]) + .then(() => doneFn()); + }, delayMs * 2); + }); + + it('log kernelProfile', doneFn => { + const delayMs = 5; + const queryTimeMs = 10; + const inputs = {'x': tf.tensor1d([1])}; + const extraInfo = ''; + const timer = new TestBackendTimer(delayMs, queryTimeMs, extraInfo); + const logger = new TestLogger(); + const profiler = new Profiler(timer, logger); + + spyOn(logger, 'logKernelProfile').and.callThrough(); + const logKernelProfileSpy = logger.logKernelProfile as jasmine.Spy; + + const result = 1; + const resultScalar = tf.scalar(result); + + const kernelProfiles = profiler.profileKernel('MatMul', inputs, () => { + return [resultScalar]; + }); + profiler.logKernelProfile(kernelProfiles); + + setTimeout(() => { + expect(logKernelProfileSpy.calls.count()).toBe(1); - expect(logKernelProfileSpy.calls.count()).toBe(2); expect(logKernelProfileSpy.calls.first().args).toEqual([ - 'Max', resultScalar, new Float32Array([result]), queryTimeMs, inputs, + 'MatMul', resultScalar, new Float32Array([result]), queryTimeMs, inputs, extraInfo ]); - expect(logKernelProfileSpy.calls.argsFor(1)).toEqual([ - 'MatMul', resultScalar, new Float32Array([result]), queryTimeMs * 2, - inputs, extraInfo - ]); - - expect(matmulKernelCalled).toBe(true); - expect(maxKernelCalled).toBe(true); doneFn(); }, delayMs * 2); }); From c2441ee7dde4eed5c74e785ee03e539d9591dad3 Mon Sep 17 00:00:00 2001 From: Linchenn <40653845+Linchenn@users.noreply.github.com> Date: Tue, 14 Jul 2020 10:50:43 -0700 Subject: [PATCH 02/10] decouple Profiler.profileKernel --- tfjs-core/src/profiler.ts | 56 ++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/tfjs-core/src/profiler.ts b/tfjs-core/src/profiler.ts index 7692d775696..fc319b6efbf 100644 --- a/tfjs-core/src/profiler.ts +++ b/tfjs-core/src/profiler.ts @@ -21,6 +21,15 @@ import {NamedTensorMap} from './tensor_types'; import {DataType, DataTypeMap, TypedArray} from './types'; import * as util from './util'; +export type KernelProfile = { + kernelName: string, + result: Tensor, + vals: Promise, + inputs: NamedTensorMap, + timeMs: Promise, + extraInfo: Promise, +}; + export class Profiler { constructor(private backendTimer: BackendTimer, private logger?: Logger) { if (logger == null) { @@ -29,32 +38,53 @@ export class Profiler { } profileKernel(kernelName: string, inputs: NamedTensorMap, f: () => Tensor[]): - Tensor[] { + KernelProfile[] { let outputs: Tensor[]; const holdResultWrapperFn = () => { outputs = f(); }; const timer = this.backendTimer.time(holdResultWrapperFn); + const kernelProfiles: KernelProfile[] = []; + outputs.forEach(r => { // Dangling promise here because we don't want to propagate up // asynchronicity. - r.data().then(vals => { - checkComputationForErrors(vals, r.dtype, kernelName); + const kernelProfile = { + kernelName, + result: r, + inputs, + timeMs: timer.then(timing => timing.kernelMs), + extraInfo: timer.then( + timing => timing.getExtraProfileInfo() != null ? + timing.getExtraProfileInfo() : + ''), + vals: r.data().then(vals => { + checkComputationForErrors(vals, r.dtype, kernelName); + return vals; + }) + }; + kernelProfiles.push(kernelProfile); + }); + + return kernelProfiles; + } + + logKernelProfile(kernelProfiles: KernelProfile[]): void { + if (!Array.isArray(kernelProfiles)) { + kernelProfiles = [kernelProfiles]; + } - timer.then(timing => { - let extraInfo = ''; - if (timing.getExtraProfileInfo != null) { - extraInfo = timing.getExtraProfileInfo(); - } + kernelProfiles.forEach(kernelProfile => { + const {kernelName, result, vals, timeMs, inputs, extraInfo} = + kernelProfile; - this.logger.logKernelProfile( - kernelName, r, vals, timing.kernelMs, inputs, extraInfo); - }); + Promise.all([vals, timeMs, extraInfo]).then(valueContainer => { + this.logger.logKernelProfile( + kernelName, result, valueContainer[0], valueContainer[1], inputs, + valueContainer[2]); }); }); - - return outputs; } } From 5e4ef9ff0a660fa5503bd3205703a6168c142d46 Mon Sep 17 00:00:00 2001 From: Linchenn <40653845+Linchenn@users.noreply.github.com> Date: Tue, 14 Jul 2020 10:53:22 -0700 Subject: [PATCH 03/10] use new Profiler --- tfjs-core/src/engine.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tfjs-core/src/engine.ts b/tfjs-core/src/engine.ts index b2d26a1be8b..da89386986f 100644 --- a/tfjs-core/src/engine.ts +++ b/tfjs-core/src/engine.ts @@ -20,6 +20,7 @@ import {Environment, setEnvironmentGlobal} from './environment'; import {getGlobalNamespace} from './global_util'; import {getGradient, getKernel, getKernelsForBackend, GradFunc, NamedAttrMap, TensorInfo} from './kernel_registry'; import {Profiler} from './profiler'; +import {KernelProfile} from './profiler'; import {backpropagateGradients, getFilteredNodesXToY, TapeNode} from './tape'; import {DataId, setTensorTracker, Tensor, TensorTracker, Variable} from './tensor'; import {GradSaveFunc, NamedTensorMap, NamedVariableMap, TensorContainer} from './tensor_types'; @@ -51,7 +52,7 @@ export type MemoryInfo = { unreliable?: boolean; reasons: string[]; }; -type KernelProfile = { +type KernelInfo = { name: string; bytesAdded: number; totalBytesSnapshot: number; tensorsAdded: number; totalTensorsSnapshot: number; @@ -61,7 +62,7 @@ type KernelProfile = { export type ProfileInfo = { newBytes: number; newTensors: number; peakBytes: number; - kernels: KernelProfile[]; + kernels: KernelInfo[]; result: TensorContainer; }; @@ -613,13 +614,15 @@ export class Engine implements TensorTracker, DataMover { } // Stop recording to a tape when running a kernel. + let kernelProfiles: KernelProfile[]; this.scopedRun( () => this.state.kernelDepth++, () => this.state.kernelDepth--, () => { if (!this.ENV.getBool('DEBUG')) { outputs = kernelFunc(); } else { - outputs = this.profiler.profileKernel( + kernelProfiles = this.profiler.profileKernel( kernelName, inputs, () => kernelFunc()); + outputs = kernelProfiles.map(kernelProfile => kernelProfile.result); } }); @@ -628,6 +631,10 @@ export class Engine implements TensorTracker, DataMover { kernelName, inputs, outputs, backwardsFunc, saved, attrs); } + if (this.ENV.getBool('DEBUG')) { + this.profiler.logKernelProfile(kernelProfiles); + } + if (this.state.profiling) { this.state.activeProfile.kernels.push({ name: kernelName, From 125c5dd193d32f998b5934cf60163638b6f4fdaa Mon Sep 17 00:00:00 2001 From: Linchenn <40653845+Linchenn@users.noreply.github.com> Date: Tue, 14 Jul 2020 11:29:55 -0700 Subject: [PATCH 04/10] fix --- tfjs-core/src/profiler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tfjs-core/src/profiler.ts b/tfjs-core/src/profiler.ts index fc319b6efbf..1cf863617ec 100644 --- a/tfjs-core/src/profiler.ts +++ b/tfjs-core/src/profiler.ts @@ -56,7 +56,7 @@ export class Profiler { inputs, timeMs: timer.then(timing => timing.kernelMs), extraInfo: timer.then( - timing => timing.getExtraProfileInfo() != null ? + timing => timing.getExtraProfileInfo != null ? timing.getExtraProfileInfo() : ''), vals: r.data().then(vals => { From 7ef411ede920e23d47f04482252e91d69107186b Mon Sep 17 00:00:00 2001 From: Linchenn <40653845+Linchenn@users.noreply.github.com> Date: Tue, 14 Jul 2020 20:17:22 -0700 Subject: [PATCH 05/10] move logging into scopedRun --- tfjs-core/src/engine.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tfjs-core/src/engine.ts b/tfjs-core/src/engine.ts index da89386986f..2eb00abe502 100644 --- a/tfjs-core/src/engine.ts +++ b/tfjs-core/src/engine.ts @@ -622,6 +622,7 @@ export class Engine implements TensorTracker, DataMover { } else { kernelProfiles = this.profiler.profileKernel( kernelName, inputs, () => kernelFunc()); + this.profiler.logKernelProfile(kernelProfiles); outputs = kernelProfiles.map(kernelProfile => kernelProfile.result); } }); @@ -631,10 +632,6 @@ export class Engine implements TensorTracker, DataMover { kernelName, inputs, outputs, backwardsFunc, saved, attrs); } - if (this.ENV.getBool('DEBUG')) { - this.profiler.logKernelProfile(kernelProfiles); - } - if (this.state.profiling) { this.state.activeProfile.kernels.push({ name: kernelName, From 74fdc9216fdd51ee6b32a770c109e6fe3b40cd4d Mon Sep 17 00:00:00 2001 From: Linchenn <40653845+Linchenn@users.noreply.github.com> Date: Wed, 15 Jul 2020 17:17:56 -0700 Subject: [PATCH 06/10] change profileKernel return type from KernelProfile[] to KernelProfile --- tfjs-core/src/engine.ts | 8 ++-- tfjs-core/src/profiler.ts | 58 ++++++++++++--------------- tfjs-core/src/profiler_test.ts | 73 +++++++++++++++++----------------- 3 files changed, 66 insertions(+), 73 deletions(-) diff --git a/tfjs-core/src/engine.ts b/tfjs-core/src/engine.ts index 2eb00abe502..befd04f4fc3 100644 --- a/tfjs-core/src/engine.ts +++ b/tfjs-core/src/engine.ts @@ -614,16 +614,16 @@ export class Engine implements TensorTracker, DataMover { } // Stop recording to a tape when running a kernel. - let kernelProfiles: KernelProfile[]; + let kernelProfile: KernelProfile; this.scopedRun( () => this.state.kernelDepth++, () => this.state.kernelDepth--, () => { if (!this.ENV.getBool('DEBUG')) { outputs = kernelFunc(); } else { - kernelProfiles = this.profiler.profileKernel( + kernelProfile = this.profiler.profileKernel( kernelName, inputs, () => kernelFunc()); - this.profiler.logKernelProfile(kernelProfiles); - outputs = kernelProfiles.map(kernelProfile => kernelProfile.result); + this.profiler.logKernelProfile(kernelProfile); + outputs = kernelProfile.outputs; } }); diff --git a/tfjs-core/src/profiler.ts b/tfjs-core/src/profiler.ts index 1cf863617ec..527e785b6e3 100644 --- a/tfjs-core/src/profiler.ts +++ b/tfjs-core/src/profiler.ts @@ -23,11 +23,11 @@ import * as util from './util'; export type KernelProfile = { kernelName: string, - result: Tensor, - vals: Promise, + outputs: Tensor[], + vals: Array>, inputs: NamedTensorMap, timeMs: Promise, - extraInfo: Promise, + extraInfo: Promise }; export class Profiler { @@ -38,48 +38,42 @@ export class Profiler { } profileKernel(kernelName: string, inputs: NamedTensorMap, f: () => Tensor[]): - KernelProfile[] { + KernelProfile { let outputs: Tensor[]; const holdResultWrapperFn = () => { outputs = f(); }; const timer = this.backendTimer.time(holdResultWrapperFn); - const kernelProfiles: KernelProfile[] = []; - - outputs.forEach(r => { + const outputVals = outputs.map(r => { // Dangling promise here because we don't want to propagate up // asynchronicity. - const kernelProfile = { - kernelName, - result: r, - inputs, - timeMs: timer.then(timing => timing.kernelMs), - extraInfo: timer.then( - timing => timing.getExtraProfileInfo != null ? - timing.getExtraProfileInfo() : - ''), - vals: r.data().then(vals => { - checkComputationForErrors(vals, r.dtype, kernelName); - return vals; - }) - }; - kernelProfiles.push(kernelProfile); + return r.data().then(tensorVals => { + checkComputationForErrors(tensorVals, r.dtype, kernelName); + return tensorVals; + }); }); - return kernelProfiles; + const kernelProfile = { + kernelName, + outputs, + inputs, + timeMs: timer.then(timing => timing.kernelMs), + extraInfo: timer.then( + timing => timing.getExtraProfileInfo != null ? + timing.getExtraProfileInfo() : + ''), + vals: outputVals + }; + return kernelProfile; } - logKernelProfile(kernelProfiles: KernelProfile[]): void { - if (!Array.isArray(kernelProfiles)) { - kernelProfiles = [kernelProfiles]; - } - - kernelProfiles.forEach(kernelProfile => { - const {kernelName, result, vals, timeMs, inputs, extraInfo} = - kernelProfile; + logKernelProfile(kernelProfile: KernelProfile): void { + const {kernelName, outputs, vals, timeMs, inputs, extraInfo} = + kernelProfile; - Promise.all([vals, timeMs, extraInfo]).then(valueContainer => { + outputs.forEach((result, index) => { + Promise.all([vals[index], timeMs, extraInfo]).then(valueContainer => { this.logger.logKernelProfile( kernelName, result, valueContainer[0], valueContainer[1], inputs, valueContainer[2]); diff --git a/tfjs-core/src/profiler_test.ts b/tfjs-core/src/profiler_test.ts index 3747984236c..80e5e2b1717 100644 --- a/tfjs-core/src/profiler_test.ts +++ b/tfjs-core/src/profiler_test.ts @@ -43,30 +43,34 @@ class TestLogger extends Logger { name: string, result: Tensor, vals: TypedArray, timeMs: number) {} } -async function promiseCheckWrapper( - acturalValPromise: Promise<{}>, truthVal: {}) { +function promiseCheckWrapper(acturalValPromise: Promise<{}>, truthVal: {}) { return acturalValPromise.then(acturalVal => { expect(acturalVal).toEqual(truthVal); }); } -async function checkKernelProfile(acturalVal: KernelProfile, truthVal: { +function checkKernelProfile(acturalVal: KernelProfile, truthVal: { kernelName: string, - result: Tensor, - vals: TypedArray, + outputs: Tensor[], + vals: TypedArray[], timeMs: number|{error: string}, inputs: NamedTensorMap, extraInfo: string }) { expect(acturalVal.kernelName).toBe(truthVal.kernelName); - expect(acturalVal.result).toBe(truthVal.result); expect(acturalVal.inputs).toBe(truthVal.inputs); + acturalVal.outputs.forEach((output, index) => { + expect(output).toBe(truthVal.outputs[index]); + }); - return Promise.all([ - promiseCheckWrapper(acturalVal.vals, truthVal.vals), + const promiseContainer = [ promiseCheckWrapper(acturalVal.timeMs, truthVal.timeMs), promiseCheckWrapper(acturalVal.extraInfo, truthVal.extraInfo), - ]); + ]; + acturalVal.vals.forEach((val, index) => { + promiseContainer.push(promiseCheckWrapper(val, truthVal.vals[index])); + }); + return Promise.all(promiseContainer); } describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { @@ -88,19 +92,18 @@ describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { const result = 1; const resultScalar = tf.scalar(result); - const kernelProfiles = profiler.profileKernel('MatMul', inputs, () => { + const kernelProfile = profiler.profileKernel('MatMul', inputs, () => { kernelCalled = true; return [resultScalar]; }); setTimeout(() => { expect(timeSpy.calls.count()).toBe(1); expect(kernelCalled).toBe(true); - expect(kernelProfiles.length).toBe(1); - checkKernelProfile(kernelProfiles[0], { + checkKernelProfile(kernelProfile, { kernelName: 'MatMul', - result: resultScalar, - vals: new Float32Array([result]), + outputs: [resultScalar], + vals: [new Float32Array([result])], timeMs: queryTimeMs, inputs, extraInfo, @@ -126,41 +129,37 @@ describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { const result = 1; const resultScalar = tf.scalar(result); - let innerKernelProfile: KernelProfile[]; + let innerKernelProfile: KernelProfile; const outerKernelProfile = profiler.profileKernel('MatMul', inputs, () => { innerKernelProfile = profiler.profileKernel('Max', inputs, () => { maxKernelCalled = true; return [resultScalar]; }); matmulKernelCalled = true; - return innerKernelProfile.map(kernelProfile => kernelProfile.result); + return innerKernelProfile.outputs; }); setTimeout(() => { expect(timeSpy.calls.count()).toBe(2); expect(matmulKernelCalled).toBe(true); expect(maxKernelCalled).toBe(true); - expect(innerKernelProfile.length).toBe(1); - expect(outerKernelProfile.length).toBe(1); - - const checkInnerKernelProfile = - checkKernelProfile(innerKernelProfile[0], { - kernelName: 'Max', - result: resultScalar, - vals: new Float32Array([result]), - timeMs: queryTimeMs, - inputs, - extraInfo - }); - const checkOuterKernelProfile = - checkKernelProfile(outerKernelProfile[0], { - kernelName: 'MatMul', - result: resultScalar, - vals: new Float32Array([result]), - timeMs: queryTimeMs * 2, - inputs, - extraInfo - }); + + const checkInnerKernelProfile = checkKernelProfile(innerKernelProfile, { + kernelName: 'Max', + outputs: [resultScalar], + vals: [new Float32Array([result])], + timeMs: queryTimeMs, + inputs, + extraInfo + }); + const checkOuterKernelProfile = checkKernelProfile(outerKernelProfile, { + kernelName: 'MatMul', + outputs: [resultScalar], + vals: [new Float32Array([result])], + timeMs: queryTimeMs * 2, + inputs, + extraInfo + }); Promise.all([checkInnerKernelProfile, checkOuterKernelProfile]) .then(() => doneFn()); }, delayMs * 2); From e48efcb6cf2e7640759ca9144cda143ead99460f Mon Sep 17 00:00:00 2001 From: Linchenn <40653845+Linchenn@users.noreply.github.com> Date: Mon, 20 Jul 2020 09:28:30 -0700 Subject: [PATCH 07/10] delete vals --- tfjs-core/src/profiler.ts | 16 ++++++---------- tfjs-core/src/profiler_test.ts | 7 ------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/tfjs-core/src/profiler.ts b/tfjs-core/src/profiler.ts index 527e785b6e3..eb04520f082 100644 --- a/tfjs-core/src/profiler.ts +++ b/tfjs-core/src/profiler.ts @@ -24,7 +24,6 @@ import * as util from './util'; export type KernelProfile = { kernelName: string, outputs: Tensor[], - vals: Array>, inputs: NamedTensorMap, timeMs: Promise, extraInfo: Promise @@ -45,12 +44,11 @@ export class Profiler { }; const timer = this.backendTimer.time(holdResultWrapperFn); - const outputVals = outputs.map(r => { + outputs.map(r => { // Dangling promise here because we don't want to propagate up // asynchronicity. - return r.data().then(tensorVals => { + r.data().then(tensorVals => { checkComputationForErrors(tensorVals, r.dtype, kernelName); - return tensorVals; }); }); @@ -62,18 +60,16 @@ export class Profiler { extraInfo: timer.then( timing => timing.getExtraProfileInfo != null ? timing.getExtraProfileInfo() : - ''), - vals: outputVals + '') }; return kernelProfile; } logKernelProfile(kernelProfile: KernelProfile): void { - const {kernelName, outputs, vals, timeMs, inputs, extraInfo} = - kernelProfile; + const {kernelName, outputs, timeMs, inputs, extraInfo} = kernelProfile; - outputs.forEach((result, index) => { - Promise.all([vals[index], timeMs, extraInfo]).then(valueContainer => { + outputs.forEach(result => { + Promise.all([result.data(), timeMs, extraInfo]).then(valueContainer => { this.logger.logKernelProfile( kernelName, result, valueContainer[0], valueContainer[1], inputs, valueContainer[2]); diff --git a/tfjs-core/src/profiler_test.ts b/tfjs-core/src/profiler_test.ts index 80e5e2b1717..bdf9014f1dd 100644 --- a/tfjs-core/src/profiler_test.ts +++ b/tfjs-core/src/profiler_test.ts @@ -52,7 +52,6 @@ function promiseCheckWrapper(acturalValPromise: Promise<{}>, truthVal: {}) { function checkKernelProfile(acturalVal: KernelProfile, truthVal: { kernelName: string, outputs: Tensor[], - vals: TypedArray[], timeMs: number|{error: string}, inputs: NamedTensorMap, extraInfo: string @@ -67,9 +66,6 @@ function checkKernelProfile(acturalVal: KernelProfile, truthVal: { promiseCheckWrapper(acturalVal.timeMs, truthVal.timeMs), promiseCheckWrapper(acturalVal.extraInfo, truthVal.extraInfo), ]; - acturalVal.vals.forEach((val, index) => { - promiseContainer.push(promiseCheckWrapper(val, truthVal.vals[index])); - }); return Promise.all(promiseContainer); } @@ -103,7 +99,6 @@ describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { checkKernelProfile(kernelProfile, { kernelName: 'MatMul', outputs: [resultScalar], - vals: [new Float32Array([result])], timeMs: queryTimeMs, inputs, extraInfo, @@ -147,7 +142,6 @@ describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { const checkInnerKernelProfile = checkKernelProfile(innerKernelProfile, { kernelName: 'Max', outputs: [resultScalar], - vals: [new Float32Array([result])], timeMs: queryTimeMs, inputs, extraInfo @@ -155,7 +149,6 @@ describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { const checkOuterKernelProfile = checkKernelProfile(outerKernelProfile, { kernelName: 'MatMul', outputs: [resultScalar], - vals: [new Float32Array([result])], timeMs: queryTimeMs * 2, inputs, extraInfo From 8e244f65dd35ca1bc5e4e3713d4c72eeeeb97257 Mon Sep 17 00:00:00 2001 From: Linchenn <40653845+Linchenn@users.noreply.github.com> Date: Mon, 20 Jul 2020 17:12:00 -0700 Subject: [PATCH 08/10] fix --- tfjs-core/src/engine.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tfjs-core/src/engine.ts b/tfjs-core/src/engine.ts index befd04f4fc3..284d3ad836b 100644 --- a/tfjs-core/src/engine.ts +++ b/tfjs-core/src/engine.ts @@ -19,8 +19,7 @@ import {BackendTimingInfo, DataMover, KernelBackend} from './backends/backend'; import {Environment, setEnvironmentGlobal} from './environment'; import {getGlobalNamespace} from './global_util'; import {getGradient, getKernel, getKernelsForBackend, GradFunc, NamedAttrMap, TensorInfo} from './kernel_registry'; -import {Profiler} from './profiler'; -import {KernelProfile} from './profiler'; +import {KernelProfile, Profiler} from './profiler'; import {backpropagateGradients, getFilteredNodesXToY, TapeNode} from './tape'; import {DataId, setTensorTracker, Tensor, TensorTracker, Variable} from './tensor'; import {GradSaveFunc, NamedTensorMap, NamedVariableMap, TensorContainer} from './tensor_types'; From ef1b9e8d2f45bda808f8dfcad8d7b4bd6f0fe223 Mon Sep 17 00:00:00 2001 From: Linchenn <40653845+Linchenn@users.noreply.github.com> Date: Thu, 30 Jul 2020 17:34:50 -0700 Subject: [PATCH 09/10] try fixing memory error move `let kernelProfile: KernelProfile;` from `runKernelFunc` into its `scopedRun` --- tfjs-core/src/engine.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tfjs-core/src/engine.ts b/tfjs-core/src/engine.ts index 1243b9e13d6..5df5fbd3680 100644 --- a/tfjs-core/src/engine.ts +++ b/tfjs-core/src/engine.ts @@ -613,13 +613,12 @@ export class Engine implements TensorTracker, DataMover { } // Stop recording to a tape when running a kernel. - let kernelProfile: KernelProfile; this.scopedRun( () => this.state.kernelDepth++, () => this.state.kernelDepth--, () => { if (!this.ENV.getBool('DEBUG')) { outputs = kernelFunc(); } else { - kernelProfile = this.profiler.profileKernel( + const kernelProfile = this.profiler.profileKernel( kernelName, inputs, () => kernelFunc()); this.profiler.logKernelProfile(kernelProfile); outputs = kernelProfile.outputs; From b89996e15f6a90f8ead41a233d8258bef62e4180 Mon Sep 17 00:00:00 2001 From: Linchenn <40653845+Linchenn@users.noreply.github.com> Date: Thu, 30 Jul 2020 18:04:18 -0700 Subject: [PATCH 10/10] fix --- tfjs-core/src/engine.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tfjs-core/src/engine.ts b/tfjs-core/src/engine.ts index 5df5fbd3680..b18af07bb94 100644 --- a/tfjs-core/src/engine.ts +++ b/tfjs-core/src/engine.ts @@ -618,7 +618,8 @@ export class Engine implements TensorTracker, DataMover { if (!this.ENV.getBool('DEBUG')) { outputs = kernelFunc(); } else { - const kernelProfile = this.profiler.profileKernel( + let kernelProfile: KernelProfile; + kernelProfile = this.profiler.profileKernel( kernelName, inputs, () => kernelFunc()); this.profiler.logKernelProfile(kernelProfile); outputs = kernelProfile.outputs;