UNPKG

@tensorflow/tfjs-core

Version:

Hardware-accelerated JavaScript library for machine intelligence

247 lines 9.07 kB
/** * @license * Copyright 2019 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 './index'; import { ALL_ENVS, describeWithFlags, NODE_ENVS } from './jasmine_util'; import { expectArraysClose } from './test_util'; describe('deprecation warnings', () => { beforeEach(() => { spyOn(console, 'warn').and.callFake((msg) => null); }); it('deprecationWarn warns', () => { tf.deprecationWarn('xyz is deprecated.'); expect(console.warn).toHaveBeenCalledTimes(1); expect(console.warn) .toHaveBeenCalledWith('xyz is deprecated. You can disable deprecation warnings with ' + 'tf.disableDeprecationWarnings().'); }); it('disableDeprecationWarnings called, deprecationWarn doesnt warn', () => { tf.disableDeprecationWarnings(); expect(console.warn).toHaveBeenCalledTimes(1); expect(console.warn) .toHaveBeenCalledWith('TensorFlow.js deprecation warnings have been disabled.'); // deprecationWarn no longer warns. tf.deprecationWarn('xyz is deprecated.'); expect(console.warn).toHaveBeenCalledTimes(1); }); }); describe('Flag flipping methods', () => { beforeEach(() => { tf.env().reset(); }); afterEach(() => { tf.env().reset(); }); it('tf.enableProdMode', () => { tf.enableProdMode(); expect(tf.env().getBool('PROD')).toBe(true); }); it('tf.enableDebugMode', () => { // Silence debug warnings. spyOn(console, 'warn'); tf.enableDebugMode(); expect(tf.env().getBool('DEBUG')).toBe(true); }); }); describeWithFlags('time cpu', NODE_ENVS, () => { it('simple upload', async () => { const a = tf.zeros([10, 10]); const time = await tf.time(() => a.square()); expect(time.kernelMs > 0); expect(time.wallMs >= time.kernelMs); }); }); describeWithFlags('tidy', ALL_ENVS, () => { it('returns Tensor', async () => { tf.tidy(() => { const a = tf.tensor1d([1, 2, 3]); let b = tf.tensor1d([0, 0, 0]); expect(tf.memory().numTensors).toBe(2); tf.tidy(() => { const result = tf.tidy(() => { b = tf.add(a, b); b = tf.add(a, b); b = tf.add(a, b); return tf.add(a, b); }); // result is new. All intermediates should be disposed. expect(tf.memory().numTensors).toBe(2 + 1); expect(result.shape).toEqual([3]); expect(result.isDisposed).toBe(false); }); // a, b are still here, result should be disposed. expect(tf.memory().numTensors).toBe(2); }); expect(tf.memory().numTensors).toBe(0); }); it('multiple disposes does not affect num arrays', () => { expect(tf.memory().numTensors).toBe(0); const a = tf.tensor1d([1, 2, 3]); const b = tf.tensor1d([1, 2, 3]); expect(tf.memory().numTensors).toBe(2); a.dispose(); a.dispose(); expect(tf.memory().numTensors).toBe(1); b.dispose(); expect(tf.memory().numTensors).toBe(0); }); it('allows primitive types', () => { const a = tf.tidy(() => 5); expect(a).toBe(5); const b = tf.tidy(() => 'hello'); expect(b).toBe('hello'); }); it('allows complex types', async () => { const res = tf.tidy(() => { return { a: tf.scalar(1), b: 'hello', c: [tf.scalar(2), 'world'] }; }); expectArraysClose(await res.a.data(), [1]); expectArraysClose(await res.c[0].data(), [2]); }); it('returns Tensor[]', async () => { const a = tf.tensor1d([1, 2, 3]); const b = tf.tensor1d([0, -1, 1]); expect(tf.memory().numTensors).toBe(2); tf.tidy(() => { const result = tf.tidy(() => { tf.add(a, b); return [tf.add(a, b), tf.sub(a, b)]; }); // the 2 results are new. All intermediates should be disposed. expect(tf.memory().numTensors).toBe(4); expect(result[0].isDisposed).toBe(false); expect(result[0].shape).toEqual([3]); expect(result[1].isDisposed).toBe(false); expect(result[1].shape).toEqual([3]); expect(tf.memory().numTensors).toBe(4); }); // the 2 results should be disposed. expect(tf.memory().numTensors).toBe(2); a.dispose(); b.dispose(); expect(tf.memory().numTensors).toBe(0); }); it('basic usage without return', () => { const a = tf.tensor1d([1, 2, 3]); let b = tf.tensor1d([0, 0, 0]); expect(tf.memory().numTensors).toBe(2); tf.tidy(() => { b = tf.add(a, b); b = tf.add(a, b); b = tf.add(a, b); tf.add(a, b); }); // all intermediates should be disposed. expect(tf.memory().numTensors).toBe(2); }); it('nested usage', async () => { const a = tf.tensor1d([1, 2, 3]); let b = tf.tensor1d([0, 0, 0]); expect(tf.memory().numTensors).toBe(2); tf.tidy(() => { const result = tf.tidy(() => { b = tf.add(a, b); b = tf.tidy(() => { b = tf.tidy(() => { return tf.add(a, b); }); // original a, b, and two intermediates. expect(tf.memory().numTensors).toBe(4); tf.tidy(() => { tf.add(a, b); }); // All the intermediates should be cleaned up. expect(tf.memory().numTensors).toBe(4); return tf.add(a, b); }); expect(tf.memory().numTensors).toBe(4); return tf.add(a, b); }); expect(tf.memory().numTensors).toBe(3); expect(result.isDisposed).toBe(false); expect(result.shape).toEqual([3]); }); expect(tf.memory().numTensors).toBe(2); }); it('nested usage returns tensor created from outside scope', () => { const x = tf.scalar(1); tf.tidy(() => { tf.tidy(() => { return x; }); }); expect(x.isDisposed).toBe(false); }); it('nested usage with keep works', () => { let b; tf.tidy(() => { const a = tf.scalar(1); tf.tidy(() => { b = tf.keep(a); }); }); expect(b.isDisposed).toBe(false); b.dispose(); }); it('single argument', () => { let hasRan = false; tf.tidy(() => { hasRan = true; }); expect(hasRan).toBe(true); }); it('single argument, but not a function throws error', () => { expect(() => { tf.tidy('asdf'); }).toThrowError(); }); it('2 arguments, first is string', () => { let hasRan = false; tf.tidy('name', () => { hasRan = true; }); expect(hasRan).toBe(true); }); it('2 arguments, but first is not string throws error', () => { expect(() => { // tslint:disable-next-line:no-any tf.tidy(4, () => { }); }).toThrowError(); }); it('2 arguments, but second is not a function throws error', () => { expect(() => { // tslint:disable-next-line:no-any tf.tidy('name', 'another name'); }).toThrowError(); }); it('works with arbitrary depth of result', async () => { tf.tidy(() => { const res = tf.tidy(() => { return [tf.scalar(1), [[tf.scalar(2)]], { list: [tf.scalar(3)] }]; }); expect(res[0].isDisposed).toBe(false); // tslint:disable-next-line:no-any expect(res[1][0][0].isDisposed).toBe(false); // tslint:disable-next-line:no-any expect(res[2].list[0].isDisposed).toBe(false); expect(tf.memory().numTensors).toBe(3); return res[0]; }); // Everything but scalar(1) got disposed. expect(tf.memory().numTensors).toBe(1); }); }); //# sourceMappingURL=globals_test.js.map