From db89ef64b5a9a006d713cacb6a437c0b476dafbc Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Tue, 13 Aug 2019 14:54:33 -0400 Subject: [PATCH 01/14] init --- tfjs-core/src/index.ts | 4 +- tfjs-webgpu/package.json | 4 +- tfjs-webgpu/src/backend_webgpu.ts | 73 ++++++++++++++++++++++++++++++- tfjs-webgpu/yarn.lock | 43 +++++------------- 4 files changed, 85 insertions(+), 39 deletions(-) diff --git a/tfjs-core/src/index.ts b/tfjs-core/src/index.ts index 453925df6f9..4a67212d042 100644 --- a/tfjs-core/src/index.ts +++ b/tfjs-core/src/index.ts @@ -55,7 +55,7 @@ export {RMSPropOptimizer} from './optimizers/rmsprop_optimizer'; export {SGDOptimizer} from './optimizers/sgd_optimizer'; export {Scalar, Tensor, Tensor1D, Tensor2D, Tensor3D, Tensor4D, Tensor5D, TensorBuffer, variable, Variable} from './tensor'; export {GradSaveFunc, NamedTensorMap, TensorContainer, TensorContainerArray, TensorContainerObject} from './tensor_types'; -export {DataType, DataTypeMap, DataValues, Rank, ShapeMap, TensorLike} from './types'; +export {DataType, DataTypeMap, DataValues, Rank, RecursiveArray, ShapeMap, TensorLike} from './types'; export * from './ops/ops'; export {LSTMCellFunc} from './ops/lstm'; @@ -65,7 +65,7 @@ export * from './train'; export * from './globals'; export {customGrad, grad, grads, valueAndGrad, valueAndGrads, variableGrads} from './gradients'; -export {TimingInfo} from './engine'; +export {TimingInfo, MemoryInfo} from './engine'; export {ENV, Environment} from './environment'; export {Platform} from './platforms/platform'; diff --git a/tfjs-webgpu/package.json b/tfjs-webgpu/package.json index f257f356207..5e4a3ef08d0 100644 --- a/tfjs-webgpu/package.json +++ b/tfjs-webgpu/package.json @@ -18,7 +18,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@tensorflow/tfjs-core": "1.2.1", + "@tensorflow/tfjs-core": "1.2.7", "@types/jasmine": "~2.5.53", "clang-format": "~1.2.2", "http-server": "~0.10.0", @@ -47,4 +47,4 @@ "peerDependencies": { "@tensorflow/tfjs-core": "1.2.1" } -} \ No newline at end of file +} diff --git a/tfjs-webgpu/src/backend_webgpu.ts b/tfjs-webgpu/src/backend_webgpu.ts index 19fe0055db7..19b53588d66 100644 --- a/tfjs-webgpu/src/backend_webgpu.ts +++ b/tfjs-webgpu/src/backend_webgpu.ts @@ -19,7 +19,7 @@ import './flags_webgpu'; -import {backend_util, DataMover, DataType, ENV, KernelBackend, Rank, ShapeMap, Tensor, Tensor2D, Tensor3D, Tensor4D, util} from '@tensorflow/tfjs-core'; +import {backend_util, DataMover, DataType, ENV, KernelBackend, Rank, ShapeMap, Tensor, Tensor2D, Tensor3D, Tensor4D, TimingInfo, util} from '@tensorflow/tfjs-core'; import * as shaderc from '@webgpu/shaderc'; import {BufferManager} from './buffer_manager'; @@ -40,12 +40,20 @@ import {UnaryOpProgram} from './kernels/unary_op_webgpu'; import * as webgpu_program from './kernels/webgpu_program'; import {WebGPUBinary} from './kernels/webgpu_program'; -// TODO: Delete this and import from core once new release is published. +// START TO-IMPORT-FROM-CORE ============================ +// TODO: Delete definitions in this section and import from core once new +// release is published. type MemoryInfo = { numTensors: number; numDataBuffers: number; numBytes: number; unreliable?: boolean; reasons: string[]; }; +// tslint:disable-next-line:no-any +interface RecursiveArray { + [index: number]: T|RecursiveArray; +} +// END TO-IMPORT-FROM-CORE ============================== + export interface WebGPUMemoryInfo extends MemoryInfo { numBytesInGPU: number; unreliable: boolean; @@ -66,6 +74,17 @@ type TensorInfo = { interface DataId {} +export type WebGPUKernelInfo = { + name: string; query: Promise; +}; + +export type TimerNode = RecursiveArray|WebGPUKernelInfo; + +export interface WebGPUTimingInfo extends TimingInfo { + uploadWaitMs: number; + downloadWaitMs: number; +} + const DEFAULT_GPUBUFFER_USAGE = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST; @@ -86,6 +105,11 @@ export class WebGPUBackend extends KernelBackend { private disposed = false; + private programTimersStack: TimerNode[]; + private activeTimers: TimerNode[]; + private uploadWaitMs = 0; + private downloadWaitMs = 0; + constructor(device: GPUDevice, shaderc: shaderc.Shaderc) { super(); this.binaryCache = {}; @@ -244,6 +268,51 @@ export class WebGPUBackend extends KernelBackend { return dataAsTypedArray; } + async time(f: () => void): Promise { + const oldActiveTimers = this.activeTimers; + const newActiveTimers: TimerNode[] = []; + + let outerMostTime = false; + if (this.programTimersStack == null) { + this.programTimersStack = newActiveTimers; + outerMostTime = true; + } else { + this.activeTimers.push(newActiveTimers); + } + this.activeTimers = newActiveTimers; + + f(); + + const flattenedActiveTimerQueries = + util.flatten(this.activeTimers.map((d: WebGPUKernelInfo) => d.query)) + .filter(d => d != null); + const flattenedActiveTimerNames = + util.flatten(this.activeTimers.map((d: WebGPUKernelInfo) => d.name)) + .filter(d => d != null); + + this.activeTimers = oldActiveTimers; + + if (outerMostTime) { + this.programTimersStack = null; + } + + const kernelMs = await Promise.all(flattenedActiveTimerQueries); + + const res: WebGPUTimingInfo = { + uploadWaitMs: this.uploadWaitMs, + downloadWaitMs: this.downloadWaitMs, + kernelMs: util.sum(kernelMs), + getExtraProfileInfo: () => + kernelMs.map((d, i) => ({name: flattenedActiveTimerNames[i], ms: d})) + .map(d => `${d.name}: ${d.ms}`) + .join(', '), + wallMs: null + }; + this.uploadWaitMs = 0; + this.downloadWaitMs = 0; + return res; + } + private getAndSavePipeline( key: string, getBinary: () => webgpu_program.WebGPUBinary) { if (!(key in this.binaryCache)) { diff --git a/tfjs-webgpu/yarn.lock b/tfjs-webgpu/yarn.lock index cb989bf7df9..a14481396b1 100644 --- a/tfjs-webgpu/yarn.lock +++ b/tfjs-webgpu/yarn.lock @@ -2,18 +2,17 @@ # yarn lockfile v1 -"@tensorflow/tfjs-core@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-1.2.1.tgz#0ff54aa7fd412b8c17e39f6ec5a97bf032e8f530" - integrity sha512-cpSHl+tP7cketq0cAyJPbIGxNlPV7mR6lkMLLDvZAmZUTBSyBufCdJg/KwgjHMZksE/KqjL4/RyccOGBAQcb7g== +"@tensorflow/tfjs-core@1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-1.2.7.tgz#522328de16470aa9f7c15b91e4b68616f425002a" + integrity sha512-RsXavYKMc0MOcCmOyD7HE8am1tWlDGXl0nJbsdib7ubmvMuH6KnrZ302eTYV7k1RMq+/ukkioJmCcw13hopuHQ== dependencies: + "@types/offscreencanvas" "~2019.3.0" "@types/seedrandom" "2.4.27" "@types/webgl-ext" "0.0.30" "@types/webgl2" "0.0.4" node-fetch "~2.1.2" seedrandom "2.4.3" - optionalDependencies: - rollup-plugin-visualizer "~1.1.1" "@types/estree@0.0.38": version "0.0.38" @@ -30,6 +29,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.4.tgz#f83ec3c3e05b174b7241fadeb6688267fe5b22ca" integrity sha512-+rabAZZ3Yn7tF/XPGHupKIL5EcAbrLxnTr/hgQICxbeuAfWtT0UZSfULE+ndusckBItcv4o6ZeOJplQikVcLvQ== +"@types/offscreencanvas@~2019.3.0": + version "2019.3.0" + resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz#3336428ec7e9180cf4566dfea5da04eb586a6553" + integrity sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q== + "@types/seedrandom@2.4.27": version "2.4.27" resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.27.tgz#9db563937dd86915f69092bc43259d2f48578e41" @@ -1974,11 +1978,6 @@ is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -2671,13 +2670,6 @@ opener@~1.4.0: resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" integrity sha1-XG2ixdflgx6P+jlklQ+NZnSskLg= -opn@^5.4.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" - integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== - dependencies: - is-wsl "^1.1.0" - optimist@0.6.x, optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -3185,16 +3177,6 @@ rollup-plugin-uglify@~3.0.0: dependencies: uglify-es "^3.3.7" -rollup-plugin-visualizer@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-1.1.1.tgz#454ae0aed23845407ebfb81cc52114af308d6d90" - integrity sha512-7xkSKp+dyJmSC7jg2LXqViaHuOnF1VvIFCnsZEKjrgT5ZVyiLLSbeszxFcQSfNJILphqgAEmWAUz0Z4xYScrRw== - dependencies: - mkdirp "^0.5.1" - opn "^5.4.0" - source-map "^0.7.3" - typeface-oswald "0.0.54" - rollup-pluginutils@^2.0.1: version "2.8.1" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.1.tgz#8fa6dd0697344938ef26c2c09d2488ce9e33ce97" @@ -3709,11 +3691,6 @@ type-is@~1.6.16: media-typer "0.3.0" mime-types "~2.1.18" -typeface-oswald@0.0.54: - version "0.0.54" - resolved "https://registry.yarnpkg.com/typeface-oswald/-/typeface-oswald-0.0.54.tgz#1e253011622cdd50f580c04e7d625e7f449763d7" - integrity sha512-U1WMNp4qfy4/3khIfHMVAIKnNu941MXUfs3+H9R8PFgnoz42Hh9pboSFztWr86zut0eXC8byalmVhfkiKON/8Q== - typescript@3.3.3333: version "3.3.3333" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.3333.tgz#171b2c5af66c59e9431199117a3bcadc66fdcfd6" From e4f65c2be7da7cf996a93bedde72debce574db7e Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Tue, 13 Aug 2019 15:04:35 -0400 Subject: [PATCH 02/14] break apart benchmark page --- tfjs-core/benchmarks/index.html | 284 +--------------------------- tfjs-core/benchmarks/main.css | 120 ++++++++++++ tfjs-core/benchmarks/modelConfig.js | 131 +++++++++++++ tfjs-core/benchmarks/util.js | 22 +++ 4 files changed, 278 insertions(+), 279 deletions(-) create mode 100644 tfjs-core/benchmarks/main.css create mode 100644 tfjs-core/benchmarks/modelConfig.js create mode 100644 tfjs-core/benchmarks/util.js diff --git a/tfjs-core/benchmarks/index.html b/tfjs-core/benchmarks/index.html index e45195205a4..bac90fc829d 100644 --- a/tfjs-core/benchmarks/index.html +++ b/tfjs-core/benchmarks/index.html @@ -3,128 +3,7 @@ TensorFlow.js Model Benchmark - + @@ -195,143 +74,11 @@

TensorFlow.js Model Benchmark

+ + + @@ -112,8 +113,9 @@

TensorFlow.js Model Benchmark

} async function showEnvironment() { - await tf.time(() => tf.square(3).data()); - envDiv.innerHTML += `
${JSON.stringify(tf.ENV.features, null, 2)}`; + await tf.time(() => tf.add(tf.tensor1d([1]), tf.tensor1d([1])).data()); + envDiv.innerHTML += `
${JSON.stringify(tf.ENV.features, null, 2) + } `; } function appendRow(tbody, ...cells) { @@ -139,7 +141,7 @@

TensorFlow.js Model Benchmark

} if (res instanceof tf.Tensor) { - res.dataSync(); + res = await res.data(); } const elapsed = performance.now() - start; @@ -157,8 +159,8 @@

TensorFlow.js Model Benchmark

const elapsed = performance.now() - start; await showMsg(null); - appendRow(timeTable, `Benchmark: ${state.benchmark}`, - `Runs: ${state.numRuns}`); + appendRow(timeTable, `< b > Benchmark: ${state.benchmark} `, + `< b > Runs: ${state.numRuns} `); appendRow(timeTable, 'Model load', printTime(elapsed)); } @@ -176,7 +178,7 @@

TensorFlow.js Model Benchmark

const xIncrement = chartWidth / (data.length - 1); node.querySelector("path") - .setAttribute("d", `M${data.map((d, i) => `${i * xIncrement},${chartHeight - ((d - yMin) / (yMax - yMin)) * chartHeight}`).join('L')}`); + .setAttribute("d", `M${data.map((d, i) => `${i * xIncrement},${chartHeight - ((d - yMin) / (yMax - yMin)) * chartHeight}`).join('L')} `); } async function measureAveragePredictTime() { @@ -195,7 +197,7 @@

TensorFlow.js Model Benchmark

} if (res instanceof tf.Tensor) { - res.dataSync(); + res = await res.data(); } times.push(performance.now() - start); @@ -209,12 +211,12 @@

TensorFlow.js Model Benchmark

populateTrendline(document.querySelector("#mem-trendline-container"), numTensors); const forceBytesTrendlineYMinToZero = false; - populateTrendline(document.querySelector("#bytes-trendline-container"), numBytes, forceBytesTrendlineYMinToZero, d => `${(d / 1e6).toPrecision(3)}MB`); + populateTrendline(document.querySelector("#bytes-trendline-container"), numBytes, forceBytesTrendlineYMinToZero, d => `${(d / 1e6).toPrecision(3)} MB`); await showMsg(null); const average = times.reduce((acc, curr) => acc + curr, 0) / times.length; const min = Math.min(...times); - appendRow(timeTable, `Subsequent average (${state.numRuns} runs)`, printTime(average)); + appendRow(timeTable, `Subsequent average(${state.numRuns} runs)`, printTime(average)); appendRow(timeTable, 'Best time', printTime(min)); } @@ -228,7 +230,7 @@

TensorFlow.js Model Benchmark

} if (res instanceof tf.Tensor) { - res.dataSync(); + res = await res.data(); } const elapsed = performance.now() - start; await showMsg(null); @@ -281,7 +283,7 @@

TensorFlow.js Model Benchmark

} if (res instanceof tf.Tensor) { - res.dataSync(); + res = await res.data(); } await showMsg(null); diff --git a/tfjs-core/benchmarks/modelConfig.js b/tfjs-core/benchmarks/modelConfig.js index b3562cd34ba..a365e8f92cf 100644 --- a/tfjs-core/benchmarks/modelConfig.js +++ b/tfjs-core/benchmarks/modelConfig.js @@ -64,8 +64,19 @@ const benchmarks = { predictFunc: () => { const zeros = tf.zeros([1, 224, 224, 3]); + const lib = []; + for (let i = 0; i < 10; i++) { + lib.push(tf.randomNormal([50, 50])); + } + return (model) => { - return model.predict(zeros); + let result = tf.randomNormal([50, 50]); + + for (let i = 0; i < lib.length; i++) { + result = tf.matMul(result, lib[i]); + } + + return result; } } }, diff --git a/tfjs-webgpu/package.json b/tfjs-webgpu/package.json index 5e4a3ef08d0..aa153c4c130 100644 --- a/tfjs-webgpu/package.json +++ b/tfjs-webgpu/package.json @@ -42,7 +42,8 @@ }, "dependencies": { "@webgpu/shaderc": "0.0.6", - "@webgpu/types": "0.0.6" + "@webgpu/types": "0.0.6", + "rollup-plugin-terser": "^5.1.1" }, "peerDependencies": { "@tensorflow/tfjs-core": "1.2.1" diff --git a/tfjs-webgpu/rollup.config.js b/tfjs-webgpu/rollup.config.js index aa763590c67..8ff5d41bb34 100644 --- a/tfjs-webgpu/rollup.config.js +++ b/tfjs-webgpu/rollup.config.js @@ -26,9 +26,7 @@ function config({plugins = [], output = {}, external = []}) { return { input: 'src/index.ts', plugins: [ - typescript({ - tsconfigOverride: {compilerOptions: {module: 'ES2015'}} - }), + typescript({tsconfigOverride: {compilerOptions: {module: 'ES2015'}}}), node(), // Polyfill require() from dependencies. commonjs({ diff --git a/tfjs-webgpu/yarn.lock b/tfjs-webgpu/yarn.lock index a14481396b1..d4bcd6e9fed 100644 --- a/tfjs-webgpu/yarn.lock +++ b/tfjs-webgpu/yarn.lock @@ -2,6 +2,22 @@ # yarn lockfile v1 +"@babel/code-frame@^7.0.0": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/highlight@^7.0.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + "@tensorflow/tfjs-core@1.2.7": version "1.2.7" resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-1.2.7.tgz#522328de16470aa9f7c15b91e4b68616f425002a" @@ -505,6 +521,11 @@ buffer-fill@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + buffer-indexof-polyfill@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.1.tgz#a9fb806ce8145d5428510ce72f278bb363a638bf" @@ -604,7 +625,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.3.0: +chalk@^2.0.0, chalk@^2.3.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -723,7 +744,7 @@ combine-source-map@^0.8.0: lodash.memoize "~3.0.3" source-map "~0.5.3" -commander@^2.12.1, commander@~2.20.0: +commander@^2.12.1, commander@^2.20.0, commander@~2.20.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== @@ -2037,11 +2058,24 @@ jasmine-core@~3.1.0: resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.1.0.tgz#a4785e135d5df65024dfc9224953df585bd2766c" integrity sha1-pHheE11d9lAk38kiSVPfWFvSdmw= +jest-worker@^24.6.0: + version "24.6.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.6.0.tgz#7f81ceae34b7cde0c9827a6980c35b7cdc0161b3" + integrity sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ== + dependencies: + merge-stream "^1.0.1" + supports-color "^6.1.0" + js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + js-yaml@3.x, js-yaml@^3.7.0: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" @@ -2337,6 +2371,13 @@ meow@^3.3.0: redent "^1.0.0" trim-newlines "^1.0.0" +merge-stream@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" + integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= + dependencies: + readable-stream "^2.0.1" + micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -3006,7 +3047,7 @@ read-pkg@^1.0.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@~2.3.6: +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -3160,6 +3201,17 @@ rollup-plugin-node-resolve@3.3.0: is-module "^1.0.0" resolve "^1.1.6" +rollup-plugin-terser@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.1.1.tgz#e9d2545ec8d467f96ba99b9216d2285aad8d5b66" + integrity sha512-McIMCDEY8EU6Y839C09UopeRR56wXHGdvKKjlfiZG/GrP6wvZQ62u2ko/Xh1MNH2M9WDL+obAAHySljIZYCuPQ== + dependencies: + "@babel/code-frame" "^7.0.0" + jest-worker "^24.6.0" + rollup-pluginutils "^2.8.1" + serialize-javascript "^1.7.0" + terser "^4.1.0" + rollup-plugin-typescript2@0.13.0: version "0.13.0" resolved "https://registry.yarnpkg.com/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.13.0.tgz#5fc838657d05af82e04554832cadf06cdb32f657" @@ -3177,7 +3229,7 @@ rollup-plugin-uglify@~3.0.0: dependencies: uglify-es "^3.3.7" -rollup-pluginutils@^2.0.1: +rollup-pluginutils@^2.0.1, rollup-pluginutils@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.1.tgz#8fa6dd0697344938ef26c2c09d2488ce9e33ce97" integrity sha512-J5oAoysWar6GuZo0s+3bZ6sVZAC0pfqKz68De7ZgDi5z63jOVZn1uJL/+z1jeKHNbGII8kAyHF5q8LnxSX5lQg== @@ -3229,6 +3281,11 @@ seedrandom@2.4.3: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== +serialize-javascript@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" + integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== + set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -3354,12 +3411,20 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-support@~0.5.12: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@0.6.1, source-map@^0.6.1, source-map@~0.6.1: +source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -3549,6 +3614,13 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + tar@^4: version "4.4.8" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" @@ -3562,6 +3634,15 @@ tar@^4: safe-buffer "^5.1.2" yallist "^3.0.2" +terser@^4.1.0: + version "4.1.4" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.1.4.tgz#4478b6a08bb096a61e793fea1a4434408bab936c" + integrity sha512-+ZwXJvdSwbd60jG0Illav0F06GDJF0R4ydZ21Q3wGAFKoBGyJGo34F63vzJHgvYxc1ukOtIjvwEvl9MkjzM6Pg== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + through2@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.0.tgz#468b461df9cd9fcc170f22ebf6852e467e578ff2" From 35db75662b79d5f8ef35dfa7cc8ce7dcc220ac4d Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Tue, 13 Aug 2019 16:25:39 -0400 Subject: [PATCH 04/14] increase target --- tfjs-webgpu/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tfjs-webgpu/tsconfig.json b/tfjs-webgpu/tsconfig.json index ecb732e2195..1dd0670aac9 100644 --- a/tfjs-webgpu/tsconfig.json +++ b/tfjs-webgpu/tsconfig.json @@ -7,6 +7,7 @@ "node_modules/" ], "compilerOptions": { - "outDir": "./dist" + "outDir": "./dist", + "target": "es2017" } } From 9cfeffadb36fa419632fca4b33441ed02127da36 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Tue, 13 Aug 2019 17:23:21 -0400 Subject: [PATCH 05/14] sigh --- tfjs-core/src/debug_mode_test.ts | 17 +++++++++++++--- tfjs-core/src/profiler.ts | 35 +++++++++++++++++++++++--------- tfjs-core/src/util.ts | 14 ++----------- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/tfjs-core/src/debug_mode_test.ts b/tfjs-core/src/debug_mode_test.ts index d79eca55c0d..e6fa17dcf76 100644 --- a/tfjs-core/src/debug_mode_test.ts +++ b/tfjs-core/src/debug_mode_test.ts @@ -55,11 +55,22 @@ describeWithFlags('debug on', SYNC_BACKEND_ENVS, () => { expect(a).toThrowError(); }); - it('debug mode errors when infinities in op output', () => { + fit('debug mode errors when infinities in op output', async () => { const a = tf.tensor1d([1, 2, 3, 4]); const b = tf.tensor1d([2, -1, 0, 3]); - const c = () => a.div(b); - expect(c).toThrowError(); + + spyOn(tf.util, 'UserException'); + + const c = async () => { + const result = a.div(b); + const data = await result.data(); + return data; + }; + + c(); + + expect(tf.util.UserException) + .toHaveBeenCalledWith(`The result of the 'div' is NaN.`); }); it('debug mode errors when nans in op output', () => { diff --git a/tfjs-core/src/profiler.ts b/tfjs-core/src/profiler.ts index bfaa9d80950..a5144f3f62e 100644 --- a/tfjs-core/src/profiler.ts +++ b/tfjs-core/src/profiler.ts @@ -18,7 +18,7 @@ import {BackendTimer} from './backends/backend'; import {Tensor} from './tensor'; import {NamedTensorMap} from './tensor_types'; -import {TypedArray} from './types'; +import {DataType, DataTypeMap, TypedArray} from './types'; import * as util from './util'; export class Profiler { @@ -39,17 +39,18 @@ export class Profiler { const results: Tensor[] = Array.isArray(result) ? result : [result] as Tensor[]; results.forEach(r => { - const vals = r.dataSync(); - util.checkComputationForErrors(vals, r.dtype, name); + r.data().then(vals => { + checkComputationForErrors(vals, r.dtype, name); - timer.then(timing => { - let extraInfo = ''; - if (timing.getExtraProfileInfo != null) { - extraInfo = timing.getExtraProfileInfo(); - } + timer.then(timing => { + let extraInfo = ''; + if (timing.getExtraProfileInfo != null) { + extraInfo = timing.getExtraProfileInfo(); + } - this.logger.logKernelProfile( - name, r, vals, timing.kernelMs, inputs, extraInfo); + this.logger.logKernelProfile( + name, r, vals, timing.kernelMs, inputs, extraInfo); + }); }); }); @@ -57,6 +58,20 @@ export class Profiler { } } +export function checkComputationForErrors( + vals: DataTypeMap[D], dtype: D, name: string): void { + if (dtype !== 'float32') { + // Only floating point computations will generate NaN values + return; + } + for (let i = 0; i < vals.length; i++) { + const num = vals[i] as number; + if (isNaN(num) || !isFinite(num)) { + throw util.UserException(`The result of the '${name}' is ${num}.`); + } + } +} + export class Logger { logKernelProfile( name: string, result: Tensor, vals: TypedArray, timeMs: number, diff --git a/tfjs-core/src/util.ts b/tfjs-core/src/util.ts index f9817c417cc..3cb66b2fc85 100644 --- a/tfjs-core/src/util.ts +++ b/tfjs-core/src/util.ts @@ -405,18 +405,8 @@ export function getArrayFromDType( return values as DataTypeMap[D]; } -export function checkComputationForErrors( - vals: DataTypeMap[D], dtype: D, name: string): void { - if (dtype !== 'float32') { - // Only floating point computations will generate NaN values - return; - } - for (let i = 0; i < vals.length; i++) { - const num = vals[i] as number; - if (isNaN(num) || !isFinite(num)) { - throw Error(`The result of the '${name}' is ${num}.`); - } - } +export function UserException(msg: string) { + console.error(msg); } export function checkConversionForErrors( From 11b5c1ce38677781404e8ccc608cb64634a25f98 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Tue, 13 Aug 2019 17:56:30 -0400 Subject: [PATCH 06/14] add timer --- tfjs-webgpu/src/backend_webgpu.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tfjs-webgpu/src/backend_webgpu.ts b/tfjs-webgpu/src/backend_webgpu.ts index 19b53588d66..50f1c017a60 100644 --- a/tfjs-webgpu/src/backend_webgpu.ts +++ b/tfjs-webgpu/src/backend_webgpu.ts @@ -74,6 +74,11 @@ type TensorInfo = { interface DataId {} +export interface CPUTimerQuery { + startMs: number; + endMs: number; +} + export type WebGPUKernelInfo = { name: string; query: Promise; }; @@ -342,6 +347,20 @@ export class WebGPUBackend extends KernelBackend { }; } + startTimer() { + return {startMs: util.now(), endMs: 0}; + } + + endTimer(query: CPUTimerQuery) { + query.endMs = util.now(); + return query; + } + + async getQueryTime(query: CPUTimerQuery): Promise { + const timerQuery = query; + return timerQuery.endMs - timerQuery.startMs; + } + private compileAndRun< K extends {dtype: DataType, size: number, dataId: {}, shape: number[]}>( program: webgpu_program.WebGPUProgram, inputs: Tensor[], output?: Tensor, @@ -414,6 +433,12 @@ export class WebGPUBackend extends KernelBackend { this.device, program, inputsData, output, uniforms); }); + const shouldTimeProgram = this.activeTimers != null; + let query: CPUTimerQuery; + if (shouldTimeProgram) { + query = this.startTimer(); + } + // Creating bind groups on the fly should never be a bottleneck. const bg = webgpu_program.makeBindGroup( this.device, bindGroupLayout, inputs.map(t => this.tensorToBinding(t)), @@ -439,6 +464,12 @@ export class WebGPUBackend extends KernelBackend { this.releaseBuffer( uniforms.resource.buffer, uniformData.byteLength, GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM); + + if (shouldTimeProgram) { + query = this.endTimer(query); + this.activeTimers.push( + {name: program.constructor.name, query: this.getQueryTime(query)}); + } return output as {} as K; } From d5db8833a6033d71421490541d8884fe4ec041f9 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 14 Aug 2019 15:16:14 -0400 Subject: [PATCH 07/14] update lic --- tfjs-core/benchmarks/index.html | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tfjs-core/benchmarks/index.html b/tfjs-core/benchmarks/index.html index 91da0629e42..89f02b54bf4 100644 --- a/tfjs-core/benchmarks/index.html +++ b/tfjs-core/benchmarks/index.html @@ -1,9 +1,14 @@ - + From 8d49cd29bb577a9b46b43aa86c469cbfcc42bc5b Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 14 Aug 2019 15:17:40 -0400 Subject: [PATCH 08/14] move tests around --- tfjs-core/src/profiler_test.ts | 26 +++++++++++++++++++++++++- tfjs-core/src/util_test.ts | 24 ------------------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tfjs-core/src/profiler_test.ts b/tfjs-core/src/profiler_test.ts index 445a3c54789..635eab84ce2 100644 --- a/tfjs-core/src/profiler_test.ts +++ b/tfjs-core/src/profiler_test.ts @@ -18,7 +18,7 @@ import {BackendTimer, BackendTimingInfo} from './backends/backend'; import * as tf from './index'; import {describeWithFlags, SYNC_BACKEND_ENVS} from './jasmine_util'; -import {Logger, Profiler} from './profiler'; +import {checkComputationForErrors, Logger, Profiler} from './profiler'; import {Tensor} from './tensor'; import {TypedArray} from './types'; @@ -129,3 +129,27 @@ describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { }, delayMs * 2); }); }); + +describe('profiler.checkComputationForErrors', () => { + it('Float32Array has NaN', () => { + expect( + () => checkComputationForErrors( + new Float32Array([1, 2, 3, NaN, 4, 255]), 'float32', '')) + .toThrowError(); + }); + + it('Float32Array has Infinity', () => { + expect( + () => checkComputationForErrors( + new Float32Array([1, 2, 3, Infinity, 4, 255]), 'float32', '')) + .toThrowError(); + }); + + it('Float32Array no NaN', () => { + // Int32 and Bool NaNs should not trigger an error. + expect( + () => checkComputationForErrors( + new Float32Array([1, 2, 3, 4, -1, 255]), 'float32', '')) + .not.toThrowError(); + }); +}); diff --git a/tfjs-core/src/util_test.ts b/tfjs-core/src/util_test.ts index 7ac5ab1821b..65a1b230f6a 100644 --- a/tfjs-core/src/util_test.ts +++ b/tfjs-core/src/util_test.ts @@ -407,30 +407,6 @@ describe('util.squeezeShape', () => { }); }); -describe('util.checkComputationForErrors', () => { - it('Float32Array has NaN', () => { - expect( - () => util.checkComputationForErrors( - new Float32Array([1, 2, 3, NaN, 4, 255]), 'float32', '')) - .toThrowError(); - }); - - it('Float32Array has Infinity', () => { - expect( - () => util.checkComputationForErrors( - new Float32Array([1, 2, 3, Infinity, 4, 255]), 'float32', '')) - .toThrowError(); - }); - - it('Float32Array no NaN', () => { - // Int32 and Bool NaNs should not trigger an error. - expect( - () => util.checkComputationForErrors( - new Float32Array([1, 2, 3, 4, -1, 255]), 'float32', '')) - .not.toThrowError(); - }); -}); - describe('util.checkConversionForErrors', () => { it('Float32Array has NaN', () => { expect( From c87e5c378e0f5ff2354f4170771689ddd484423b Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 14 Aug 2019 15:23:55 -0400 Subject: [PATCH 09/14] fix tests --- tfjs-core/src/debug_mode_test.ts | 27 ++++++++++++++++++--------- tfjs-core/src/util.ts | 1 + 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/tfjs-core/src/debug_mode_test.ts b/tfjs-core/src/debug_mode_test.ts index e6fa17dcf76..3426ae9d2c4 100644 --- a/tfjs-core/src/debug_mode_test.ts +++ b/tfjs-core/src/debug_mode_test.ts @@ -55,7 +55,7 @@ describeWithFlags('debug on', SYNC_BACKEND_ENVS, () => { expect(a).toThrowError(); }); - fit('debug mode errors when infinities in op output', async () => { + it('debug mode errors when infinities in op output', async () => { const a = tf.tensor1d([1, 2, 3, 4]); const b = tf.tensor1d([2, -1, 0, 3]); @@ -63,21 +63,30 @@ describeWithFlags('debug on', SYNC_BACKEND_ENVS, () => { const c = async () => { const result = a.div(b); - const data = await result.data(); - return data; + // Must await result so we know exception would have happened by the time + // we call `expect`. + await result.data(); }; - c(); + await c(); - expect(tf.util.UserException) - .toHaveBeenCalledWith(`The result of the 'div' is NaN.`); + expect(tf.util.UserException).toHaveBeenCalled(); }); - it('debug mode errors when nans in op output', () => { + it('debug mode errors when nans in op output', async () => { const a = tf.tensor1d([-1, 2]); const b = tf.tensor1d([0.5, 1]); - const c = () => a.pow(b); - expect(c).toThrowError(); + + spyOn(tf.util, 'UserException'); + + const c = async () => { + const result = a.pow(b); + await result.data(); + }; + + await c(); + + expect(tf.util.UserException).toHaveBeenCalled(); }); it('debug mode errors when nans in oneHot op (tensorlike), int32', () => { diff --git a/tfjs-core/src/util.ts b/tfjs-core/src/util.ts index 3cb66b2fc85..0708fbc0cdc 100644 --- a/tfjs-core/src/util.ts +++ b/tfjs-core/src/util.ts @@ -405,6 +405,7 @@ export function getArrayFromDType( return values as DataTypeMap[D]; } +// Created a custom exception class so it could be stubbed in tests. export function UserException(msg: string) { console.error(msg); } From 5eeb504f7c34691286ef3588c0df287864fdb481 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 14 Aug 2019 15:26:48 -0400 Subject: [PATCH 10/14] remove import --- tfjs-core/benchmarks/index.html | 1 - 1 file changed, 1 deletion(-) diff --git a/tfjs-core/benchmarks/index.html b/tfjs-core/benchmarks/index.html index 89f02b54bf4..ac28d272398 100644 --- a/tfjs-core/benchmarks/index.html +++ b/tfjs-core/benchmarks/index.html @@ -81,7 +81,6 @@

TensorFlow.js Model Benchmark

- From 78ebbf009231eecd31100e62a46646dae6404f1c Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 14 Aug 2019 15:27:52 -0400 Subject: [PATCH 11/14] whitespace --- tfjs-core/benchmarks/index.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tfjs-core/benchmarks/index.html b/tfjs-core/benchmarks/index.html index ac28d272398..aea9aa6d230 100644 --- a/tfjs-core/benchmarks/index.html +++ b/tfjs-core/benchmarks/index.html @@ -1,14 +1,18 @@ + From 702a4ee84ec9fd8146826a1de902dad7e7e18d80 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 14 Aug 2019 15:28:13 -0400 Subject: [PATCH 12/14] ws --- tfjs-core/benchmarks/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tfjs-core/benchmarks/index.html b/tfjs-core/benchmarks/index.html index aea9aa6d230..9ef899279fb 100644 --- a/tfjs-core/benchmarks/index.html +++ b/tfjs-core/benchmarks/index.html @@ -4,7 +4,7 @@ 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 + 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, From bcb49a525650cf0bbc96db8c145715ffb1d486cb Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 14 Aug 2019 16:24:28 -0400 Subject: [PATCH 13/14] update name --- tfjs-core/src/debug_mode_test.ts | 12 ++++++------ tfjs-core/src/profiler.ts | 7 ++++++- tfjs-core/src/profiler_test.ts | 24 ++++++++++++------------ tfjs-core/src/util.ts | 5 ----- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tfjs-core/src/debug_mode_test.ts b/tfjs-core/src/debug_mode_test.ts index 3426ae9d2c4..6570dd44131 100644 --- a/tfjs-core/src/debug_mode_test.ts +++ b/tfjs-core/src/debug_mode_test.ts @@ -59,25 +59,25 @@ describeWithFlags('debug on', SYNC_BACKEND_ENVS, () => { const a = tf.tensor1d([1, 2, 3, 4]); const b = tf.tensor1d([2, -1, 0, 3]); - spyOn(tf.util, 'UserException'); + spyOn(console, 'error'); const c = async () => { const result = a.div(b); - // Must await result so we know exception would have happened by the time - // we call `expect`. + // Must await result so we know exception would have happened by the + // time we call `expect`. await result.data(); }; await c(); - expect(tf.util.UserException).toHaveBeenCalled(); + expect(console.error).toHaveBeenCalled(); }); it('debug mode errors when nans in op output', async () => { const a = tf.tensor1d([-1, 2]); const b = tf.tensor1d([0.5, 1]); - spyOn(tf.util, 'UserException'); + spyOn(console, 'error'); const c = async () => { const result = a.pow(b); @@ -86,7 +86,7 @@ describeWithFlags('debug on', SYNC_BACKEND_ENVS, () => { await c(); - expect(tf.util.UserException).toHaveBeenCalled(); + expect(console.error).toHaveBeenCalled(); }); it('debug mode errors when nans in oneHot op (tensorlike), int32', () => { diff --git a/tfjs-core/src/profiler.ts b/tfjs-core/src/profiler.ts index a5144f3f62e..5beae5b553a 100644 --- a/tfjs-core/src/profiler.ts +++ b/tfjs-core/src/profiler.ts @@ -58,6 +58,11 @@ export class Profiler { } } +// Create a custom exception class so it can be stubbed in tests. +export function ProfilerException(msg: string) { + console.error(msg); +} + export function checkComputationForErrors( vals: DataTypeMap[D], dtype: D, name: string): void { if (dtype !== 'float32') { @@ -67,7 +72,7 @@ export function checkComputationForErrors( for (let i = 0; i < vals.length; i++) { const num = vals[i] as number; if (isNaN(num) || !isFinite(num)) { - throw util.UserException(`The result of the '${name}' is ${num}.`); + throw ProfilerException(`The result of the '${name}' is ${num}.`); } } } diff --git a/tfjs-core/src/profiler_test.ts b/tfjs-core/src/profiler_test.ts index 635eab84ce2..08d001b533b 100644 --- a/tfjs-core/src/profiler_test.ts +++ b/tfjs-core/src/profiler_test.ts @@ -132,24 +132,24 @@ describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { describe('profiler.checkComputationForErrors', () => { it('Float32Array has NaN', () => { - expect( - () => checkComputationForErrors( - new Float32Array([1, 2, 3, NaN, 4, 255]), 'float32', '')) - .toThrowError(); + const f = () => checkComputationForErrors( + new Float32Array([1, 2, 3, NaN, 4, 255]), 'float32', ''); + + expect(f).toThrow(); }); it('Float32Array has Infinity', () => { - expect( - () => checkComputationForErrors( - new Float32Array([1, 2, 3, Infinity, 4, 255]), 'float32', '')) - .toThrowError(); + const f = () => checkComputationForErrors( + new Float32Array([1, 2, 3, Infinity, 4, 255]), 'float32', ''); + + expect(f).toThrow(); }); it('Float32Array no NaN', () => { // Int32 and Bool NaNs should not trigger an error. - expect( - () => checkComputationForErrors( - new Float32Array([1, 2, 3, 4, -1, 255]), 'float32', '')) - .not.toThrowError(); + const f = () => checkComputationForErrors( + new Float32Array([1, 2, 3, -1, 4, 255]), 'float32', ''); + + expect(f).not.toThrow(); }); }); diff --git a/tfjs-core/src/util.ts b/tfjs-core/src/util.ts index 0708fbc0cdc..e36cbd0e5b9 100644 --- a/tfjs-core/src/util.ts +++ b/tfjs-core/src/util.ts @@ -405,11 +405,6 @@ export function getArrayFromDType( return values as DataTypeMap[D]; } -// Created a custom exception class so it could be stubbed in tests. -export function UserException(msg: string) { - console.error(msg); -} - export function checkConversionForErrors( vals: DataTypeMap[D]|number[], dtype: D): void { for (let i = 0; i < vals.length; i++) { From a3f2cf0ec5e7636adc50cd27911e69c40db9dbc9 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 14 Aug 2019 16:30:09 -0400 Subject: [PATCH 14/14] pr comments --- tfjs-core/src/profiler.ts | 3 +++ tfjs-core/src/profiler_test.ts | 24 ++++++++++++------------ tfjs-webgpu/package.json | 4 ++-- tfjs-webgpu/src/backend_webgpu.ts | 4 ++-- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/tfjs-core/src/profiler.ts b/tfjs-core/src/profiler.ts index 5beae5b553a..17cb5831eac 100644 --- a/tfjs-core/src/profiler.ts +++ b/tfjs-core/src/profiler.ts @@ -39,6 +39,8 @@ export class Profiler { const results: Tensor[] = Array.isArray(result) ? result : [result] as Tensor[]; results.forEach(r => { + // Dangling promise here because we don't want to propagate up + // asynchronicity. r.data().then(vals => { checkComputationForErrors(vals, r.dtype, name); @@ -72,6 +74,7 @@ export function checkComputationForErrors( for (let i = 0; i < vals.length; i++) { const num = vals[i] as number; if (isNaN(num) || !isFinite(num)) { + // Throwing custom exception so behavior is testable. throw ProfilerException(`The result of the '${name}' is ${num}.`); } } diff --git a/tfjs-core/src/profiler_test.ts b/tfjs-core/src/profiler_test.ts index 08d001b533b..3a7f6545bb1 100644 --- a/tfjs-core/src/profiler_test.ts +++ b/tfjs-core/src/profiler_test.ts @@ -132,24 +132,24 @@ describeWithFlags('profiler.Profiler', SYNC_BACKEND_ENVS, () => { describe('profiler.checkComputationForErrors', () => { it('Float32Array has NaN', () => { - const f = () => checkComputationForErrors( - new Float32Array([1, 2, 3, NaN, 4, 255]), 'float32', ''); - - expect(f).toThrow(); + expect( + () => checkComputationForErrors( + new Float32Array([1, 2, 3, NaN, 4, 255]), 'float32', '')) + .toThrow(); }); it('Float32Array has Infinity', () => { - const f = () => checkComputationForErrors( - new Float32Array([1, 2, 3, Infinity, 4, 255]), 'float32', ''); - - expect(f).toThrow(); + expect( + () => checkComputationForErrors( + new Float32Array([1, 2, 3, Infinity, 4, 255]), 'float32', '')) + .toThrow(); }); it('Float32Array no NaN', () => { // Int32 and Bool NaNs should not trigger an error. - const f = () => checkComputationForErrors( - new Float32Array([1, 2, 3, -1, 4, 255]), 'float32', ''); - - expect(f).not.toThrow(); + expect( + () => checkComputationForErrors( + new Float32Array([1, 2, 3, -1, 4, 255]), 'float32', '')) + .not.toThrow(); }); }); diff --git a/tfjs-webgpu/package.json b/tfjs-webgpu/package.json index aa153c4c130..69e8cd80d19 100644 --- a/tfjs-webgpu/package.json +++ b/tfjs-webgpu/package.json @@ -34,6 +34,7 @@ "rollup-plugin-commonjs": "9.1.3", "rollup-plugin-node-resolve": "3.3.0", "rollup-plugin-typescript2": "0.13.0", + "rollup-plugin-terser": "^5.1.1", "rollup-plugin-uglify": "~3.0.0", "tslint": "~5.11.0", "tslint-no-circular-imports": "^0.5.0", @@ -42,8 +43,7 @@ }, "dependencies": { "@webgpu/shaderc": "0.0.6", - "@webgpu/types": "0.0.6", - "rollup-plugin-terser": "^5.1.1" + "@webgpu/types": "0.0.6" }, "peerDependencies": { "@tensorflow/tfjs-core": "1.2.1" diff --git a/tfjs-webgpu/src/backend_webgpu.ts b/tfjs-webgpu/src/backend_webgpu.ts index 50f1c017a60..7253798938c 100644 --- a/tfjs-webgpu/src/backend_webgpu.ts +++ b/tfjs-webgpu/src/backend_webgpu.ts @@ -41,8 +41,8 @@ import * as webgpu_program from './kernels/webgpu_program'; import {WebGPUBinary} from './kernels/webgpu_program'; // START TO-IMPORT-FROM-CORE ============================ -// TODO: Delete definitions in this section and import from core once new -// release is published. +// TODO(annyuan): Delete definitions in this section and import from core once +// new release is published. type MemoryInfo = { numTensors: number; numDataBuffers: number; numBytes: number; unreliable?: boolean; reasons: string[];