From a0279ce3ca0f71935b8f78d2b8964017606dcbb8 Mon Sep 17 00:00:00 2001 From: Linchenn <40653845+Linchenn@users.noreply.github.com> Date: Thu, 13 Aug 2020 10:22:28 -0700 Subject: [PATCH 1/3] mig --- README.md | 2 +- e2e/benchmarks/SpecRunner.html | 5 - e2e/benchmarks/benchmark_util.js | 5 + .../browserstack-benchmark/app_test.js | 5 + e2e/benchmarks/index_test.js | 255 ----------------- .../{ => local-benchmark}/README.md | 6 +- .../local-benchmark/SpecRunner.html | 48 ++++ .../{ => local-benchmark}/index.html | 4 +- e2e/benchmarks/{ => local-benchmark}/index.js | 0 e2e/benchmarks/local-benchmark/index_test.js | 258 ++++++++++++++++++ e2e/benchmarks/{ => local-benchmark}/main.css | 0 e2e/benchmarks/{ => local-benchmark}/util.js | 0 tfjs-backend-wasm/scripts/build-benchmark.sh | 8 +- 13 files changed, 326 insertions(+), 270 deletions(-) delete mode 100644 e2e/benchmarks/index_test.js rename e2e/benchmarks/{ => local-benchmark}/README.md (88%) create mode 100644 e2e/benchmarks/local-benchmark/SpecRunner.html rename e2e/benchmarks/{ => local-benchmark}/index.html (99%) rename e2e/benchmarks/{ => local-benchmark}/index.js (100%) create mode 100644 e2e/benchmarks/local-benchmark/index_test.js rename e2e/benchmarks/{ => local-benchmark}/main.css (100%) rename e2e/benchmarks/{ => local-benchmark}/util.js (100%) diff --git a/README.md b/README.md index ab8a0dc6d62..8aa496a251f 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ on NPM. ## Benchmarks -[Benchmark tool](https://tensorflow.github.io/tfjs/e2e/benchmarks/index.html). Use this webpage tool to test the performance related metrics (speed, memory, power, etc) of TensorFlow.js models on your local device with CPU, WebGL or WASM backend. You can benchmark custom models following this [guide](https://github.com/tensorflow/tfjs/e2e/benchmarks/README.md). +[Benchmark tool](https://tensorflow.github.io/tfjs/e2e/benchmarks/local-benchmark/index.html). Use this webpage tool to test the performance related metrics (speed, memory, power, etc) of TensorFlow.js models on your local device with CPU, WebGL or WASM backend. You can benchmark custom models following this [guide](https://github.com/tensorflow/tfjs/blob/master/e2e/benchmarks/local-benchmark/README.md). ## Getting started diff --git a/e2e/benchmarks/SpecRunner.html b/e2e/benchmarks/SpecRunner.html index 1cf56321d64..8e1dc4fbfba 100644 --- a/e2e/benchmarks/SpecRunner.html +++ b/e2e/benchmarks/SpecRunner.html @@ -25,23 +25,18 @@ - - - - - diff --git a/e2e/benchmarks/benchmark_util.js b/e2e/benchmarks/benchmark_util.js index 65fd5ad5808..1b49c3e1901 100644 --- a/e2e/benchmarks/benchmark_util.js +++ b/e2e/benchmarks/benchmark_util.js @@ -15,6 +15,11 @@ * ============================================================================= */ +/** + * This tool depends on tf-core, tf-layers, tf-converter and the backends + * (tf-backend-cpu, tf-backend-webgl or tf-backend-wasm) that you would use. + */ + /** * Generates a random input for `model`, based on `model.inputs`. For * tf.GraphModel, `NamedTensorMap` input will be returned; otherwise, diff --git a/e2e/benchmarks/browserstack-benchmark/app_test.js b/e2e/benchmarks/browserstack-benchmark/app_test.js index 258b6468646..6ffa6dc5328 100644 --- a/e2e/benchmarks/browserstack-benchmark/app_test.js +++ b/e2e/benchmarks/browserstack-benchmark/app_test.js @@ -15,6 +15,11 @@ * ============================================================================= */ +/** + * The unit tests in this file can be run by opening `./SpecRunner.html` in + * browser. + */ + describe('benchmark multiple browsers', () => { const browsersList = [ { diff --git a/e2e/benchmarks/index_test.js b/e2e/benchmarks/index_test.js deleted file mode 100644 index 3b1cd66ff0c..00000000000 --- a/e2e/benchmarks/index_test.js +++ /dev/null @@ -1,255 +0,0 @@ -/** - * @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. - * ============================================================================= - */ - -const state = { - backend: 'wasm', - flags: {} -}; - -describe('index', () => { - describe('showFlagSettings', () => { - beforeAll(() => { - this.originalInitDefaultValueMap = initDefaultValueMap; - this.originalShowBackendFlagSettings = showBackendFlagSettings; - this.originalTUNABLE_FLAG_DEFAULT_VALUE_MAP = - TUNABLE_FLAG_DEFAULT_VALUE_MAP; - }); - - afterAll(() => { - initDefaultValueMap = this.originalInitDefaultValueMap; - showBackendFlagSettings = this.originalShowBackendFlagSettings; - TUNABLE_FLAG_DEFAULT_VALUE_MAP = - this.originalTUNABLE_FLAG_DEFAULT_VALUE_MAP; - }); - - describe('at the first call', () => { - beforeAll(() => { - // Only the backend setting is shown and the general flag settings have - // not been shown. - this.folderController = new dat.gui.GUI(); - this.folderController.add(state, 'backend', ['wasm', 'webgl', 'cpu']); - - // The flag default value map has not been initialized. - TUNABLE_FLAG_DEFAULT_VALUE_MAP = null; - - BACKEND_FLAGS_MAP.general.push('testGeneralFlag'); - }); - - afterAll(() => { - this.folderController.destroy(); - BACKEND_FLAGS_MAP.general.pop(); // Pop 'testGeneralFlag'. - }); - - it('shows general flag settings', async () => { - initDefaultValueMap = jasmine.createSpy(); - showBackendFlagSettings = jasmine.createSpy(); - - await showFlagSettings(this.folderController, 'webgl'); - - expect(showBackendFlagSettings.calls.count()).toBe(2); - expect(showBackendFlagSettings.calls.first().args).toEqual([ - this.folderController, 'general' - ]); - }); - - it('initializes default value map', async () => { - initDefaultValueMap = jasmine.createSpy(); - showBackendFlagSettings = jasmine.createSpy(); - await showFlagSettings(this.folderController, 'webgl'); - expect(initDefaultValueMap.calls.count()).toBe(1); - }); - - it('shows flag settings for the given backend', async () => { - initDefaultValueMap = jasmine.createSpy(); - showBackendFlagSettings = jasmine.createSpy(); - - await showFlagSettings(this.folderController, 'webgl'); - - expect(showBackendFlagSettings.calls.count()).toBe(2); - expect(showBackendFlagSettings.calls.argsFor(0)).toEqual([ - this.folderController, 'general' - ]); - expect(showBackendFlagSettings.calls.argsFor(1)).toEqual([ - this.folderController, 'webgl' - ]); - }); - }); - - describe('When switching the backend', () => { - beforeAll(() => { - // The flag default value map has been initialized and the state.flags - // is populated with all tunable flags. - this.originalInitDefaultValueMap(); - BACKEND_FLAGS_MAP.general.push('testGeneralFlag'); - TUNABLE_FLAG_DEFAULT_VALUE_MAP.testGeneralFlag = true; - state.flags.testGeneralFlag = true; - }); - - afterAll(() => { - BACKEND_FLAGS_MAP.general.pop(); // Pop 'testGeneralFlag'. - delete TUNABLE_FLAG_DEFAULT_VALUE_MAP['testGeneralFlag']; - delete state.flags['testGeneralFlag']; - }); - - beforeEach(() => { - // The backend setting and the general flag settings have been shown. - this.folderController = new dat.gui.GUI(); - this.folderController.add(state, 'backend', ['wasm', 'webgl', 'cpu']); - this.originalShowBackendFlagSettings(this.folderController, 'general'); - - // Flag settings for a certain backend have been shown. - this.originalShowBackendFlagSettings(this.folderController, 'webgl'); - }); - - afterEach(() => { - this.folderController.destroy(); - }); - - it('removes flag settings of the previous backend', async () => { - initDefaultValueMap = jasmine.createSpy(); - showBackendFlagSettings = jasmine.createSpy(); - spyOn(this.folderController, 'remove').and.callThrough(); - - await showFlagSettings(this.folderController, 'wasm'); - - expect(initDefaultValueMap.calls.count()).toBe(0); - expect(this.folderController.remove.calls.count()) - .toBe(BACKEND_FLAGS_MAP.webgl.length); - }); - - it('only add flag settings for the new backend', async () => { - initDefaultValueMap = jasmine.createSpy(); - showBackendFlagSettings = jasmine.createSpy(); - - await showFlagSettings(folderController, 'webgl'); - - expect(initDefaultValueMap.calls.count()).toBe(0); - expect(showBackendFlagSettings.calls.count()).toBe(1); - expect(showBackendFlagSettings.calls.first().args).toEqual([ - this.folderController, 'webgl' - ]); - }); - }); - }); - - describe('showBackendFlagSettings', () => { - beforeAll(() => { - // Assume testBackend has only one flag, testFlag. - // A DOM element is shown based on this flag's tunable range. - BACKEND_FLAGS_MAP['testBackend'] = ['testFlag']; - state.flags['testFlag'] = null; - this.originalGetTunableRange = getTunableRange; - - this.folderController = new dat.gui.GUI(); - }); - - afterAll(() => { - delete BACKEND_FLAGS_MAP['testBackend']; - delete state.flags['testFlag']; - getTunableRange = this.originalGetTunableRange; - - this.folderController.destroy(); - }); - - it('does not show DOM element for untunable flags', () => { - // The flag with only one value option is considered as untunable. - const flagValueRange = [false]; - getTunableRange = jasmine.createSpy().and.returnValue(flagValueRange); - spyOn(this.folderController, 'add'); - spyOn(console, 'warn'); - - showBackendFlagSettings(this.folderController, 'testBackend'); - - expect(this.folderController.add.calls.count()).toBe(0); - expect(console.warn.calls.count()).toBe(1); - }); - - it('shows a checkbox for a tunable boolean flag', () => { - state.flags.testFlag = true; - const flagValueRange = [true, false]; - getTunableRange = jasmine.createSpy().and.returnValue(flagValueRange); - spyOn(this.folderController, 'add').and.callThrough(); - - showBackendFlagSettings(this.folderController, 'testBackend'); - - expect(this.folderController.add.calls.count()).toBe(1); - expect(this.folderController.add.calls.first().args).toEqual([ - state.flags, 'testFlag' - ]); - expect(this.folderController.add.calls.first().returnValue.__checkbox) - .toBeDefined(); - }); - - it('shows a dropdown menu for a tunable number type flag', () => { - state.flags.testFlag = 1; - const flagValueRange = [1, 2]; - getTunableRange = jasmine.createSpy().and.returnValue(flagValueRange); - spyOn(this.folderController, 'add').and.callThrough(); - - showBackendFlagSettings(this.folderController, 'testBackend'); - - expect(this.folderController.add.calls.count()).toBe(1); - expect(this.folderController.add.calls.first().args).toEqual([ - state.flags, 'testFlag', flagValueRange - ]); - expect(this.folderController.add.calls.first().returnValue.__select) - .toBeDefined(); - }); - }); - - describe('getTunableRange', () => { - beforeAll(() => { - this.originalTUNABLE_FLAG_DEFAULT_VALUE_MAP = - TUNABLE_FLAG_DEFAULT_VALUE_MAP; - TUNABLE_FLAG_DEFAULT_VALUE_MAP = {}; - }); - - afterAll(() => { - TUNABLE_FLAG_DEFAULT_VALUE_MAP = - this.originalTUNABLE_FLAG_DEFAULT_VALUE_MAP; - }); - - it(`returns [false, true] for 'WEBGL_FORCE_F16_TEXTURES'`, () => { - const flagValueRange = getTunableRange('WEBGL_FORCE_F16_TEXTURES'); - expect(flagValueRange).toEqual([false, true]); - }); - - it(`returns [1, 2] for 'WEBGL_VERSION' if its default value is 2`, () => { - TUNABLE_FLAG_DEFAULT_VALUE_MAP.WEBGL_VERSION = 2; - const flagValueRange = getTunableRange('WEBGL_VERSION'); - expect(flagValueRange).toEqual([1, 2]); - }); - - it(`returns [1] for 'WEBGL_VERSION' if its default value is 1`, () => { - TUNABLE_FLAG_DEFAULT_VALUE_MAP.WEBGL_VERSION = 1; - const flagValueRange = getTunableRange('WEBGL_VERSION'); - expect(flagValueRange).toEqual([1]); - }); - - it('returns [false] for the flag with false as default value', () => { - TUNABLE_FLAG_DEFAULT_VALUE_MAP.testFlag = false; - const flagValueRange = getTunableRange('testFlag'); - expect(flagValueRange).toEqual([false]); - }); - - it('returns [false, true] for the flag with true as default value', () => { - TUNABLE_FLAG_DEFAULT_VALUE_MAP.testFlag = true; - const flagValueRange = getTunableRange('testFlag'); - expect(flagValueRange).toEqual([false, true]); - }); - }); -}); diff --git a/e2e/benchmarks/README.md b/e2e/benchmarks/local-benchmark/README.md similarity index 88% rename from e2e/benchmarks/README.md rename to e2e/benchmarks/local-benchmark/README.md index e57ffeae5ed..d5df2f5bdd5 100644 --- a/e2e/benchmarks/README.md +++ b/e2e/benchmarks/local-benchmark/README.md @@ -1,14 +1,14 @@ # Benchmark custom models -The `custom model` in the [benchmark tool](https://tensorflow.github.io/tfjs/e2e/benchmarks/index.html) currently only supports `tf.GraphModel` or `tf.LayersModel`. +The `custom model` in the [benchmark tool](https://tensorflow.github.io/tfjs/e2e/benchmarks/local-benchmark/index.html) currently only supports `tf.GraphModel` or `tf.LayersModel`. If you want to benchmark models in other types or customize the inputs for model inference, you need to implement `load` and `predictFunc` methods, following this [example PR](https://github.com/tensorflow/tfjs/pull/3168/files). ## Models in local file system If you have a model in local file system, you can follow the steps below: 1. Download [tfjs repository](https://github.com/tensorflow/tfjs.git). -2. Put your `model.json` file and the weight files under the `tfjs/e2e/benchmarks/` folder. -3. Under the `tfjs/e2e/benchmarks/` folder, run `npx http-server`. +2. Put your `model.json` file and the weight files under the `tfjs/e2e/benchmarks/local-benchmark/` folder. +3. Under the `tfjs/e2e/benchmarks/local-benchmark/` folder, run `npx http-server`. 4. Open the browser go to `http://127.0.0.1:8080/`, this will open the benchmark tool. Then populate the `model.json` url to `modelUrl` under the custom model, which is `http://127.0.0.1:8080/model.json`. In addition, if the online tool is blocked by `CORS` problems when fetching the custom model, you can locally serve the model by the above steps to solve this problem. diff --git a/e2e/benchmarks/local-benchmark/SpecRunner.html b/e2e/benchmarks/local-benchmark/SpecRunner.html new file mode 100644 index 00000000000..4a57886f99c --- /dev/null +++ b/e2e/benchmarks/local-benchmark/SpecRunner.html @@ -0,0 +1,48 @@ + + + + +
+ +