1 parent
076800ed2d
commit
1c44426ff2
189 files changed
+23703
No files matched your search
Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/.bin/detect-libc
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../detect-libc/bin/detect-libc.js
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../mkdirp/bin/cmd.js
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../needle/bin/needle
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../node-pre-gyp/bin/node-pre-gyp
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../nopt/bin/nopt.js
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../rc/cli.js
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../rimraf/bin.js
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../semver/bin/semver
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
0.24.0
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"extension": [
|
||||
".ts"
|
||||
],
|
||||
"reporter": [
|
||||
"html",
|
||||
"text-summary"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"src/run_tests.ts",
|
||||
"src/**/*_test.ts",
|
||||
"src/proto/*"
|
||||
],
|
||||
"cache": false,
|
||||
"sourceMap": true,
|
||||
"instrument": true
|
||||
}
|
||||
Generated
Vendored
+117
@@ -0,0 +1,117 @@
|
||||
# TensorFlow.js Node.js bindings development.
|
||||
|
||||
The @tensorflow/tfjs-node repo supports npm package @tensorflow/tfjs-node and @tensorflow/tfjs-node-gpu on Windows/Mac/Linux. This guide lists commands to use when developing this package.
|
||||
|
||||
## Install
|
||||
|
||||
#### Dependencies and addon module
|
||||
|
||||
```sh
|
||||
$ yarn
|
||||
```
|
||||
|
||||
This command installs all dependencies and devDependencies listed in package.json. It also downloads the TensorFlow C library and native node addon.
|
||||
|
||||
#### Compile native addon from source files
|
||||
|
||||
```sh
|
||||
$ yarn build-addon-from-source
|
||||
```
|
||||
|
||||
This command will compile a new native node addon from source files.
|
||||
|
||||
####
|
||||
|
||||
```sh
|
||||
$ yarn install-from-source
|
||||
```
|
||||
|
||||
This command does the following:
|
||||
|
||||
1. Clears local binary and addon resources
|
||||
2. Downloads the TensorFlow C library
|
||||
3. Compiles the native addon from source files (instead of downloading pre-compile addon)
|
||||
|
||||
#### Switching local workflow to CUDA/GPU
|
||||
|
||||
```sh
|
||||
$ yarn enable-gpu
|
||||
```
|
||||
|
||||
This command is the same as `yarn install-from-source` except it uses the TensorFlow GPU library.
|
||||
|
||||
## Build and test
|
||||
|
||||
#### Compile javascript files from typescript
|
||||
|
||||
```sh
|
||||
$ yarn build
|
||||
```
|
||||
|
||||
#### Publish locally through yalc to test this package in another repo
|
||||
|
||||
```sh
|
||||
$ yarn publish-local
|
||||
```
|
||||
|
||||
This command packs the `tfjs-node` package and publishes locally through [yalc](https://github.com/whitecolor/yalc).
|
||||
NOTE: Dependent packages must install this locally published package through yalc and compile the node native addon locally. In the dependent package run the following command to link local published `tfjs-node` package:
|
||||
|
||||
```sh
|
||||
$ yalc link @tensorflow/tfjs-node
|
||||
$ cd .yalc/@tensorflow/tfjs-node
|
||||
$ yarn && yarn build-addon-from-source
|
||||
$ cd ../../..
|
||||
```
|
||||
|
||||
#### Run tests
|
||||
|
||||
```sh
|
||||
$ yarn test
|
||||
```
|
||||
|
||||
## Prepare and publish
|
||||
|
||||
#### Prerequisite: install GCP command line tool
|
||||
|
||||
Publishing this package requires uploading objects to GCP bucket. Developers need to install GCP command line tool [gsutil](https://cloud.google.com/storage/docs/gsutil_install) before publishing. Please ask TFJS developers for GCP project ID.
|
||||
|
||||
#### Build and upload node addon to Google Cloud Platform
|
||||
|
||||
```sh
|
||||
$ yarn build-addon cpu for-publish
|
||||
```
|
||||
|
||||
This command will compile, compress, and upload a new node addon to GCP bucket. Please read [build-and-upload-addon.sh](./scripts/build-and-upload-addon.sh) for details.
|
||||
|
||||
#### Build NPM package
|
||||
|
||||
```sh
|
||||
$ yarn build-npm
|
||||
```
|
||||
|
||||
This command will build a new version of tfjs-node/tfjs-node-gpu NPM tarball. NOTE: this command does not update the pre-compiled node addon to GCP (see `yarn build-addon upload`).
|
||||
|
||||
#### Build NPM package and upload node addon
|
||||
|
||||
```sh
|
||||
$ yarn build-npm upload
|
||||
```
|
||||
|
||||
This command combines the above two commands.
|
||||
|
||||
#### Publish NPM package
|
||||
|
||||
```sh
|
||||
$ yarn publish-npm
|
||||
```
|
||||
|
||||
This command compiles a new node addon, upload it to GCP, then builds and publishes a new npm package. Please read instruction in [publish-npm.sh](./scripts/publish.sh) before publishing.
|
||||
|
||||
#### Build and upload node addon on Windows
|
||||
|
||||
```sh
|
||||
$ yarn upload-windows-addon
|
||||
```
|
||||
|
||||
Most times the NPM package is published on Linux machine, and only the Linux node addon is compiled and uploaded to GCP bucket. To build and upload the native node addon for Windows, developers should run the above commands on Windows machine. Please read [build-and-upload-windows-addon.bat](./scripts/build-and-upload-windows-addon.bat) for details.
|
||||
Generated
Vendored
+176
@@ -0,0 +1,176 @@
|
||||
# TensorFlow backend for TensorFlow.js via Node.js
|
||||
This repository provides native TensorFlow execution in backend JavaScript applications under the Node.js runtime,
|
||||
accelerated by the TensorFlow C binary under the hood. It provides the same API as [TensorFlow.js](https://js.tensorflow.org/api/latest/).
|
||||
|
||||
This package will work on Linux, Windows, and Mac platforms where TensorFlow is supported.
|
||||
|
||||
## Installing
|
||||
|
||||
TensorFlow.js for Node currently supports the following platforms:
|
||||
- Mac OS X CPU (10.12.6 Siera or higher)
|
||||
- Linux CPU (Ubuntu 14.04 or higher)
|
||||
- Linux GPU (Ubuntu 14.04 or higher and Cuda 10.0 w/ CUDNN v7) ([see installation instructions](https://www.tensorflow.org/install/gpu#software_requirements))
|
||||
- Windows CPU (Win 7 or higher)
|
||||
- Windows GPU (Win 7 or higher and Cuda 10.0 w/ CUDNN v7) ([see installation instructions](https://www.tensorflow.org/install/gpu#windows_setup))
|
||||
|
||||
For GPU support, tfjs-node-gpu@1.2.4 or later requires the following NVIDIA® software installed on your system:
|
||||
|
||||
| Name | Version |
|
||||
| ------------- | ------------- |
|
||||
| [NVIDIA® GPU drivers](https://www.nvidia.com/Download/index.aspx?lang=en-us) | >410.x |
|
||||
| [CUDA® Toolkit](https://developer.nvidia.com/cuda-10.0-download-archive) | 10.0 |
|
||||
| [cuDNN SDK](https://developer.nvidia.com/rdp/cudnn-download) | >=7.4.1 |
|
||||
|
||||
*Other Linux variants might also work but this project matches [core TensorFlow installation requirements](https://www.tensorflow.org/install/install_linux).*
|
||||
|
||||
#### Installing CPU TensorFlow.js for Node:
|
||||
|
||||
```sh
|
||||
npm install @tensorflow/tfjs-node
|
||||
(or)
|
||||
yarn add @tensorflow/tfjs-node
|
||||
```
|
||||
|
||||
#### Installing Linux/Windows GPU TensorFlow.js for Node:
|
||||
|
||||
```sh
|
||||
npm install @tensorflow/tfjs-node-gpu
|
||||
(or)
|
||||
yarn add @tensorflow/tfjs-node-gpu
|
||||
```
|
||||
|
||||
#### Windows / Mac OS X Requires Python 2.7
|
||||
|
||||
Windows & OSX build support for `node-gyp` requires Python 2.7. Be sure to have this version before installing `@tensorflow/tfjs-node` or `@tensorflow/tfjs-node-gpu`. Machines with Python 3.x will not install the bindings properly.
|
||||
|
||||
*For more troubleshooting on Windows, check out [WINDOWS_TROUBLESHOOTING.md](./WINDOWS_TROUBLESHOOTING.md).*
|
||||
|
||||
#### Mac OS X Requires Xcode
|
||||
|
||||
If you do not have Xcode setup on your machine, please run the following commands:
|
||||
|
||||
```sh
|
||||
$ xcode-select --install
|
||||
```
|
||||
For Mac OS Catalina please follow [this guide](https://github.com/nodejs/node-gyp/blob/master/macOS_Catalina.md#installing-node-gyp-using-the-xcode-command-line-tools-via-manual-download) to install node-gyp.
|
||||
|
||||
After that operation completes, re-run `yarn add` or `npm install` for the `@tensorflow/tfjs-node` package.
|
||||
|
||||
You only need to include `@tensorflow/tfjs-node` or `@tensorflow/tfjs-node-gpu` in the package.json file, since those packages ship with `@tensorflow/tfjs` already.
|
||||
|
||||
#### Rebuild the package on Raspberry Pi
|
||||
|
||||
To use this package on Raspberry Pi, you need to rebuild the node native addon with the following command after you installed the package:
|
||||
|
||||
```sh
|
||||
$ npm rebuild @tensorflow/tfjs-node --build-from-source
|
||||
```
|
||||
|
||||
#### Custom binaries URI
|
||||
|
||||
If you happen to be using a mirror for the libtensorflow binaries (default is [https://storage.googleapis.com/]), you have 3 options (in order of priority):
|
||||
|
||||
1. Set the environment variable `TFJS_NODE_CDN_STORAGE`. This has the same behavior as `CDN_STORAGE`, but introduced to prevent collisions with other npm packages that might use `CDN_STORAGE`.
|
||||
|
||||
```sh
|
||||
TFJS_NODE_CDN_STORAGE="https://yourmirrorofchoice.com/" npm install <package>
|
||||
(or)
|
||||
TFJS_NODE_CDN_STORAGE="https://yourmirrorofchoice.com/" yarn install <package>
|
||||
```
|
||||
|
||||
2. Add the variable `TFJS_NODE_CDN_STORAGE` to your `.npmrc` file.
|
||||
|
||||
```
|
||||
TFJS_NODE_CDN_STORAGE=https://yourmirrorofchoice.com/
|
||||
```
|
||||
|
||||
3. Set the environment variable `CDN_STORAGE`. This option is deprecated in favor of the `TFJS_NODE_` prefix version above and will be removed in a future release.
|
||||
|
||||
```sh
|
||||
CDN_STORAGE="https://yourmirrorofchoice.com/" npm install <package>
|
||||
(or)
|
||||
CDN_STORAGE="https://yourmirrorofchoice.com/" yarn install <package>
|
||||
```
|
||||
|
||||
If your "mirror" uses a custom URI path that doesn't match the default, you have 2 options (in order of priority):
|
||||
|
||||
1. Set the environment variable `TFJS_NODE_BASE_URI`
|
||||
|
||||
```sh
|
||||
TFJS_NODE_BASE_URI="https://yourhost.com/your/path/libtensorflow-" npm install <package>
|
||||
(or)
|
||||
TFJS_NODE_BASE_URI="https://yourhost.com/your/path/libtensorflow-" yarn install <package>
|
||||
```
|
||||
|
||||
2. Add the variable `TFJS_NODE_BASE_URI` to your `.npmrc` file
|
||||
|
||||
```
|
||||
TFJS_NODE_BASE_URI=https://yourhost.com/your/path/libtensorflow-
|
||||
```
|
||||
|
||||
## Using the binding
|
||||
|
||||
Before executing any TensorFlow.js code, import the node package:
|
||||
|
||||
```js
|
||||
// Load the binding
|
||||
const tf = require('@tensorflow/tfjs-node');
|
||||
|
||||
// Or if running with GPU:
|
||||
const tf = require('@tensorflow/tfjs-node-gpu');
|
||||
```
|
||||
|
||||
Note: you do not need to add the `@tensorflow/tfjs` package to your dependencies or import it directly.
|
||||
|
||||
## Development
|
||||
|
||||
```sh
|
||||
# Download and install JS dependencies, including libtensorflow 1.8.
|
||||
yarn
|
||||
|
||||
# Run TFJS tests against Node.js backend:
|
||||
yarn test
|
||||
```
|
||||
|
||||
```sh
|
||||
# Switch to GPU for local development:
|
||||
yarn enable-gpu
|
||||
```
|
||||
|
||||
|
||||
## MNIST demo for Node.js
|
||||
|
||||
See the [tfjs-examples repository](https://github.com/tensorflow/tfjs-examples/tree/master/mnist-node) for training the MNIST dataset using the Node.js bindings.
|
||||
|
||||
### Optional: Build optimal TensorFlow from source
|
||||
|
||||
To get the most optimal TensorFlow build that can take advantage of your specific hardware (AVX512, MKL-DNN), you can build the `libtensorflow` library from source:
|
||||
- [Install bazel](https://docs.bazel.build/versions/master/install.html)
|
||||
- Checkout the [main tensorflow repo](https://github.com/tensorflow/tensorflow) and follow the instructions in [here](https://www.tensorflow.org/install/source) with **one difference**: instead of building the pip package, build `libtensorflow`:
|
||||
|
||||
```sh
|
||||
./configure
|
||||
bazel build --config=opt --config=monolithic //tensorflow/tools/lib_package:libtensorflow
|
||||
```
|
||||
|
||||
The build might take a while and will produce a `bazel-bin/tensorflow/tools/lib_package/libtensorflow.tar.gz` file, which should be unpacked and replace the files in `deps` folder of `tfjs-node` repo:
|
||||
```sh
|
||||
cp bazel-bin/tensorflow/tools/lib_package/libtensorflow.tar.gz ~/myproject/node_modules/@tensorflow/tfjs-node/deps
|
||||
cd path-to-my-project/node_modules/@tensorflow/tfjs-node/deps
|
||||
tar -xf libtensorflow.tar.gz
|
||||
```
|
||||
|
||||
If you want to publish an addon library with your own libtensorflow binary, you can host the custom libtensorflow binary and optional pre-compiled node addon module on the cloud service you choose, and add a `custom-binary.json` file in `scripts` folder with the following information:
|
||||
|
||||
```js
|
||||
{
|
||||
"tf-lib": "url-to-download-customized-binary",
|
||||
"addon": {
|
||||
"host": "host-of-pre-compiled-addon",
|
||||
"remote_path": "remote-path-of-pre-compiled-addon",
|
||||
"package_name": "file-name-of-pre-compile-addon"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The installation scripts will automatically catch this file and use the custom libtensorflow binary and addon. If `addon` is not provided, the installation script will compile addon from source.
|
||||
Generated
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
# TensorFlow.js Node.js bindings Windows troubleshooting.
|
||||
|
||||
The tfjs-node package uses the [node-gyp](https://github.com/nodejs/node-gyp) package to handle cross-compiling the C++ code required to bind TensorFlow to Node.js. This cross platform solution can be somewhat tricky on Windows platforms. This guide helps reference solutions that have been triaged through Issues on the main [tfjs repo](https://github.com/tensorflow/tfjs).
|
||||
|
||||
## Ensure Python 2.x is installed
|
||||
|
||||
Currently, node-gyp requires Python 2.x to work properly. If Python 3.x is installed, you will see build failures. Also double check your python version `python --version` and update the Windows `$PATH` as needed.
|
||||
|
||||
## 'The system cannot find the patch specified' Exceptions
|
||||
|
||||
This can happen for a variety of reasons. First, to inspect what is missing either `cd node_modules/@tensorflow/tfjs-node` or clone the [tensorflow/tfjs repo](https://github.com/tensorflow/tfjs).
|
||||
|
||||
After `cd`'ing or cloning, run the following command (you might need node-gyp installed globablly `npm install -g node-gyp`):
|
||||
|
||||
```sh
|
||||
node-gyp configure --verbose
|
||||
```
|
||||
|
||||
### Missing `python2`
|
||||
|
||||
From the verbose output, if you see something like:
|
||||
|
||||
```sh
|
||||
gyp verb check python checking for Python executable "python2" in the PATH
|
||||
gyp verb `which` failed Error: not found: python2
|
||||
```
|
||||
|
||||
This means that node-gyp expects a 'python2' exe somewhere in `%PATH%`. Try running this command from an Admin (elevated privilaged prompt):
|
||||
|
||||
You can try running this from an Adminstrative prompt:
|
||||
|
||||
```sh
|
||||
$ npm --add-python-to-path='true' --debug install --global windows-build-tools
|
||||
```
|
||||
|
||||
### Something else?
|
||||
|
||||
If another missing component shows up - please file an issue on [tensorflow/tfjs](https://github.com/tensorflow/tfjs/issues/new) with the output from the `node-gyp configure --verbose` command.
|
||||
|
||||
## msbuild.exe Exceptions
|
||||
|
||||
Check the full stack trace from `npm install` (or `yarn`) command. If you see something like:
|
||||
|
||||
```
|
||||
gyp ERR! stack Error: C:\Program Files (x86)\MSBuild\14.0\bin\msbuild.exe failed with exit code: 1
|
||||
```
|
||||
|
||||
You might need to install the system tools manually. This can be done via:
|
||||
|
||||
```
|
||||
npm install -g --production windows-build-tools
|
||||
```
|
||||
|
||||
If that still does not work - try re-running the command above in a privileged shell.
|
||||
Generated
Vendored
+108
@@ -0,0 +1,108 @@
|
||||
##
|
||||
# @license
|
||||
# Copyright 2018 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.
|
||||
# =============================================================================
|
||||
|
||||
# Node.js TensorFlow Binding config:
|
||||
{
|
||||
'variables' : {
|
||||
'tensorflow_include_dir' : '<(module_root_dir)/deps/include',
|
||||
'tensorflow_headers' : [
|
||||
'<@(tensorflow_include_dir)/tensorflow/c/c_api.h',
|
||||
'<@(tensorflow_include_dir)/tensorflow/c/eager/c_api.h',
|
||||
],
|
||||
'tensorflow-library-action': 'move'
|
||||
},
|
||||
'targets' : [{
|
||||
'target_name' : 'tfjs_binding',
|
||||
'sources' : [
|
||||
'binding/tfjs_backend.cc',
|
||||
'binding/tfjs_binding.cc'
|
||||
],
|
||||
'include_dirs' : [ '..', '<(tensorflow_include_dir)' ],
|
||||
'conditions' : [
|
||||
[
|
||||
'OS=="linux"', {
|
||||
'libraries' : [
|
||||
'-Wl,-rpath,\$$ORIGIN/../../deps/lib',
|
||||
'-ltensorflow',
|
||||
'-ltensorflow_framework',
|
||||
],
|
||||
'library_dirs' : ['<(module_root_dir)/deps/lib'],
|
||||
}
|
||||
],
|
||||
[
|
||||
'OS=="mac"', {
|
||||
'libraries' : [
|
||||
'<(module_root_dir)/deps/lib/libtensorflow.2.dylib',
|
||||
'<(module_root_dir)/deps/lib/libtensorflow_framework.2.dylib',
|
||||
],
|
||||
'postbuilds': [
|
||||
{
|
||||
'postbuild_name': 'Adjust libtensorflow load path',
|
||||
'action': [
|
||||
'install_name_tool',
|
||||
"-change",
|
||||
"@rpath/libtensorflow.2.dylib",
|
||||
"@loader_path/../../deps/lib/libtensorflow.dylib",
|
||||
"<(PRODUCT_DIR)/tfjs_binding.node"
|
||||
]
|
||||
},
|
||||
{
|
||||
'postbuild_name': 'Adjust libtensorflow_framework load path',
|
||||
'action': [
|
||||
'install_name_tool',
|
||||
"-change",
|
||||
"@rpath/libtensorflow_framework.2.dylib",
|
||||
"@loader_path/../../deps/lib/libtensorflow_framework.2.dylib",
|
||||
"<(PRODUCT_DIR)/tfjs_binding.node"
|
||||
]
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
[
|
||||
'OS=="win"', {
|
||||
'defines': ['COMPILER_MSVC'],
|
||||
'libraries': ['tensorflow'],
|
||||
'library_dirs' : ['<(module_root_dir)/deps/lib'],
|
||||
'variables': {
|
||||
'tensorflow-library-target': 'windows'
|
||||
},
|
||||
'msvs_disabled_warnings': [
|
||||
# Warning C4190: 'TF_NewWhile' has C-linkage specified, but returns
|
||||
# UDT 'TF_WhileParams' which is incompatible with C.
|
||||
# (in include/tensorflow/c/c_api.h)
|
||||
4190
|
||||
]
|
||||
},
|
||||
]
|
||||
],
|
||||
}
|
||||
, {
|
||||
"target_name": "action_after_build",
|
||||
"type": "none",
|
||||
"dependencies": [ "<(module_name)" ],
|
||||
"copies": [
|
||||
{
|
||||
"files": [ "<(PRODUCT_DIR)/<(module_name).node" ],
|
||||
"destination": "<(module_path)"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"defines": [
|
||||
"NAPI_VERSION=<(napi_build_version)"
|
||||
]
|
||||
}
|
||||
Generated
Vendored
+70
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @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.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef TF_NODEJS_NAPI_AUTO_REF_H_
|
||||
#define TF_NODEJS_NAPI_AUTO_REF_H_
|
||||
|
||||
#include <node_api.h>
|
||||
#include "utils.h"
|
||||
|
||||
namespace tfnodejs {
|
||||
|
||||
// Helper class to automatically cleanup napi_ref instances.
|
||||
class NapiAutoRef {
|
||||
public:
|
||||
NapiAutoRef() : env_(nullptr), ref_(nullptr) {}
|
||||
|
||||
napi_status Init(napi_env env, napi_value value) {
|
||||
env_ = env;
|
||||
return napi_create_reference(env_, value, 1, &ref_);
|
||||
}
|
||||
|
||||
napi_status Cleanup() {
|
||||
if (!env_ || !ref_) {
|
||||
#if DEBUG
|
||||
NAPI_THROW_ERROR(env_, "Uninitialized reference attempted to cleanup");
|
||||
#endif
|
||||
return napi_invalid_arg;
|
||||
}
|
||||
|
||||
napi_status nstatus = napi_delete_reference(env_, ref_);
|
||||
env_ = nullptr;
|
||||
ref_ = nullptr;
|
||||
return nstatus;
|
||||
}
|
||||
|
||||
virtual ~NapiAutoRef() {
|
||||
if (env_) {
|
||||
#if DEBUG
|
||||
NAPI_THROW_ERROR(env_, "Non-cleaned up napi_env instance");
|
||||
#endif
|
||||
}
|
||||
if (ref_) {
|
||||
#if DEBUG
|
||||
NAPI_THROW_ERROR(env_, "Non-cleaned up napi_ref instance");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
napi_env env_;
|
||||
napi_ref ref_;
|
||||
};
|
||||
|
||||
} // namespace tfnodejs
|
||||
|
||||
#endif // TF_NODEJS_NAPI_AUTO_REF_H_
|
||||
Generated
Vendored
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef TF_NODEJS_TF_AUTO_STATUS_H_
|
||||
#define TF_NODEJS_TF_AUTO_STATUS_H_
|
||||
|
||||
#include "tensorflow/c/c_api.h"
|
||||
|
||||
namespace tfnodejs {
|
||||
|
||||
// Automatically cleans up a TF_Status instance.
|
||||
class TF_AutoStatus {
|
||||
public:
|
||||
TF_AutoStatus() : status(TF_NewStatus()) {}
|
||||
virtual ~TF_AutoStatus() { TF_DeleteStatus(status); }
|
||||
|
||||
TF_Status* status;
|
||||
};
|
||||
|
||||
} // namespace tfnodejs
|
||||
|
||||
#endif // TF_NODEJS_TF_AUTO_STATUS_H_
|
||||
Generated
Vendored
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef TF_NODEJS_TF_AUTO_TENSOR_H_
|
||||
#define TF_NODEJS_TF_AUTO_TENSOR_H_
|
||||
|
||||
#include "tensorflow/c/c_api.h"
|
||||
|
||||
namespace tfnodejs {
|
||||
|
||||
// Automatically cleans up a TF_Tensor instance.
|
||||
class TF_AutoTensor {
|
||||
public:
|
||||
TF_AutoTensor(TF_Tensor* tensor) : tensor(tensor) {}
|
||||
virtual ~TF_AutoTensor() { TF_DeleteTensor(tensor); }
|
||||
|
||||
TF_Tensor* tensor;
|
||||
};
|
||||
|
||||
} // namespace tfnodejs
|
||||
|
||||
#endif // TF_NODEJS_TF_AUTO_TENSOR_H_
|
||||
Generated
Vendored
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef TF_NODEJS_TFE_AUTO_OP_H_
|
||||
#define TF_NODEJS_TFE_AUTO_OP_H_
|
||||
|
||||
#include "tensorflow/c/eager/c_api.h"
|
||||
|
||||
namespace tfnodejs {
|
||||
|
||||
// Automatically cleans up a TF_Op instance.
|
||||
class TFE_AutoOp {
|
||||
public:
|
||||
TFE_AutoOp(TFE_Op* op) : op(op) {}
|
||||
virtual ~TFE_AutoOp() { TFE_DeleteOp(op); }
|
||||
|
||||
TFE_Op* op;
|
||||
};
|
||||
|
||||
} // namespace tfnodejs
|
||||
|
||||
#endif // TF_NODEJS_TFE_AUTO_OP_H_
|
||||
Generated
Vendored
+1192
File diff suppressed because it is too large.
Load diff
Generated
Vendored
+108
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef TF_NODEJS_TFJS_BACKEND_H_
|
||||
#define TF_NODEJS_TFJS_BACKEND_H_
|
||||
|
||||
#include <node_api.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "tensorflow/c/c_api.h"
|
||||
#include "tensorflow/c/eager/c_api.h"
|
||||
|
||||
namespace tfnodejs {
|
||||
|
||||
class TFJSBackend {
|
||||
public:
|
||||
// Creates, initializes, and returns a TFJSBackend instance. If initialization
|
||||
// fails, a nullptr is returned.
|
||||
static TFJSBackend *Create(napi_env env);
|
||||
|
||||
// Creates a new Tensor with given shape and data and returns an ID that
|
||||
// refernces the new Tensor.
|
||||
// - shape_value (number[])
|
||||
// - dtype_value (number)
|
||||
// - array_value (TypedArray|Array)
|
||||
napi_value CreateTensor(napi_env env, napi_value shape_value,
|
||||
napi_value dtype_value, napi_value array_value);
|
||||
|
||||
// Deletes a created Tensor.
|
||||
// - tensor_id_value (number)
|
||||
void DeleteTensor(napi_env env, napi_value tensor_id_value);
|
||||
|
||||
// Returns a typed-array as a `napi_value` with the data associated with the
|
||||
// TF/TFE pointers.
|
||||
// - tensor_id_value (number)
|
||||
napi_value GetTensorData(napi_env env, napi_value tensor_id_value);
|
||||
|
||||
// Executes a TFE Op and returns an array of objects containing tensor
|
||||
// attributes (id, dtype, shape).
|
||||
// - op_name_value (string)
|
||||
// - op_attr_inputs (array of TFE Op attributes)
|
||||
// - input_tensor_ids (array of input tensor IDs)
|
||||
// - num_output_values (number)
|
||||
napi_value ExecuteOp(napi_env env, napi_value op_name_value,
|
||||
napi_value op_attr_inputs, napi_value input_tensor_ids,
|
||||
napi_value num_output_values);
|
||||
|
||||
// Load a SavedModel from a path:
|
||||
// - export_dir (string)
|
||||
// - tags_value (string)
|
||||
napi_value LoadSavedModel(napi_env env, napi_value export_dir,
|
||||
napi_value tags_value);
|
||||
|
||||
// Delete the SavedModel corresponding TF_Session and TF_Graph
|
||||
// - saved_model_id (number)
|
||||
void DeleteSavedModel(napi_env env, napi_value saved_model_id);
|
||||
|
||||
// Execute a session from SavedModel with the provided inputs:
|
||||
// - saved_model_id (number)
|
||||
// - input_tensor_ids (array of input tensor IDs)
|
||||
// - input_op_names (array of input op names)
|
||||
// - output_op_names (array of output op names)
|
||||
napi_value RunSavedModel(napi_env env, napi_value saved_model_id,
|
||||
napi_value input_tensor_ids,
|
||||
napi_value input_op_names,
|
||||
napi_value output_op_names);
|
||||
|
||||
// Get number of loaded SavedModel in the backend:
|
||||
napi_value GetNumOfSavedModels(napi_env env);
|
||||
|
||||
private:
|
||||
TFJSBackend(napi_env env);
|
||||
~TFJSBackend();
|
||||
|
||||
int32_t InsertHandle(TFE_TensorHandle *tfe_handle);
|
||||
int32_t InsertSavedModel(TF_Session *tf_session, TF_Graph *tf_graph);
|
||||
napi_value GenerateOutputTensorInfo(napi_env env, TFE_TensorHandle *handle);
|
||||
|
||||
TFE_Context *tfe_context_;
|
||||
std::unordered_map<int32_t, TFE_TensorHandle *> tfe_handle_map_;
|
||||
std::unordered_map<int32_t, std::pair<TF_Session *, TF_Graph *>>
|
||||
tf_savedmodel_map_;
|
||||
int32_t next_tensor_id_;
|
||||
int32_t next_savedmodel_id_;
|
||||
std::string device_name;
|
||||
|
||||
public:
|
||||
bool is_gpu_device;
|
||||
};
|
||||
|
||||
} // namespace tfnodejs
|
||||
|
||||
#endif // TF_NODEJS_TFJS_BACKEND_H_
|
||||
Generated
Vendored
+296
@@ -0,0 +1,296 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
#include <node_api.h>
|
||||
#include "tfjs_backend.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace tfnodejs {
|
||||
|
||||
TFJSBackend *gBackend = nullptr;
|
||||
|
||||
static void AssignIntProperty(napi_env env, napi_value exports,
|
||||
const char *name, int32_t value) {
|
||||
napi_value js_value;
|
||||
napi_status nstatus = napi_create_int32(env, value, &js_value);
|
||||
ENSURE_NAPI_OK(env, nstatus);
|
||||
|
||||
napi_property_descriptor property = {name, nullptr, nullptr,
|
||||
nullptr, nullptr, js_value,
|
||||
napi_default, nullptr};
|
||||
nstatus = napi_define_properties(env, exports, 1, &property);
|
||||
ENSURE_NAPI_OK(env, nstatus);
|
||||
}
|
||||
|
||||
static napi_value CreateTensor(napi_env env, napi_callback_info info) {
|
||||
napi_status nstatus;
|
||||
|
||||
// Create tensor takes 3 params: shape, dtype, typed-array/array:
|
||||
size_t argc = 3;
|
||||
napi_value args[3];
|
||||
napi_value js_this;
|
||||
nstatus = napi_get_cb_info(env, info, &argc, args, &js_this, nullptr);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, nullptr);
|
||||
|
||||
if (argc < 3) {
|
||||
NAPI_THROW_ERROR(env,
|
||||
"Invalid number of args passed to createTensor(). "
|
||||
"Expecting 3 args but got %d.",
|
||||
argc);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ENSURE_VALUE_IS_ARRAY_RETVAL(env, args[0], nullptr);
|
||||
ENSURE_VALUE_IS_NUMBER_RETVAL(env, args[1], nullptr);
|
||||
|
||||
// The third array can either be a typed array or an array:
|
||||
bool is_typed_array;
|
||||
nstatus = napi_is_typedarray(env, args[2], &is_typed_array);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, nullptr);
|
||||
if (!is_typed_array) {
|
||||
ENSURE_VALUE_IS_ARRAY_RETVAL(env, args[2], nullptr);
|
||||
}
|
||||
|
||||
return gBackend->CreateTensor(env, args[0], args[1], args[2]);
|
||||
}
|
||||
|
||||
static napi_value DeleteTensor(napi_env env, napi_callback_info info) {
|
||||
napi_status nstatus;
|
||||
|
||||
// Delete tensor takes 1 param: tensor ID;
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
napi_value js_this;
|
||||
nstatus = napi_get_cb_info(env, info, &argc, args, &js_this, nullptr);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, js_this);
|
||||
|
||||
if (argc < 1) {
|
||||
NAPI_THROW_ERROR(env,
|
||||
"Invalid number of args passed to deleteTensor(). "
|
||||
"Expecting 1 arg but got %d.",
|
||||
argc);
|
||||
return js_this;
|
||||
}
|
||||
|
||||
ENSURE_VALUE_IS_NUMBER_RETVAL(env, args[0], js_this);
|
||||
|
||||
gBackend->DeleteTensor(env, args[0]);
|
||||
return js_this;
|
||||
}
|
||||
|
||||
static napi_value TensorDataSync(napi_env env, napi_callback_info info) {
|
||||
napi_status nstatus;
|
||||
|
||||
// Tensor data-sync takes 1 param: tensor ID;
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
napi_value js_this;
|
||||
nstatus = napi_get_cb_info(env, info, &argc, args, &js_this, nullptr);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, js_this);
|
||||
|
||||
if (argc < 1) {
|
||||
NAPI_THROW_ERROR(env,
|
||||
"Invalid number of args passed to tensorDataSync(). "
|
||||
"Expecting 1 arg but got %d.",
|
||||
argc);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ENSURE_VALUE_IS_NUMBER_RETVAL(env, args[0], js_this);
|
||||
|
||||
return gBackend->GetTensorData(env, args[0]);
|
||||
}
|
||||
|
||||
static napi_value ExecuteOp(napi_env env, napi_callback_info info) {
|
||||
napi_status nstatus;
|
||||
|
||||
// Create tensor takes 4 params: op-name, op-attrs, input-tensor-ids,
|
||||
// num-outputs:
|
||||
size_t argc = 4;
|
||||
napi_value args[4];
|
||||
napi_value js_this;
|
||||
nstatus = napi_get_cb_info(env, info, &argc, args, &js_this, nullptr);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, nullptr);
|
||||
|
||||
if (argc < 4) {
|
||||
NAPI_THROW_ERROR(env,
|
||||
"Invalid number of args passed to executeOp(). Expecting "
|
||||
"4 args but got %d.",
|
||||
argc);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ENSURE_VALUE_IS_STRING_RETVAL(env, args[0], nullptr);
|
||||
ENSURE_VALUE_IS_ARRAY_RETVAL(env, args[1], nullptr);
|
||||
ENSURE_VALUE_IS_ARRAY_RETVAL(env, args[2], nullptr);
|
||||
ENSURE_VALUE_IS_NUMBER_RETVAL(env, args[3], nullptr);
|
||||
|
||||
return gBackend->ExecuteOp(env, args[0], args[1], args[2], args[3]);
|
||||
}
|
||||
|
||||
static napi_value IsUsingGPUDevice(napi_env env, napi_callback_info info) {
|
||||
napi_value result;
|
||||
|
||||
napi_status nstatus;
|
||||
nstatus = napi_get_boolean(env, gBackend->is_gpu_device, &result);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, nullptr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static napi_value LoadSavedModel(napi_env env, napi_callback_info info) {
|
||||
napi_status nstatus;
|
||||
|
||||
// Load saved model takes 2 params: export_dir, tags:
|
||||
size_t argc = 2;
|
||||
napi_value args[2];
|
||||
napi_value js_this;
|
||||
nstatus = napi_get_cb_info(env, info, &argc, args, &js_this, nullptr);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, nullptr);
|
||||
|
||||
if (argc < 2) {
|
||||
NAPI_THROW_ERROR(env,
|
||||
"Invalid number of args passed to LoadSavedModel(). "
|
||||
"Expecting 2 args but got %d.",
|
||||
argc);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ENSURE_VALUE_IS_STRING_RETVAL(env, args[0], nullptr);
|
||||
ENSURE_VALUE_IS_STRING_RETVAL(env, args[1], nullptr);
|
||||
|
||||
return gBackend->LoadSavedModel(env, args[0], args[1]);
|
||||
}
|
||||
|
||||
static napi_value DeleteSavedModel(napi_env env, napi_callback_info info) {
|
||||
napi_status nstatus;
|
||||
|
||||
// Delete SavedModel takes 1 param: savedModel ID;
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
napi_value js_this;
|
||||
nstatus = napi_get_cb_info(env, info, &argc, args, &js_this, nullptr);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, js_this);
|
||||
|
||||
if (argc < 1) {
|
||||
NAPI_THROW_ERROR(env,
|
||||
"Invalid number of args passed to deleteSavedModel(). "
|
||||
"Expecting 1 arg but got %d.",
|
||||
argc);
|
||||
return js_this;
|
||||
}
|
||||
|
||||
ENSURE_VALUE_IS_NUMBER_RETVAL(env, args[0], js_this);
|
||||
|
||||
gBackend->DeleteSavedModel(env, args[0]);
|
||||
return js_this;
|
||||
}
|
||||
|
||||
static napi_value RunSavedModel(napi_env env, napi_callback_info info) {
|
||||
napi_status nstatus;
|
||||
|
||||
// Run SavedModel takes 4 params: session_id, input_tensor_ids,
|
||||
// input_op_names, output_op_names.
|
||||
size_t argc = 4;
|
||||
napi_value args[4];
|
||||
napi_value js_this;
|
||||
nstatus = napi_get_cb_info(env, info, &argc, args, &js_this, nullptr);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, nullptr);
|
||||
|
||||
if (argc < 4) {
|
||||
NAPI_THROW_ERROR(env, "Invalid number of args passed to RunSavedModel()");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ENSURE_VALUE_IS_NUMBER_RETVAL(env, args[0], nullptr);
|
||||
ENSURE_VALUE_IS_ARRAY_RETVAL(env, args[1], nullptr);
|
||||
ENSURE_VALUE_IS_STRING_RETVAL(env, args[2], nullptr);
|
||||
ENSURE_VALUE_IS_STRING_RETVAL(env, args[3], nullptr);
|
||||
|
||||
return gBackend->RunSavedModel(env, args[0], args[1], args[2], args[3]);
|
||||
}
|
||||
|
||||
static napi_value GetNumOfSavedModels(napi_env env, napi_callback_info info) {
|
||||
// Delete SavedModel takes 0 param;
|
||||
return gBackend->GetNumOfSavedModels(env);
|
||||
}
|
||||
|
||||
static napi_value InitTFNodeJSBinding(napi_env env, napi_value exports) {
|
||||
napi_status nstatus;
|
||||
|
||||
gBackend = TFJSBackend::Create(env);
|
||||
ENSURE_VALUE_IS_NOT_NULL_RETVAL(env, gBackend, nullptr);
|
||||
|
||||
// TF version
|
||||
napi_value tf_version;
|
||||
nstatus = napi_create_string_latin1(env, TF_Version(), -1, &tf_version);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, exports);
|
||||
|
||||
// Set all export values list here.
|
||||
napi_property_descriptor exports_properties[] = {
|
||||
{"createTensor", nullptr, CreateTensor, nullptr, nullptr, nullptr,
|
||||
napi_default, nullptr},
|
||||
{"deleteTensor", nullptr, DeleteTensor, nullptr, nullptr, nullptr,
|
||||
napi_default, nullptr},
|
||||
{"tensorDataSync", nullptr, TensorDataSync, nullptr, nullptr, nullptr,
|
||||
napi_default, nullptr},
|
||||
{"executeOp", nullptr, ExecuteOp, nullptr, nullptr, nullptr, napi_default,
|
||||
nullptr},
|
||||
{"loadSavedModel", nullptr, LoadSavedModel, nullptr, nullptr, nullptr,
|
||||
napi_default, nullptr},
|
||||
{"deleteSavedModel", nullptr, DeleteSavedModel, nullptr, nullptr, nullptr,
|
||||
napi_default, nullptr},
|
||||
{"runSavedModel", nullptr, RunSavedModel, nullptr, nullptr, nullptr,
|
||||
napi_default, nullptr},
|
||||
{"TF_Version", nullptr, nullptr, nullptr, nullptr, tf_version,
|
||||
napi_default, nullptr},
|
||||
{"isUsingGpuDevice", nullptr, IsUsingGPUDevice, nullptr, nullptr, nullptr,
|
||||
napi_default, nullptr},
|
||||
{"getNumOfSavedModels", nullptr, GetNumOfSavedModels, nullptr, nullptr,
|
||||
nullptr, napi_default, nullptr},
|
||||
};
|
||||
nstatus = napi_define_properties(env, exports, ARRAY_SIZE(exports_properties),
|
||||
exports_properties);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, exports);
|
||||
|
||||
// Export TF property types to JS
|
||||
#define EXPORT_INT_PROPERTY(v) AssignIntProperty(env, exports, #v, v)
|
||||
// Types
|
||||
EXPORT_INT_PROPERTY(TF_FLOAT);
|
||||
EXPORT_INT_PROPERTY(TF_INT32);
|
||||
EXPORT_INT_PROPERTY(TF_INT64);
|
||||
EXPORT_INT_PROPERTY(TF_BOOL);
|
||||
EXPORT_INT_PROPERTY(TF_COMPLEX64);
|
||||
EXPORT_INT_PROPERTY(TF_STRING);
|
||||
EXPORT_INT_PROPERTY(TF_RESOURCE);
|
||||
EXPORT_INT_PROPERTY(TF_UINT8);
|
||||
|
||||
// Op AttrType
|
||||
EXPORT_INT_PROPERTY(TF_ATTR_STRING);
|
||||
EXPORT_INT_PROPERTY(TF_ATTR_INT);
|
||||
EXPORT_INT_PROPERTY(TF_ATTR_FLOAT);
|
||||
EXPORT_INT_PROPERTY(TF_ATTR_BOOL);
|
||||
EXPORT_INT_PROPERTY(TF_ATTR_TYPE);
|
||||
EXPORT_INT_PROPERTY(TF_ATTR_SHAPE);
|
||||
#undef EXPORT_INT_PROPERTY
|
||||
|
||||
return exports;
|
||||
}
|
||||
|
||||
NAPI_MODULE(tfe_binding, InitTFNodeJSBinding)
|
||||
|
||||
} // namespace tfnodejs
|
||||
Generated
Vendored
+329
@@ -0,0 +1,329 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef TF_NODEJS_UTILS_H_
|
||||
#define TF_NODEJS_UTILS_H_
|
||||
|
||||
#include <node_api.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include "tensorflow/c/c_api.h"
|
||||
#include "tf_auto_status.h"
|
||||
|
||||
#define MAX_TENSOR_SHAPE 4
|
||||
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
#ifndef DEBUG
|
||||
#define DEBUG 0
|
||||
#endif
|
||||
|
||||
#define DEBUG_LOG(message, file, line_number) \
|
||||
do { \
|
||||
if (DEBUG) \
|
||||
fprintf(stderr, "** -%s:%zu\n-- %s\n", file, line_number, message); \
|
||||
} while (0)
|
||||
|
||||
namespace tfnodejs {
|
||||
|
||||
#define NAPI_THROW_ERROR(env, message, ...) \
|
||||
NapiThrowError(env, __FILE__, __LINE__, message, ##__VA_ARGS__);
|
||||
|
||||
inline void NapiThrowError(napi_env env, const char *file,
|
||||
const size_t line_number, const char *message, ...) {
|
||||
char buffer[500];
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
std::vsnprintf(buffer, 500, message, args);
|
||||
va_end(args);
|
||||
DEBUG_LOG(buffer, file, line_number);
|
||||
napi_throw_error(env, nullptr, buffer);
|
||||
}
|
||||
|
||||
#define ENSURE_NAPI_OK(env, status) \
|
||||
if (!EnsureNapiOK(env, status, __FILE__, __LINE__)) return;
|
||||
#define ENSURE_NAPI_OK_RETVAL(env, status, retval) \
|
||||
if (!EnsureNapiOK(env, status, __FILE__, __LINE__)) return retval;
|
||||
|
||||
inline bool EnsureNapiOK(napi_env env, napi_status status, const char *file,
|
||||
const size_t line_number) {
|
||||
if (status != napi_ok) {
|
||||
const napi_extended_error_info *error_info = 0;
|
||||
napi_get_last_error_info(env, &error_info);
|
||||
NapiThrowError(
|
||||
env, file, line_number, "Invalid napi_status: %s\n",
|
||||
error_info->error_message ? error_info->error_message : "unknown");
|
||||
}
|
||||
return status == napi_ok;
|
||||
}
|
||||
|
||||
#define ENSURE_TF_OK(env, status) \
|
||||
if (!EnsureTFOK(env, status, __FILE__, __LINE__)) return;
|
||||
#define ENSURE_TF_OK_RETVAL(env, status, retval) \
|
||||
if (!EnsureTFOK(env, status, __FILE__, __LINE__)) return retval;
|
||||
|
||||
inline bool EnsureTFOK(napi_env env, TF_AutoStatus &status, const char *file,
|
||||
const size_t line_number) {
|
||||
TF_Code tf_code = TF_GetCode(status.status);
|
||||
if (tf_code != TF_OK) {
|
||||
NapiThrowError(env, file, line_number, "Invalid TF_Status: %u\nMessage: %s",
|
||||
TF_GetCode(status.status), TF_Message(status.status));
|
||||
}
|
||||
return tf_code == TF_OK;
|
||||
}
|
||||
|
||||
#define ENSURE_CONSTRUCTOR_CALL(env, info) \
|
||||
if (!EnsureConstructorCall(env, info, __FILE__, __LINE__)) return;
|
||||
#define ENSURE_CONSTRUCTOR_CALL_RETVAL(env, info, retval) \
|
||||
if (!EnsureConstructorCall(env, info, __FILE__, __LINE__)) return retval;
|
||||
|
||||
inline bool EnsureConstructorCall(napi_env env, napi_callback_info info,
|
||||
const char *file, const size_t line_number) {
|
||||
napi_value js_target;
|
||||
napi_status nstatus = napi_get_new_target(env, info, &js_target);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, false);
|
||||
bool is_target = js_target != nullptr;
|
||||
if (!is_target) {
|
||||
NapiThrowError(env, file, line_number,
|
||||
"Function not used as a constructor!");
|
||||
}
|
||||
return is_target;
|
||||
}
|
||||
|
||||
#define ENSURE_VALUE_IS_OBJECT(env, value) \
|
||||
if (!EnsureValueIsObject(env, value, __FILE__, __LINE__)) return;
|
||||
#define ENSURE_VALUE_IS_OBJECT_RETVAL(env, value, retval) \
|
||||
if (!EnsureValueIsObject(env, value, __FILE__, __LINE__)) return retval;
|
||||
|
||||
inline bool EnsureValueIsObject(napi_env env, napi_value value,
|
||||
const char *file, const size_t line_number) {
|
||||
napi_valuetype type;
|
||||
ENSURE_NAPI_OK_RETVAL(env, napi_typeof(env, value, &type), false);
|
||||
bool is_object = type == napi_object;
|
||||
if (!is_object) {
|
||||
NapiThrowError(env, file, line_number, "Argument is not an object!");
|
||||
}
|
||||
return is_object;
|
||||
}
|
||||
|
||||
#define ENSURE_VALUE_IS_STRING(env, value) \
|
||||
if (!EnsureValueIsString(env, value, __FILE__, __LINE__)) return;
|
||||
#define ENSURE_VALUE_IS_STRING_RETVAL(env, value, retval) \
|
||||
if (!EnsureValueIsString(env, value, __FILE__, __LINE__)) return retval;
|
||||
|
||||
inline bool EnsureValueIsString(napi_env env, napi_value value,
|
||||
const char *file, const size_t line_number) {
|
||||
napi_valuetype type;
|
||||
ENSURE_NAPI_OK_RETVAL(env, napi_typeof(env, value, &type), false);
|
||||
bool is_string = type == napi_string;
|
||||
if (!is_string) {
|
||||
NapiThrowError(env, file, line_number, "Argument is not a string!");
|
||||
}
|
||||
return is_string;
|
||||
}
|
||||
|
||||
#define ENSURE_VALUE_IS_NUMBER(env, value) \
|
||||
if (!EnsureValueIsNumber(env, value, __FILE__, __LINE__)) return;
|
||||
#define ENSURE_VALUE_IS_NUMBER_RETVAL(env, value, retval) \
|
||||
if (!EnsureValueIsNumber(env, value, __FILE__, __LINE__)) return retval;
|
||||
|
||||
inline bool EnsureValueIsNumber(napi_env env, napi_value value,
|
||||
const char *file, const size_t line_number) {
|
||||
napi_valuetype type;
|
||||
ENSURE_NAPI_OK_RETVAL(env, napi_typeof(env, value, &type), false);
|
||||
bool is_number = type == napi_number;
|
||||
if (!is_number) {
|
||||
NapiThrowError(env, file, line_number, "Argument is not a number!");
|
||||
}
|
||||
return is_number;
|
||||
}
|
||||
|
||||
#define ENSURE_VALUE_IS_ARRAY(env, value) \
|
||||
if (!EnsureValueIsArray(env, value, __FILE__, __LINE__)) return;
|
||||
#define ENSURE_VALUE_IS_ARRAY_RETVAL(env, value, retval) \
|
||||
if (!EnsureValueIsArray(env, value, __FILE__, __LINE__)) return retval;
|
||||
|
||||
inline bool EnsureValueIsArray(napi_env env, napi_value value, const char *file,
|
||||
const size_t line_number) {
|
||||
bool is_array;
|
||||
ENSURE_NAPI_OK_RETVAL(env, napi_is_array(env, value, &is_array), false);
|
||||
if (!is_array) {
|
||||
NapiThrowError(env, file, line_number, "Argument is not an array!");
|
||||
}
|
||||
return is_array;
|
||||
}
|
||||
|
||||
#define ENSURE_VALUE_IS_TYPED_ARRAY(env, value) \
|
||||
if (!EnsureValueIsTypedArray(env, value, __FILE__, __LINE__)) return;
|
||||
#define ENSURE_VALUE_IS_TYPED_ARRAY_RETVAL(env, value, retval) \
|
||||
if (!EnsureValueIsTypedArray(env, value, __FILE__, __LINE__)) return retval;
|
||||
|
||||
inline bool EnsureValueIsTypedArray(napi_env env, napi_value value,
|
||||
const char *file,
|
||||
const size_t line_number) {
|
||||
bool is_array;
|
||||
ENSURE_NAPI_OK_RETVAL(env, napi_is_typedarray(env, value, &is_array), false);
|
||||
if (!is_array) {
|
||||
NapiThrowError(env, file, line_number, "Argument is not a typed-array!");
|
||||
}
|
||||
return is_array;
|
||||
}
|
||||
|
||||
#define ENSURE_VALUE_IS_LESS_THAN(env, value, max) \
|
||||
if (!EnsureValueIsLessThan(env, value, max, __FILE__, __LINE__)) return;
|
||||
#define ENSURE_VALUE_IS_LESS_THAN_RETVAL(env, value, max, retval) \
|
||||
if (!EnsureValueIsLessThan(env, value, max, __FILE__, __LINE__)) \
|
||||
return retval;
|
||||
|
||||
inline bool EnsureValueIsLessThan(napi_env env, uint32_t value, uint32_t max,
|
||||
const char *file, const size_t line_number) {
|
||||
if (value > max) {
|
||||
NapiThrowError(env, file, line_number,
|
||||
"Argument is greater than max: %u > %u", value, max);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#define REPORT_UNKNOWN_TF_DATA_TYPE(env, type) \
|
||||
ReportUnknownTFDataType(env, type, __FILE__, __LINE__)
|
||||
|
||||
inline void ReportUnknownTFDataType(napi_env env, TF_DataType type,
|
||||
const char *file,
|
||||
const size_t line_number) {
|
||||
NapiThrowError(env, file, line_number, "Unhandled TF_DataType: %u\n", type);
|
||||
}
|
||||
|
||||
#define REPORT_UNKNOWN_TF_ATTR_TYPE(env, type) \
|
||||
ReportUnknownTFAttrType(env, type, __FILE__, __LINE__)
|
||||
|
||||
inline void ReportUnknownTFAttrType(napi_env env, TF_AttrType type,
|
||||
const char *file,
|
||||
const size_t line_number) {
|
||||
NapiThrowError(env, file, line_number, "Unhandled TF_AttrType: %u\n", type);
|
||||
}
|
||||
|
||||
#define REPORT_UNKNOWN_TYPED_ARRAY_TYPE(env, type) \
|
||||
ReportUnknownTypedArrayType(env, type, __FILE__, __LINE__)
|
||||
|
||||
inline void ReportUnknownTypedArrayType(napi_env env, napi_typedarray_type type,
|
||||
const char *file,
|
||||
const size_t line_number) {
|
||||
NapiThrowError(env, file, line_number, "Unhandled napi typed_array_type: %u",
|
||||
type);
|
||||
}
|
||||
|
||||
// Returns a vector with the shape values of an array.
|
||||
inline void ExtractArrayShape(napi_env env, napi_value array_value,
|
||||
std::vector<int64_t> *result) {
|
||||
napi_status nstatus;
|
||||
|
||||
uint32_t array_length;
|
||||
nstatus = napi_get_array_length(env, array_value, &array_length);
|
||||
ENSURE_NAPI_OK(env, nstatus);
|
||||
|
||||
for (uint32_t i = 0; i < array_length; i++) {
|
||||
napi_value dimension_value;
|
||||
nstatus = napi_get_element(env, array_value, i, &dimension_value);
|
||||
ENSURE_NAPI_OK(env, nstatus);
|
||||
|
||||
int64_t dimension;
|
||||
nstatus = napi_get_value_int64(env, dimension_value, &dimension);
|
||||
ENSURE_NAPI_OK(env, nstatus);
|
||||
|
||||
result->push_back(dimension);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool IsExceptionPending(napi_env env) {
|
||||
bool has_exception = false;
|
||||
ENSURE_NAPI_OK_RETVAL(env, napi_is_exception_pending(env, &has_exception),
|
||||
has_exception);
|
||||
return has_exception;
|
||||
}
|
||||
|
||||
#define ENSURE_VALUE_IS_NOT_NULL(env, value) \
|
||||
if (!EnsureValueIsNotNull(env, value, __FILE__, __LINE__)) return;
|
||||
#define ENSURE_VALUE_IS_NOT_NULL_RETVAL(env, value, retval) \
|
||||
if (!EnsureValueIsNotNull(env, value, __FILE__, __LINE__)) return retval;
|
||||
|
||||
inline bool EnsureValueIsNotNull(napi_env env, void *value, const char *file,
|
||||
const size_t line_number) {
|
||||
bool is_null = value == nullptr;
|
||||
if (is_null) {
|
||||
NapiThrowError(env, file, line_number, "Argument is null!");
|
||||
}
|
||||
return !is_null;
|
||||
}
|
||||
|
||||
inline napi_status GetStringParam(napi_env env, napi_value string_value,
|
||||
std::string &string) {
|
||||
ENSURE_VALUE_IS_STRING_RETVAL(env, string_value, napi_invalid_arg);
|
||||
|
||||
napi_status nstatus;
|
||||
|
||||
size_t str_length;
|
||||
nstatus =
|
||||
napi_get_value_string_utf8(env, string_value, nullptr, 0, &str_length);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, nstatus);
|
||||
|
||||
char *buffer = (char *)(malloc(sizeof(char) * (str_length + 1)));
|
||||
ENSURE_VALUE_IS_NOT_NULL_RETVAL(env, buffer, napi_generic_failure);
|
||||
|
||||
nstatus = napi_get_value_string_utf8(env, string_value, buffer,
|
||||
str_length + 1, &str_length);
|
||||
ENSURE_NAPI_OK_RETVAL(env, nstatus, nstatus);
|
||||
|
||||
string.assign(buffer, str_length);
|
||||
free(buffer);
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
// Returns the number of elements in a Tensor.
|
||||
inline size_t GetTensorNumElements(TF_Tensor *tensor) {
|
||||
size_t ret = 1;
|
||||
for (int i = 0; i < TF_NumDims(tensor); ++i) {
|
||||
ret *= TF_Dim(tensor, i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Split a string into an array of characters array with `,` as delimiter.
|
||||
inline std::vector<const char *> splitStringByComma(const std::string &str) {
|
||||
std::vector<const char *> tokens;
|
||||
size_t prev = 0, pos = 0;
|
||||
do {
|
||||
pos = str.find(',', prev);
|
||||
if (pos == std::string::npos) pos = str.length();
|
||||
std::string token = str.substr(prev, pos - prev);
|
||||
if (!token.empty()) {
|
||||
char *cstr = new char[str.length() + 1];
|
||||
std::strcpy(cstr, token.c_str());
|
||||
tokens.push_back(cstr);
|
||||
}
|
||||
prev = pos + 1;
|
||||
} while (pos < str.length() && prev < str.length());
|
||||
return tokens;
|
||||
}
|
||||
|
||||
} // namespace tfnodejs
|
||||
|
||||
#endif // TF_NODEJS_UTILS_H_
|
||||
Generated
Vendored
+329
@@ -0,0 +1,329 @@
|
||||
# We borrow heavily from the kernel build setup, though we are simpler since
|
||||
# we don't have Kconfig tweaking settings on us.
|
||||
|
||||
# The implicit make rules have it looking for RCS files, among other things.
|
||||
# We instead explicitly write all the rules we care about.
|
||||
# It's even quicker (saves ~200ms) to pass -r on the command line.
|
||||
MAKEFLAGS=-r
|
||||
|
||||
# The source directory tree.
|
||||
srcdir := ..
|
||||
abs_srcdir := $(abspath $(srcdir))
|
||||
|
||||
# The name of the builddir.
|
||||
builddir_name ?= .
|
||||
|
||||
# The V=1 flag on command line makes us verbosely print command lines.
|
||||
ifdef V
|
||||
quiet=
|
||||
else
|
||||
quiet=quiet_
|
||||
endif
|
||||
|
||||
# Specify BUILDTYPE=Release on the command line for a release build.
|
||||
BUILDTYPE ?= Release
|
||||
|
||||
# Directory all our build output goes into.
|
||||
# Note that this must be two directories beneath src/ for unit tests to pass,
|
||||
# as they reach into the src/ directory for data with relative paths.
|
||||
builddir ?= $(builddir_name)/$(BUILDTYPE)
|
||||
abs_builddir := $(abspath $(builddir))
|
||||
depsdir := $(builddir)/.deps
|
||||
|
||||
# Object output directory.
|
||||
obj := $(builddir)/obj
|
||||
abs_obj := $(abspath $(obj))
|
||||
|
||||
# We build up a list of every single one of the targets so we can slurp in the
|
||||
# generated dependency rule Makefiles in one pass.
|
||||
all_deps :=
|
||||
|
||||
|
||||
|
||||
CC.target ?= $(CC)
|
||||
CFLAGS.target ?= $(CPPFLAGS) $(CFLAGS)
|
||||
CXX.target ?= $(CXX)
|
||||
CXXFLAGS.target ?= $(CPPFLAGS) $(CXXFLAGS)
|
||||
LINK.target ?= $(LINK)
|
||||
LDFLAGS.target ?= $(LDFLAGS)
|
||||
AR.target ?= $(AR)
|
||||
|
||||
# C++ apps need to be linked with g++.
|
||||
LINK ?= $(CXX.target)
|
||||
|
||||
# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
|
||||
# to replicate this environment fallback in make as well.
|
||||
CC.host ?= gcc
|
||||
CFLAGS.host ?= $(CPPFLAGS_host) $(CFLAGS_host)
|
||||
CXX.host ?= g++
|
||||
CXXFLAGS.host ?= $(CPPFLAGS_host) $(CXXFLAGS_host)
|
||||
LINK.host ?= $(CXX.host)
|
||||
LDFLAGS.host ?= $(LDFLAGS_host)
|
||||
AR.host ?= ar
|
||||
|
||||
# Define a dir function that can handle spaces.
|
||||
# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
|
||||
# "leading spaces cannot appear in the text of the first argument as written.
|
||||
# These characters can be put into the argument value by variable substitution."
|
||||
empty :=
|
||||
space := $(empty) $(empty)
|
||||
|
||||
# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
|
||||
replace_spaces = $(subst $(space),?,$1)
|
||||
unreplace_spaces = $(subst ?,$(space),$1)
|
||||
dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
|
||||
|
||||
# Flags to make gcc output dependency info. Note that you need to be
|
||||
# careful here to use the flags that ccache and distcc can understand.
|
||||
# We write to a dep file on the side first and then rename at the end
|
||||
# so we can't end up with a broken dep file.
|
||||
depfile = $(depsdir)/$(call replace_spaces,$@).d
|
||||
DEPFLAGS = -MMD -MF $(depfile).raw
|
||||
|
||||
# We have to fixup the deps output in a few ways.
|
||||
# (1) the file output should mention the proper .o file.
|
||||
# ccache or distcc lose the path to the target, so we convert a rule of
|
||||
# the form:
|
||||
# foobar.o: DEP1 DEP2
|
||||
# into
|
||||
# path/to/foobar.o: DEP1 DEP2
|
||||
# (2) we want missing files not to cause us to fail to build.
|
||||
# We want to rewrite
|
||||
# foobar.o: DEP1 DEP2 \
|
||||
# DEP3
|
||||
# to
|
||||
# DEP1:
|
||||
# DEP2:
|
||||
# DEP3:
|
||||
# so if the files are missing, they're just considered phony rules.
|
||||
# We have to do some pretty insane escaping to get those backslashes
|
||||
# and dollar signs past make, the shell, and sed at the same time.
|
||||
# Doesn't work with spaces, but that's fine: .d files have spaces in
|
||||
# their names replaced with other characters.
|
||||
define fixup_dep
|
||||
# The depfile may not exist if the input file didn't have any #includes.
|
||||
touch $(depfile).raw
|
||||
# Fixup path as in (1).
|
||||
sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
|
||||
# Add extra rules as in (2).
|
||||
# We remove slashes and replace spaces with new lines;
|
||||
# remove blank lines;
|
||||
# delete the first line and append a colon to the remaining lines.
|
||||
sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
|
||||
grep -v '^$$' |\
|
||||
sed -e 1d -e 's|$$|:|' \
|
||||
>> $(depfile)
|
||||
rm $(depfile).raw
|
||||
endef
|
||||
|
||||
# Command definitions:
|
||||
# - cmd_foo is the actual command to run;
|
||||
# - quiet_cmd_foo is the brief-output summary of the command.
|
||||
|
||||
quiet_cmd_cc = CC($(TOOLSET)) $@
|
||||
cmd_cc = $(CC.$(TOOLSET)) -o $@ $< $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c
|
||||
|
||||
quiet_cmd_cxx = CXX($(TOOLSET)) $@
|
||||
cmd_cxx = $(CXX.$(TOOLSET)) -o $@ $< $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c
|
||||
|
||||
quiet_cmd_touch = TOUCH $@
|
||||
cmd_touch = touch $@
|
||||
|
||||
quiet_cmd_copy = COPY $@
|
||||
# send stderr to /dev/null to ignore messages when linking directories.
|
||||
cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
|
||||
|
||||
quiet_cmd_alink = AR($(TOOLSET)) $@
|
||||
cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
|
||||
|
||||
quiet_cmd_alink_thin = AR($(TOOLSET)) $@
|
||||
cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^)
|
||||
|
||||
# Due to circular dependencies between libraries :(, we wrap the
|
||||
# special "figure out circular dependencies" flags around the entire
|
||||
# input list during linking.
|
||||
quiet_cmd_link = LINK($(TOOLSET)) $@
|
||||
cmd_link = $(LINK.$(TOOLSET)) -o $@ $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,--start-group $(LD_INPUTS) $(LIBS) -Wl,--end-group
|
||||
|
||||
# We support two kinds of shared objects (.so):
|
||||
# 1) shared_library, which is just bundling together many dependent libraries
|
||||
# into a link line.
|
||||
# 2) loadable_module, which is generating a module intended for dlopen().
|
||||
#
|
||||
# They differ only slightly:
|
||||
# In the former case, we want to package all dependent code into the .so.
|
||||
# In the latter case, we want to package just the API exposed by the
|
||||
# outermost module.
|
||||
# This means shared_library uses --whole-archive, while loadable_module doesn't.
|
||||
# (Note that --whole-archive is incompatible with the --start-group used in
|
||||
# normal linking.)
|
||||
|
||||
# Other shared-object link notes:
|
||||
# - Set SONAME to the library filename so our binaries don't reference
|
||||
# the local, absolute paths used on the link command-line.
|
||||
quiet_cmd_solink = SOLINK($(TOOLSET)) $@
|
||||
cmd_solink = $(LINK.$(TOOLSET)) -o $@ -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
|
||||
|
||||
quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
|
||||
cmd_solink_module = $(LINK.$(TOOLSET)) -o $@ -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
|
||||
|
||||
|
||||
# Define an escape_quotes function to escape single quotes.
|
||||
# This allows us to handle quotes properly as long as we always use
|
||||
# use single quotes and escape_quotes.
|
||||
escape_quotes = $(subst ','\'',$(1))
|
||||
# This comment is here just to include a ' to unconfuse syntax highlighting.
|
||||
# Define an escape_vars function to escape '$' variable syntax.
|
||||
# This allows us to read/write command lines with shell variables (e.g.
|
||||
# $LD_LIBRARY_PATH), without triggering make substitution.
|
||||
escape_vars = $(subst $$,$$$$,$(1))
|
||||
# Helper that expands to a shell command to echo a string exactly as it is in
|
||||
# make. This uses printf instead of echo because printf's behaviour with respect
|
||||
# to escape sequences is more portable than echo's across different shells
|
||||
# (e.g., dash, bash).
|
||||
exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
|
||||
|
||||
# Helper to compare the command we're about to run against the command
|
||||
# we logged the last time we ran the command. Produces an empty
|
||||
# string (false) when the commands match.
|
||||
# Tricky point: Make has no string-equality test function.
|
||||
# The kernel uses the following, but it seems like it would have false
|
||||
# positives, where one string reordered its arguments.
|
||||
# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
|
||||
# $(filter-out $(cmd_$@), $(cmd_$(1))))
|
||||
# We instead substitute each for the empty string into the other, and
|
||||
# say they're equal if both substitutions produce the empty string.
|
||||
# .d files contain ? instead of spaces, take that into account.
|
||||
command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
|
||||
$(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
|
||||
|
||||
# Helper that is non-empty when a prerequisite changes.
|
||||
# Normally make does this implicitly, but we force rules to always run
|
||||
# so we can check their command lines.
|
||||
# $? -- new prerequisites
|
||||
# $| -- order-only dependencies
|
||||
prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
|
||||
|
||||
# Helper that executes all postbuilds until one fails.
|
||||
define do_postbuilds
|
||||
@E=0;\
|
||||
for p in $(POSTBUILDS); do\
|
||||
eval $$p;\
|
||||
E=$$?;\
|
||||
if [ $$E -ne 0 ]; then\
|
||||
break;\
|
||||
fi;\
|
||||
done;\
|
||||
if [ $$E -ne 0 ]; then\
|
||||
rm -rf "$@";\
|
||||
exit $$E;\
|
||||
fi
|
||||
endef
|
||||
|
||||
# do_cmd: run a command via the above cmd_foo names, if necessary.
|
||||
# Should always run for a given target to handle command-line changes.
|
||||
# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
|
||||
# Third argument, if non-zero, makes it do POSTBUILDS processing.
|
||||
# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
|
||||
# spaces already and dirx strips the ? characters.
|
||||
define do_cmd
|
||||
$(if $(or $(command_changed),$(prereq_changed)),
|
||||
@$(call exact_echo, $($(quiet)cmd_$(1)))
|
||||
@mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
|
||||
$(if $(findstring flock,$(word 1,$(cmd_$1))),
|
||||
@$(cmd_$(1))
|
||||
@echo " $(quiet_cmd_$(1)): Finished",
|
||||
@$(cmd_$(1))
|
||||
)
|
||||
@$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
|
||||
@$(if $(2),$(fixup_dep))
|
||||
$(if $(and $(3), $(POSTBUILDS)),
|
||||
$(call do_postbuilds)
|
||||
)
|
||||
)
|
||||
endef
|
||||
|
||||
# Declare the "all" target first so it is the default,
|
||||
# even though we don't have the deps yet.
|
||||
.PHONY: all
|
||||
all:
|
||||
|
||||
# make looks for ways to re-generate included makefiles, but in our case, we
|
||||
# don't have a direct way. Explicitly telling make that it has nothing to do
|
||||
# for them makes it go faster.
|
||||
%.d: ;
|
||||
|
||||
# Use FORCE_DO_CMD to force a target to run. Should be coupled with
|
||||
# do_cmd.
|
||||
.PHONY: FORCE_DO_CMD
|
||||
FORCE_DO_CMD:
|
||||
|
||||
TOOLSET := target
|
||||
# Suffix rules, putting all outputs into $(obj).
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
|
||||
# Try building from generated source, too.
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
|
||||
|
||||
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
|
||||
$(findstring $(join ^,$(prefix)),\
|
||||
$(join ^,action_after_build.target.mk)))),)
|
||||
include action_after_build.target.mk
|
||||
endif
|
||||
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
|
||||
$(findstring $(join ^,$(prefix)),\
|
||||
$(join ^,tfjs_binding.target.mk)))),)
|
||||
include tfjs_binding.target.mk
|
||||
endif
|
||||
|
||||
quiet_cmd_regen_makefile = ACTION Regenerating $@
|
||||
cmd_regen_makefile = cd $(srcdir); /usr/share/nodejs/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/build/config.gypi -I/usr/share/nodejs/node-gyp/addon.gypi -I/usr/include/nodejs/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/usr/include/nodejs" "-Dnode_gyp_dir=/usr/share/nodejs/node-gyp" "-Dnode_lib_file=/usr/include/nodejs/<(target_arch)/node.lib" "-Dmodule_root_dir=/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node" "-Dnode_engine=v8" binding.gyp
|
||||
Makefile: $(srcdir)/../../../../../../../../../../../../usr/include/nodejs/common.gypi $(srcdir)/../../../../../../../../../../../../usr/share/nodejs/node-gyp/addon.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp
|
||||
$(call do_cmd,regen_makefile)
|
||||
|
||||
# "all" is a concatenation of the "all" targets from all the included
|
||||
# sub-makefiles. This is just here to clarify.
|
||||
all:
|
||||
|
||||
# Add in dependency-tracking rules. $(all_deps) is the list of every single
|
||||
# target in our tree. Only consider the ones with .d (dependency) info:
|
||||
d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
|
||||
ifneq ($(d_files),)
|
||||
include $(d_files)
|
||||
endif
|
||||
+1
@@ -0,0 +1 @@
|
||||
cmd_Release/obj.target/action_after_build.stamp := touch Release/obj.target/action_after_build.stamp
|
||||
+1
@@ -0,0 +1 @@
|
||||
cmd_Release/obj.target/tfjs_binding.node := g++ -o Release/obj.target/tfjs_binding.node -shared -pthread -rdynamic -m64 -L/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/lib -Wl,-soname=tfjs_binding.node -Wl,--start-group Release/obj.target/tfjs_binding/binding/tfjs_backend.o Release/obj.target/tfjs_binding/binding/tfjs_binding.o -Wl,--end-group -lnode -Wl,-rpath,\$$ORIGIN/../../deps/lib -ltensorflow -ltensorflow_framework
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
cmd_Release/obj.target/tfjs_binding/binding/tfjs_backend.o := g++ -o Release/obj.target/tfjs_binding/binding/tfjs_backend.o ../binding/tfjs_backend.cc '-DNODE_GYP_MODULE_NAME=tfjs_binding' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/usr/include/nodejs/include/node -I/usr/include/nodejs/src -I/usr/include/nodejs/deps/openssl/config -I/usr/include/nodejs/deps/openssl/openssl/include -I/usr/include/nodejs/deps/uv/include -I/usr/include/nodejs/deps/zlib -I/usr/include/nodejs/deps/v8/include -I../.. -I/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include -fPIC -pthread -Wall -Wextra -Wno-unused-parameter -m64 -fPIC -O3 -fno-omit-frame-pointer -fno-rtti -fno-exceptions -std=gnu++1y -MMD -MF ./Release/.deps/Release/obj.target/tfjs_binding/binding/tfjs_backend.o.d.raw -c
|
||||
Release/obj.target/tfjs_binding/binding/tfjs_backend.o: \
|
||||
../binding/tfjs_backend.cc ../binding/tfjs_backend.h \
|
||||
/usr/include/nodejs/src/node_api.h \
|
||||
/usr/include/nodejs/src/node_api_types.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/c_api.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_attrtype.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_datatype.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_status.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_tensor.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/c_api_macros.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_tstring.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/core/platform/ctstring.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/core/platform/ctstring_internal.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/eager/c_api.h \
|
||||
../binding/napi_auto_ref.h ../binding/utils.h \
|
||||
../binding/tf_auto_status.h ../binding/tf_auto_tensor.h \
|
||||
../binding/tfe_auto_op.h
|
||||
../binding/tfjs_backend.cc:
|
||||
../binding/tfjs_backend.h:
|
||||
/usr/include/nodejs/src/node_api.h:
|
||||
/usr/include/nodejs/src/node_api_types.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/c_api.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_attrtype.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_datatype.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_status.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_tensor.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/c_api_macros.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_tstring.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/core/platform/ctstring.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/core/platform/ctstring_internal.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/eager/c_api.h:
|
||||
../binding/napi_auto_ref.h:
|
||||
../binding/utils.h:
|
||||
../binding/tf_auto_status.h:
|
||||
../binding/tf_auto_tensor.h:
|
||||
../binding/tfe_auto_op.h:
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
cmd_Release/obj.target/tfjs_binding/binding/tfjs_binding.o := g++ -o Release/obj.target/tfjs_binding/binding/tfjs_binding.o ../binding/tfjs_binding.cc '-DNODE_GYP_MODULE_NAME=tfjs_binding' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/usr/include/nodejs/include/node -I/usr/include/nodejs/src -I/usr/include/nodejs/deps/openssl/config -I/usr/include/nodejs/deps/openssl/openssl/include -I/usr/include/nodejs/deps/uv/include -I/usr/include/nodejs/deps/zlib -I/usr/include/nodejs/deps/v8/include -I../.. -I/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include -fPIC -pthread -Wall -Wextra -Wno-unused-parameter -m64 -fPIC -O3 -fno-omit-frame-pointer -fno-rtti -fno-exceptions -std=gnu++1y -MMD -MF ./Release/.deps/Release/obj.target/tfjs_binding/binding/tfjs_binding.o.d.raw -c
|
||||
Release/obj.target/tfjs_binding/binding/tfjs_binding.o: \
|
||||
../binding/tfjs_binding.cc /usr/include/nodejs/src/node_api.h \
|
||||
/usr/include/nodejs/src/node_api_types.h ../binding/tfjs_backend.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/c_api.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_attrtype.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_datatype.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_status.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_tensor.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/c_api_macros.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_tstring.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/core/platform/ctstring.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/core/platform/ctstring_internal.h \
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/eager/c_api.h \
|
||||
../binding/utils.h ../binding/tf_auto_status.h
|
||||
../binding/tfjs_binding.cc:
|
||||
/usr/include/nodejs/src/node_api.h:
|
||||
/usr/include/nodejs/src/node_api_types.h:
|
||||
../binding/tfjs_backend.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/c_api.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_attrtype.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_datatype.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_status.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_tensor.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/c_api_macros.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/tf_tstring.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/core/platform/ctstring.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/core/platform/ctstring_internal.h:
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include/tensorflow/c/eager/c_api.h:
|
||||
../binding/utils.h:
|
||||
../binding/tf_auto_status.h:
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
cmd_Release/tfjs_binding.node := ln -f "Release/obj.target/tfjs_binding.node" "Release/tfjs_binding.node" 2>/dev/null || (rm -rf "Release/tfjs_binding.node" && cp -af "Release/obj.target/tfjs_binding.node" "Release/tfjs_binding.node")
|
||||
Generated
Vendored
Whitespace-only changes.
Generated
Vendored
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
Vendored
Executable
BIN
Binary file not shown.
Generated
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
# This file is generated by gyp; do not edit.
|
||||
|
||||
TOOLSET := target
|
||||
TARGET := action_after_build
|
||||
### Generated for copy rule.
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/lib/napi-v5/tfjs_binding.node: TOOLSET := $(TOOLSET)
|
||||
/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/lib/napi-v5/tfjs_binding.node: $(builddir)/tfjs_binding.node FORCE_DO_CMD
|
||||
$(call do_cmd,copy)
|
||||
|
||||
all_deps += /home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/lib/napi-v5/tfjs_binding.node
|
||||
binding_gyp_action_after_build_target_copies = /home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/lib/napi-v5/tfjs_binding.node
|
||||
|
||||
### Rules for final target.
|
||||
# Build our special outputs first.
|
||||
$(obj).target/action_after_build.stamp: | $(binding_gyp_action_after_build_target_copies)
|
||||
|
||||
# Preserve order dependency of special output on deps.
|
||||
$(binding_gyp_action_after_build_target_copies): | $(builddir)/tfjs_binding.node
|
||||
|
||||
$(obj).target/action_after_build.stamp: TOOLSET := $(TOOLSET)
|
||||
$(obj).target/action_after_build.stamp: $(builddir)/tfjs_binding.node FORCE_DO_CMD
|
||||
$(call do_cmd,touch)
|
||||
|
||||
all_deps += $(obj).target/action_after_build.stamp
|
||||
# Add target alias
|
||||
.PHONY: action_after_build
|
||||
action_after_build: $(obj).target/action_after_build.stamp
|
||||
|
||||
# Add target alias to "all" target.
|
||||
.PHONY: all
|
||||
all: action_after_build
|
||||
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
# This file is generated by gyp; do not edit.
|
||||
|
||||
export builddir_name ?= ./build/.
|
||||
.PHONY: all
|
||||
all:
|
||||
$(MAKE) tfjs_binding action_after_build
|
||||
Generated
Vendored
+201
@@ -0,0 +1,201 @@
|
||||
# Do not edit. File was generated by node-gyp's "configure" step
|
||||
{
|
||||
"target_defaults": {
|
||||
"cflags": [],
|
||||
"default_configuration": "Release",
|
||||
"defines": [],
|
||||
"include_dirs": [],
|
||||
"libraries": []
|
||||
},
|
||||
"variables": {
|
||||
"arch_triplet": "x86_64-linux-gnu",
|
||||
"asan": 0,
|
||||
"build_v8_with_gn": "false",
|
||||
"coverage": "false",
|
||||
"debug_nghttp2": "false",
|
||||
"enable_lto": "false",
|
||||
"enable_pgo_generate": "false",
|
||||
"enable_pgo_use": "false",
|
||||
"force_dynamic_crt": 1,
|
||||
"host_arch": "x64",
|
||||
"icu_gyp_path": "tools/icu/icu-system.gyp",
|
||||
"icu_small": "false",
|
||||
"icu_ver_major": "66",
|
||||
"llvm_version": 0,
|
||||
"node_byteorder": "little",
|
||||
"node_debug_lib": "false",
|
||||
"node_enable_d8": "false",
|
||||
"node_enable_v8_vtunejit": "false",
|
||||
"node_install_npm": "false",
|
||||
"node_module_version": 64,
|
||||
"node_no_browser_globals": "false",
|
||||
"node_prefix": "/usr",
|
||||
"node_relative_path": "lib/x86_64-linux-gnu/nodejs:share/nodejs:lib/nodejs",
|
||||
"node_release_urlbase": "",
|
||||
"node_shared": "true",
|
||||
"node_shared_cares": "true",
|
||||
"node_shared_http_parser": "false",
|
||||
"node_shared_libuv": "true",
|
||||
"node_shared_nghttp2": "true",
|
||||
"node_shared_openssl": "true",
|
||||
"node_shared_zlib": "true",
|
||||
"node_tag": "",
|
||||
"node_target_type": "shared_library",
|
||||
"node_use_bundled_v8": "true",
|
||||
"node_use_dtrace": "false",
|
||||
"node_use_etw": "false",
|
||||
"node_use_large_pages": "false",
|
||||
"node_use_openssl": "true",
|
||||
"node_use_pch": "false",
|
||||
"node_use_perfctr": "false",
|
||||
"node_use_v8_platform": "true",
|
||||
"node_with_ltcg": "false",
|
||||
"node_without_node_options": "false",
|
||||
"openssl_fips": "",
|
||||
"openssl_no_asm": 0,
|
||||
"shlib_suffix": "so.64",
|
||||
"target_arch": "x64",
|
||||
"v8_enable_gdbjit": 0,
|
||||
"v8_enable_i18n_support": 1,
|
||||
"v8_enable_inspector": 1,
|
||||
"v8_no_strict_aliasing": 1,
|
||||
"v8_optimized_debug": 0,
|
||||
"v8_promise_internal_field_count": 1,
|
||||
"v8_random_seed": 0,
|
||||
"v8_trace_maps": 0,
|
||||
"v8_typed_array_max_size_in_heap": 0,
|
||||
"v8_use_snapshot": "false",
|
||||
"want_separate_host_toolset": 0,
|
||||
"nodedir": "/usr/include/nodejs",
|
||||
"standalone_static_library": 1,
|
||||
"fallback_to_build": "true",
|
||||
"module": "/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/lib/napi-v5/tfjs_binding.node",
|
||||
"module_name": "tfjs_binding",
|
||||
"module_path": "/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/lib/napi-v5",
|
||||
"napi_version": "5",
|
||||
"node_abi_napi": "napi",
|
||||
"napi_build_version": "5",
|
||||
"node_napi_label": "napi-v5",
|
||||
"cache_lock_stale": "60000",
|
||||
"ham_it_up": "",
|
||||
"legacy_bundling": "",
|
||||
"sign_git_tag": "",
|
||||
"user_agent": "npm/6.14.4 node/v10.19.0 linux x64",
|
||||
"always_auth": "",
|
||||
"bin_links": "true",
|
||||
"key": "",
|
||||
"allow_same_version": "",
|
||||
"description": "true",
|
||||
"fetch_retries": "2",
|
||||
"heading": "npm",
|
||||
"if_present": "",
|
||||
"init_version": "1.0.0",
|
||||
"user": "",
|
||||
"prefer_online": "",
|
||||
"force": "",
|
||||
"only": "",
|
||||
"read_only": "",
|
||||
"cache_min": "10",
|
||||
"init_license": "ISC",
|
||||
"editor": "vi",
|
||||
"rollback": "true",
|
||||
"tag_version_prefix": "v",
|
||||
"cache_max": "Infinity",
|
||||
"timing": "",
|
||||
"userconfig": "/home/brenden/.npmrc",
|
||||
"engine_strict": "",
|
||||
"init_author_name": "",
|
||||
"init_author_url": "",
|
||||
"preid": "",
|
||||
"tmp": "/tmp",
|
||||
"depth": "Infinity",
|
||||
"package_lock_only": "",
|
||||
"save_dev": "",
|
||||
"usage": "",
|
||||
"metrics_registry": "https://registry.npmjs.org/",
|
||||
"otp": "",
|
||||
"package_lock": "true",
|
||||
"progress": "true",
|
||||
"https_proxy": "",
|
||||
"save_prod": "",
|
||||
"audit": "true",
|
||||
"cidr": "",
|
||||
"onload_script": "",
|
||||
"sso_type": "oauth",
|
||||
"rebuild_bundle": "true",
|
||||
"save_bundle": "",
|
||||
"shell": "/bin/bash",
|
||||
"prefix": "/usr/local",
|
||||
"dry_run": "",
|
||||
"format_package_lock": "true",
|
||||
"scope": "",
|
||||
"browser": "",
|
||||
"cache_lock_wait": "10000",
|
||||
"ignore_prepublish": "",
|
||||
"registry": "https://registry.npmjs.org/",
|
||||
"save_optional": "",
|
||||
"searchopts": "",
|
||||
"versions": "",
|
||||
"cache": "/home/brenden/.npm",
|
||||
"send_metrics": "",
|
||||
"global_style": "",
|
||||
"ignore_scripts": "",
|
||||
"version": "",
|
||||
"local_address": "",
|
||||
"viewer": "man",
|
||||
"node_gyp": "/usr/bin/node-gyp",
|
||||
"audit_level": "low",
|
||||
"prefer_offline": "",
|
||||
"color": "true",
|
||||
"sign_git_commit": "",
|
||||
"fetch_retry_mintimeout": "10000",
|
||||
"maxsockets": "50",
|
||||
"offline": "",
|
||||
"sso_poll_frequency": "500",
|
||||
"umask": "0002",
|
||||
"fund": "true",
|
||||
"fetch_retry_maxtimeout": "60000",
|
||||
"logs_max": "10",
|
||||
"message": "%s",
|
||||
"ca": "",
|
||||
"cert": "",
|
||||
"global": "",
|
||||
"link": "",
|
||||
"access": "",
|
||||
"also": "",
|
||||
"save": "true",
|
||||
"unicode": "true",
|
||||
"before": "",
|
||||
"long": "",
|
||||
"production": "",
|
||||
"searchlimit": "20",
|
||||
"unsafe_perm": "true",
|
||||
"update_notifier": "true",
|
||||
"auth_type": "legacy",
|
||||
"node_version": "10.19.0",
|
||||
"tag": "latest",
|
||||
"git_tag_version": "true",
|
||||
"commit_hooks": "true",
|
||||
"script_shell": "",
|
||||
"shrinkwrap": "true",
|
||||
"fetch_retry_factor": "10",
|
||||
"save_exact": "",
|
||||
"strict_ssl": "true",
|
||||
"globalconfig": "/etc/npmrc",
|
||||
"dev": "",
|
||||
"init_module": "/home/brenden/.npm-init.js",
|
||||
"parseable": "",
|
||||
"globalignorefile": "/etc/npmignore",
|
||||
"cache_lock_retries": "10",
|
||||
"searchstaleness": "900",
|
||||
"node_options": "",
|
||||
"save_prefix": "^",
|
||||
"scripts_prepend_node_path": "warn-only",
|
||||
"group": "1000",
|
||||
"init_author_email": "",
|
||||
"searchexclude": "",
|
||||
"git": "git",
|
||||
"optional": "true",
|
||||
"json": ""
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+160
@@ -0,0 +1,160 @@
|
||||
# This file is generated by gyp; do not edit.
|
||||
|
||||
TOOLSET := target
|
||||
TARGET := tfjs_binding
|
||||
DEFS_Debug := \
|
||||
'-DNODE_GYP_MODULE_NAME=tfjs_binding' \
|
||||
'-DUSING_UV_SHARED=1' \
|
||||
'-DUSING_V8_SHARED=1' \
|
||||
'-DV8_DEPRECATION_WARNINGS=1' \
|
||||
'-D_LARGEFILE_SOURCE' \
|
||||
'-D_FILE_OFFSET_BITS=64' \
|
||||
'-DBUILDING_NODE_EXTENSION' \
|
||||
'-DDEBUG' \
|
||||
'-D_DEBUG' \
|
||||
'-DV8_ENABLE_CHECKS'
|
||||
|
||||
# Flags passed to all source files.
|
||||
CFLAGS_Debug := \
|
||||
-fPIC \
|
||||
-pthread \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Wno-unused-parameter \
|
||||
-m64 \
|
||||
-fPIC \
|
||||
-g \
|
||||
-O0
|
||||
|
||||
# Flags passed to only C files.
|
||||
CFLAGS_C_Debug :=
|
||||
|
||||
# Flags passed to only C++ files.
|
||||
CFLAGS_CC_Debug := \
|
||||
-fno-rtti \
|
||||
-fno-exceptions \
|
||||
-std=gnu++1y
|
||||
|
||||
INCS_Debug := \
|
||||
-I/usr/include/nodejs/include/node \
|
||||
-I/usr/include/nodejs/src \
|
||||
-I/usr/include/nodejs/deps/openssl/config \
|
||||
-I/usr/include/nodejs/deps/openssl/openssl/include \
|
||||
-I/usr/include/nodejs/deps/uv/include \
|
||||
-I/usr/include/nodejs/deps/zlib \
|
||||
-I/usr/include/nodejs/deps/v8/include \
|
||||
-I$(srcdir)/.. \
|
||||
-I/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include
|
||||
|
||||
DEFS_Release := \
|
||||
'-DNODE_GYP_MODULE_NAME=tfjs_binding' \
|
||||
'-DUSING_UV_SHARED=1' \
|
||||
'-DUSING_V8_SHARED=1' \
|
||||
'-DV8_DEPRECATION_WARNINGS=1' \
|
||||
'-D_LARGEFILE_SOURCE' \
|
||||
'-D_FILE_OFFSET_BITS=64' \
|
||||
'-DBUILDING_NODE_EXTENSION'
|
||||
|
||||
# Flags passed to all source files.
|
||||
CFLAGS_Release := \
|
||||
-fPIC \
|
||||
-pthread \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Wno-unused-parameter \
|
||||
-m64 \
|
||||
-fPIC \
|
||||
-O3 \
|
||||
-fno-omit-frame-pointer
|
||||
|
||||
# Flags passed to only C files.
|
||||
CFLAGS_C_Release :=
|
||||
|
||||
# Flags passed to only C++ files.
|
||||
CFLAGS_CC_Release := \
|
||||
-fno-rtti \
|
||||
-fno-exceptions \
|
||||
-std=gnu++1y
|
||||
|
||||
INCS_Release := \
|
||||
-I/usr/include/nodejs/include/node \
|
||||
-I/usr/include/nodejs/src \
|
||||
-I/usr/include/nodejs/deps/openssl/config \
|
||||
-I/usr/include/nodejs/deps/openssl/openssl/include \
|
||||
-I/usr/include/nodejs/deps/uv/include \
|
||||
-I/usr/include/nodejs/deps/zlib \
|
||||
-I/usr/include/nodejs/deps/v8/include \
|
||||
-I$(srcdir)/.. \
|
||||
-I/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/include
|
||||
|
||||
OBJS := \
|
||||
$(obj).target/$(TARGET)/binding/tfjs_backend.o \
|
||||
$(obj).target/$(TARGET)/binding/tfjs_binding.o
|
||||
|
||||
# Add to the list of files we specially track dependencies for.
|
||||
all_deps += $(OBJS)
|
||||
|
||||
# CFLAGS et al overrides must be target-local.
|
||||
# See "Target-specific Variable Values" in the GNU Make manual.
|
||||
$(OBJS): TOOLSET := $(TOOLSET)
|
||||
$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
|
||||
$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
|
||||
|
||||
# Suffix rules, putting all outputs into $(obj).
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
# Try building from generated source, too.
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
# End of this set of suffix rules
|
||||
### Rules for final target.
|
||||
LDFLAGS_Debug := \
|
||||
-pthread \
|
||||
-rdynamic \
|
||||
-m64 \
|
||||
-L/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/lib
|
||||
|
||||
LDFLAGS_Release := \
|
||||
-pthread \
|
||||
-rdynamic \
|
||||
-m64 \
|
||||
-L/home/brenden/Superalgos/Projects/TensorFlow/TS/Bot-Modules/Learning-Bot/Low-Frequency-Learning/node_modules/@tensorflow/tfjs-node/deps/lib
|
||||
|
||||
LIBS := \
|
||||
-lnode \
|
||||
-Wl,-rpath,\$$ORIGIN/../../deps/lib \
|
||||
-ltensorflow \
|
||||
-ltensorflow_framework
|
||||
|
||||
$(obj).target/tfjs_binding.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
|
||||
$(obj).target/tfjs_binding.node: LIBS := $(LIBS)
|
||||
$(obj).target/tfjs_binding.node: TOOLSET := $(TOOLSET)
|
||||
$(obj).target/tfjs_binding.node: $(OBJS) FORCE_DO_CMD
|
||||
$(call do_cmd,solink_module)
|
||||
|
||||
all_deps += $(obj).target/tfjs_binding.node
|
||||
# Add target alias
|
||||
.PHONY: tfjs_binding
|
||||
tfjs_binding: $(builddir)/tfjs_binding.node
|
||||
|
||||
# Copy this to the executable output path.
|
||||
$(builddir)/tfjs_binding.node: TOOLSET := $(TOOLSET)
|
||||
$(builddir)/tfjs_binding.node: $(obj).target/tfjs_binding.node FORCE_DO_CMD
|
||||
$(call do_cmd,copy)
|
||||
|
||||
all_deps += $(builddir)/tfjs_binding.node
|
||||
# Short alias for building this executable.
|
||||
.PHONY: tfjs_binding.node
|
||||
tfjs_binding.node: $(obj).target/tfjs_binding.node $(builddir)/tfjs_binding.node
|
||||
|
||||
# Add executable to "all" target.
|
||||
.PHONY: all
|
||||
all: $(builddir)/tfjs_binding.node
|
||||
|
||||
Generated
Vendored
Executable
+203
@@ -0,0 +1,203 @@
|
||||
Copyright 2019 The TensorFlow Authors. All rights reserved.
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
Generated
Vendored
Executable
+8963
File diff suppressed because it is too large.
Load diff
Generated
Vendored
Executable
+1591
File diff suppressed because it is too large.
Load diff
Generated
Vendored
Executable
+311
@@ -0,0 +1,311 @@
|
||||
/* Copyright 2018 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef TENSORFLOW_C_C_API_EXPERIMENTAL_H_
|
||||
#define TENSORFLOW_C_C_API_EXPERIMENTAL_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "tensorflow/c/c_api.h"
|
||||
#include "tensorflow/c/eager/c_api.h"
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Experimental C API for TensorFlow.
|
||||
//
|
||||
// The API here is subject to changes in the future.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Macro to control visibility of exported symbols in the shared library (.so,
|
||||
// .dylib, .dll).
|
||||
// This duplicates the TF_EXPORT macro definition in
|
||||
// tensorflow/core/platform/macros.h in order to keep this .h file independent
|
||||
// of any other includes.$a
|
||||
#ifdef SWIG
|
||||
#define TF_CAPI_EXPORT
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
#ifdef TF_COMPILE_LIBRARY
|
||||
#define TF_CAPI_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define TF_CAPI_EXPORT __declspec(dllimport)
|
||||
#endif // TF_COMPILE_LIBRARY
|
||||
#else
|
||||
#define TF_CAPI_EXPORT __attribute__((visibility("default")))
|
||||
#endif // _WIN32
|
||||
#endif // SWIG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// When `enable` is true, set
|
||||
// tensorflow.ConfigProto.OptimizerOptions.global_jit_level to ON_1, and also
|
||||
// set XLA flag values to prepare for XLA compilation. Otherwise set
|
||||
// global_jit_level to OFF.
|
||||
//
|
||||
// This and the next API are syntax sugar over TF_SetConfig(), and is used by
|
||||
// clients that cannot read/write the tensorflow.ConfigProto proto.
|
||||
// TODO: Migrate to TF_CreateConfig() below.
|
||||
TF_CAPI_EXPORT extern void TF_EnableXLACompilation(TF_SessionOptions* options,
|
||||
unsigned char enable);
|
||||
|
||||
// Set XLA's internal BuildXlaOpsPassFlags.tf_xla_enable_lazy_compilation to the
|
||||
// value of 'enabled'. Also returns the original value of that flag.
|
||||
//
|
||||
// Use in tests to allow XLA to fallback to TF classic. This has global effect.
|
||||
TF_CAPI_EXPORT unsigned char TF_SetXlaEnableLazyCompilation(
|
||||
unsigned char enable);
|
||||
TF_CAPI_EXPORT unsigned char TF_SetTfXlaCpuGlobalJit(unsigned char enable);
|
||||
|
||||
// Sets XLA's auto jit mode according to the specified string, which is parsed
|
||||
// as if passed in XLA_FLAGS. This has global effect.
|
||||
TF_CAPI_EXPORT void TF_SetXlaAutoJitMode(const char* mode);
|
||||
|
||||
// Sets XLA's minimum cluster size. This has global effect.
|
||||
TF_CAPI_EXPORT void TF_SetXlaMinClusterSize(int size);
|
||||
|
||||
// Gets/Sets TF/XLA flag for whether(true) or not(false) to disable constant
|
||||
// folding. This is for testing to ensure that XLA is being tested rather than
|
||||
// Tensorflow's CPU implementation through constant folding.
|
||||
TF_CAPI_EXPORT unsigned char TF_GetXlaConstantFoldingDisabled();
|
||||
TF_CAPI_EXPORT void TF_SetXlaConstantFoldingDisabled(
|
||||
unsigned char should_enable);
|
||||
|
||||
// Create a serialized tensorflow.ConfigProto proto, where:
|
||||
//
|
||||
// a) ConfigProto.optimizer_options.global_jit_level is set to to ON_1 if
|
||||
// `enable_xla_compilation` is non-zero, and OFF otherwise.
|
||||
// b) ConfigProto.gpu_options.allow_growth is set to `gpu_memory_allow_growth`.
|
||||
// c) ConfigProto.device_count is set to `num_cpu_devices`.
|
||||
TF_CAPI_EXPORT extern TF_Buffer* TF_CreateConfig(
|
||||
unsigned char enable_xla_compilation, unsigned char gpu_memory_allow_growth,
|
||||
unsigned int num_cpu_devices);
|
||||
|
||||
// Create a serialized tensorflow.RunOptions proto, where RunOptions.trace_level
|
||||
// is set to FULL_TRACE if `enable_full_trace` is non-zero, and NO_TRACE
|
||||
// otherwise.
|
||||
TF_CAPI_EXPORT extern TF_Buffer* TF_CreateRunOptions(
|
||||
unsigned char enable_full_trace);
|
||||
|
||||
// Returns the graph content in a human-readable format, with length set in
|
||||
// `len`. The format is subject to change in the future.
|
||||
// The returned string is heap-allocated, and caller should call free() on it.
|
||||
TF_CAPI_EXPORT extern const char* TF_GraphDebugString(TF_Graph* graph,
|
||||
size_t* len);
|
||||
|
||||
// Returns the function content in a human-readable format, with length set in
|
||||
// `len`. The format is subject to change in the future.
|
||||
// The returned string is heap-allocated, and caller should call free() on it.
|
||||
//
|
||||
// Do not return const char*, because some foreign language binding
|
||||
// (e.g. swift) cannot then call free() on the returned pointer.
|
||||
TF_CAPI_EXPORT extern char* TF_FunctionDebugString(TF_Function* func,
|
||||
size_t* len);
|
||||
|
||||
// On success, dequeues a tensor from a TF-managed FifoQueue given by
|
||||
// `tensor_id`, associated with `session`. There must be a graph node named
|
||||
// "fifo_queue_dequeue_<tensor_id>", to be executed by this API call.
|
||||
|
||||
// Caller must call TF_DeleteTensor() over the returned tensor. If the queue is
|
||||
// empty, this call is blocked.
|
||||
//
|
||||
// Tensors are enqueued via the corresponding TF enqueue op.
|
||||
// TODO(hongm): Add support for `timeout_ms`.
|
||||
TF_CAPI_EXPORT extern TF_Tensor* TF_DequeueNamedTensor(TF_Session* session,
|
||||
int tensor_id,
|
||||
TF_Status* status);
|
||||
|
||||
// On success, enqueues `tensor` into a TF-managed FifoQueue given by
|
||||
// `tensor_id`, associated with `session`. There must be a graph node named
|
||||
// "fifo_queue_enqueue_<tensor_id>", to be executed by this API call. It reads
|
||||
// from a placeholder node "arg_tensor_enqueue_<tensor_id>".
|
||||
//
|
||||
// `tensor` is still owned by the caller. This call will be blocked if the queue
|
||||
// has reached its capacity, and will be unblocked when the queued tensors again
|
||||
// drop below the capacity due to dequeuing.
|
||||
//
|
||||
// Tensors are dequeued via the corresponding TF dequeue op.
|
||||
// TODO(hongm): Add support for `timeout_ms`.
|
||||
TF_CAPI_EXPORT extern void TF_EnqueueNamedTensor(TF_Session* session,
|
||||
int tensor_id,
|
||||
TF_Tensor* tensor,
|
||||
TF_Status* status);
|
||||
// Create a serialized tensorflow.ServerDef proto.
|
||||
TF_Buffer* TFE_GetServerDef(const char* text_proto, TF_Status* status);
|
||||
|
||||
TF_CAPI_EXPORT extern void TF_MakeInternalErrorStatus(TF_Status* status,
|
||||
const char* errMsg);
|
||||
|
||||
// TF_NewCheckpointReader() return the CheckpointReader that can be use to
|
||||
// investigate or load the variable from the checkpoint file
|
||||
typedef struct TF_CheckpointReader TF_CheckpointReader;
|
||||
TF_CAPI_EXPORT extern TF_CheckpointReader* TF_NewCheckpointReader(
|
||||
const char* filename, TF_Status* status);
|
||||
TF_CAPI_EXPORT extern void TF_DeleteCheckpointReader(
|
||||
TF_CheckpointReader* reader);
|
||||
TF_CAPI_EXPORT extern int TF_CheckpointReaderHasTensor(
|
||||
TF_CheckpointReader* reader, const char* name);
|
||||
// Get the variable name at the given index
|
||||
TF_CAPI_EXPORT extern const char* TF_CheckpointReaderGetVariable(
|
||||
TF_CheckpointReader* reader, int index);
|
||||
// Get the number of variable in the checkpoint
|
||||
TF_CAPI_EXPORT extern int TF_CheckpointReaderSize(TF_CheckpointReader* reader);
|
||||
// Get the DataType of a variable
|
||||
TF_CAPI_EXPORT extern TF_DataType TF_CheckpointReaderGetVariableDataType(
|
||||
TF_CheckpointReader* reader, const char* name);
|
||||
// Read the shape of a variable and write to `dims`
|
||||
TF_CAPI_EXPORT extern void TF_CheckpointReaderGetVariableShape(
|
||||
TF_CheckpointReader* reader, const char* name, int64_t* dims, int num_dims,
|
||||
TF_Status* status);
|
||||
// Get the number of dimension of a variable
|
||||
TF_CAPI_EXPORT extern int TF_CheckpointReaderGetVariableNumDims(
|
||||
TF_CheckpointReader* reader, const char* name);
|
||||
// Load the weight of a variable
|
||||
TF_CAPI_EXPORT extern TF_Tensor* TF_CheckpointReaderGetTensor(
|
||||
TF_CheckpointReader* reader, const char* name, TF_Status* status);
|
||||
|
||||
// TF_NewAttrBuilder() returns an object that you can set attributes on as
|
||||
// though it were an op. This allows querying properties of that op for
|
||||
// type-checking purposes like if the op will run on a particular device type.
|
||||
typedef struct TF_AttrBuilder TF_AttrBuilder;
|
||||
TF_CAPI_EXPORT extern TF_AttrBuilder* TF_NewAttrBuilder(const char* op_name);
|
||||
TF_CAPI_EXPORT extern void TF_DeleteAttrBuilder(TF_AttrBuilder* builder);
|
||||
TF_CAPI_EXPORT extern void TF_AttrBuilderSetType(TF_AttrBuilder* builder,
|
||||
const char* attr_name,
|
||||
TF_DataType value);
|
||||
TF_CAPI_EXPORT extern void TF_AttrBuilderSetTypeList(TF_AttrBuilder* builder,
|
||||
const char* attr_name,
|
||||
const TF_DataType* values,
|
||||
int num_values);
|
||||
|
||||
// Checks the tensorflow::NodeDef built via the methods above to see if it can
|
||||
// run on device_type.
|
||||
TF_CAPI_EXPORT extern void TF_AttrBuilderCheckCanRunOnDevice(
|
||||
TF_AttrBuilder* builder, const char* device_type, TF_Status* status);
|
||||
|
||||
// For argument number input_index, fetch the corresponding number_attr that
|
||||
// needs to be updated with the argument length of the input list.
|
||||
// Returns nullptr if there is any problem like op_name is not found, or the
|
||||
// argument does not support this attribute type.
|
||||
TF_CAPI_EXPORT extern const char* TF_GetNumberAttrForOpListInput(
|
||||
const char* op_name, int input_index, TF_Status* status);
|
||||
|
||||
// Returns 1 if the op is stateful, 0 otherwise. The return value is undefined
|
||||
// if the status is not ok.
|
||||
TF_CAPI_EXPORT extern int TF_OpIsStateful(const char* op_type,
|
||||
TF_Status* status);
|
||||
|
||||
// Platform specific initialization routine. Very few platforms actually require
|
||||
// this to be called.
|
||||
TF_CAPI_EXPORT void TF_InitMain(const char* usage, int* argc, char*** argv);
|
||||
|
||||
// Platform-specific implementation to return an unused port. (This should used
|
||||
// in tests only.)
|
||||
TF_CAPI_EXPORT int TF_PickUnusedPortOrDie(void);
|
||||
|
||||
// Fast path method that makes constructing a single scalar tensor require less
|
||||
// overhead and copies.
|
||||
TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_NewTensorHandleFromScalar(
|
||||
TF_DataType data_type, void* data, size_t len, TF_Status* status);
|
||||
|
||||
// Specify the server_def that enables collective ops.
|
||||
// This is different to the above function in that it doesn't create remote
|
||||
// contexts, and remotely executing ops is not possible. It just enables
|
||||
// communication for collective ops.
|
||||
TF_CAPI_EXPORT extern void TFE_EnableCollectiveOps(TFE_Context* ctx,
|
||||
const void* proto,
|
||||
size_t proto_len,
|
||||
TF_Status* status);
|
||||
|
||||
// Aborts all ongoing collectives with the specified status. After abortion,
|
||||
// subsequent collectives will error with this status immediately. To reset the
|
||||
// collectives, create a new EagerContext.
|
||||
//
|
||||
// This is intended to be used when a peer failure is detected.
|
||||
TF_CAPI_EXPORT extern void TFE_AbortCollectiveOps(TFE_Context* ctx,
|
||||
TF_Status* status);
|
||||
|
||||
// Checks the health of collective ops peers. Explicit health check is needed in
|
||||
// multi worker collective ops to detect failures in the cluster. If a peer is
|
||||
// down, collective ops may hang.
|
||||
TF_CAPI_EXPORT extern void TFE_CollectiveOpsCheckPeerHealth(
|
||||
TFE_Context* ctx, const char* task, int64_t timeout_in_ms,
|
||||
TF_Status* status);
|
||||
|
||||
// Information about the shape of a Tensor and its type.
|
||||
struct TF_ShapeAndType {
|
||||
// Number of dimensions. -1 indicates unknown rank.
|
||||
int num_dims;
|
||||
// Array of dimensions. -1 indicates unknown dim.
|
||||
int64_t* dims;
|
||||
// The data type. May be 0 to denote unknown type.
|
||||
TF_DataType dtype;
|
||||
};
|
||||
|
||||
typedef struct TF_ShapeAndType TF_ShapeAndType;
|
||||
|
||||
// A list of TF_ShapeAndType elements..
|
||||
struct TF_ShapeAndTypeList {
|
||||
int num_items;
|
||||
TF_ShapeAndType* items;
|
||||
};
|
||||
typedef struct TF_ShapeAndTypeList TF_ShapeAndTypeList;
|
||||
|
||||
// API for manipulating TF_ShapeAndTypeList objects.
|
||||
//
|
||||
TF_CAPI_EXPORT extern TF_ShapeAndTypeList* TF_NewShapeAndTypeList(
|
||||
int num_shapes);
|
||||
TF_CAPI_EXPORT extern void TF_ShapeAndTypeListSetShape(
|
||||
TF_ShapeAndTypeList* shape_list, int index, const int64_t* dims,
|
||||
int num_dims);
|
||||
TF_CAPI_EXPORT extern void TF_ShapeAndTypeListSetUnknownShape(
|
||||
TF_ShapeAndTypeList* shape_list, int index);
|
||||
TF_CAPI_EXPORT extern void TF_ShapeAndTypeListSetDtype(
|
||||
TF_ShapeAndTypeList* shape_list, int index, TF_DataType dtype);
|
||||
TF_CAPI_EXPORT extern void TF_DeleteShapeAndTypeList(
|
||||
TF_ShapeAndTypeList* shape_list);
|
||||
TF_CAPI_EXPORT extern void TF_DeleteShapeAndTypeListArray(
|
||||
TF_ShapeAndTypeList** shape_list_array, int num_items);
|
||||
|
||||
// Infer shapes for the given `op`. The arguments mimic the arguments of the
|
||||
// `shape_inference::InferenceContext` constructor. Note the following:
|
||||
// - The inputs of the `op` are not used for shape inference. So, it is
|
||||
// OK to not have the inputs properly set in `op`. See `input_tensors`
|
||||
// if you want shape inference to consider the input tensors of the
|
||||
// op for shape inference.
|
||||
// - The types need not be set in `input_shapes` as it is not used.
|
||||
// - The number of `input_tensors` should be the same as the number of items
|
||||
// in `input_shapes`.
|
||||
//
|
||||
// The results are returned in `output_shapes` and
|
||||
// `output_resource_shapes_and_types`. The caller is responsible for freeing the
|
||||
// memory in these buffers by calling `TF_DeleteShapeAndTypeList`.
|
||||
TF_CAPI_EXPORT extern void TFE_InferShapes(
|
||||
TFE_Op* op, TF_ShapeAndTypeList* input_shapes, TF_Tensor** input_tensors,
|
||||
TF_ShapeAndTypeList* input_tensor_as_shapes,
|
||||
TF_ShapeAndTypeList** input_resource_shapes_and_types,
|
||||
TF_ShapeAndTypeList** output_shapes,
|
||||
TF_ShapeAndTypeList*** output_resource_shapes_and_types, TF_Status* status);
|
||||
|
||||
TF_CAPI_EXPORT extern void
|
||||
TF_ImportGraphDefOptionsSetValidateColocationConstraints(
|
||||
TF_ImportGraphDefOptions* opts, unsigned char enable);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif // TENSORFLOW_C_C_API_EXPERIMENTAL_H_
|
||||
Generated
Vendored
Executable
+46
@@ -0,0 +1,46 @@
|
||||
/* Copyright 2020 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef TENSORFLOW_C_C_API_MACROS_H_
|
||||
#define TENSORFLOW_C_C_API_MACROS_H_
|
||||
|
||||
#ifdef SWIG
|
||||
#define TF_CAPI_EXPORT
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
#ifdef TF_COMPILE_LIBRARY
|
||||
#define TF_CAPI_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define TF_CAPI_EXPORT __declspec(dllimport)
|
||||
#endif // TF_COMPILE_LIBRARY
|
||||
#else
|
||||
#define TF_CAPI_EXPORT __attribute__((visibility("default")))
|
||||
#endif // _WIN32
|
||||
#endif // SWIG
|
||||
|
||||
// TF_Bool is the C API typedef for unsigned char, while TF_BOOL is
|
||||
// the datatype for boolean tensors.
|
||||
#ifndef TF_Bool
|
||||
#define TF_Bool unsigned char
|
||||
#endif // TF_Bool
|
||||
|
||||
// Macro used to calculate struct size for maintaining ABI stability across
|
||||
// different struct implementations.
|
||||
#ifndef TF_OFFSET_OF_END
|
||||
#define TF_OFFSET_OF_END(TYPE, MEMBER) \
|
||||
(offsetof(TYPE, MEMBER) + sizeof(((TYPE *)0)->MEMBER))
|
||||
#endif // TF_OFFSET_OF_END
|
||||
|
||||
#endif // TENSORFLOW_C_C_API_MACROS_H_
|
||||
Generated
Vendored
Executable
+466
@@ -0,0 +1,466 @@
|
||||
/* Copyright 2017 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef TENSORFLOW_C_EAGER_C_API_H_
|
||||
#define TENSORFLOW_C_EAGER_C_API_H_
|
||||
|
||||
// C API extensions to experiment with eager execution of kernels.
|
||||
// WARNING: Unlike tensorflow/c/c_api.h, the API here is not guaranteed to be
|
||||
// stable and can change without notice.
|
||||
|
||||
#include "tensorflow/c/c_api.h"
|
||||
|
||||
// Macro to control visibility of exported symbols in the shared library (.so,
|
||||
// .dylib, .dll).
|
||||
// This duplicates the TF_EXPORT macro definition in
|
||||
// tensorflow/core/platform/macros.h in order to keep this .h file independent
|
||||
// of any other includes.$a
|
||||
#ifdef SWIG
|
||||
#define TF_CAPI_EXPORT
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
#ifdef TF_COMPILE_LIBRARY
|
||||
#define TF_CAPI_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define TF_CAPI_EXPORT __declspec(dllimport)
|
||||
#endif // TF_COMPILE_LIBRARY
|
||||
#else
|
||||
#define TF_CAPI_EXPORT __attribute__((visibility("default")))
|
||||
#endif // _WIN32
|
||||
#endif // SWIG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct TFE_ContextOptions TFE_ContextOptions;
|
||||
|
||||
// Return a new options object.
|
||||
TF_CAPI_EXPORT extern TFE_ContextOptions* TFE_NewContextOptions(void);
|
||||
|
||||
// Set the config in TF_ContextOptions.options.
|
||||
// config should be a serialized tensorflow.ConfigProto proto.
|
||||
// If config was not parsed successfully as a ConfigProto, record the
|
||||
// error information in *status.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextOptionsSetConfig(
|
||||
TFE_ContextOptions* options, const void* proto, size_t proto_len,
|
||||
TF_Status* status);
|
||||
|
||||
// Controls how to act when we try to run an operation on a given device but
|
||||
// some input tensors are not on that device.
|
||||
// LINT.IfChange
|
||||
// Note: Keep in sync with internal copy of enum in eager/context.h.
|
||||
typedef enum TFE_ContextDevicePlacementPolicy {
|
||||
// Running operations with input tensors on the wrong device will fail.
|
||||
TFE_DEVICE_PLACEMENT_EXPLICIT = 0,
|
||||
// Copy the tensor to the right device but log a warning.
|
||||
TFE_DEVICE_PLACEMENT_WARN = 1,
|
||||
// Silently copy the tensor, which has a performance cost since the operation
|
||||
// will be blocked till the copy completes. This is the default placement
|
||||
// policy.
|
||||
TFE_DEVICE_PLACEMENT_SILENT = 2,
|
||||
// Placement policy which silently copies int32 tensors but not other dtypes.
|
||||
TFE_DEVICE_PLACEMENT_SILENT_FOR_INT32 = 3,
|
||||
} TFE_ContextDevicePlacementPolicy;
|
||||
// LINT.ThenChange(//tensorflow/c/eager/immediate_execution_context.h)
|
||||
|
||||
// Sets the default execution mode (sync/async). Note that this can be
|
||||
// overridden per thread using TFE_ContextSetExecutorForThread.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextOptionsSetAsync(TFE_ContextOptions*,
|
||||
unsigned char enable);
|
||||
|
||||
TF_CAPI_EXPORT extern void TFE_ContextOptionsSetDevicePlacementPolicy(
|
||||
TFE_ContextOptions*, TFE_ContextDevicePlacementPolicy);
|
||||
|
||||
// Destroy an options object.
|
||||
TF_CAPI_EXPORT extern void TFE_DeleteContextOptions(TFE_ContextOptions*);
|
||||
|
||||
// "Context" under which operations/functions are executed. It encapsulates
|
||||
// things like the available devices, resource manager etc.
|
||||
// TFE_Context must outlive all tensor handles created using it. In other
|
||||
// words, TFE_DeleteContext() must be called after all tensor handles have
|
||||
// been deleted (with TFE_DeleteTensorHandle).
|
||||
//
|
||||
// TODO(ashankar): Merge with TF_Session?
|
||||
typedef struct TFE_Context TFE_Context;
|
||||
|
||||
TF_CAPI_EXPORT extern TFE_Context* TFE_NewContext(
|
||||
const TFE_ContextOptions* opts, TF_Status* status);
|
||||
TF_CAPI_EXPORT extern void TFE_DeleteContext(TFE_Context* ctx);
|
||||
TF_CAPI_EXPORT extern TF_DeviceList* TFE_ContextListDevices(TFE_Context* ctx,
|
||||
TF_Status* status);
|
||||
|
||||
// Clears the internal caches in the TFE context. Useful when reseeding random
|
||||
// ops.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextClearCaches(TFE_Context* ctx);
|
||||
|
||||
// Sets a thread-local device placement policy. After this call, other calls to
|
||||
// TFE_Execute in the same thread will use the device policy specified here
|
||||
// instead of the device policy used to construct the context. This has no
|
||||
// effect on the device policy used by other program threads.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextSetThreadLocalDevicePlacementPolicy(
|
||||
TFE_Context* ctx, TFE_ContextDevicePlacementPolicy policy);
|
||||
|
||||
// Returns the device placement policy to be used by this context in the current
|
||||
// thread.
|
||||
TF_CAPI_EXPORT extern TFE_ContextDevicePlacementPolicy
|
||||
TFE_ContextGetDevicePlacementPolicy(TFE_Context* ctx);
|
||||
|
||||
// A tensorflow.ServerDef specifies remote workers (in addition to the current
|
||||
// workers name). Operations created on this context can then be executed on
|
||||
// any of these remote workers by setting an appropriate device.
|
||||
//
|
||||
// If the following is set, all servers identified by the
|
||||
// ServerDef must be up when the context is created.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextSetServerDef(TFE_Context* ctx,
|
||||
int keep_alive_secs,
|
||||
const void* proto,
|
||||
size_t proto_len,
|
||||
TF_Status* status);
|
||||
|
||||
// A handle to a tensor on a device.
|
||||
//
|
||||
// Like a TF_Tensor, a TFE_TensorHandle refers to a tensor with a value, shape,
|
||||
// type etc. Unlike a TF_Tensor, a TFE_TensorHandle may refer to such tensors
|
||||
// placed in memory of different devices or remote address spaces.
|
||||
typedef struct TFE_TensorHandle TFE_TensorHandle;
|
||||
|
||||
TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_NewTensorHandle(const TF_Tensor* t,
|
||||
TF_Status* status);
|
||||
// Indicates that the caller will not be using `h` any more.
|
||||
TF_CAPI_EXPORT extern void TFE_DeleteTensorHandle(TFE_TensorHandle* h);
|
||||
TF_CAPI_EXPORT extern TF_DataType TFE_TensorHandleDataType(TFE_TensorHandle* h);
|
||||
// This function will block till the operation that produces `h` has completed.
|
||||
TF_CAPI_EXPORT extern int TFE_TensorHandleNumDims(TFE_TensorHandle* h,
|
||||
TF_Status* status);
|
||||
TF_CAPI_EXPORT extern int64_t TFE_TensorHandleNumElements(TFE_TensorHandle* h,
|
||||
TF_Status* status);
|
||||
// This function will block till the operation that produces `h` has completed.
|
||||
TF_CAPI_EXPORT extern int64_t TFE_TensorHandleDim(TFE_TensorHandle* h,
|
||||
int dim_index,
|
||||
TF_Status* status);
|
||||
|
||||
// Returns the device of the operation that produced `h`. If `h` was produced by
|
||||
// a copy, returns the destination device of the copy. Note that the returned
|
||||
// device name is not always the device holding the tensor handle's memory. If
|
||||
// you want the latter, use TFE_TensorHandleBackingDeviceName. This function
|
||||
// will block till the operation that produces `h` has completed.
|
||||
TF_CAPI_EXPORT extern const char* TFE_TensorHandleDeviceName(
|
||||
TFE_TensorHandle* h, TF_Status* status);
|
||||
|
||||
// Returns the name of the device in whose memory `h` resides.
|
||||
//
|
||||
// This function will block till the operation that produces `h` has completed.
|
||||
TF_CAPI_EXPORT extern const char* TFE_TensorHandleBackingDeviceName(
|
||||
TFE_TensorHandle* h, TF_Status* status);
|
||||
|
||||
// Return a pointer to a new TFE_TensorHandle that shares the underlying tensor
|
||||
// with `h`. On success, `status` is set to OK. On failure, `status` reflects
|
||||
// the error and a nullptr is returned.
|
||||
TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_TensorHandleCopySharingTensor(
|
||||
TFE_TensorHandle* h, TF_Status* status);
|
||||
|
||||
// This function will block till the operation that produces `h` has
|
||||
// completed. The memory returned might alias the internal memory used by
|
||||
// TensorFlow. Hence, callers should not mutate this memory (for example by
|
||||
// modifying the memory region pointed to by TF_TensorData() on the returned
|
||||
// TF_Tensor).
|
||||
TF_CAPI_EXPORT extern TF_Tensor* TFE_TensorHandleResolve(TFE_TensorHandle* h,
|
||||
TF_Status* status);
|
||||
|
||||
// Create a new TFE_TensorHandle with the same contents as 'h' but placed
|
||||
// in the memory of the device name 'device_name'.
|
||||
// If source and destination are the same device, then this creates a new handle
|
||||
// that shares the underlying buffer. Otherwise, it currently requires at least
|
||||
// one of the source or destination devices to be CPU (i.e., for the source or
|
||||
// destination tensor to be placed in host memory).
|
||||
// If async execution is enabled, the copy may be enqueued and the call will
|
||||
// return "non-ready" handle. Else, this function returns after the copy has
|
||||
// been done.
|
||||
TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_TensorHandleCopyToDevice(
|
||||
TFE_TensorHandle* h, TFE_Context* ctx, const char* device_name,
|
||||
TF_Status* status);
|
||||
|
||||
// Debugging/Profiling information for TFE_TensorHandle
|
||||
//
|
||||
// TFE_TensorDebugInfo contains information useful for debugging and
|
||||
// profiling tensors.
|
||||
typedef struct TFE_TensorDebugInfo TFE_TensorDebugInfo;
|
||||
|
||||
// Retrieves TFE_TensorDebugInfo for `handle`.
|
||||
// If TFE_TensorHandleTensorDebugInfo succeeds, `status` is set to OK and caller
|
||||
// is responsible for deleting returned TFE_TensorDebugInfo.
|
||||
// If TFE_TensorHandleTensorDebugInfo fails, `status` is set to appropriate
|
||||
// error and nullptr is returned. This function can block till the operation
|
||||
// that produces `handle` has completed.
|
||||
TF_CAPI_EXPORT extern TFE_TensorDebugInfo* TFE_TensorHandleTensorDebugInfo(
|
||||
TFE_TensorHandle* h, TF_Status* status);
|
||||
|
||||
// Deletes `debug_info`.
|
||||
TF_CAPI_EXPORT extern void TFE_DeleteTensorDebugInfo(
|
||||
TFE_TensorDebugInfo* debug_info);
|
||||
|
||||
// Returns the number of dimensions used to represent the tensor on its device.
|
||||
// The number of dimensions used to represent the tensor on device can be
|
||||
// different from the number returned by TFE_TensorHandleNumDims.
|
||||
// The return value was current at the time of TFE_TensorDebugInfo creation.
|
||||
TF_CAPI_EXPORT extern int TFE_TensorDebugInfoOnDeviceNumDims(
|
||||
TFE_TensorDebugInfo* debug_info);
|
||||
|
||||
// Returns the number of elements in dimension `dim_index`.
|
||||
// Tensor representation on device can be transposed from its representation
|
||||
// on host. The data contained in dimension `dim_index` on device
|
||||
// can correspond to the data contained in another dimension in on-host
|
||||
// representation. The dimensions are indexed using the standard TensorFlow
|
||||
// major-to-minor order (slowest varying dimension first),
|
||||
// not the XLA's minor-to-major order.
|
||||
// On-device dimensions can be padded. TFE_TensorDebugInfoOnDeviceDim returns
|
||||
// the number of elements in a dimension after padding.
|
||||
// The return value was current at the time of TFE_TensorDebugInfo creation.
|
||||
TF_CAPI_EXPORT extern int64_t TFE_TensorDebugInfoOnDeviceDim(
|
||||
TFE_TensorDebugInfo* debug_info, int dim_index);
|
||||
|
||||
// Description of the TensorFlow op to execute.
|
||||
//
|
||||
// Assumes that the provided 'ctx' outlives the returned TFE_Op, i.e.,
|
||||
// TFE_DeleteOp() is called before TFE_DeleteContext().
|
||||
//
|
||||
// Very similar to TF_OperationDescription with some differences:
|
||||
// (1) TF_Output or TFE_TensorHandle* as arguments to TF_AddInput,
|
||||
// TF_AddInputList
|
||||
// (2) TF_ColocateWith, TF_AddControlInput etc. do not make sense.
|
||||
// (3) Implementation detail: Avoid use of NodeBuilder/NodeDefBuilder since
|
||||
// the additional sanity checks there seem unnecessary;
|
||||
typedef struct TFE_Op TFE_Op;
|
||||
|
||||
TF_CAPI_EXPORT extern TFE_Op* TFE_NewOp(TFE_Context* ctx,
|
||||
const char* op_or_function_name,
|
||||
TF_Status* status);
|
||||
TF_CAPI_EXPORT extern void TFE_DeleteOp(TFE_Op* op);
|
||||
|
||||
// Returns the op or function name `op` will execute.
|
||||
//
|
||||
// The returned string remains valid throughout the lifetime of 'op'.
|
||||
TF_CAPI_EXPORT extern const char* TFE_OpGetName(const TFE_Op* op,
|
||||
TF_Status* status);
|
||||
TF_CAPI_EXPORT extern TFE_Context* TFE_OpGetContext(const TFE_Op* op,
|
||||
TF_Status* status);
|
||||
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetDevice(TFE_Op* op, const char* device_name,
|
||||
TF_Status* status);
|
||||
// The returned string remains valid throughout the lifetime of 'op'.
|
||||
TF_CAPI_EXPORT extern const char* TFE_OpGetDevice(const TFE_Op* op,
|
||||
TF_Status* status);
|
||||
|
||||
TF_CAPI_EXPORT extern void TFE_OpAddInput(TFE_Op* op, TFE_TensorHandle* input,
|
||||
TF_Status* status);
|
||||
|
||||
TF_CAPI_EXPORT extern void TFE_OpAddInputList(TFE_Op* op,
|
||||
TFE_TensorHandle** inputs,
|
||||
int num_inputs,
|
||||
TF_Status* status);
|
||||
|
||||
// Fetches the current number of inputs attached to `op`.
|
||||
//
|
||||
// Does not use the operation's definition to determine how many inputs should
|
||||
// be attached. It is intended for use with TFE_OpGetFlatInput to inspect an
|
||||
// already-finalized operation.
|
||||
//
|
||||
// Note that TFE_OpGetFlatInputCount and TFE_OpGetFlatInput operate on a flat
|
||||
// sequence of inputs, unlike TFE_OpGetInputLength (for getting the length of a
|
||||
// particular named input list, which may only be part of the op's inputs).
|
||||
TF_CAPI_EXPORT extern int TFE_OpGetFlatInputCount(const TFE_Op* op,
|
||||
TF_Status* status);
|
||||
// Returns a borrowed reference to one of `op`'s inputs. Use
|
||||
// `TFE_TensorHandleCopySharingTensor` to make a new reference.
|
||||
TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_OpGetFlatInput(const TFE_Op* op,
|
||||
int index,
|
||||
TF_Status* status);
|
||||
|
||||
TF_CAPI_EXPORT extern TF_AttrType TFE_OpGetAttrType(TFE_Op* op,
|
||||
const char* attr_name,
|
||||
unsigned char* is_list,
|
||||
TF_Status* status);
|
||||
// Get an attribute type given an op name; a fusion of TFE_NewOp and
|
||||
// TFE_OpGetAttrType for use from Python without the overhead of the individual
|
||||
// calls and memory management of TFE_Op.
|
||||
TF_CAPI_EXPORT extern TF_AttrType TFE_OpNameGetAttrType(
|
||||
TFE_Context* ctx, const char* op_or_function_name, const char* attr_name,
|
||||
unsigned char* is_list, TF_Status* status);
|
||||
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrString(TFE_Op* op,
|
||||
const char* attr_name,
|
||||
const void* value,
|
||||
size_t length);
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrInt(TFE_Op* op, const char* attr_name,
|
||||
int64_t value);
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrFloat(TFE_Op* op, const char* attr_name,
|
||||
float value);
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrBool(TFE_Op* op, const char* attr_name,
|
||||
unsigned char value);
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrType(TFE_Op* op, const char* attr_name,
|
||||
TF_DataType value);
|
||||
// If the number of dimensions is unknown, `num_dims` must be set to
|
||||
// -1 and `dims` can be null. If a dimension is unknown, the
|
||||
// corresponding entry in the `dims` array must be -1.
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrShape(TFE_Op* op, const char* attr_name,
|
||||
const int64_t* dims,
|
||||
const int num_dims,
|
||||
TF_Status* out_status);
|
||||
|
||||
// Sets the attribute attr_name to be a function specified by 'function'.
|
||||
//
|
||||
// TODO(ashankar,iga): Add this functionality to the C API for graph
|
||||
// construction. Perhaps we want an AttrValueMap equivalent in the C API?
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrFunction(TFE_Op* op,
|
||||
const char* attr_name,
|
||||
const TFE_Op* value);
|
||||
|
||||
TF_CAPI_EXPORT void TFE_OpSetAttrFunctionName(TFE_Op* op, const char* attr_name,
|
||||
const char* data, size_t length);
|
||||
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrTensor(TFE_Op* op,
|
||||
const char* attr_name,
|
||||
TF_Tensor* tensor,
|
||||
TF_Status* status);
|
||||
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrStringList(TFE_Op* op,
|
||||
const char* attr_name,
|
||||
const void* const* values,
|
||||
const size_t* lengths,
|
||||
int num_values);
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrIntList(TFE_Op* op,
|
||||
const char* attr_name,
|
||||
const int64_t* values,
|
||||
int num_values);
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrFloatList(TFE_Op* op,
|
||||
const char* attr_name,
|
||||
const float* values,
|
||||
int num_values);
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrBoolList(TFE_Op* op,
|
||||
const char* attr_name,
|
||||
const unsigned char* values,
|
||||
int num_values);
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrTypeList(TFE_Op* op,
|
||||
const char* attr_name,
|
||||
const TF_DataType* values,
|
||||
int num_values);
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrShapeList(
|
||||
TFE_Op* op, const char* attr_name, const int64_t** dims,
|
||||
const int* num_dims, int num_values, TF_Status* out_status);
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrFunctionList(TFE_Op* op,
|
||||
const char* attr_name,
|
||||
const TFE_Op** value,
|
||||
int num_values);
|
||||
|
||||
// Returns the length (number of tensors) of the input argument `input_name`
|
||||
// found in the provided `op`.
|
||||
TF_CAPI_EXPORT extern int TFE_OpGetInputLength(TFE_Op* op,
|
||||
const char* input_name,
|
||||
TF_Status* status);
|
||||
|
||||
// Returns the length (number of tensors) of the output argument `output_name`
|
||||
// found in the provided `op`.
|
||||
TF_CAPI_EXPORT extern int TFE_OpGetOutputLength(TFE_Op* op,
|
||||
const char* output_name,
|
||||
TF_Status* status);
|
||||
|
||||
// Execute the operation defined by 'op' and return handles to computed
|
||||
// tensors in `retvals`.
|
||||
//
|
||||
// 'retvals' must point to a pre-allocated array of TFE_TensorHandle* and
|
||||
// '*num_retvals' should be set to the size of this array. It is an error if
|
||||
// the size of 'retvals' is less than the number of outputs. This call sets
|
||||
// *num_retvals to the number of outputs.
|
||||
//
|
||||
// If async execution is enabled, the call may simply enqueue the execution
|
||||
// and return "non-ready" handles in `retvals`. Note that any handles contained
|
||||
// in 'op' should not be mutated till the kernel execution actually finishes.
|
||||
//
|
||||
// For sync execution, if any of the inputs to `op` are not ready, this call
|
||||
// will block till they become ready and then return when the kernel execution
|
||||
// is done.
|
||||
// TODO(agarwal): change num_retvals to int from int*.
|
||||
TF_CAPI_EXPORT extern void TFE_Execute(TFE_Op* op, TFE_TensorHandle** retvals,
|
||||
int* num_retvals, TF_Status* status);
|
||||
|
||||
// Add a function (serialized FunctionDef protocol buffer) to ctx so
|
||||
// that it can be invoked using TFE_Execute.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextAddFunctionDef(
|
||||
TFE_Context* ctx, const char* serialized_function_def, size_t size,
|
||||
TF_Status* status);
|
||||
|
||||
// Adds a function (created from TF_GraphToFunction or
|
||||
// TF_FunctionImportFunctionDef) to the context, allowing it to be executed with
|
||||
// TFE_Execute by creating an op with the same name as the function.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextAddFunction(TFE_Context* ctx,
|
||||
TF_Function* function,
|
||||
TF_Status* status);
|
||||
|
||||
// Removes a function from the context. Once removed, you can no longer
|
||||
// TFE_Execute it or TFE_Execute any TFE_Op which has it as an attribute or any
|
||||
// other function which calls it as an attribute.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextRemoveFunction(TFE_Context* ctx,
|
||||
const char* name,
|
||||
TF_Status* status);
|
||||
|
||||
// Checks whether a function is registered under `name`.
|
||||
TF_CAPI_EXPORT unsigned char TFE_ContextHasFunction(TFE_Context* ctx,
|
||||
const char* name);
|
||||
|
||||
// Enables tracing of RunMetadata on the ops executed from this context.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextEnableRunMetadata(TFE_Context* ctx);
|
||||
|
||||
// Disables tracing of RunMetadata on the ops executed from this context.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextDisableRunMetadata(TFE_Context* ctx);
|
||||
|
||||
// Populates the passed-in buffer with a serialized RunMetadata protocol buffer
|
||||
// containing any run metadata information accumulated so far and clears this
|
||||
// information.
|
||||
// If async mode is enabled, this call blocks till all currently pending ops are
|
||||
// done.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextExportRunMetadata(TFE_Context* ctx,
|
||||
TF_Buffer* buf,
|
||||
TF_Status* status);
|
||||
|
||||
// Some TF ops need a step container to be set to limit the lifetime of some
|
||||
// resources (mostly TensorArray and Stack, used in while loop gradients in
|
||||
// graph mode). Calling this on a context tells it to start a step.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextStartStep(TFE_Context* ctx);
|
||||
|
||||
// Ends a step. When there is no active step (that is, every started step has
|
||||
// been ended) step containers will be cleared. Note: it is not safe to call
|
||||
// TFE_ContextEndStep while ops which rely on the step container may be running.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextEndStep(TFE_Context* ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
// A workaround to ease conversion to and from numpy objects and
|
||||
// TFE_TensorHandle's.
|
||||
//
|
||||
// TODO(ashankar): Figure out an alternative scheme that precludes the need for
|
||||
// these API-boundary breaking methods.
|
||||
namespace tensorflow {
|
||||
class Tensor;
|
||||
} // namespace tensorflow
|
||||
|
||||
TFE_TensorHandle* TFE_NewTensorHandle(const tensorflow::Tensor& t,
|
||||
TF_Status* status);
|
||||
#endif
|
||||
|
||||
#endif // TENSORFLOW_C_EAGER_C_API_H_
|
||||
Generated
Vendored
Executable
+568
@@ -0,0 +1,568 @@
|
||||
/* Copyright 2018 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
#ifndef TENSORFLOW_C_EAGER_C_API_EXPERIMENTAL_H_
|
||||
#define TENSORFLOW_C_EAGER_C_API_EXPERIMENTAL_H_
|
||||
|
||||
#include "tensorflow/c/c_api.h"
|
||||
#include "tensorflow/c/eager/c_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Resets `op_to_reset` with `op_or_function_name` and `raw_device_name`. This
|
||||
// is for performance optimization by reusing an exiting unused op rather than
|
||||
// creating a new op every time. If `raw_device_name` is `NULL` or empty, it
|
||||
// does not set the device name. If it's not `NULL`, then it attempts to parse
|
||||
// and set the device name. It's effectively `TFE_OpSetDevice`, but it is faster
|
||||
// than separately calling it because if the existing op has the same
|
||||
// `raw_device_name`, it skips parsing and just leave as it is.
|
||||
TF_CAPI_EXPORT extern void TFE_OpReset(TFE_Op* op_to_reset,
|
||||
const char* op_or_function_name,
|
||||
const char* raw_device_name,
|
||||
TF_Status* status);
|
||||
|
||||
// Enables only graph collection in RunMetadata on the functions executed from
|
||||
// this context.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextEnableGraphCollection(TFE_Context* ctx);
|
||||
|
||||
// Disables only graph collection in RunMetadata on the functions executed from
|
||||
// this context.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextDisableGraphCollection(TFE_Context* ctx);
|
||||
|
||||
// TODO(fishx): Move these monitoring APIs into a separate file.
|
||||
// -----------------------------------------------------------------------------
|
||||
// Monitoring Counter APIs.
|
||||
// These APIs de-templated monitoring Counter for swig.
|
||||
|
||||
typedef struct TFE_MonitoringCounterCell TFE_MonitoringCounterCell;
|
||||
|
||||
// Atomically increments the value of the cell. The value must be non-negative.
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringCounterCellIncrementBy(
|
||||
TFE_MonitoringCounterCell* cell, int64_t value);
|
||||
|
||||
// Retrieves the current value of the cell.
|
||||
TF_CAPI_EXPORT extern int64_t TFE_MonitoringCounterCellValue(
|
||||
TFE_MonitoringCounterCell* cell);
|
||||
|
||||
// APIs for Counter without label.
|
||||
typedef struct TFE_MonitoringCounter0 TFE_MonitoringCounter0;
|
||||
// Returns a new Counter metric object. The caller should manage lifetime of
|
||||
// the object. Using duplicate metric name will crash the program with fatal
|
||||
// error.
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringCounter0* TFE_MonitoringNewCounter0(
|
||||
const char* name, TF_Status* status, const char* description);
|
||||
// Deletes the Counter object.
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteCounter0(
|
||||
TFE_MonitoringCounter0* counter);
|
||||
// Retrieves the cell from the Counter object. The Counter object will manage
|
||||
// lifetime of the cell.
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringCounterCell* TFE_MonitoringGetCellCounter0(
|
||||
TFE_MonitoringCounter0* counter);
|
||||
|
||||
// APIs for Counter with 1 label.
|
||||
typedef struct TFE_MonitoringCounter1 TFE_MonitoringCounter1;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringCounter1* TFE_MonitoringNewCounter1(
|
||||
const char* name, TF_Status* status, const char* description,
|
||||
const char* label1);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteCounter1(
|
||||
TFE_MonitoringCounter1* counter);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringCounterCell* TFE_MonitoringGetCellCounter1(
|
||||
TFE_MonitoringCounter1* counter, const char* label1);
|
||||
|
||||
// APIs for Counter with 2 labels.
|
||||
typedef struct TFE_MonitoringCounter2 TFE_MonitoringCounter2;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringCounter2* TFE_MonitoringNewCounter2(
|
||||
const char* name, TF_Status* status, const char* description,
|
||||
const char* label1, const char* label2);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteCounter2(
|
||||
TFE_MonitoringCounter2* counter);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringCounterCell* TFE_MonitoringGetCellCounter2(
|
||||
TFE_MonitoringCounter2* counter, const char* label1, const char* label2);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Monitoring Gauge APIs.
|
||||
// These APIs de-templated monitoring Gauge for swig.
|
||||
|
||||
typedef struct TFE_MonitoringIntGaugeCell TFE_MonitoringIntGaugeCell;
|
||||
|
||||
// Atomically set the value of the cell.
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringIntGaugeCellSet(
|
||||
TFE_MonitoringIntGaugeCell* cell, int64_t value);
|
||||
|
||||
// Retrieves the current value of the cell.
|
||||
TF_CAPI_EXPORT extern int64_t TFE_MonitoringIntGaugeCellValue(
|
||||
TFE_MonitoringIntGaugeCell* cell);
|
||||
|
||||
// APIs for Int Gauge without label.
|
||||
typedef struct TFE_MonitoringIntGauge0 TFE_MonitoringIntGauge0;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringIntGauge0* TFE_MonitoringNewIntGauge0(
|
||||
const char* name, TF_Status* out_status, const char* description);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteIntGauge0(
|
||||
TFE_MonitoringIntGauge0* gauge);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringIntGaugeCell*
|
||||
TFE_MonitoringGetCellIntGauge0(TFE_MonitoringIntGauge0* gauge);
|
||||
|
||||
// APIs for Int Gauge with 1 label.
|
||||
typedef struct TFE_MonitoringIntGauge1 TFE_MonitoringIntGauge1;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringIntGauge1* TFE_MonitoringNewIntGauge1(
|
||||
const char* name, TF_Status* out_status, const char* description,
|
||||
const char* label1);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteIntGauge1(
|
||||
TFE_MonitoringIntGauge1* gauge);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringIntGaugeCell*
|
||||
TFE_MonitoringGetCellIntGauge1(TFE_MonitoringIntGauge1* gauge,
|
||||
const char* label1);
|
||||
|
||||
// APIs for Int Gauge with 2 label.
|
||||
typedef struct TFE_MonitoringIntGauge2 TFE_MonitoringIntGauge2;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringIntGauge2* TFE_MonitoringNewIntGauge2(
|
||||
const char* name, TF_Status* out_status, const char* description,
|
||||
const char* label1, const char* label2);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteIntGauge2(
|
||||
TFE_MonitoringIntGauge2* gauge);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringIntGaugeCell*
|
||||
TFE_MonitoringGetCellIntGauge2(TFE_MonitoringIntGauge2* gauge,
|
||||
const char* label1, const char* label2);
|
||||
|
||||
typedef struct TFE_MonitoringStringGaugeCell TFE_MonitoringStringGaugeCell;
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringStringGaugeCellSet(
|
||||
TFE_MonitoringStringGaugeCell* cell, const char* value);
|
||||
// Retrieves the string value and saves it in buffer.
|
||||
TF_CAPI_EXPORT extern const void TFE_MonitoringStringGaugeCellValue(
|
||||
TFE_MonitoringStringGaugeCell* cell, TF_Buffer* buf);
|
||||
|
||||
// APIs for String Gauge without label.
|
||||
typedef struct TFE_MonitoringStringGauge0 TFE_MonitoringStringGauge0;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringStringGauge0* TFE_MonitoringNewStringGauge0(
|
||||
const char* name, TF_Status* out_status, const char* description);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteStringGauge0(
|
||||
TFE_MonitoringStringGauge0* gauge);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringStringGaugeCell*
|
||||
TFE_MonitoringGetCellStringGauge0(TFE_MonitoringStringGauge0* gauge);
|
||||
|
||||
// APIs for String Gauge with 1 label.
|
||||
typedef struct TFE_MonitoringStringGauge1 TFE_MonitoringStringGauge1;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringStringGauge1* TFE_MonitoringNewStringGauge1(
|
||||
const char* name, TF_Status* out_status, const char* description,
|
||||
const char* label1);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteStringGauge1(
|
||||
TFE_MonitoringStringGauge1* gauge);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringStringGaugeCell*
|
||||
TFE_MonitoringGetCellStringGauge1(TFE_MonitoringStringGauge1* gauge,
|
||||
const char* label1);
|
||||
|
||||
// APIs for String Gauge with 2 label.
|
||||
typedef struct TFE_MonitoringStringGauge2 TFE_MonitoringStringGauge2;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringStringGauge2* TFE_MonitoringNewStringGauge2(
|
||||
const char* name, TF_Status* out_status, const char* description,
|
||||
const char* label1, const char* label2);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteStringGauge2(
|
||||
TFE_MonitoringStringGauge2* gauge);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringStringGaugeCell*
|
||||
TFE_MonitoringGetCellStringGauge2(TFE_MonitoringStringGauge2* gauge,
|
||||
const char* label1, const char* label2);
|
||||
|
||||
typedef struct TFE_MonitoringBoolGaugeCell TFE_MonitoringBoolGaugeCell;
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringBoolGaugeCellSet(
|
||||
TFE_MonitoringBoolGaugeCell* cell, bool value);
|
||||
TF_CAPI_EXPORT extern bool TFE_MonitoringBoolGaugeCellValue(
|
||||
TFE_MonitoringBoolGaugeCell* cell);
|
||||
|
||||
// APIs for Bool Gauge without label.
|
||||
typedef struct TFE_MonitoringBoolGauge0 TFE_MonitoringBoolGauge0;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringBoolGauge0* TFE_MonitoringNewBoolGauge0(
|
||||
const char* name, TF_Status* out_status, const char* description);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteBoolGauge0(
|
||||
TFE_MonitoringBoolGauge0* gauge);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringBoolGaugeCell*
|
||||
TFE_MonitoringGetCellBoolGauge0(TFE_MonitoringBoolGauge0* gauge);
|
||||
|
||||
// APIs for Bool Gauge with 1 label.
|
||||
typedef struct TFE_MonitoringBoolGauge1 TFE_MonitoringBoolGauge1;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringBoolGauge1* TFE_MonitoringNewBoolGauge1(
|
||||
const char* name, TF_Status* out_status, const char* description,
|
||||
const char* label1);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteBoolGauge1(
|
||||
TFE_MonitoringBoolGauge1* gauge);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringBoolGaugeCell*
|
||||
TFE_MonitoringGetCellBoolGauge1(TFE_MonitoringBoolGauge1* gauge,
|
||||
const char* label1);
|
||||
|
||||
// APIs for Bool Gauge with 2 label.
|
||||
typedef struct TFE_MonitoringBoolGauge2 TFE_MonitoringBoolGauge2;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringBoolGauge2* TFE_MonitoringNewBoolGauge2(
|
||||
const char* name, TF_Status* out_status, const char* description,
|
||||
const char* label1, const char* label2);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteBoolGauge2(
|
||||
TFE_MonitoringBoolGauge2* gauge);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringBoolGaugeCell*
|
||||
TFE_MonitoringGetCellBoolGauge2(TFE_MonitoringBoolGauge2* gauge,
|
||||
const char* label1, const char* label2);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Monitoring Sampler APIs.
|
||||
// These APIs de-templated monitoring Sampler for swig.
|
||||
|
||||
typedef struct TFE_MonitoringSamplerCell TFE_MonitoringSamplerCell;
|
||||
|
||||
// Atomically add the value of the cell.
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringSamplerCellAdd(
|
||||
TFE_MonitoringSamplerCell* cell, double value);
|
||||
|
||||
// Retrieves the current value of the cell. The return value is a HistogramProto
|
||||
// saved in buffer.
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringSamplerCellValue(
|
||||
TFE_MonitoringSamplerCell* cell, TF_Buffer* buf);
|
||||
|
||||
// APIs for sampler buckets
|
||||
typedef struct TFE_MonitoringBuckets TFE_MonitoringBuckets;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringBuckets*
|
||||
TFE_MonitoringNewExponentialBuckets(double scale, double growth_factor,
|
||||
int bucket_count);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteBuckets(
|
||||
TFE_MonitoringBuckets* buckets);
|
||||
|
||||
// APIs for Sampler without label.
|
||||
typedef struct TFE_MonitoringSampler0 TFE_MonitoringSampler0;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringSampler0* TFE_MonitoringNewSampler0(
|
||||
const char* name, TFE_MonitoringBuckets* buckets, TF_Status* out_status,
|
||||
const char* description);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteSampler0(
|
||||
TFE_MonitoringSampler0* sampler);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringSamplerCell* TFE_MonitoringGetCellSampler0(
|
||||
TFE_MonitoringSampler0* sampler);
|
||||
|
||||
// APIs for Sampler with 1 label.
|
||||
typedef struct TFE_MonitoringSampler1 TFE_MonitoringSampler1;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringSampler1* TFE_MonitoringNewSampler1(
|
||||
const char* name, TFE_MonitoringBuckets* buckets, TF_Status* out_status,
|
||||
const char* description, const char* label1);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteSampler1(
|
||||
TFE_MonitoringSampler1* sampler);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringSamplerCell* TFE_MonitoringGetCellSampler1(
|
||||
TFE_MonitoringSampler1* sampler, const char* label1);
|
||||
|
||||
// APIs for Sampler with 2 label.
|
||||
typedef struct TFE_MonitoringSampler2 TFE_MonitoringSampler2;
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringSampler2* TFE_MonitoringNewSampler2(
|
||||
const char* name, TFE_MonitoringBuckets* buckets, TF_Status* out_status,
|
||||
const char* description, const char* label1, const char* label2);
|
||||
TF_CAPI_EXPORT extern void TFE_MonitoringDeleteSampler2(
|
||||
TFE_MonitoringSampler2* sampler);
|
||||
TF_CAPI_EXPORT extern TFE_MonitoringSamplerCell* TFE_MonitoringGetCellSampler2(
|
||||
TFE_MonitoringSampler2* sampler, const char* label1, const char* label2);
|
||||
|
||||
// Sets whether to copy the remote inputs of a function lazily.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextOptionsSetLazyRemoteInputsCopy(
|
||||
TFE_ContextOptions*, bool lazy_copy);
|
||||
|
||||
// Sets whether to use TFRT
|
||||
TF_CAPI_EXPORT extern void TFE_ContextOptionsSetTfrt(TFE_ContextOptions*,
|
||||
bool use_tfrt);
|
||||
|
||||
// Returns the context_id from the EagerContext which is used by the
|
||||
// EagerService to maintain consistency between client and worker. The
|
||||
// context_id is initialized with a dummy value and is later set when the worker
|
||||
// is initialized (either locally or remotely). The context_id can change during
|
||||
// the process lifetime although this should cause the worker to be
|
||||
// reinitialized (e.g. cleared caches) as well.
|
||||
TF_CAPI_EXPORT extern uint64_t TFE_GetContextId(TFE_Context* ctx);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Cancellation APIs.
|
||||
|
||||
typedef struct TFE_CancellationManager TFE_CancellationManager;
|
||||
TF_CAPI_EXPORT extern TFE_CancellationManager* TFE_NewCancellationManager();
|
||||
TF_CAPI_EXPORT extern bool TFE_CancellationManagerIsCancelled(
|
||||
TFE_CancellationManager*);
|
||||
TF_CAPI_EXPORT extern void TFE_CancellationManagerStartCancel(
|
||||
TFE_CancellationManager*);
|
||||
TF_CAPI_EXPORT extern void TFE_DeleteCancellationManager(
|
||||
TFE_CancellationManager*);
|
||||
|
||||
// Associates the given `cancellation_manager` with `op`, so that invoking
|
||||
// `TFE_CancellationManagerStartCancel(cancellation_manager)` will cancel the
|
||||
// execution of `op`.
|
||||
typedef struct TFE_CancellationManager TFE_CancellationManager;
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetCancellationManager(
|
||||
TFE_Op* op, TFE_CancellationManager* cancellation_manager,
|
||||
TF_Status* status);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Eager Executor APIs.
|
||||
typedef struct TFE_Executor TFE_Executor;
|
||||
|
||||
// Creates a new eager Executor. Nodes in one executor are guaranteed to be
|
||||
// executed in sequence. Assigning nodes to different executors allows executing
|
||||
// nodes in parallel.
|
||||
TF_CAPI_EXPORT extern TFE_Executor* TFE_NewExecutor(bool is_async);
|
||||
|
||||
// Deletes the eager Executor without waiting for enqueued nodes. Please call
|
||||
// TFE_ExecutorWaitForAllPendingNodes before calling this API if you want to
|
||||
// make sure all nodes are finished.
|
||||
TF_CAPI_EXPORT extern void TFE_DeleteExecutor(TFE_Executor*);
|
||||
|
||||
// Returns true if the executor is in async mode.
|
||||
TF_CAPI_EXPORT extern bool TFE_ExecutorIsAsync(TFE_Executor*);
|
||||
|
||||
// Causes the calling thread to block till all ops dispatched in this executor
|
||||
// have been executed. Note that "execution" here refers to kernel execution /
|
||||
// scheduling of copies, etc. Similar to sync execution, it doesn't guarantee
|
||||
// that lower level device queues (like GPU streams) have been flushed.
|
||||
//
|
||||
// This call may not block for execution of ops enqueued concurrently with this
|
||||
// call.
|
||||
TF_CAPI_EXPORT extern void TFE_ExecutorWaitForAllPendingNodes(
|
||||
TFE_Executor*, TF_Status* status);
|
||||
|
||||
// When an error happens, any pending operations are discarded and newly issued
|
||||
// ops return an error. This call clears the error state and re-enables
|
||||
// execution of newly issued ops.
|
||||
//
|
||||
// Note that outputs of discarded ops remain in a corrupt state and should not
|
||||
// be used for future calls.
|
||||
// TODO(agarwal): mark the affected handles and raise errors if they are used.
|
||||
TF_CAPI_EXPORT extern void TFE_ExecutorClearError(TFE_Executor*);
|
||||
|
||||
// Sets a custom Executor for current thread. All nodes created by this thread
|
||||
// will be added to this Executor. It will override current executor.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextSetExecutorForThread(TFE_Context*,
|
||||
TFE_Executor*);
|
||||
|
||||
// Returns the Executor for current thread.
|
||||
TF_CAPI_EXPORT extern TFE_Executor* TFE_ContextGetExecutorForThread(
|
||||
TFE_Context*);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Dynamic cluster API.
|
||||
|
||||
// Update an existing context with a new set of servers defined in a ServerDef
|
||||
// proto. Servers can be added to and removed from the list of remote workers
|
||||
// in the context. New set of servers identified by the ServerDef must be up
|
||||
// when the context is updated.
|
||||
//
|
||||
// This API is for experimental usage and may be subject to change.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextUpdateServerDef(TFE_Context* ctx,
|
||||
int keep_alive_secs,
|
||||
const void* proto,
|
||||
size_t proto_len,
|
||||
TF_Status* status);
|
||||
|
||||
// Checks whether a remote worker is alive or not. This will return true even if
|
||||
// the context doesn't exist on the remote worker.
|
||||
TF_CAPI_EXPORT extern bool TFE_ContextCheckAlive(TFE_Context* ctx,
|
||||
const char* worker_name,
|
||||
TF_Status* status);
|
||||
|
||||
// Sync pending nodes in local executors (including the context default executor
|
||||
// and thread executors) and streaming requests to remote executors, and get the
|
||||
// combined status.
|
||||
TF_CAPI_EXPORT extern void TFE_ContextAsyncWait(TFE_Context* ctx,
|
||||
TF_Status* status);
|
||||
|
||||
// This function will block till the operation that produces `h` has
|
||||
// completed. This is only valid on local TFE_TensorHandles. The pointer
|
||||
// returned will be on the device in which the TFE_TensorHandle resides (so e.g.
|
||||
// for a GPU tensor this will return a pointer to GPU memory). The pointer is
|
||||
// only guaranteed to be valid until TFE_DeleteTensorHandle is called on this
|
||||
// TensorHandle. Only supports POD data types.
|
||||
TF_CAPI_EXPORT extern void* TFE_TensorHandleDevicePointer(TFE_TensorHandle*,
|
||||
TF_Status*);
|
||||
|
||||
// This function will block till the operation that produces `h` has
|
||||
// completed. This is only valid on local TFE_TensorHandles. Returns the size in
|
||||
// bytes of the memory pointed to by the device pointer returned above.
|
||||
TF_CAPI_EXPORT extern size_t TFE_TensorHandleDeviceMemorySize(TFE_TensorHandle*,
|
||||
TF_Status*);
|
||||
|
||||
// Creates a new TensorHandle from memory residing in device_name. Takes
|
||||
// ownership of the memory, and will call deleter to release it after TF
|
||||
// no longer needs it or in case of error.
|
||||
TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_NewTensorHandleFromDeviceMemory(
|
||||
TFE_Context* ctx, const char* device_name, TF_DataType, const int64_t* dims,
|
||||
int num_dims, void* data, size_t len,
|
||||
void (*deallocator)(void* data, size_t len, void* arg),
|
||||
void* deallocator_arg, TF_Status* status);
|
||||
|
||||
// Retrieves the address space (i.e. job, replia, task) of the local host and
|
||||
// saves it in the buffer.
|
||||
TF_CAPI_EXPORT extern void TFE_HostAddressSpace(TFE_Context* ctx,
|
||||
TF_Buffer* buf);
|
||||
|
||||
// APIs for generically dealing with op attributes (e.g. when forwarding them
|
||||
// through custom device implementations).
|
||||
//
|
||||
// TODO(allenl): Currently these are black boxes, but we should have some way to
|
||||
// inspect values. This would let people e.g. copy over most attributes and then
|
||||
// modify some based on their values.
|
||||
|
||||
// A reference to an op's name -> attribute mapping
|
||||
typedef struct TFE_OpAttrs TFE_OpAttrs;
|
||||
|
||||
// Fetch a reference to `op`'s attributes. The returned reference is only valid
|
||||
// while `op` is alive.
|
||||
TF_CAPI_EXPORT extern const TFE_OpAttrs* TFE_OpGetAttrs(const TFE_Op* op);
|
||||
// Add attributes in `attrs` to `op`.
|
||||
//
|
||||
// Does not overwrite or update existing attributes, but adds new ones.
|
||||
TF_CAPI_EXPORT extern void TFE_OpAddAttrs(TFE_Op* op, const TFE_OpAttrs* attrs);
|
||||
|
||||
// Serialize `attrs` as a tensorflow::NameAttrList protocol buffer (into `buf`),
|
||||
// containing the op name and a map of its attributes.
|
||||
TF_CAPI_EXPORT extern void TFE_OpAttrsSerialize(const TFE_OpAttrs* attrs,
|
||||
TF_Buffer* buf,
|
||||
TF_Status* status);
|
||||
|
||||
// Set an op's attribute from a serialized AttrValue protocol buffer.
|
||||
//
|
||||
// Analogous to TF_SetAttrValueProto for building graph operations.
|
||||
TF_CAPI_EXPORT extern void TFE_OpSetAttrValueProto(const TFE_Op* op,
|
||||
const char* attr_name,
|
||||
const void* proto,
|
||||
size_t proto_len,
|
||||
TF_Status* status);
|
||||
|
||||
// TODO(b/166642410): It would be nice, for custom devices and for other users,
|
||||
// to have a non-string representation of devices (TF_Device) extracted from
|
||||
// tensors/ops/etc. and usable in APIs like OpSetDevice/ResetOp/etc.
|
||||
|
||||
#define TFE_CUSTOM_DEVICE_VERSION 3
|
||||
|
||||
// Struct to be filled in
|
||||
typedef struct TFE_CustomDevice {
|
||||
int version = TFE_CUSTOM_DEVICE_VERSION;
|
||||
// Method to copy a tensor to the custom device.
|
||||
TFE_TensorHandle* (*copy_tensor_to_device)(TFE_Context* context,
|
||||
TFE_TensorHandle* tensor,
|
||||
TF_Status* status,
|
||||
void* device_info) = nullptr;
|
||||
|
||||
// Method to copy a tensor from the custom device to a target device.
|
||||
TFE_TensorHandle* (*copy_tensor_from_device)(TFE_Context* context,
|
||||
TFE_TensorHandle* tensor,
|
||||
const char* target_device_name,
|
||||
TF_Status* status,
|
||||
void* device_info);
|
||||
|
||||
// Method to execute an operation.
|
||||
//
|
||||
// Arguments provide enough information to reconstruct the original `TFE_Op`,
|
||||
// or construct a transformed version, by inspecting the passed `op`.
|
||||
//
|
||||
// TFE_OpGetDevice(op) records the original placement of the operation. It may
|
||||
// be an empty string if no device was explicitly requested, but will
|
||||
// otherwise be the name of this custom device. Ops are placed onto a custom
|
||||
// device if any of their inputs are on that custom device, but custom devices
|
||||
// are free to set a bad status in order to require explicit placement.
|
||||
void (*execute)(const TFE_Op* op, int* num_outputs,
|
||||
TFE_TensorHandle** outputs, TF_Status* s, void* device_info);
|
||||
|
||||
// Method to delete a device.
|
||||
void (*delete_device)(void* device_info);
|
||||
} TFE_CustomDevice;
|
||||
|
||||
// Registers a custom device for use with eager execution.
|
||||
//
|
||||
// Eager operations may be placed on this device, e.g. `with
|
||||
// tf.device("CUSTOM"):` from Python if `device_name` for this call is
|
||||
// "/job:localhost/replica:0/task:0/device:CUSTOM:0".
|
||||
//
|
||||
// The custom device defines copy operations for moving TensorHandles on and
|
||||
// off, and an an execution operation for named operations. Often execution will
|
||||
// simply wrap op execution on one or more physical devices.
|
||||
//
|
||||
// device_info is an opaque caller-defined type stored with the custom device
|
||||
// which is passed to the functions referenced in the TFE_CustomDevice struct
|
||||
// `device` (execute, delete_device, etc.). It can for example contain the
|
||||
// names of wrapped devices.
|
||||
//
|
||||
// There are currently no graph semantics implemented for registered custom
|
||||
// devices, so executing tf.functions which contain operations placed on custom
|
||||
// devices will fail.
|
||||
//
|
||||
// `device_name` must not name an existing physical or custom device. It must
|
||||
// follow the format:
|
||||
//
|
||||
// /job:<name>/replica:<replica>/task:<task>/device:<type>:<device_num>
|
||||
//
|
||||
// If the device is successfully registered, `status` is set to TF_OK. Otherwise
|
||||
// the device is not usable. In case of a bad status, `device.delete_device` is
|
||||
// still called on `device_info` (i.e. the caller does not retain ownership).
|
||||
//
|
||||
// This API is highly experimental, and in particular is expected to change when
|
||||
// it starts supporting operations with attributes and when tf.function support
|
||||
// is added.
|
||||
TF_CAPI_EXPORT extern void TFE_RegisterCustomDevice(TFE_Context* ctx,
|
||||
TFE_CustomDevice device,
|
||||
const char* device_name,
|
||||
void* device_info,
|
||||
TF_Status* status);
|
||||
|
||||
TF_CAPI_EXPORT extern void TFE_ContextGetFunctionDef(TFE_Context* ctx,
|
||||
const char* function_name,
|
||||
TF_Buffer* buf,
|
||||
TF_Status* status);
|
||||
|
||||
// Allocate and return a new Tensor on the host.
|
||||
//
|
||||
// The caller must set the Tensor values by writing them to the pointer returned
|
||||
// by TF_TensorData with length TF_TensorByteSize.
|
||||
TF_CAPI_EXPORT extern TF_Tensor* TFE_AllocateHostTensor(TFE_Context* ctx,
|
||||
TF_DataType dtype,
|
||||
const int64_t* dims,
|
||||
int num_dims,
|
||||
TF_Status* status);
|
||||
|
||||
// Given a Tensor, wrap it with a TensorHandle
|
||||
//
|
||||
// Similar to TFE_NewTensorHandle, but includes a pointer to the TFE_Context.
|
||||
// The context should be identical to that of the Tensor.
|
||||
TF_CAPI_EXPORT TFE_TensorHandle* TFE_NewTensorHandleFromTensor(
|
||||
TFE_Context* ctx, TF_Tensor* t, TF_Status* status);
|
||||
|
||||
// Create a packed TensorHandle with the given list of TensorHandles.
|
||||
// If `handles` are on the same device, assign the same device to the packed
|
||||
// handle; if `handles` are on different deivces, assign a CompositeDevice to
|
||||
// it.
|
||||
TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_CreatePackedTensorHandle(
|
||||
TFE_Context* ctx, TFE_TensorHandle** handles, int* num_handles,
|
||||
TF_Status* status);
|
||||
|
||||
// Configure soft device placement policy for the eager executor. Note this
|
||||
// policy is applied to any subsequent op executions.
|
||||
TF_CAPI_EXPORT void TFE_ContextSetSoftDevicePlacement(TFE_Context* ctx,
|
||||
unsigned char enable,
|
||||
TF_Status* status);
|
||||
|
||||
// Configure device placement policy logging for the eager executor. Note this
|
||||
// policy is applied to any subsequent op executions.
|
||||
TF_CAPI_EXPORT void TFE_ContextSetLogDevicePlacement(TFE_Context* ctx,
|
||||
unsigned char enable,
|
||||
TF_Status* status);
|
||||
|
||||
// Returns the device type of the operation that produced `h`.
|
||||
TF_CAPI_EXPORT extern const char* TFE_TensorHandleDeviceType(
|
||||
TFE_TensorHandle* h, TF_Status* status);
|
||||
|
||||
// Returns the device ID of the operation that produced `h`.
|
||||
TF_CAPI_EXPORT extern int TFE_TensorHandleDeviceID(TFE_TensorHandle* h,
|
||||
TF_Status* status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif // TENSORFLOW_C_EAGER_C_API_EXPERIMENTAL_H_
|
||||
Generated
Vendored
Executable
+40
@@ -0,0 +1,40 @@
|
||||
/* Copyright 2020 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef TENSORFLOW_C_EAGER_DLPACK_H_
|
||||
#define TENSORFLOW_C_EAGER_DLPACK_H_
|
||||
|
||||
#include "tensorflow/c/eager/c_api.h"
|
||||
|
||||
namespace tensorflow {
|
||||
|
||||
// PyCapsule name for DLPack Tensor
|
||||
const char* const kDlTensorCapsuleName = "dltensor";
|
||||
|
||||
// Converts eager tensor handle to DLPack (DLManagedTensor*), and return the
|
||||
// void* for further PyCapsule construction.
|
||||
TF_CAPI_EXPORT extern void* TFE_HandleToDLPack(TFE_TensorHandle* h,
|
||||
TF_Status* status);
|
||||
|
||||
// Converts DLPack (DLManagedTensor*) to eager tensor handle.
|
||||
TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_HandleFromDLPack(void* dlm,
|
||||
TF_Status* status,
|
||||
TFE_Context* ctx);
|
||||
|
||||
// Calls the destructor of DLManagedTensor, used in the destructor of PyCapsule.
|
||||
TF_CAPI_EXPORT extern void TFE_CallDLManagedTensorDeleter(void* dlm_ptr);
|
||||
} // namespace tensorflow
|
||||
|
||||
#endif // TENSORFLOW_C_EAGER_DLPACK_H_
|
||||
Generated
Vendored
Executable
+73
@@ -0,0 +1,73 @@
|
||||
/* Copyright 2020 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef TENSORFLOW_C_TENSOR_INTERFACE_H_
|
||||
#define TENSORFLOW_C_TENSOR_INTERFACE_H_
|
||||
|
||||
#include "tensorflow/core/framework/types.pb.h"
|
||||
#include "tensorflow/core/platform/status.h"
|
||||
|
||||
namespace tensorflow {
|
||||
|
||||
// Abstract interface to a Tensor.
|
||||
//
|
||||
// This allows us to hide concrete implementations of Tensor from header
|
||||
// files. The interface lists the common functionality that must be provided by
|
||||
// any concrete implementation. However, in cases where the true concrete class
|
||||
// is needed a static_cast can be applied.
|
||||
class AbstractTensorInterface {
|
||||
public:
|
||||
// Release any underlying resources, including the interface object.
|
||||
virtual void Release() = 0;
|
||||
|
||||
// Returns tensor dtype.
|
||||
virtual DataType Type() const = 0;
|
||||
// Returns number of dimensions.
|
||||
virtual int NumDims() const = 0;
|
||||
// Returns size of specified dimension
|
||||
virtual int64_t Dim(int dim_index) const = 0;
|
||||
// Returns number of elements across all dimensions.
|
||||
virtual int64_t NumElements() const = 0;
|
||||
// Return size in bytes of the Tensor
|
||||
virtual size_t ByteSize() const = 0;
|
||||
// Returns a pointer to tensor data
|
||||
virtual void* Data() const = 0;
|
||||
|
||||
// Returns if the tensor is aligned
|
||||
virtual bool IsAligned() const = 0;
|
||||
// Returns if their is sole ownership of this Tensor and thus it can be moved.
|
||||
virtual bool CanMove() const = 0;
|
||||
|
||||
protected:
|
||||
virtual ~AbstractTensorInterface() {}
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
struct AbstractTensorInterfaceDeleter {
|
||||
void operator()(AbstractTensorInterface* p) const {
|
||||
if (p != nullptr) {
|
||||
p->Release();
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
using AbstractTensorPtr =
|
||||
std::unique_ptr<AbstractTensorInterface,
|
||||
internal::AbstractTensorInterfaceDeleter>;
|
||||
|
||||
} // namespace tensorflow
|
||||
|
||||
#endif // TENSORFLOW_C_TENSOR_INTERFACE_H_
|
||||
Generated
Vendored
Executable
+39
@@ -0,0 +1,39 @@
|
||||
/* Copyright 2019 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
#ifndef TENSORFLOW_C_TF_ATTRTYPE_H_
|
||||
#define TENSORFLOW_C_TF_ATTRTYPE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// TF_AttrType describes the type of the value of an attribute on an operation.
|
||||
typedef enum TF_AttrType {
|
||||
TF_ATTR_STRING = 0,
|
||||
TF_ATTR_INT = 1,
|
||||
TF_ATTR_FLOAT = 2,
|
||||
TF_ATTR_BOOL = 3,
|
||||
TF_ATTR_TYPE = 4,
|
||||
TF_ATTR_SHAPE = 5,
|
||||
TF_ATTR_TENSOR = 6,
|
||||
TF_ATTR_PLACEHOLDER = 7,
|
||||
TF_ATTR_FUNC = 8,
|
||||
} TF_AttrType;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif // TENSORFLOW_C_TF_ATTRTYPE_H_
|
||||
Generated
Vendored
Executable
+83
@@ -0,0 +1,83 @@
|
||||
/* Copyright 2019 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef TENSORFLOW_C_TF_DATATYPE_H_
|
||||
#define TENSORFLOW_C_TF_DATATYPE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
// Macro to control visibility of exported symbols in the shared library (.so,
|
||||
// .dylib, .dll).
|
||||
// This duplicates the TF_EXPORT macro definition in
|
||||
// tensorflow/core/platform/macros.h in order to keep this .h file independent
|
||||
// of any other includes.
|
||||
#ifdef SWIG
|
||||
#define TF_CAPI_EXPORT
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
#ifdef TF_COMPILE_LIBRARY
|
||||
#define TF_CAPI_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define TF_CAPI_EXPORT __declspec(dllimport)
|
||||
#endif // TF_COMPILE_LIBRARY
|
||||
#else
|
||||
#define TF_CAPI_EXPORT __attribute__((visibility("default")))
|
||||
#endif // _WIN32
|
||||
#endif // SWIG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// TF_DataType holds the type for a scalar value. E.g., one slot in a tensor.
|
||||
// The enum values here are identical to corresponding values in types.proto.
|
||||
typedef enum TF_DataType {
|
||||
TF_FLOAT = 1,
|
||||
TF_DOUBLE = 2,
|
||||
TF_INT32 = 3, // Int32 tensors are always in 'host' memory.
|
||||
TF_UINT8 = 4,
|
||||
TF_INT16 = 5,
|
||||
TF_INT8 = 6,
|
||||
TF_STRING = 7,
|
||||
TF_COMPLEX64 = 8, // Single-precision complex
|
||||
TF_COMPLEX = 8, // Old identifier kept for API backwards compatibility
|
||||
TF_INT64 = 9,
|
||||
TF_BOOL = 10,
|
||||
TF_QINT8 = 11, // Quantized int8
|
||||
TF_QUINT8 = 12, // Quantized uint8
|
||||
TF_QINT32 = 13, // Quantized int32
|
||||
TF_BFLOAT16 = 14, // Float32 truncated to 16 bits. Only for cast ops.
|
||||
TF_QINT16 = 15, // Quantized int16
|
||||
TF_QUINT16 = 16, // Quantized uint16
|
||||
TF_UINT16 = 17,
|
||||
TF_COMPLEX128 = 18, // Double-precision complex
|
||||
TF_HALF = 19,
|
||||
TF_RESOURCE = 20,
|
||||
TF_VARIANT = 21,
|
||||
TF_UINT32 = 22,
|
||||
TF_UINT64 = 23,
|
||||
} TF_DataType;
|
||||
|
||||
// TF_DataTypeSize returns the sizeof() for the underlying type corresponding
|
||||
// to the given TF_DataType enum value. Returns 0 for variable length types
|
||||
// (eg. TF_STRING) or on failure.
|
||||
TF_CAPI_EXPORT extern size_t TF_DataTypeSize(TF_DataType dt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif // TENSORFLOW_C_TF_DATATYPE_H_
|
||||
Generated
Vendored
Executable
+34
@@ -0,0 +1,34 @@
|
||||
/* Copyright 2019 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef TENSORFLOW_C_TF_FILE_STATISTICS_H_
|
||||
#define TENSORFLOW_C_TF_FILE_STATISTICS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct TF_FileStatistics {
|
||||
// The length of the file in bytes.
|
||||
int64_t length;
|
||||
// The last modified time in nanoseconds.
|
||||
int64_t mtime_nsec;
|
||||
// Whether the name refers to a directory.
|
||||
bool is_directory;
|
||||
} TF_FileStatistics;
|
||||
|
||||
// TODO(mihaimaruseac): `tensorflow::FileStatistics` from
|
||||
// `core/platform/file_statistics.h` is a duplicate of this so maybe try to
|
||||
// remove duplication later?
|
||||
|
||||
#endif // TENSORFLOW_C_TF_FILE_STATISTICS_H_
|
||||
Generated
Vendored
Executable
+94
@@ -0,0 +1,94 @@
|
||||
/* Copyright 2019 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef TENSORFLOW_C_TF_STATUS_H_
|
||||
#define TENSORFLOW_C_TF_STATUS_H_
|
||||
|
||||
#ifdef SWIG
|
||||
#define TF_CAPI_EXPORT
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
#ifdef TF_COMPILE_LIBRARY
|
||||
#define TF_CAPI_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define TF_CAPI_EXPORT __declspec(dllimport)
|
||||
#endif // TF_COMPILE_LIBRARY
|
||||
#else
|
||||
#define TF_CAPI_EXPORT __attribute__((visibility("default")))
|
||||
#endif // _WIN32
|
||||
#endif // SWIG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct TF_Status TF_Status;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// TF_Code holds an error code. The enum values here are identical to
|
||||
// corresponding values in error_codes.proto.
|
||||
typedef enum TF_Code {
|
||||
TF_OK = 0,
|
||||
TF_CANCELLED = 1,
|
||||
TF_UNKNOWN = 2,
|
||||
TF_INVALID_ARGUMENT = 3,
|
||||
TF_DEADLINE_EXCEEDED = 4,
|
||||
TF_NOT_FOUND = 5,
|
||||
TF_ALREADY_EXISTS = 6,
|
||||
TF_PERMISSION_DENIED = 7,
|
||||
TF_UNAUTHENTICATED = 16,
|
||||
TF_RESOURCE_EXHAUSTED = 8,
|
||||
TF_FAILED_PRECONDITION = 9,
|
||||
TF_ABORTED = 10,
|
||||
TF_OUT_OF_RANGE = 11,
|
||||
TF_UNIMPLEMENTED = 12,
|
||||
TF_INTERNAL = 13,
|
||||
TF_UNAVAILABLE = 14,
|
||||
TF_DATA_LOSS = 15,
|
||||
} TF_Code;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Return a new status object.
|
||||
TF_CAPI_EXPORT extern TF_Status* TF_NewStatus(void);
|
||||
|
||||
// Delete a previously created status object.
|
||||
TF_CAPI_EXPORT extern void TF_DeleteStatus(TF_Status*);
|
||||
|
||||
// Record <code, msg> in *s. Any previous information is lost.
|
||||
// A common use is to clear a status: TF_SetStatus(s, TF_OK, "");
|
||||
TF_CAPI_EXPORT extern void TF_SetStatus(TF_Status* s, TF_Code code,
|
||||
const char* msg);
|
||||
|
||||
// Convert from an I/O error code (e.g., errno) to a TF_Status value.
|
||||
// Any previous information is lost. Prefer to use this instead of TF_SetStatus
|
||||
// when the error comes from I/O operations.
|
||||
TF_CAPI_EXPORT extern void TF_SetStatusFromIOError(TF_Status* s, int error_code,
|
||||
const char* context);
|
||||
|
||||
// Return the code record in *s.
|
||||
TF_CAPI_EXPORT extern TF_Code TF_GetCode(const TF_Status* s);
|
||||
|
||||
// Return a pointer to the (null-terminated) error message in *s. The
|
||||
// return value points to memory that is only usable until the next
|
||||
// mutation to *s. Always returns an empty string if TF_GetCode(s) is
|
||||
// TF_OK.
|
||||
TF_CAPI_EXPORT extern const char* TF_Message(const TF_Status* s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif // TENSORFLOW_C_TF_STATUS_H_
|
||||
Generated
Vendored
Executable
+169
@@ -0,0 +1,169 @@
|
||||
/* Copyright 2019 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef TENSORFLOW_C_TF_TENSOR_H_
|
||||
#define TENSORFLOW_C_TF_TENSOR_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "tensorflow/c/c_api_macros.h"
|
||||
#include "tensorflow/c/tf_datatype.h"
|
||||
#include "tensorflow/c/tf_status.h"
|
||||
|
||||
// Macro to control visibility of exported symbols in the shared library (.so,
|
||||
// .dylib, .dll).
|
||||
// This duplicates the TF_EXPORT macro definition in
|
||||
// tensorflow/core/platform/macros.h in order to keep this .h file independent
|
||||
// of any other includes.
|
||||
#ifdef SWIG
|
||||
#define TF_CAPI_EXPORT
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
#ifdef TF_COMPILE_LIBRARY
|
||||
#define TF_CAPI_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define TF_CAPI_EXPORT __declspec(dllimport)
|
||||
#endif // TF_COMPILE_LIBRARY
|
||||
#else
|
||||
#define TF_CAPI_EXPORT __attribute__((visibility("default")))
|
||||
#endif // _WIN32
|
||||
#endif // SWIG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Allocator Attributes used for tensor allocation.
|
||||
typedef struct TF_AllocatorAttributes {
|
||||
size_t struct_size;
|
||||
// Set boolean to 1 for CPU allocation, else 0.
|
||||
TF_Bool on_host;
|
||||
} TF_AllocatorAttributes;
|
||||
|
||||
#define TF_ALLOCATOR_ATTRIBUTES_STRUCT_SIZE \
|
||||
TF_OFFSET_OF_END(TF_AllocatorAttributes, on_host)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// TF_Tensor holds a multi-dimensional array of elements of a single data type.
|
||||
// For all types other than TF_STRING, the data buffer stores elements
|
||||
// in row major order. E.g. if data is treated as a vector of TF_DataType:
|
||||
//
|
||||
// element 0: index (0, ..., 0)
|
||||
// element 1: index (0, ..., 1)
|
||||
// ...
|
||||
//
|
||||
// The format for TF_STRING tensors is:
|
||||
// start_offset: array[uint64]
|
||||
// data: byte[...]
|
||||
//
|
||||
// The string length (as a varint, start_offset[i + 1] - start_offset[i]),
|
||||
// followed by the contents of the string is encoded at data[start_offset[i]].
|
||||
// TF_StringEncode and TF_StringDecode facilitate this encoding.
|
||||
|
||||
typedef struct TF_Tensor TF_Tensor;
|
||||
|
||||
// Return a new tensor that holds the bytes data[0,len-1].
|
||||
//
|
||||
// The data will be deallocated by a subsequent call to TF_DeleteTensor via:
|
||||
// (*deallocator)(data, len, deallocator_arg)
|
||||
// Clients must provide a custom deallocator function so they can pass in
|
||||
// memory managed by something like numpy.
|
||||
//
|
||||
// May return NULL (and invoke the deallocator) if the provided data buffer
|
||||
// (data, len) is inconsistent with a tensor of the given TF_DataType
|
||||
// and the shape specified by (dima, num_dims).
|
||||
TF_CAPI_EXPORT extern TF_Tensor* TF_NewTensor(
|
||||
TF_DataType, const int64_t* dims, int num_dims, void* data, size_t len,
|
||||
void (*deallocator)(void* data, size_t len, void* arg),
|
||||
void* deallocator_arg);
|
||||
|
||||
// Allocate and return a new Tensor.
|
||||
//
|
||||
// This function is an alternative to TF_NewTensor and should be used when
|
||||
// memory is allocated to pass the Tensor to the C API. The allocated memory
|
||||
// satisfies TensorFlow's memory alignment preferences and should be preferred
|
||||
// over calling malloc and free.
|
||||
//
|
||||
// The caller must set the Tensor values by writing them to the pointer returned
|
||||
// by TF_TensorData with length TF_TensorByteSize.
|
||||
TF_CAPI_EXPORT extern TF_Tensor* TF_AllocateTensor(TF_DataType,
|
||||
const int64_t* dims,
|
||||
int num_dims, size_t len);
|
||||
|
||||
// Deletes `tensor` and returns a new TF_Tensor with the same content if
|
||||
// possible. Returns nullptr and leaves `tensor` untouched if not.
|
||||
TF_CAPI_EXPORT extern TF_Tensor* TF_TensorMaybeMove(TF_Tensor* tensor);
|
||||
|
||||
// Destroy a tensor.
|
||||
TF_CAPI_EXPORT extern void TF_DeleteTensor(TF_Tensor*);
|
||||
|
||||
// Return the type of a tensor element.
|
||||
TF_CAPI_EXPORT extern TF_DataType TF_TensorType(const TF_Tensor*);
|
||||
|
||||
// Return the number of dimensions that the tensor has.
|
||||
TF_CAPI_EXPORT extern int TF_NumDims(const TF_Tensor*);
|
||||
|
||||
// Return the length of the tensor in the "dim_index" dimension.
|
||||
// REQUIRES: 0 <= dim_index < TF_NumDims(tensor)
|
||||
TF_CAPI_EXPORT extern int64_t TF_Dim(const TF_Tensor* tensor, int dim_index);
|
||||
|
||||
// Return the size of the underlying data in bytes.
|
||||
TF_CAPI_EXPORT extern size_t TF_TensorByteSize(const TF_Tensor*);
|
||||
|
||||
// Return a pointer to the underlying data buffer.
|
||||
TF_CAPI_EXPORT extern void* TF_TensorData(const TF_Tensor*);
|
||||
|
||||
// Returns the number of elements in the tensor.
|
||||
TF_CAPI_EXPORT extern int64_t TF_TensorElementCount(const TF_Tensor* tensor);
|
||||
|
||||
// Copy the internal data representation of `from` to `to`. `new_dims` and
|
||||
// `num_new_dims` specify the new shape of the `to` tensor, `type` specifies its
|
||||
// data type. On success, *status is set to TF_OK and the two tensors share the
|
||||
// same data buffer.
|
||||
//
|
||||
// This call requires that the `from` tensor and the given type and shape (dims
|
||||
// and num_dims) are "compatible" (i.e. they occupy the same number of bytes).
|
||||
// Specifically, given from_type_size = TF_DataTypeSize(TF_TensorType(from)):
|
||||
//
|
||||
// ShapeElementCount(dims, num_dims) * TF_DataTypeSize(type)
|
||||
//
|
||||
// must equal
|
||||
//
|
||||
// TF_TensorElementCount(from) * from_type_size
|
||||
//
|
||||
// where TF_ShapeElementCount would be the number of elements in a tensor with
|
||||
// the given shape.
|
||||
//
|
||||
// In addition, this function requires:
|
||||
// * TF_DataTypeSize(TF_TensorType(from)) != 0
|
||||
// * TF_DataTypeSize(type) != 0
|
||||
//
|
||||
// If any of the requirements are not met, *status is set to
|
||||
// TF_INVALID_ARGUMENT.
|
||||
TF_CAPI_EXPORT extern void TF_TensorBitcastFrom(const TF_Tensor* from,
|
||||
TF_DataType type, TF_Tensor* to,
|
||||
const int64_t* new_dims,
|
||||
int num_new_dims,
|
||||
TF_Status* status);
|
||||
|
||||
// Returns bool iff this tensor is aligned.
|
||||
TF_CAPI_EXPORT extern bool TF_TensorIsAligned(const TF_Tensor*);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif // TENSORFLOW_C_TF_TENSOR_H_
|
||||
Generated
Vendored
Executable
+20
@@ -0,0 +1,20 @@
|
||||
/* Copyright 2020 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
#ifndef TENSORFLOW_C_TF_TSTRING_H_
|
||||
#define TENSORFLOW_C_TF_TSTRING_H_
|
||||
|
||||
#include "tensorflow/core/platform/ctstring.h"
|
||||
|
||||
#endif // THIRD_PARTY_TENSORFLOW_C_TF_TSTRING_H_
|
||||
Generated
Vendored
Executable
+120
@@ -0,0 +1,120 @@
|
||||
/* Copyright 2019 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef TENSORFLOW_CORE_PLATFORM_CTSTRING_H_
|
||||
#define TENSORFLOW_CORE_PLATFORM_CTSTRING_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "tensorflow/core/platform/ctstring_internal.h"
|
||||
|
||||
// Initialize a new tstring. This must be called before using any function
|
||||
// below.
|
||||
inline void TF_TString_Init(TF_TString *str);
|
||||
// Deallocate a tstring.
|
||||
inline void TF_TString_Dealloc(TF_TString *str);
|
||||
|
||||
// Resizes `str' to `new_size'. This function will appropriately grow or shrink
|
||||
// the string buffer to fit a `new_size' string. Grown regions of the string
|
||||
// will be initialized with `c'.
|
||||
inline char *TF_TString_Resize(TF_TString *str, size_t new_size, char c);
|
||||
// Similar to TF_TString_Resize, except the newly allocated regions will remain
|
||||
// uninitialized. This is useful if you plan on overwriting the newly grown
|
||||
// regions immediately after allocation; doing so will elide a superfluous
|
||||
// initialization of the new buffer.
|
||||
inline char *TF_TString_ResizeUninitialized(TF_TString *str, size_t new_size);
|
||||
// Reserves a string buffer with a capacity of at least `new_cap'.
|
||||
// ResizeUninitialized will not change the size, or the contents of the existing
|
||||
// string. This is useful if you have a rough idea of `str's upperbound in
|
||||
// size, and want to avoid allocations as you append to `str'. It should not be
|
||||
// considered safe to write in the region between size and capacity; explicitly
|
||||
// resize before doing so.
|
||||
inline void TF_TString_Reserve(TF_TString *str, size_t new_cap);
|
||||
|
||||
// Returns the size of the string.
|
||||
inline size_t TF_TString_GetSize(const TF_TString *str);
|
||||
// Returns the capacity of the string buffer. It should not be considered safe
|
||||
// to write in the region between size and capacity---call Resize or
|
||||
// ResizeUninitialized before doing so.
|
||||
inline size_t TF_TString_GetCapacity(const TF_TString *str);
|
||||
// Returns the underlying type of the tstring:
|
||||
// TF_TSTR_SMALL:
|
||||
// Small string optimization; the contents of strings
|
||||
// less than 22-bytes are stored in the TF_TString struct. This avoids any
|
||||
// heap allocations.
|
||||
// TF_TSTR_LARGE:
|
||||
// Heap allocated string.
|
||||
// TF_TSTR_OFFSET: (currently unused)
|
||||
// An offset defined string. The string buffer begins at an internally
|
||||
// defined little-endian offset from `str'; i.e. GetDataPointer() = str +
|
||||
// offset. This type is useful for memory mapping or reading string tensors
|
||||
// directly from file, without the need to deserialize the data. For
|
||||
// security reasons, it is imperative that OFFSET based string tensors are
|
||||
// validated before use, or are from a trusted source.
|
||||
// TF_TSTR_VIEW:
|
||||
// A view into an unowned character string.
|
||||
//
|
||||
// NOTE:
|
||||
// VIEW and OFFSET types are immutable, so any modifcation via Append,
|
||||
// AppendN, or GetMutableDataPointer of a VIEW/OFFSET based tstring will
|
||||
// result in a conversion to an owned type (SMALL/LARGE).
|
||||
inline TF_TString_Type TF_TString_GetType(const TF_TString *str);
|
||||
|
||||
// Returns a const char pointer to the start of the underlying string. The
|
||||
// underlying character buffer may not be null-terminated.
|
||||
inline const char *TF_TString_GetDataPointer(const TF_TString *str);
|
||||
// Returns a char pointer to a mutable representation of the underlying string.
|
||||
// In the case of VIEW and OFFSET types, `src' is converted to an owned type
|
||||
// (SMALL/LARGE). The underlying character buffer may not be null-terminated.
|
||||
inline char *TF_TString_GetMutableDataPointer(TF_TString *str);
|
||||
|
||||
// Sets `dst' as a VIEW type to `src'. `dst' will not take ownership of `src'.
|
||||
// It is the user's responsibility to ensure that the lifetime of `src' exceeds
|
||||
// `dst'. Any mutations to `dst' via Append, AppendN, or GetMutableDataPointer,
|
||||
// will result in a copy into an owned SMALL or LARGE type, and will not modify
|
||||
// `src'.
|
||||
inline void TF_TString_AssignView(TF_TString *dst, const char *src,
|
||||
size_t size);
|
||||
|
||||
// Appends `src' onto `dst'. If `dst' is a VIEW or OFFSET type, it will first
|
||||
// be converted to an owned LARGE or SMALL type. `dst' should not point to
|
||||
// memory owned by `src'.
|
||||
inline void TF_TString_Append(TF_TString *dst, const TF_TString *src);
|
||||
inline void TF_TString_AppendN(TF_TString *dst, const char *src, size_t size);
|
||||
|
||||
// Copy/Move/Assign semantics
|
||||
//
|
||||
// | src | dst | complexity
|
||||
// Copy | * | SMALL/LARGE | fixed/O(size)
|
||||
// Assign | SMALL | SMALL | fixed
|
||||
// Assign | OFFSET | VIEW | fixed
|
||||
// Assign | VIEW | VIEW | fixed
|
||||
// Assign | LARGE | LARGE | O(size)
|
||||
// Move | * | same as src | fixed
|
||||
|
||||
// Copies `src' to `dst'. `dst' will be an owned type (SMALL/LARGE). `src'
|
||||
// should not point to memory owned by `dst'.
|
||||
inline void TF_TString_Copy(TF_TString *dst, const char *src, size_t size);
|
||||
// Assigns a `src' tstring to `dst'. An OFFSET `src' type will yield a `VIEW'
|
||||
// `dst'. LARGE `src' types will be copied to a new buffer; all other `src'
|
||||
// types will incur a fixed cost.
|
||||
inline void TF_TString_Assign(TF_TString *dst, const TF_TString *src);
|
||||
// Moves a `src' tstring to `dst'. Moving a LARGE `src' to `dst' will result in
|
||||
// a valid but unspecified `src'. This function incurs a fixed cost for all
|
||||
// inputs.
|
||||
inline void TF_TString_Move(TF_TString *dst, TF_TString *src);
|
||||
|
||||
#endif // TENSORFLOW_CORE_PLATFORM_CTSTRING_H_
|
||||
Generated
Vendored
Executable
+449
@@ -0,0 +1,449 @@
|
||||
/* Copyright 2019 The TensorFlow Authors. 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.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef TENSORFLOW_CORE_PLATFORM_CTSTRING_INTERNAL_H_
|
||||
#define TENSORFLOW_CORE_PLATFORM_CTSTRING_INTERNAL_H_
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
|
||||
__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
|
||||
defined(_WIN32)
|
||||
#define TF_TSTRING_LITTLE_ENDIAN 1
|
||||
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
|
||||
__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define TF_TSTRING_LITTLE_ENDIAN 0
|
||||
#else
|
||||
#error "Unable to detect endianness."
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || \
|
||||
(defined(__GNUC__) && \
|
||||
((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ >= 5))
|
||||
static inline uint32_t TF_swap32(uint32_t host_int) {
|
||||
return __builtin_bswap32(host_int);
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
static inline uint32_t TF_swap32(uint32_t host_int) {
|
||||
return _byteswap_ulong(host_int);
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
static inline uint32_t TF_swap32(uint32_t host_int) {
|
||||
return OSSwapInt32(host_int);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline uint32_t TF_swap32(uint32_t host_int) {
|
||||
#if defined(__GLIBC__)
|
||||
return bswap_32(host_int);
|
||||
#else // defined(__GLIBC__)
|
||||
return (((host_int & uint32_t{0xFF}) << 24) |
|
||||
((host_int & uint32_t{0xFF00}) << 8) |
|
||||
((host_int & uint32_t{0xFF0000}) >> 8) |
|
||||
((host_int & uint32_t{0xFF000000}) >> 24));
|
||||
#endif // defined(__GLIBC__)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TF_TSTRING_LITTLE_ENDIAN
|
||||
#define TF_le32toh(x) TF_swap32(x)
|
||||
#else // TF_TSTRING_LITTLE_ENDIAN
|
||||
#define TF_le32toh(x) x
|
||||
#endif // TF_TSTRING_LITTLE_ENDIAN
|
||||
|
||||
static inline size_t TF_align16(size_t i) { return (i + 0xF) & ~0xF; }
|
||||
|
||||
static inline size_t TF_max(size_t a, size_t b) { return a > b ? a : b; }
|
||||
static inline size_t TF_min(size_t a, size_t b) { return a < b ? a : b; }
|
||||
|
||||
typedef enum TF_TString_Type { // NOLINT
|
||||
TF_TSTR_SMALL = 0x00,
|
||||
TF_TSTR_LARGE = 0x01,
|
||||
TF_TSTR_OFFSET = 0x02,
|
||||
TF_TSTR_VIEW = 0x03,
|
||||
TF_TSTR_TYPE_MASK = 0x03
|
||||
} TF_TString_Type;
|
||||
|
||||
typedef struct TF_TString_Large { // NOLINT
|
||||
size_t size;
|
||||
size_t cap;
|
||||
char *ptr;
|
||||
} TF_TString_Large;
|
||||
|
||||
typedef struct TF_TString_Offset { // NOLINT
|
||||
uint32_t size;
|
||||
uint32_t offset;
|
||||
uint32_t count;
|
||||
} TF_TString_Offset;
|
||||
|
||||
typedef struct TF_TString_View { // NOLINT
|
||||
size_t size;
|
||||
const char *ptr;
|
||||
} TF_TString_View;
|
||||
|
||||
typedef struct TF_TString_Raw { // NOLINT
|
||||
uint8_t raw[24];
|
||||
} TF_TString_Raw;
|
||||
|
||||
typedef union TF_TString_Union { // NOLINT
|
||||
TF_TString_Large large;
|
||||
TF_TString_Offset offset;
|
||||
TF_TString_View view;
|
||||
TF_TString_Raw raw;
|
||||
} TF_TString_Union;
|
||||
|
||||
enum {
|
||||
TF_TString_SmallCapacity =
|
||||
(sizeof(TF_TString_Union) - sizeof(/* null delim */ char) -
|
||||
sizeof(/* uint8_t size */ uint8_t)),
|
||||
};
|
||||
|
||||
typedef struct TF_TString_Small { // NOLINT
|
||||
uint8_t size;
|
||||
char str[TF_TString_SmallCapacity + sizeof(/* null delim */ char)];
|
||||
} TF_TString_Small;
|
||||
|
||||
typedef struct TF_TString { // NOLINT
|
||||
union {
|
||||
// small conflicts with '#define small char' in RpcNdr.h for MSVC, so we use
|
||||
// smll instead.
|
||||
TF_TString_Small smll;
|
||||
TF_TString_Large large;
|
||||
TF_TString_Offset offset;
|
||||
TF_TString_View view;
|
||||
TF_TString_Raw raw;
|
||||
} u;
|
||||
} TF_TString;
|
||||
|
||||
// TODO(dero): Fix for OSS, and add C only build test.
|
||||
// _Static_assert(CHAR_BIT == 8);
|
||||
// _Static_assert(sizeof(TF_TString) == 24);
|
||||
|
||||
static inline TF_TString_Type TF_TString_GetType(const TF_TString *str) {
|
||||
return (TF_TString_Type)(str->u.raw.raw[0] & TF_TSTR_TYPE_MASK); // NOLINT
|
||||
}
|
||||
|
||||
// XXX(dero): For the big-endian case, this function could potentially be more
|
||||
// performant and readable by always storing the string size as little-endian
|
||||
// and always byte-swapping on big endian, resulting in a simple 'bswap'+'shr'
|
||||
// (for architectures that have a bswap op).
|
||||
static inline size_t TF_TString_ToActualSizeT(size_t size) {
|
||||
#if TF_TSTRING_LITTLE_ENDIAN
|
||||
return size >> 2;
|
||||
#else // TF_TSTRING_LITTLE_ENDIAN
|
||||
// 0xFF000000 or 0xFF00000000000000 depending on platform
|
||||
static const size_t mask = ~((~(size_t)0) >> 8);
|
||||
|
||||
return (((mask << 2) & size) >> 2) | (~mask & size);
|
||||
#endif // TF_TSTRING_LITTLE_ENDIAN
|
||||
}
|
||||
|
||||
static inline size_t TF_TString_ToInternalSizeT(size_t size,
|
||||
TF_TString_Type type) {
|
||||
#if TF_TSTRING_LITTLE_ENDIAN
|
||||
return (size << 2) | type;
|
||||
#else // TF_TSTRING_LITTLE_ENDIAN
|
||||
// 0xFF000000 or 0xFF00000000000000 depending on platform
|
||||
static const size_t mask = ~((~(size_t)0) >> 8);
|
||||
|
||||
return (mask & (size << 2)) | (~mask & size) |
|
||||
((size_t)type << ((sizeof(size_t) - 1) * 8)); // NOLINT
|
||||
#endif // TF_TSTRING_LITTLE_ENDIAN
|
||||
}
|
||||
|
||||
static inline void TF_TString_Init(TF_TString *str) {
|
||||
memset(str->u.raw.raw, 0, sizeof(TF_TString_Raw));
|
||||
}
|
||||
|
||||
static inline void TF_TString_Dealloc(TF_TString *str) {
|
||||
if (TF_TString_GetType(str) == TF_TSTR_LARGE &&
|
||||
str->u.large.ptr != NULL) { // NOLINT
|
||||
free(str->u.large.ptr);
|
||||
TF_TString_Init(str);
|
||||
}
|
||||
}
|
||||
|
||||
static inline size_t TF_TString_GetSize(const TF_TString *str) {
|
||||
switch (TF_TString_GetType(str)) {
|
||||
case TF_TSTR_SMALL:
|
||||
return str->u.smll.size >> 2;
|
||||
case TF_TSTR_LARGE:
|
||||
return TF_TString_ToActualSizeT(str->u.large.size);
|
||||
case TF_TSTR_OFFSET:
|
||||
return TF_le32toh(str->u.offset.size) >> 2;
|
||||
case TF_TSTR_VIEW:
|
||||
return TF_TString_ToActualSizeT(str->u.view.size);
|
||||
default:
|
||||
return 0; // Unreachable.
|
||||
}
|
||||
}
|
||||
|
||||
static inline size_t TF_TString_GetCapacity(const TF_TString *str) {
|
||||
switch (TF_TString_GetType(str)) {
|
||||
case TF_TSTR_SMALL:
|
||||
return TF_TString_SmallCapacity;
|
||||
case TF_TSTR_LARGE:
|
||||
return str->u.large.cap;
|
||||
case TF_TSTR_OFFSET:
|
||||
case TF_TSTR_VIEW:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline const char *TF_TString_GetDataPointer(const TF_TString *str) {
|
||||
switch (TF_TString_GetType(str)) {
|
||||
case TF_TSTR_SMALL:
|
||||
return str->u.smll.str;
|
||||
case TF_TSTR_LARGE:
|
||||
return str->u.large.ptr;
|
||||
case TF_TSTR_OFFSET:
|
||||
return (const char *)str + str->u.offset.offset; // NOLINT
|
||||
case TF_TSTR_VIEW:
|
||||
return str->u.view.ptr;
|
||||
default:
|
||||
// Unreachable.
|
||||
return NULL; // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
static inline char *TF_TString_ResizeUninitialized(TF_TString *str,
|
||||
size_t new_size) {
|
||||
size_t curr_size = TF_TString_GetSize(str);
|
||||
size_t copy_size = TF_min(new_size, curr_size);
|
||||
|
||||
TF_TString_Type curr_type = TF_TString_GetType(str);
|
||||
const char *curr_ptr = TF_TString_GetDataPointer(str);
|
||||
|
||||
// Case: SMALL/LARGE/VIEW/OFFSET -> SMALL
|
||||
if (new_size <= TF_TString_SmallCapacity) {
|
||||
str->u.smll.size = (uint8_t)((new_size << 2) | TF_TSTR_SMALL); // NOLINT
|
||||
str->u.smll.str[new_size] = '\0';
|
||||
|
||||
if (curr_type != TF_TSTR_SMALL && copy_size) {
|
||||
memcpy(str->u.smll.str, curr_ptr, copy_size);
|
||||
}
|
||||
|
||||
if (curr_type == TF_TSTR_LARGE) {
|
||||
free((void *)curr_ptr); // NOLINT
|
||||
}
|
||||
|
||||
// We do not clear out the newly excluded region.
|
||||
|
||||
return str->u.smll.str;
|
||||
}
|
||||
|
||||
// Case: SMALL/LARGE/VIEW/OFFSET -> LARGE
|
||||
size_t new_cap;
|
||||
size_t curr_cap = TF_TString_GetCapacity(str);
|
||||
// We assume SIZE_MAX % 16 == 0.
|
||||
size_t curr_cap_x2 = curr_cap >= SIZE_MAX / 2 ? SIZE_MAX - 1 : curr_cap * 2;
|
||||
|
||||
if (new_size < curr_size && new_size < curr_cap / 2) {
|
||||
// TODO(dero): Replace with shrink_to_fit flag.
|
||||
new_cap = TF_align16(curr_cap / 2 + 1) - 1;
|
||||
} else if (new_size > curr_cap_x2) {
|
||||
new_cap = TF_align16(new_size + 1) - 1;
|
||||
} else if (new_size > curr_cap) {
|
||||
new_cap = TF_align16(curr_cap_x2 + 1) - 1;
|
||||
} else {
|
||||
new_cap = curr_cap;
|
||||
}
|
||||
|
||||
char *new_ptr;
|
||||
if (new_cap == curr_cap) {
|
||||
new_ptr = str->u.large.ptr;
|
||||
} else if (curr_type == TF_TSTR_LARGE) {
|
||||
new_ptr = (char *)realloc(str->u.large.ptr, new_cap + 1); // NOLINT
|
||||
} else {
|
||||
new_ptr = (char *)malloc(new_cap + 1); // NOLINT
|
||||
if (copy_size) {
|
||||
memcpy(new_ptr, curr_ptr, copy_size);
|
||||
}
|
||||
}
|
||||
|
||||
str->u.large.size = TF_TString_ToInternalSizeT(new_size, TF_TSTR_LARGE);
|
||||
str->u.large.ptr = new_ptr;
|
||||
str->u.large.ptr[new_size] = '\0';
|
||||
str->u.large.cap = new_cap;
|
||||
|
||||
return str->u.large.ptr;
|
||||
}
|
||||
|
||||
static inline char *TF_TString_GetMutableDataPointer(TF_TString *str) {
|
||||
switch (TF_TString_GetType(str)) {
|
||||
case TF_TSTR_SMALL:
|
||||
return str->u.smll.str;
|
||||
case TF_TSTR_OFFSET:
|
||||
case TF_TSTR_VIEW:
|
||||
// Convert OFFSET/VIEW to SMALL/LARGE
|
||||
TF_TString_ResizeUninitialized(str, TF_TString_GetSize(str));
|
||||
return (TF_TString_GetType(str) == TF_TSTR_SMALL) ? str->u.smll.str
|
||||
: str->u.large.ptr;
|
||||
case TF_TSTR_LARGE:
|
||||
return str->u.large.ptr;
|
||||
default:
|
||||
// Unreachable.
|
||||
return NULL; // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
static inline void TF_TString_Reserve(TF_TString *str, size_t new_cap) {
|
||||
TF_TString_Type curr_type = TF_TString_GetType(str);
|
||||
|
||||
if (new_cap <= TF_TString_SmallCapacity) {
|
||||
// We do nothing, we let Resize/GetMutableDataPointer handle the
|
||||
// conversion to SMALL from VIEW/OFFSET when the need arises.
|
||||
// In the degenerate case, where new_cap <= TF_TString_SmallCapacity,
|
||||
// curr_size > TF_TString_SmallCapacity, and the type is VIEW/OFFSET, we
|
||||
// defer the malloc to Resize/GetMutableDataPointer.
|
||||
return;
|
||||
}
|
||||
|
||||
if (curr_type == TF_TSTR_LARGE && new_cap <= str->u.large.cap) {
|
||||
// We handle reduced cap in resize.
|
||||
return;
|
||||
}
|
||||
|
||||
// Case: VIEW/OFFSET -> LARGE or grow an existing LARGE type
|
||||
size_t curr_size = TF_TString_GetSize(str);
|
||||
const char *curr_ptr = TF_TString_GetDataPointer(str);
|
||||
|
||||
// Since VIEW and OFFSET types are read-only, their capacity is effectively 0.
|
||||
// So we make sure we have enough room in the VIEW and OFFSET cases.
|
||||
new_cap = TF_align16(TF_max(new_cap, curr_size) + 1) - 1;
|
||||
|
||||
if (curr_type == TF_TSTR_LARGE) {
|
||||
str->u.large.ptr =
|
||||
(char *)realloc(str->u.large.ptr, new_cap + 1); // NOLINT
|
||||
} else {
|
||||
// Convert to Large
|
||||
char *new_ptr = (char *)malloc(new_cap + 1); // NOLINT
|
||||
memcpy(new_ptr, curr_ptr, curr_size);
|
||||
|
||||
str->u.large.size = TF_TString_ToInternalSizeT(curr_size, TF_TSTR_LARGE);
|
||||
str->u.large.ptr = new_ptr;
|
||||
str->u.large.ptr[curr_size] = '\0';
|
||||
}
|
||||
|
||||
str->u.large.cap = new_cap;
|
||||
}
|
||||
|
||||
static inline char *TF_TString_Resize(TF_TString *str, size_t new_size,
|
||||
char c) {
|
||||
size_t curr_size = TF_TString_GetSize(str);
|
||||
char *cstr = TF_TString_ResizeUninitialized(str, new_size);
|
||||
|
||||
if (new_size > curr_size) {
|
||||
memset(cstr + curr_size, c, new_size - curr_size);
|
||||
}
|
||||
|
||||
return cstr;
|
||||
}
|
||||
|
||||
static inline void TF_TString_AssignView(TF_TString *dst, const char *src,
|
||||
size_t size) {
|
||||
TF_TString_Dealloc(dst);
|
||||
|
||||
dst->u.view.size = TF_TString_ToInternalSizeT(size, TF_TSTR_VIEW);
|
||||
dst->u.view.ptr = src;
|
||||
}
|
||||
|
||||
static inline void TF_TString_AppendN(TF_TString *dst, const char *src,
|
||||
size_t src_size) {
|
||||
if (!src_size) return;
|
||||
|
||||
size_t dst_size = TF_TString_GetSize(dst);
|
||||
|
||||
char *dst_c = TF_TString_ResizeUninitialized(dst, dst_size + src_size);
|
||||
|
||||
memcpy(dst_c + dst_size, src, src_size);
|
||||
}
|
||||
|
||||
static inline void TF_TString_Append(TF_TString *dst, const TF_TString *src) {
|
||||
const char *src_c = TF_TString_GetDataPointer(src);
|
||||
size_t size = TF_TString_GetSize(src);
|
||||
|
||||
TF_TString_AppendN(dst, src_c, size);
|
||||
}
|
||||
|
||||
static inline void TF_TString_Copy(TF_TString *dst, const char *src,
|
||||
size_t size) {
|
||||
char *dst_c = TF_TString_ResizeUninitialized(dst, size);
|
||||
|
||||
if (size) memcpy(dst_c, src, size);
|
||||
}
|
||||
|
||||
static inline void TF_TString_Assign(TF_TString *dst, const TF_TString *src) {
|
||||
if (dst == src) return;
|
||||
|
||||
TF_TString_Dealloc(dst);
|
||||
|
||||
switch (TF_TString_GetType(src)) {
|
||||
case TF_TSTR_SMALL:
|
||||
case TF_TSTR_VIEW:
|
||||
*dst = *src;
|
||||
return;
|
||||
case TF_TSTR_LARGE: {
|
||||
const char *src_c = TF_TString_GetDataPointer(src);
|
||||
size_t size = TF_TString_GetSize(src);
|
||||
|
||||
TF_TString_Copy(dst, src_c, size);
|
||||
}
|
||||
return;
|
||||
case TF_TSTR_OFFSET: {
|
||||
const char *src_c = TF_TString_GetDataPointer(src);
|
||||
size_t size = TF_TString_GetSize(src);
|
||||
|
||||
TF_TString_AssignView(dst, src_c, size);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return; // Unreachable.
|
||||
}
|
||||
}
|
||||
|
||||
static inline void TF_TString_Move(TF_TString *dst, TF_TString *src) {
|
||||
if (dst == src) return;
|
||||
|
||||
TF_TString_Dealloc(dst);
|
||||
|
||||
switch (TF_TString_GetType(src)) {
|
||||
case TF_TSTR_SMALL:
|
||||
case TF_TSTR_VIEW:
|
||||
*dst = *src;
|
||||
return;
|
||||
case TF_TSTR_LARGE:
|
||||
*dst = *src;
|
||||
TF_TString_Init(src);
|
||||
return;
|
||||
case TF_TSTR_OFFSET: {
|
||||
const char *src_c = TF_TString_GetDataPointer(src);
|
||||
size_t size = TF_TString_GetSize(src);
|
||||
|
||||
TF_TString_AssignView(dst, src_c, size);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return; // Unreachable.
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TENSORFLOW_CORE_PLATFORM_CTSTRING_INTERNAL_H_
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
libtensorflow.so.2
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
libtensorflow.so.2.4.1
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
libtensorflow_framework.so.2
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
libtensorflow_framework.so.2.4.1
|
||||
Generated
Vendored
Executable
BIN
Binary file not shown.
Generated
Vendored
+144
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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 { CustomCallback } from '@tensorflow/tfjs';
|
||||
export declare const progressBarHelper: {
|
||||
ProgressBar: any;
|
||||
log: Function;
|
||||
};
|
||||
/**
|
||||
* Terminal-based progress bar callback for tf.Model.fit().
|
||||
*/
|
||||
export declare class ProgbarLogger extends CustomCallback {
|
||||
private numTrainBatchesPerEpoch;
|
||||
private progressBar;
|
||||
private currentEpochBegin;
|
||||
private epochDurationMillis;
|
||||
private usPerStep;
|
||||
private batchesInLatestEpoch;
|
||||
private terminalWidth;
|
||||
private readonly RENDER_THROTTLE_MS;
|
||||
/**
|
||||
* Construtor of LoggingCallback.
|
||||
*/
|
||||
constructor();
|
||||
private formatLogsAsMetricsContent;
|
||||
private isFieldRelevant;
|
||||
}
|
||||
/**
|
||||
* Get a succint string representation of a number.
|
||||
*
|
||||
* Uses decimal notation if the number isn't too small.
|
||||
* Otherwise, use engineering notation.
|
||||
*
|
||||
* @param x Input number.
|
||||
* @return Succinct string representing `x`.
|
||||
*/
|
||||
export declare function getSuccinctNumberDisplay(x: number): string;
|
||||
/**
|
||||
* Determine the number of decimal places to display.
|
||||
*
|
||||
* @param x Number to display.
|
||||
* @return Number of decimal places to display for `x`.
|
||||
*/
|
||||
export declare function getDisplayDecimalPlaces(x: number): number;
|
||||
export interface TensorBoardCallbackArgs {
|
||||
/**
|
||||
* The frequency at which loss and metric values are written to logs.
|
||||
*
|
||||
* Currently supported options are:
|
||||
*
|
||||
* - 'batch': Write logs at the end of every batch of training, in addition
|
||||
* to the end of every epoch of training.
|
||||
* - 'epoch': Write logs at the end of every epoch of training.
|
||||
*
|
||||
* Note that writing logs too often slows down the training.
|
||||
*
|
||||
* Default: 'epoch'.
|
||||
*/
|
||||
updateFreq?: 'batch' | 'epoch';
|
||||
}
|
||||
/**
|
||||
* Callback for logging to TensorBoard during training.
|
||||
*
|
||||
* Users are expected to access this class through the `tensorBoardCallback()`
|
||||
* factory method instead.
|
||||
*/
|
||||
export declare class TensorBoardCallback extends CustomCallback {
|
||||
readonly logdir: string;
|
||||
private trainWriter;
|
||||
private valWriter;
|
||||
private batchesSeen;
|
||||
private readonly args;
|
||||
constructor(logdir?: string, args?: TensorBoardCallbackArgs);
|
||||
private logMetrics;
|
||||
private ensureTrainWriterCreated;
|
||||
private ensureValWriterCreated;
|
||||
}
|
||||
/**
|
||||
* Callback for logging to TensorBoard during training.
|
||||
*
|
||||
* Writes the loss and metric values (if any) to the specified log directory
|
||||
* (`logdir`) which can be ingested and visualized by TensorBoard.
|
||||
* This callback is usually passed as a callback to `tf.Model.fit()` or
|
||||
* `tf.Model.fitDataset()` calls during model training. The frequency at which
|
||||
* the values are logged can be controlled with the `updateFreq` field of the
|
||||
* configuration object (2nd argument).
|
||||
*
|
||||
* Usage example:
|
||||
* ```js
|
||||
* // Constructor a toy multilayer-perceptron regressor for demo purpose.
|
||||
* const model = tf.sequential();
|
||||
* model.add(
|
||||
* tf.layers.dense({units: 100, activation: 'relu', inputShape: [200]}));
|
||||
* model.add(tf.layers.dense({units: 1}));
|
||||
* model.compile({
|
||||
* loss: 'meanSquaredError',
|
||||
* optimizer: 'sgd',
|
||||
* metrics: ['MAE']
|
||||
* });
|
||||
*
|
||||
* // Generate some random fake data for demo purpose.
|
||||
* const xs = tf.randomUniform([10000, 200]);
|
||||
* const ys = tf.randomUniform([10000, 1]);
|
||||
* const valXs = tf.randomUniform([1000, 200]);
|
||||
* const valYs = tf.randomUniform([1000, 1]);
|
||||
*
|
||||
* // Start model training process.
|
||||
* await model.fit(xs, ys, {
|
||||
* epochs: 100,
|
||||
* validationData: [valXs, valYs],
|
||||
* // Add the tensorBoard callback here.
|
||||
* callbacks: tf.node.tensorBoard('/tmp/fit_logs_1')
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Then you can use the following commands to point tensorboard
|
||||
* to the logdir:
|
||||
*
|
||||
* ```sh
|
||||
* pip install tensorboard # Unless you've already installed it.
|
||||
* tensorboard --logdir /tmp/fit_logs_1
|
||||
* ```
|
||||
*
|
||||
* @param logdir Directory to which the logs will be written.
|
||||
* @param args Optional configuration arguments.
|
||||
* @returns An instance of `TensorBoardCallback`, which is a subclass of
|
||||
* `tf.CustomCallback`.
|
||||
*
|
||||
* @doc {heading: 'TensorBoard', namespace: 'node'}
|
||||
*/
|
||||
export declare function tensorBoard(logdir?: string, args?: TensorBoardCallbackArgs): TensorBoardCallback;
|
||||
Generated
Vendored
+371
@@ -0,0 +1,371 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tfjs_1 = require("@tensorflow/tfjs");
|
||||
var path = require("path");
|
||||
var ProgressBar = require("progress");
|
||||
var tensorboard_1 = require("./tensorboard");
|
||||
// A helper class created for testing with the jasmine `spyOn` method, which
|
||||
// operates only on member methods of objects.
|
||||
// tslint:disable-next-line:no-any
|
||||
exports.progressBarHelper = {
|
||||
ProgressBar: ProgressBar,
|
||||
log: console.log
|
||||
};
|
||||
/**
|
||||
* Terminal-based progress bar callback for tf.Model.fit().
|
||||
*/
|
||||
var ProgbarLogger = /** @class */ (function (_super) {
|
||||
__extends(ProgbarLogger, _super);
|
||||
/**
|
||||
* Construtor of LoggingCallback.
|
||||
*/
|
||||
function ProgbarLogger() {
|
||||
var _this = _super.call(this, {
|
||||
onTrainBegin: function (logs) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var samples, batchSize, steps;
|
||||
return __generator(this, function (_a) {
|
||||
samples = this.params.samples;
|
||||
batchSize = this.params.batchSize;
|
||||
steps = this.params.steps;
|
||||
if (samples != null || steps != null) {
|
||||
this.numTrainBatchesPerEpoch =
|
||||
samples != null ? Math.ceil(samples / batchSize) : steps;
|
||||
}
|
||||
else {
|
||||
// Undetermined number of batches per epoch, e.g., due to
|
||||
// `fitDataset()` without `batchesPerEpoch`.
|
||||
this.numTrainBatchesPerEpoch = 0;
|
||||
}
|
||||
return [2 /*return*/];
|
||||
});
|
||||
}); },
|
||||
onEpochBegin: function (epoch, logs) { return __awaiter(_this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
exports.progressBarHelper.log("Epoch " + (epoch + 1) + " / " + this.params.epochs);
|
||||
this.currentEpochBegin = tfjs_1.util.now();
|
||||
this.epochDurationMillis = null;
|
||||
this.usPerStep = null;
|
||||
this.batchesInLatestEpoch = 0;
|
||||
this.terminalWidth = process.stderr.columns;
|
||||
return [2 /*return*/];
|
||||
});
|
||||
}); },
|
||||
onBatchEnd: function (batch, logs) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var maxMetricsStringLength, tickTokens;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
this.batchesInLatestEpoch++;
|
||||
if (batch === 0) {
|
||||
this.progressBar = new exports.progressBarHelper.ProgressBar('eta=:eta :bar :placeholderForLossesAndMetrics', {
|
||||
width: Math.floor(0.5 * this.terminalWidth),
|
||||
total: this.numTrainBatchesPerEpoch + 1,
|
||||
head: ">",
|
||||
renderThrottle: this.RENDER_THROTTLE_MS
|
||||
});
|
||||
}
|
||||
maxMetricsStringLength = Math.floor(this.terminalWidth * 0.5 - 12);
|
||||
tickTokens = {
|
||||
placeholderForLossesAndMetrics: this.formatLogsAsMetricsContent(logs, maxMetricsStringLength)
|
||||
};
|
||||
if (this.numTrainBatchesPerEpoch === 0) {
|
||||
// Undetermined number of batches per epoch.
|
||||
this.progressBar.tick(0, tickTokens);
|
||||
}
|
||||
else {
|
||||
this.progressBar.tick(tickTokens);
|
||||
}
|
||||
return [4 /*yield*/, tfjs_1.nextFrame()];
|
||||
case 1:
|
||||
_a.sent();
|
||||
if (batch === this.numTrainBatchesPerEpoch - 1) {
|
||||
this.epochDurationMillis = tfjs_1.util.now() - this.currentEpochBegin;
|
||||
this.usPerStep = this.params.samples != null ?
|
||||
this.epochDurationMillis / this.params.samples * 1e3 :
|
||||
this.epochDurationMillis / this.batchesInLatestEpoch * 1e3;
|
||||
}
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); },
|
||||
onEpochEnd: function (epoch, logs) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var lossesAndMetricsString;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
if (this.epochDurationMillis == null) {
|
||||
// In cases where the number of batches per epoch is not determined,
|
||||
// the calculation of the per-step duration is done at the end of the
|
||||
// epoch. N.B., this includes the time spent on validation.
|
||||
this.epochDurationMillis = tfjs_1.util.now() - this.currentEpochBegin;
|
||||
this.usPerStep =
|
||||
this.epochDurationMillis / this.batchesInLatestEpoch * 1e3;
|
||||
}
|
||||
this.progressBar.tick({ placeholderForLossesAndMetrics: '' });
|
||||
lossesAndMetricsString = this.formatLogsAsMetricsContent(logs);
|
||||
exports.progressBarHelper.log(this.epochDurationMillis.toFixed(0) + "ms " +
|
||||
(this.usPerStep.toFixed(0) + "us/step - ") +
|
||||
("" + lossesAndMetricsString));
|
||||
return [4 /*yield*/, tfjs_1.nextFrame()];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); },
|
||||
}) || this;
|
||||
_this.RENDER_THROTTLE_MS = 50;
|
||||
return _this;
|
||||
}
|
||||
ProgbarLogger.prototype.formatLogsAsMetricsContent = function (logs, maxMetricsLength) {
|
||||
var metricsContent = '';
|
||||
var keys = Object.keys(logs).sort();
|
||||
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
|
||||
var key = keys_1[_i];
|
||||
if (this.isFieldRelevant(key)) {
|
||||
var value = logs[key];
|
||||
metricsContent += key + "=" + getSuccinctNumberDisplay(value) + " ";
|
||||
}
|
||||
}
|
||||
if (maxMetricsLength != null && metricsContent.length > maxMetricsLength) {
|
||||
// Cut off metrics strings that are too long to avoid new lines being
|
||||
// constantly created.
|
||||
metricsContent = metricsContent.slice(0, maxMetricsLength - 3) + '...';
|
||||
}
|
||||
return metricsContent;
|
||||
};
|
||||
ProgbarLogger.prototype.isFieldRelevant = function (key) {
|
||||
return key !== 'batch' && key !== 'size';
|
||||
};
|
||||
return ProgbarLogger;
|
||||
}(tfjs_1.CustomCallback));
|
||||
exports.ProgbarLogger = ProgbarLogger;
|
||||
var BASE_NUM_DIGITS = 2;
|
||||
var MAX_NUM_DECIMAL_PLACES = 4;
|
||||
/**
|
||||
* Get a succint string representation of a number.
|
||||
*
|
||||
* Uses decimal notation if the number isn't too small.
|
||||
* Otherwise, use engineering notation.
|
||||
*
|
||||
* @param x Input number.
|
||||
* @return Succinct string representing `x`.
|
||||
*/
|
||||
function getSuccinctNumberDisplay(x) {
|
||||
var decimalPlaces = getDisplayDecimalPlaces(x);
|
||||
return decimalPlaces > MAX_NUM_DECIMAL_PLACES ?
|
||||
x.toExponential(BASE_NUM_DIGITS) :
|
||||
x.toFixed(decimalPlaces);
|
||||
}
|
||||
exports.getSuccinctNumberDisplay = getSuccinctNumberDisplay;
|
||||
/**
|
||||
* Determine the number of decimal places to display.
|
||||
*
|
||||
* @param x Number to display.
|
||||
* @return Number of decimal places to display for `x`.
|
||||
*/
|
||||
function getDisplayDecimalPlaces(x) {
|
||||
if (!Number.isFinite(x) || x === 0 || x > 1 || x < -1) {
|
||||
return BASE_NUM_DIGITS;
|
||||
}
|
||||
else {
|
||||
return BASE_NUM_DIGITS - Math.floor(Math.log10(Math.abs(x)));
|
||||
}
|
||||
}
|
||||
exports.getDisplayDecimalPlaces = getDisplayDecimalPlaces;
|
||||
/**
|
||||
* Callback for logging to TensorBoard during training.
|
||||
*
|
||||
* Users are expected to access this class through the `tensorBoardCallback()`
|
||||
* factory method instead.
|
||||
*/
|
||||
var TensorBoardCallback = /** @class */ (function (_super) {
|
||||
__extends(TensorBoardCallback, _super);
|
||||
function TensorBoardCallback(logdir, args) {
|
||||
if (logdir === void 0) { logdir = './logs'; }
|
||||
var _this = _super.call(this, {
|
||||
onBatchEnd: function (batch, logs) { return __awaiter(_this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
this.batchesSeen++;
|
||||
if (this.args.updateFreq !== 'epoch') {
|
||||
this.logMetrics(logs, 'batch_', this.batchesSeen);
|
||||
}
|
||||
return [2 /*return*/];
|
||||
});
|
||||
}); },
|
||||
onEpochEnd: function (epoch, logs) { return __awaiter(_this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
this.logMetrics(logs, 'epoch_', epoch + 1);
|
||||
return [2 /*return*/];
|
||||
});
|
||||
}); },
|
||||
onTrainEnd: function (logs) { return __awaiter(_this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
if (this.trainWriter != null) {
|
||||
this.trainWriter.flush();
|
||||
}
|
||||
if (this.valWriter != null) {
|
||||
this.valWriter.flush();
|
||||
}
|
||||
return [2 /*return*/];
|
||||
});
|
||||
}); }
|
||||
}) || this;
|
||||
_this.logdir = logdir;
|
||||
_this.args = args == null ? {} : args;
|
||||
if (_this.args.updateFreq == null) {
|
||||
_this.args.updateFreq = 'epoch';
|
||||
}
|
||||
tfjs_1.util.assert(['batch', 'epoch'].indexOf(_this.args.updateFreq) !== -1, function () { return "Expected updateFreq to be 'batch' or 'epoch', but got " +
|
||||
("" + _this.args.updateFreq); });
|
||||
_this.batchesSeen = 0;
|
||||
return _this;
|
||||
}
|
||||
TensorBoardCallback.prototype.logMetrics = function (logs, prefix, step) {
|
||||
for (var key in logs) {
|
||||
if (key === 'batch' || key === 'size' || key === 'num_steps') {
|
||||
continue;
|
||||
}
|
||||
var VAL_PREFIX = 'val_';
|
||||
if (key.startsWith(VAL_PREFIX)) {
|
||||
this.ensureValWriterCreated();
|
||||
var scalarName = prefix + key.slice(VAL_PREFIX.length);
|
||||
this.valWriter.scalar(scalarName, logs[key], step);
|
||||
}
|
||||
else {
|
||||
this.ensureTrainWriterCreated();
|
||||
this.trainWriter.scalar("" + prefix + key, logs[key], step);
|
||||
}
|
||||
}
|
||||
};
|
||||
TensorBoardCallback.prototype.ensureTrainWriterCreated = function () {
|
||||
this.trainWriter = tensorboard_1.summaryFileWriter(path.join(this.logdir, 'train'));
|
||||
};
|
||||
TensorBoardCallback.prototype.ensureValWriterCreated = function () {
|
||||
this.valWriter = tensorboard_1.summaryFileWriter(path.join(this.logdir, 'val'));
|
||||
};
|
||||
return TensorBoardCallback;
|
||||
}(tfjs_1.CustomCallback));
|
||||
exports.TensorBoardCallback = TensorBoardCallback;
|
||||
/**
|
||||
* Callback for logging to TensorBoard during training.
|
||||
*
|
||||
* Writes the loss and metric values (if any) to the specified log directory
|
||||
* (`logdir`) which can be ingested and visualized by TensorBoard.
|
||||
* This callback is usually passed as a callback to `tf.Model.fit()` or
|
||||
* `tf.Model.fitDataset()` calls during model training. The frequency at which
|
||||
* the values are logged can be controlled with the `updateFreq` field of the
|
||||
* configuration object (2nd argument).
|
||||
*
|
||||
* Usage example:
|
||||
* ```js
|
||||
* // Constructor a toy multilayer-perceptron regressor for demo purpose.
|
||||
* const model = tf.sequential();
|
||||
* model.add(
|
||||
* tf.layers.dense({units: 100, activation: 'relu', inputShape: [200]}));
|
||||
* model.add(tf.layers.dense({units: 1}));
|
||||
* model.compile({
|
||||
* loss: 'meanSquaredError',
|
||||
* optimizer: 'sgd',
|
||||
* metrics: ['MAE']
|
||||
* });
|
||||
*
|
||||
* // Generate some random fake data for demo purpose.
|
||||
* const xs = tf.randomUniform([10000, 200]);
|
||||
* const ys = tf.randomUniform([10000, 1]);
|
||||
* const valXs = tf.randomUniform([1000, 200]);
|
||||
* const valYs = tf.randomUniform([1000, 1]);
|
||||
*
|
||||
* // Start model training process.
|
||||
* await model.fit(xs, ys, {
|
||||
* epochs: 100,
|
||||
* validationData: [valXs, valYs],
|
||||
* // Add the tensorBoard callback here.
|
||||
* callbacks: tf.node.tensorBoard('/tmp/fit_logs_1')
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Then you can use the following commands to point tensorboard
|
||||
* to the logdir:
|
||||
*
|
||||
* ```sh
|
||||
* pip install tensorboard # Unless you've already installed it.
|
||||
* tensorboard --logdir /tmp/fit_logs_1
|
||||
* ```
|
||||
*
|
||||
* @param logdir Directory to which the logs will be written.
|
||||
* @param args Optional configuration arguments.
|
||||
* @returns An instance of `TensorBoardCallback`, which is a subclass of
|
||||
* `tf.CustomCallback`.
|
||||
*
|
||||
* @doc {heading: 'TensorBoard', namespace: 'node'}
|
||||
*/
|
||||
function tensorBoard(logdir, args) {
|
||||
if (logdir === void 0) { logdir = './logs'; }
|
||||
return new TensorBoardCallback(logdir, args);
|
||||
}
|
||||
exports.tensorBoard = tensorBoard;
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
export {};
|
||||
Generated
Vendored
+391
@@ -0,0 +1,391 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var _this = this;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tf = require("@tensorflow/tfjs");
|
||||
var callbacks_1 = require("./callbacks");
|
||||
describe('progbarLogger', function () {
|
||||
// Fake progbar class written for testing.
|
||||
var FakeProgbar = /** @class */ (function () {
|
||||
function FakeProgbar(specs, config) {
|
||||
this.specs = specs;
|
||||
this.config = config;
|
||||
this.tickConfigs = [];
|
||||
}
|
||||
FakeProgbar.prototype.tick = function (tickConfig) {
|
||||
this.tickConfigs.push(tickConfig);
|
||||
};
|
||||
return FakeProgbar;
|
||||
}());
|
||||
var originalStderrColumns;
|
||||
beforeEach(function () {
|
||||
// In some CI environments, process.stderr.columns has a null value.
|
||||
originalStderrColumns = process.stderr.columns;
|
||||
process.stderr.columns = 100;
|
||||
});
|
||||
afterEach(function () {
|
||||
process.stderr.columns = originalStderrColumns;
|
||||
});
|
||||
it('Model.fit with loss, no metric, no validation, verobse = 1', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var fakeProgbars, consoleMessages, model, numSamples, epochs, batchSize, xs, ys, _i, fakeProgbars_1, fakeProgbar, tickConfigs, i;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
fakeProgbars = [];
|
||||
spyOn(callbacks_1.progressBarHelper, 'ProgressBar')
|
||||
.and.callFake(function (specs, config) {
|
||||
var fakeProgbar = new FakeProgbar(specs, config);
|
||||
fakeProgbars.push(fakeProgbar);
|
||||
return fakeProgbar;
|
||||
});
|
||||
consoleMessages = [];
|
||||
spyOn(callbacks_1.progressBarHelper, 'log').and.callFake(function (message) {
|
||||
consoleMessages.push(message);
|
||||
});
|
||||
model = tf.sequential();
|
||||
model.add(tf.layers.dense({ units: 10, inputShape: [8], activation: 'relu' }));
|
||||
model.add(tf.layers.dense({ units: 1 }));
|
||||
model.compile({ loss: 'meanSquaredError', optimizer: 'sgd' });
|
||||
numSamples = 14;
|
||||
epochs = 3;
|
||||
batchSize = 8;
|
||||
xs = tf.randomNormal([numSamples, 8]);
|
||||
ys = tf.randomNormal([numSamples, 1]);
|
||||
return [4 /*yield*/, model.fit(xs, ys, { epochs: epochs, batchSize: batchSize, verbose: 1 })];
|
||||
case 1:
|
||||
_a.sent();
|
||||
// A progbar object is created for each epoch.
|
||||
expect(fakeProgbars.length).toEqual(3);
|
||||
for (_i = 0, fakeProgbars_1 = fakeProgbars; _i < fakeProgbars_1.length; _i++) {
|
||||
fakeProgbar = fakeProgbars_1[_i];
|
||||
tickConfigs = fakeProgbar.tickConfigs;
|
||||
// There are ceil(14 / 8) = 2 batchs per epoch. There should be 1 tick
|
||||
// for epoch batch, plus a tick at the end of the epoch.
|
||||
expect(tickConfigs.length).toEqual(3);
|
||||
for (i = 0; i < 2; ++i) {
|
||||
expect(Object.keys(tickConfigs[i])).toEqual([
|
||||
'placeholderForLossesAndMetrics'
|
||||
]);
|
||||
expect(tickConfigs[i]['placeholderForLossesAndMetrics'])
|
||||
.toMatch(/^loss=.*/);
|
||||
}
|
||||
expect(tickConfigs[2]).toEqual({ placeholderForLossesAndMetrics: '' });
|
||||
}
|
||||
expect(consoleMessages.length).toEqual(6);
|
||||
expect(consoleMessages[0]).toEqual('Epoch 1 / 3');
|
||||
expect(consoleMessages[1]).toMatch(/.*ms .*us\/step - loss=.*/);
|
||||
expect(consoleMessages[2]).toEqual('Epoch 2 / 3');
|
||||
expect(consoleMessages[3]).toMatch(/.*ms .*us\/step - loss=.*/);
|
||||
expect(consoleMessages[4]).toEqual('Epoch 3 / 3');
|
||||
expect(consoleMessages[5]).toMatch(/.*ms .*us\/step - loss=.*/);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('Model.fit with loss, metric and validation, verbose = 2', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var fakeProgbars, consoleMessages, model, numSamples, epochs, batchSize, validationSplit, xs, ys, _i, fakeProgbars_2, fakeProgbar, tickConfigs, i;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
fakeProgbars = [];
|
||||
spyOn(callbacks_1.progressBarHelper, 'ProgressBar')
|
||||
.and.callFake(function (specs, config) {
|
||||
var fakeProgbar = new FakeProgbar(specs, config);
|
||||
fakeProgbars.push(fakeProgbar);
|
||||
return fakeProgbar;
|
||||
});
|
||||
consoleMessages = [];
|
||||
spyOn(callbacks_1.progressBarHelper, 'log').and.callFake(function (message) {
|
||||
consoleMessages.push(message);
|
||||
});
|
||||
model = tf.sequential();
|
||||
model.add(tf.layers.dense({ units: 10, inputShape: [8], activation: 'relu' }));
|
||||
model.add(tf.layers.dense({ units: 1 }));
|
||||
model.compile({ loss: 'meanSquaredError', optimizer: 'sgd', metrics: ['acc'] });
|
||||
numSamples = 40;
|
||||
epochs = 2;
|
||||
batchSize = 8;
|
||||
validationSplit = 0.15;
|
||||
xs = tf.randomNormal([numSamples, 8]);
|
||||
ys = tf.randomNormal([numSamples, 1]);
|
||||
return [4 /*yield*/, model.fit(xs, ys, { epochs: epochs, batchSize: batchSize, validationSplit: validationSplit, verbose: 2 })];
|
||||
case 1:
|
||||
_a.sent();
|
||||
// A progbar object is created for each epoch.
|
||||
expect(fakeProgbars.length).toEqual(2);
|
||||
for (_i = 0, fakeProgbars_2 = fakeProgbars; _i < fakeProgbars_2.length; _i++) {
|
||||
fakeProgbar = fakeProgbars_2[_i];
|
||||
tickConfigs = fakeProgbar.tickConfigs;
|
||||
// There are 5 batchs per epoch. There should be 1 tick for epoch batch,
|
||||
// plus a tick at the end of the epoch.
|
||||
expect(tickConfigs.length).toEqual(6);
|
||||
for (i = 0; i < 5; ++i) {
|
||||
expect(Object.keys(tickConfigs[i])).toEqual([
|
||||
'placeholderForLossesAndMetrics'
|
||||
]);
|
||||
expect(tickConfigs[i]['placeholderForLossesAndMetrics'])
|
||||
.toMatch(/^acc=.* loss=.*/);
|
||||
}
|
||||
expect(tickConfigs[5]).toEqual({ placeholderForLossesAndMetrics: '' });
|
||||
}
|
||||
expect(consoleMessages.length).toEqual(4);
|
||||
expect(consoleMessages[0]).toEqual('Epoch 1 / 2');
|
||||
expect(consoleMessages[1])
|
||||
.toMatch(/.*ms .*us\/step - acc=.* loss=.* val_acc=.* val_loss=.*/);
|
||||
expect(consoleMessages[2]).toEqual('Epoch 2 / 2');
|
||||
expect(consoleMessages[3])
|
||||
.toMatch(/.*ms .*us\/step - acc=.* loss=.* val_acc=.* val_loss=.*/);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('Model.fit does not create ProgbarLogger if verbose is 0', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var fakeProgbars, consoleMessages, model, numSamples, epochs, batchSize, validationSplit, xs, ys;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
fakeProgbars = [];
|
||||
spyOn(callbacks_1.progressBarHelper, 'ProgressBar')
|
||||
.and.callFake(function (specs, config) {
|
||||
var fakeProgbar = new FakeProgbar(specs, config);
|
||||
fakeProgbars.push(fakeProgbar);
|
||||
return fakeProgbar;
|
||||
});
|
||||
consoleMessages = [];
|
||||
spyOn(callbacks_1.progressBarHelper, 'log').and.callFake(function (message) {
|
||||
consoleMessages.push(message);
|
||||
});
|
||||
model = tf.sequential();
|
||||
model.add(tf.layers.dense({ units: 10, inputShape: [8], activation: 'relu' }));
|
||||
model.add(tf.layers.dense({ units: 1 }));
|
||||
model.compile({ loss: 'meanSquaredError', optimizer: 'sgd', metrics: ['acc'] });
|
||||
numSamples = 40;
|
||||
epochs = 2;
|
||||
batchSize = 8;
|
||||
validationSplit = 0.15;
|
||||
xs = tf.randomNormal([numSamples, 8]);
|
||||
ys = tf.randomNormal([numSamples, 1]);
|
||||
return [4 /*yield*/, model.fit(xs, ys, { epochs: epochs, batchSize: batchSize, validationSplit: validationSplit, verbose: 0 })];
|
||||
case 1:
|
||||
_a.sent();
|
||||
expect(fakeProgbars.length).toEqual(0);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('Model.fitDataset: batchesPerEpoch specified, verbose = 1', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var fakeProgbars, consoleMessages, epochs, xDataset, yDataset, dataset, model;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
fakeProgbars = [];
|
||||
spyOn(callbacks_1.progressBarHelper, 'ProgressBar')
|
||||
.and.callFake(function (specs, config) {
|
||||
var fakeProgbar = new FakeProgbar(specs, config);
|
||||
fakeProgbars.push(fakeProgbar);
|
||||
return fakeProgbar;
|
||||
});
|
||||
consoleMessages = [];
|
||||
spyOn(callbacks_1.progressBarHelper, 'log').and.callFake(function (message) {
|
||||
consoleMessages.push(message);
|
||||
});
|
||||
epochs = 2;
|
||||
xDataset = tf.data.array([[1, 2], [3, 4], [5, 6], [7, 8]])
|
||||
.map(function (x) { return tf.tensor2d(x, [1, 2]); });
|
||||
yDataset = tf.data.array([[1], [2], [3], [4]]).map(function (y) { return tf.tensor2d(y, [1, 1]); });
|
||||
dataset = tf.data.zip({ xs: xDataset, ys: yDataset }).repeat(epochs);
|
||||
model = tf.sequential();
|
||||
model.add(tf.layers.dense({ units: 1, inputShape: [2] }));
|
||||
model.compile({ loss: 'meanSquaredError', optimizer: 'sgd' });
|
||||
return [4 /*yield*/, model.fitDataset(dataset, { batchesPerEpoch: 4, epochs: epochs, verbose: 1 })];
|
||||
case 1:
|
||||
_a.sent();
|
||||
expect(consoleMessages.length).toEqual(4);
|
||||
expect(consoleMessages[0]).toEqual('Epoch 1 / 2');
|
||||
expect(consoleMessages[1]).toMatch(/.*ms .*us\/step - loss=.*/);
|
||||
expect(consoleMessages[2]).toEqual('Epoch 2 / 2');
|
||||
expect(consoleMessages[3]).toMatch(/.*ms .*us\/step - loss=.*/);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('Model.fitDataset: batchesPerEpoch unavailable, verbose = 1', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var fakeProgbars, consoleMessages, epochs, xDataset, yDataset, dataset, model;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
fakeProgbars = [];
|
||||
spyOn(callbacks_1.progressBarHelper, 'ProgressBar')
|
||||
.and.callFake(function (specs, config) {
|
||||
var fakeProgbar = new FakeProgbar(specs, config);
|
||||
fakeProgbars.push(fakeProgbar);
|
||||
return fakeProgbar;
|
||||
});
|
||||
consoleMessages = [];
|
||||
spyOn(callbacks_1.progressBarHelper, 'log').and.callFake(function (message) {
|
||||
consoleMessages.push(message);
|
||||
});
|
||||
epochs = 2;
|
||||
xDataset = tf.data.array([[1, 2], [3, 4], [5, 6], [7, 8]])
|
||||
.map(function (x) { return tf.tensor2d(x, [1, 2]); });
|
||||
yDataset = tf.data.array([[1], [2], [3], [4]]).map(function (y) { return tf.tensor2d(y, [1, 1]); });
|
||||
dataset = tf.data.zip({ xs: xDataset, ys: yDataset }).repeat(epochs);
|
||||
model = tf.sequential();
|
||||
model.add(tf.layers.dense({ units: 1, inputShape: [2] }));
|
||||
model.compile({ loss: 'meanSquaredError', optimizer: 'sgd' });
|
||||
// `batchesPerEpoch` is not specified. Instead, `fitDataset()` relies on
|
||||
// the `done` field being `true` to terminate the epoch(s).
|
||||
return [4 /*yield*/, model.fitDataset(dataset, { epochs: epochs, verbose: 1 })];
|
||||
case 1:
|
||||
// `batchesPerEpoch` is not specified. Instead, `fitDataset()` relies on
|
||||
// the `done` field being `true` to terminate the epoch(s).
|
||||
_a.sent();
|
||||
expect(consoleMessages.length).toEqual(4);
|
||||
expect(consoleMessages[0]).toEqual('Epoch 1 / 2');
|
||||
expect(consoleMessages[1]).toMatch(/.*ms .*us\/step - loss=.*/);
|
||||
expect(consoleMessages[2]).toEqual('Epoch 2 / 2');
|
||||
expect(consoleMessages[3]).toMatch(/.*ms .*us\/step - loss=.*/);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('Model.fitDataset: verbose = 0 leads to no logging', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var fakeProgbars, consoleMessages, xDataset, yDataset, dataset, model, history;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
fakeProgbars = [];
|
||||
spyOn(callbacks_1.progressBarHelper, 'ProgressBar')
|
||||
.and.callFake(function (specs, config) {
|
||||
var fakeProgbar = new FakeProgbar(specs, config);
|
||||
fakeProgbars.push(fakeProgbar);
|
||||
return fakeProgbar;
|
||||
});
|
||||
consoleMessages = [];
|
||||
spyOn(callbacks_1.progressBarHelper, 'log').and.callFake(function (message) {
|
||||
consoleMessages.push(message);
|
||||
});
|
||||
xDataset = tf.data.array([[1, 2], [3, 4], [5, 6], [7, 8]])
|
||||
.map(function (x) { return tf.tensor2d(x, [1, 2]); });
|
||||
yDataset = tf.data.array([[1], [2], [3], [4]]).map(function (y) { return tf.tensor2d(y, [1, 1]); });
|
||||
dataset = tf.data.zip({ xs: xDataset, ys: yDataset });
|
||||
model = tf.sequential();
|
||||
model.add(tf.layers.dense({ units: 1, inputShape: [2] }));
|
||||
model.compile({ loss: 'meanSquaredError', optimizer: 'sgd' });
|
||||
return [4 /*yield*/, model.fitDataset(dataset, { epochs: 1, verbose: 0 })];
|
||||
case 1:
|
||||
history = _a.sent();
|
||||
expect(history.history.loss.length).toEqual(1);
|
||||
expect(consoleMessages.length)
|
||||
.toEqual(0); // No logging should have happened.
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
});
|
||||
describe('getSuccinctNumberDisplay', function () {
|
||||
it('Not finite', function () {
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(Infinity)).toEqual('Infinity');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(-Infinity)).toEqual('-Infinity');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(NaN)).toEqual('NaN');
|
||||
});
|
||||
it('zero', function () {
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(0)).toEqual('0.00');
|
||||
});
|
||||
it('Finite and positive', function () {
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(300)).toEqual('300.00');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(30)).toEqual('30.00');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(1)).toEqual('1.00');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(1e-2)).toEqual('0.0100');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(1e-3)).toEqual('1.00e-3');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(4e-3)).toEqual('4.00e-3');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(1e-6)).toEqual('1.00e-6');
|
||||
});
|
||||
it('Finite and negative', function () {
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(-300)).toEqual('-300.00');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(-30)).toEqual('-30.00');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(-1)).toEqual('-1.00');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(-1e-2)).toEqual('-0.0100');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(-1e-3)).toEqual('-1.00e-3');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(-4e-3)).toEqual('-4.00e-3');
|
||||
expect(callbacks_1.getSuccinctNumberDisplay(-1e-6)).toEqual('-1.00e-6');
|
||||
});
|
||||
});
|
||||
describe('getDisplayDecimalPlaces', function () {
|
||||
it('Not finite', function () {
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(Infinity)).toEqual(2);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(-Infinity)).toEqual(2);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(NaN)).toEqual(2);
|
||||
});
|
||||
it('zero', function () {
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(0)).toEqual(2);
|
||||
});
|
||||
it('Finite and positive', function () {
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(300)).toEqual(2);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(30)).toEqual(2);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(1)).toEqual(2);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(1e-2)).toEqual(4);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(1e-3)).toEqual(5);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(4e-3)).toEqual(5);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(1e-6)).toEqual(8);
|
||||
});
|
||||
it('Finite and negative', function () {
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(-300)).toEqual(2);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(-30)).toEqual(2);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(-1)).toEqual(2);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(-1e-2)).toEqual(4);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(-1e-3)).toEqual(5);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(-4e-3)).toEqual(5);
|
||||
expect(callbacks_1.getDisplayDecimalPlaces(-1e-6)).toEqual(8);
|
||||
});
|
||||
});
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
export {};
|
||||
Generated
Vendored
+120
@@ -0,0 +1,120 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var _this = this;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tf = require("@tensorflow/tfjs");
|
||||
var MockContext = /** @class */ (function () {
|
||||
function MockContext() {
|
||||
}
|
||||
MockContext.prototype.getImageData = function (x, y, width, height) {
|
||||
var data = new Uint8ClampedArray(width * height * 4);
|
||||
for (var i = 0; i < data.length; ++i) {
|
||||
data[i] = i + 1;
|
||||
}
|
||||
return { data: data };
|
||||
};
|
||||
return MockContext;
|
||||
}());
|
||||
var MockCanvas = /** @class */ (function () {
|
||||
function MockCanvas(width, height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
MockCanvas.prototype.getContext = function (type) {
|
||||
return new MockContext();
|
||||
};
|
||||
return MockCanvas;
|
||||
}());
|
||||
describe('tf.browser.fromPixels with polyfills', function () {
|
||||
it('accepts a canvas-like element', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var c, t, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
c = new MockCanvas(2, 2);
|
||||
t = tf.browser.fromPixels(c);
|
||||
expect(t.dtype).toBe('int32');
|
||||
expect(t.shape).toEqual([2, 2, 3]);
|
||||
_b = (_a = tf.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, t.data()];
|
||||
case 1:
|
||||
_b.apply(_a, [_c.sent(), [1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15]]);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('accepts a canvas-like element, numChannels=4', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var c, t, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
c = new MockCanvas(2, 2);
|
||||
t = tf.browser.fromPixels(c, 4);
|
||||
expect(t.dtype).toBe('int32');
|
||||
expect(t.shape).toEqual([2, 2, 4]);
|
||||
_b = (_a = tf.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, t.data()];
|
||||
case 1:
|
||||
_b.apply(_a, [_c.sent(),
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]]);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('errors when passed a non-canvas object', function () {
|
||||
var c = 5;
|
||||
// tslint:disable-next-line:no-any
|
||||
expect(function () { return tf.browser.fromPixels(c); })
|
||||
.toThrowError(/pixels passed to tf\.browser\.fromPixels\(\) must be either an/);
|
||||
});
|
||||
});
|
||||
Generated
Vendored
+163
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* @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 { Tensor3D, Tensor4D } from '@tensorflow/tfjs';
|
||||
export declare enum ImageType {
|
||||
JPEG = "jpeg",
|
||||
PNG = "png",
|
||||
GIF = "gif",
|
||||
BMP = "BMP"
|
||||
}
|
||||
/**
|
||||
* Decode a JPEG-encoded image to a 3D Tensor of dtype `int32`.
|
||||
*
|
||||
* @param contents The JPEG-encoded image in an Uint8Array.
|
||||
* @param channels An optional int. Defaults to 0. Accepted values are
|
||||
* 0: use the number of channels in the JPEG-encoded image.
|
||||
* 1: output a grayscale image.
|
||||
* 3: output an RGB image.
|
||||
* @param ratio An optional int. Defaults to 1. Downscaling ratio. It is used
|
||||
* when image is type Jpeg.
|
||||
* @param fancyUpscaling An optional bool. Defaults to True. If true use a
|
||||
* slower but nicer upscaling of the chroma planes. It is used when image is
|
||||
* type Jpeg.
|
||||
* @param tryRecoverTruncated An optional bool. Defaults to False. If true try
|
||||
* to recover an image from truncated input. It is used when image is type
|
||||
* Jpeg.
|
||||
* @param acceptableFraction An optional float. Defaults to 1. The minimum
|
||||
* required fraction of lines before a truncated input is accepted. It is
|
||||
* used when image is type Jpeg.
|
||||
* @param dctMethod An optional string. Defaults to "". string specifying a hint
|
||||
* about the algorithm used for decompression. Defaults to "" which maps to
|
||||
* a system-specific default. Currently valid values are ["INTEGER_FAST",
|
||||
* "INTEGER_ACCURATE"]. The hint may be ignored (e.g., the internal jpeg
|
||||
* library changes to a version that does not have that specific option.) It
|
||||
* is used when image is type Jpeg.
|
||||
* @returns A 3D Tensor of dtype `int32` with shape [height, width, 1/3].
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
export declare function decodeJpeg(contents: Uint8Array, channels?: number, ratio?: number, fancyUpscaling?: boolean, tryRecoverTruncated?: boolean, acceptableFraction?: number, dctMethod?: string): Tensor3D;
|
||||
/**
|
||||
* Decode a PNG-encoded image to a 3D Tensor of dtype `int32`.
|
||||
*
|
||||
* @param contents The PNG-encoded image in an Uint8Array.
|
||||
* @param channels An optional int. Defaults to 0. Accepted values are
|
||||
* 0: use the number of channels in the PNG-encoded image.
|
||||
* 1: output a grayscale image.
|
||||
* 3: output an RGB image.
|
||||
* 4: output an RGBA image.
|
||||
* @param dtype The data type of the result. Only `int32` is supported at this
|
||||
* time.
|
||||
* @returns A 3D Tensor of dtype `int32` with shape [height, width, 1/3/4].
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
export declare function decodePng(contents: Uint8Array, channels?: number, dtype?: string): Tensor3D;
|
||||
/**
|
||||
* Decode the first frame of a BMP-encoded image to a 3D Tensor of dtype
|
||||
* `int32`.
|
||||
*
|
||||
* @param contents The BMP-encoded image in an Uint8Array.
|
||||
* @param channels An optional int. Defaults to 0. Accepted values are
|
||||
* 0: use the number of channels in the BMP-encoded image.
|
||||
* 3: output an RGB image.
|
||||
* 4: output an RGBA image.
|
||||
* @returns A 3D Tensor of dtype `int32` with shape [height, width, 3/4].
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
export declare function decodeBmp(contents: Uint8Array, channels?: number): Tensor3D;
|
||||
/**
|
||||
* Decode the frame(s) of a GIF-encoded image to a 4D Tensor of dtype `int32`.
|
||||
*
|
||||
* @param contents The GIF-encoded image in an Uint8Array.
|
||||
* @returns A 4D Tensor of dtype `int32` with shape [num_frames, height, width,
|
||||
* 3]. RGB channel order.
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
export declare function decodeGif(contents: Uint8Array): Tensor4D;
|
||||
/**
|
||||
* Given the encoded bytes of an image, it returns a 3D or 4D tensor of the
|
||||
* decoded image. Supports BMP, GIF, JPEG and PNG formats.
|
||||
*
|
||||
* @param content The encoded image in an Uint8Array.
|
||||
* @param channels An optional int. Defaults to 0, use the number of channels in
|
||||
* the image. Number of color channels for the decoded image. It is used
|
||||
* when image is type Png, Bmp, or Jpeg.
|
||||
* @param dtype The data type of the result. Only `int32` is supported at this
|
||||
* time.
|
||||
* @param expandAnimations A boolean which controls the shape of the returned
|
||||
* op's output. If True, the returned op will produce a 3-D tensor for PNG,
|
||||
* JPEG, and BMP files; and a 4-D tensor for all GIFs, whether animated or
|
||||
* not. If, False, the returned op will produce a 3-D tensor for all file
|
||||
* types and will truncate animated GIFs to the first frame.
|
||||
* @returns A Tensor with dtype `int32` and a 3- or 4-dimensional shape,
|
||||
* depending on the file type. For gif file the returned Tensor shape is
|
||||
* [num_frames, height, width, 3], and for jpeg/png/bmp the returned Tensor
|
||||
* shape is [height, width, channels]
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
export declare function decodeImage(content: Uint8Array, channels?: number, dtype?: string, expandAnimations?: boolean): Tensor3D | Tensor4D;
|
||||
/**
|
||||
* Encodes an image tensor to JPEG.
|
||||
*
|
||||
* @param image A 3-D uint8 Tensor of shape [height, width, channels].
|
||||
* @param format An optional string from: "", "grayscale", "rgb".
|
||||
* Defaults to "". Per pixel image format.
|
||||
* - '': Use a default format based on the number of channels in the image.
|
||||
* - grayscale: Output a grayscale JPEG image. The channels dimension of
|
||||
* image must be 1.
|
||||
* - rgb: Output an RGB JPEG image. The channels dimension of image must
|
||||
* be 3.
|
||||
* @param quality An optional int. Defaults to 95. Quality of the compression
|
||||
* from 0 to 100 (higher is better and slower).
|
||||
* @param progressive An optional bool. Defaults to False. If True, create a
|
||||
* JPEG that loads progressively (coarse to fine).
|
||||
* @param optimizeSize An optional bool. Defaults to False. If True, spend
|
||||
* CPU/RAM to reduce size with no quality change.
|
||||
* @param chromaDownsampling An optional bool. Defaults to True.
|
||||
* See http://en.wikipedia.org/wiki/Chroma_subsampling.
|
||||
* @param densityUnit An optional string from: "in", "cm". Defaults to "in".
|
||||
* Unit used to specify x_density and y_density: pixels per inch ('in') or
|
||||
* centimeter ('cm').
|
||||
* @param xDensity An optional int. Defaults to 300. Horizontal pixels per
|
||||
* density unit.
|
||||
* @param yDensity An optional int. Defaults to 300. Vertical pixels per
|
||||
* density unit.
|
||||
* @param xmpMetadata An optional string. Defaults to "". If not empty, embed
|
||||
* this XMP metadata in the image header.
|
||||
* @returns The JPEG encoded data as an Uint8Array.
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
export declare function encodeJpeg(image: Tensor3D, format?: '' | 'grayscale' | 'rgb', quality?: number, progressive?: boolean, optimizeSize?: boolean, chromaDownsampling?: boolean, densityUnit?: 'in' | 'cm', xDensity?: number, yDensity?: number, xmpMetadata?: string): Promise<Uint8Array>;
|
||||
/**
|
||||
* Encodes an image tensor to PNG.
|
||||
*
|
||||
* @param image A 3-D uint8 Tensor of shape [height, width, channels].
|
||||
* @param compression An optional int. Defaults to 1. Compression level.
|
||||
* @returns The PNG encoded data as an Uint8Array.
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
export declare function encodePng(image: Tensor3D, compression?: number): Promise<Uint8Array>;
|
||||
/**
|
||||
* Helper function to get image type based on starting bytes of the image file.
|
||||
*/
|
||||
export declare function getImageType(content: Uint8Array): string;
|
||||
Generated
Vendored
+355
@@ -0,0 +1,355 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @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.
|
||||
* =============================================================================
|
||||
*/
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tfjs_1 = require("@tensorflow/tfjs");
|
||||
var nodejs_kernel_backend_1 = require("./nodejs_kernel_backend");
|
||||
var ImageType;
|
||||
(function (ImageType) {
|
||||
ImageType["JPEG"] = "jpeg";
|
||||
ImageType["PNG"] = "png";
|
||||
ImageType["GIF"] = "gif";
|
||||
ImageType["BMP"] = "BMP";
|
||||
})(ImageType = exports.ImageType || (exports.ImageType = {}));
|
||||
/**
|
||||
* Decode a JPEG-encoded image to a 3D Tensor of dtype `int32`.
|
||||
*
|
||||
* @param contents The JPEG-encoded image in an Uint8Array.
|
||||
* @param channels An optional int. Defaults to 0. Accepted values are
|
||||
* 0: use the number of channels in the JPEG-encoded image.
|
||||
* 1: output a grayscale image.
|
||||
* 3: output an RGB image.
|
||||
* @param ratio An optional int. Defaults to 1. Downscaling ratio. It is used
|
||||
* when image is type Jpeg.
|
||||
* @param fancyUpscaling An optional bool. Defaults to True. If true use a
|
||||
* slower but nicer upscaling of the chroma planes. It is used when image is
|
||||
* type Jpeg.
|
||||
* @param tryRecoverTruncated An optional bool. Defaults to False. If true try
|
||||
* to recover an image from truncated input. It is used when image is type
|
||||
* Jpeg.
|
||||
* @param acceptableFraction An optional float. Defaults to 1. The minimum
|
||||
* required fraction of lines before a truncated input is accepted. It is
|
||||
* used when image is type Jpeg.
|
||||
* @param dctMethod An optional string. Defaults to "". string specifying a hint
|
||||
* about the algorithm used for decompression. Defaults to "" which maps to
|
||||
* a system-specific default. Currently valid values are ["INTEGER_FAST",
|
||||
* "INTEGER_ACCURATE"]. The hint may be ignored (e.g., the internal jpeg
|
||||
* library changes to a version that does not have that specific option.) It
|
||||
* is used when image is type Jpeg.
|
||||
* @returns A 3D Tensor of dtype `int32` with shape [height, width, 1/3].
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
function decodeJpeg(contents, channels, ratio, fancyUpscaling, tryRecoverTruncated, acceptableFraction, dctMethod) {
|
||||
if (channels === void 0) { channels = 0; }
|
||||
if (ratio === void 0) { ratio = 1; }
|
||||
if (fancyUpscaling === void 0) { fancyUpscaling = true; }
|
||||
if (tryRecoverTruncated === void 0) { tryRecoverTruncated = false; }
|
||||
if (acceptableFraction === void 0) { acceptableFraction = 1; }
|
||||
if (dctMethod === void 0) { dctMethod = ''; }
|
||||
nodejs_kernel_backend_1.ensureTensorflowBackend();
|
||||
return tfjs_1.tidy(function () {
|
||||
return nodejs_kernel_backend_1.nodeBackend()
|
||||
.decodeJpeg(contents, channels, ratio, fancyUpscaling, tryRecoverTruncated, acceptableFraction, dctMethod)
|
||||
.toInt();
|
||||
});
|
||||
}
|
||||
exports.decodeJpeg = decodeJpeg;
|
||||
/**
|
||||
* Decode a PNG-encoded image to a 3D Tensor of dtype `int32`.
|
||||
*
|
||||
* @param contents The PNG-encoded image in an Uint8Array.
|
||||
* @param channels An optional int. Defaults to 0. Accepted values are
|
||||
* 0: use the number of channels in the PNG-encoded image.
|
||||
* 1: output a grayscale image.
|
||||
* 3: output an RGB image.
|
||||
* 4: output an RGBA image.
|
||||
* @param dtype The data type of the result. Only `int32` is supported at this
|
||||
* time.
|
||||
* @returns A 3D Tensor of dtype `int32` with shape [height, width, 1/3/4].
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
function decodePng(contents, channels, dtype) {
|
||||
if (channels === void 0) { channels = 0; }
|
||||
if (dtype === void 0) { dtype = 'int32'; }
|
||||
tfjs_1.util.assert(dtype === 'int32', function () { return 'decodeImage could only return Tensor of type `int32` for now.'; });
|
||||
nodejs_kernel_backend_1.ensureTensorflowBackend();
|
||||
return tfjs_1.tidy(function () {
|
||||
return nodejs_kernel_backend_1.nodeBackend().decodePng(contents, channels).toInt();
|
||||
});
|
||||
}
|
||||
exports.decodePng = decodePng;
|
||||
/**
|
||||
* Decode the first frame of a BMP-encoded image to a 3D Tensor of dtype
|
||||
* `int32`.
|
||||
*
|
||||
* @param contents The BMP-encoded image in an Uint8Array.
|
||||
* @param channels An optional int. Defaults to 0. Accepted values are
|
||||
* 0: use the number of channels in the BMP-encoded image.
|
||||
* 3: output an RGB image.
|
||||
* 4: output an RGBA image.
|
||||
* @returns A 3D Tensor of dtype `int32` with shape [height, width, 3/4].
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
function decodeBmp(contents, channels) {
|
||||
if (channels === void 0) { channels = 0; }
|
||||
nodejs_kernel_backend_1.ensureTensorflowBackend();
|
||||
return tfjs_1.tidy(function () {
|
||||
return nodejs_kernel_backend_1.nodeBackend().decodeBmp(contents, channels).toInt();
|
||||
});
|
||||
}
|
||||
exports.decodeBmp = decodeBmp;
|
||||
/**
|
||||
* Decode the frame(s) of a GIF-encoded image to a 4D Tensor of dtype `int32`.
|
||||
*
|
||||
* @param contents The GIF-encoded image in an Uint8Array.
|
||||
* @returns A 4D Tensor of dtype `int32` with shape [num_frames, height, width,
|
||||
* 3]. RGB channel order.
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
function decodeGif(contents) {
|
||||
nodejs_kernel_backend_1.ensureTensorflowBackend();
|
||||
return tfjs_1.tidy(function () {
|
||||
return nodejs_kernel_backend_1.nodeBackend().decodeGif(contents).toInt();
|
||||
});
|
||||
}
|
||||
exports.decodeGif = decodeGif;
|
||||
/**
|
||||
* Given the encoded bytes of an image, it returns a 3D or 4D tensor of the
|
||||
* decoded image. Supports BMP, GIF, JPEG and PNG formats.
|
||||
*
|
||||
* @param content The encoded image in an Uint8Array.
|
||||
* @param channels An optional int. Defaults to 0, use the number of channels in
|
||||
* the image. Number of color channels for the decoded image. It is used
|
||||
* when image is type Png, Bmp, or Jpeg.
|
||||
* @param dtype The data type of the result. Only `int32` is supported at this
|
||||
* time.
|
||||
* @param expandAnimations A boolean which controls the shape of the returned
|
||||
* op's output. If True, the returned op will produce a 3-D tensor for PNG,
|
||||
* JPEG, and BMP files; and a 4-D tensor for all GIFs, whether animated or
|
||||
* not. If, False, the returned op will produce a 3-D tensor for all file
|
||||
* types and will truncate animated GIFs to the first frame.
|
||||
* @returns A Tensor with dtype `int32` and a 3- or 4-dimensional shape,
|
||||
* depending on the file type. For gif file the returned Tensor shape is
|
||||
* [num_frames, height, width, 3], and for jpeg/png/bmp the returned Tensor
|
||||
* shape is [height, width, channels]
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
function decodeImage(content, channels, dtype, expandAnimations) {
|
||||
if (channels === void 0) { channels = 0; }
|
||||
if (dtype === void 0) { dtype = 'int32'; }
|
||||
if (expandAnimations === void 0) { expandAnimations = true; }
|
||||
tfjs_1.util.assert(dtype === 'int32', function () { return 'decodeImage could only return Tensor of type `int32` for now.'; });
|
||||
var imageType = getImageType(content);
|
||||
// The return tensor has dtype uint8, which is not supported in
|
||||
// TensorFlow.js, casting it to int32 which is the default dtype for image
|
||||
// tensor. If the image is BMP, JPEG or PNG type, expanding the tensors
|
||||
// shape so it becomes Tensor4D, which is the default tensor shape for image
|
||||
// ([batch,imageHeight,imageWidth, depth]).
|
||||
switch (imageType) {
|
||||
case ImageType.JPEG:
|
||||
return decodeJpeg(content, channels);
|
||||
case ImageType.PNG:
|
||||
return decodePng(content, channels);
|
||||
case ImageType.GIF:
|
||||
// If not to expand animations, take first frame of the gif and return
|
||||
// as a 3D tensor.
|
||||
return tfjs_1.tidy(function () {
|
||||
var img = decodeGif(content);
|
||||
return expandAnimations ? img : img.slice(0, 1).squeeze([0]);
|
||||
});
|
||||
case ImageType.BMP:
|
||||
return decodeBmp(content, channels);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
exports.decodeImage = decodeImage;
|
||||
/**
|
||||
* Encodes an image tensor to JPEG.
|
||||
*
|
||||
* @param image A 3-D uint8 Tensor of shape [height, width, channels].
|
||||
* @param format An optional string from: "", "grayscale", "rgb".
|
||||
* Defaults to "". Per pixel image format.
|
||||
* - '': Use a default format based on the number of channels in the image.
|
||||
* - grayscale: Output a grayscale JPEG image. The channels dimension of
|
||||
* image must be 1.
|
||||
* - rgb: Output an RGB JPEG image. The channels dimension of image must
|
||||
* be 3.
|
||||
* @param quality An optional int. Defaults to 95. Quality of the compression
|
||||
* from 0 to 100 (higher is better and slower).
|
||||
* @param progressive An optional bool. Defaults to False. If True, create a
|
||||
* JPEG that loads progressively (coarse to fine).
|
||||
* @param optimizeSize An optional bool. Defaults to False. If True, spend
|
||||
* CPU/RAM to reduce size with no quality change.
|
||||
* @param chromaDownsampling An optional bool. Defaults to True.
|
||||
* See http://en.wikipedia.org/wiki/Chroma_subsampling.
|
||||
* @param densityUnit An optional string from: "in", "cm". Defaults to "in".
|
||||
* Unit used to specify x_density and y_density: pixels per inch ('in') or
|
||||
* centimeter ('cm').
|
||||
* @param xDensity An optional int. Defaults to 300. Horizontal pixels per
|
||||
* density unit.
|
||||
* @param yDensity An optional int. Defaults to 300. Vertical pixels per
|
||||
* density unit.
|
||||
* @param xmpMetadata An optional string. Defaults to "". If not empty, embed
|
||||
* this XMP metadata in the image header.
|
||||
* @returns The JPEG encoded data as an Uint8Array.
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
function encodeJpeg(image, format, quality, progressive, optimizeSize, chromaDownsampling, densityUnit, xDensity, yDensity, xmpMetadata) {
|
||||
if (format === void 0) { format = ''; }
|
||||
if (quality === void 0) { quality = 95; }
|
||||
if (progressive === void 0) { progressive = false; }
|
||||
if (optimizeSize === void 0) { optimizeSize = false; }
|
||||
if (chromaDownsampling === void 0) { chromaDownsampling = true; }
|
||||
if (densityUnit === void 0) { densityUnit = 'in'; }
|
||||
if (xDensity === void 0) { xDensity = 300; }
|
||||
if (yDensity === void 0) { yDensity = 300; }
|
||||
if (xmpMetadata === void 0) { xmpMetadata = ''; }
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var backendEncodeImage;
|
||||
return __generator(this, function (_a) {
|
||||
nodejs_kernel_backend_1.ensureTensorflowBackend();
|
||||
backendEncodeImage = function (imageData) {
|
||||
return nodejs_kernel_backend_1.nodeBackend().encodeJpeg(imageData, image.shape, format, quality, progressive, optimizeSize, chromaDownsampling, densityUnit, xDensity, yDensity, xmpMetadata);
|
||||
};
|
||||
return [2 /*return*/, encodeImage(image, backendEncodeImage)];
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.encodeJpeg = encodeJpeg;
|
||||
/**
|
||||
* Encodes an image tensor to PNG.
|
||||
*
|
||||
* @param image A 3-D uint8 Tensor of shape [height, width, channels].
|
||||
* @param compression An optional int. Defaults to 1. Compression level.
|
||||
* @returns The PNG encoded data as an Uint8Array.
|
||||
*
|
||||
* @doc {heading: 'Operations', subheading: 'Images', namespace: 'node'}
|
||||
*/
|
||||
function encodePng(image, compression) {
|
||||
if (compression === void 0) { compression = 1; }
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var backendEncodeImage;
|
||||
return __generator(this, function (_a) {
|
||||
nodejs_kernel_backend_1.ensureTensorflowBackend();
|
||||
backendEncodeImage = function (imageData) {
|
||||
return nodejs_kernel_backend_1.nodeBackend().encodePng(imageData, image.shape, compression);
|
||||
};
|
||||
return [2 /*return*/, encodeImage(image, backendEncodeImage)];
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.encodePng = encodePng;
|
||||
function encodeImage(image, backendEncodeImage) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var encodedDataTensor, _a, _b, encodedPngData;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
_a = backendEncodeImage;
|
||||
_b = Uint8Array.bind;
|
||||
return [4 /*yield*/, image.data()];
|
||||
case 1:
|
||||
encodedDataTensor = _a.apply(void 0, [new (_b.apply(Uint8Array, [void 0, _c.sent()]))()]);
|
||||
// tslint:disable-next-line:no-any
|
||||
return [4 /*yield*/, encodedDataTensor.data()];
|
||||
case 2:
|
||||
encodedPngData = (
|
||||
// tslint:disable-next-line:no-any
|
||||
_c.sent())[0];
|
||||
encodedDataTensor.dispose();
|
||||
return [2 /*return*/, encodedPngData];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Helper function to get image type based on starting bytes of the image file.
|
||||
*/
|
||||
function getImageType(content) {
|
||||
// Classify the contents of a file based on starting bytes (aka magic number:
|
||||
// https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files)
|
||||
// This aligns with TensorFlow Core code:
|
||||
// https://github.com/tensorflow/tensorflow/blob/4213d5c1bd921f8d5b7b2dc4bbf1eea78d0b5258/tensorflow/core/kernels/decode_image_op.cc#L44
|
||||
if (content.length > 3 && content[0] === 255 && content[1] === 216 &&
|
||||
content[2] === 255) {
|
||||
// JPEG byte chunk starts with `ff d8 ff`
|
||||
return ImageType.JPEG;
|
||||
}
|
||||
else if (content.length > 4 && content[0] === 71 && content[1] === 73 &&
|
||||
content[2] === 70 && content[3] === 56) {
|
||||
// GIF byte chunk starts with `47 49 46 38`
|
||||
return ImageType.GIF;
|
||||
}
|
||||
else if (content.length > 8 && content[0] === 137 && content[1] === 80 &&
|
||||
content[2] === 78 && content[3] === 71 && content[4] === 13 &&
|
||||
content[5] === 10 && content[6] === 26 && content[7] === 10) {
|
||||
// PNG byte chunk starts with `\211 P N G \r \n \032 \n (89 50 4E 47 0D 0A
|
||||
// 1A 0A)`
|
||||
return ImageType.PNG;
|
||||
}
|
||||
else if (content.length > 3 && content[0] === 66 && content[1] === 77) {
|
||||
// BMP byte chunk starts with `42 4d`
|
||||
return ImageType.BMP;
|
||||
}
|
||||
else {
|
||||
throw new Error('Expected image (BMP, JPEG, PNG, or GIF), but got unsupported ' +
|
||||
'image type');
|
||||
}
|
||||
}
|
||||
exports.getImageType = getImageType;
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export {};
|
||||
Generated
Vendored
+560
@@ -0,0 +1,560 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var _this = this;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/**
|
||||
* @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.
|
||||
* =============================================================================
|
||||
*/
|
||||
var tfjs_1 = require("@tensorflow/tfjs");
|
||||
// tslint:disable-next-line: no-imports-from-dist
|
||||
var jasmine_util_1 = require("@tensorflow/tfjs-core/dist/jasmine_util");
|
||||
var fs = require("fs");
|
||||
var util_1 = require("util");
|
||||
var image_1 = require("./image");
|
||||
var tf = require("./index");
|
||||
var readFile = util_1.promisify(fs.readFile);
|
||||
describe('decode images', function () {
|
||||
it('decode png', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_png_test.png')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodePng(uint8array);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([2, 2, 3]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(),
|
||||
[238, 101, 0, 50, 50, 50, 100, 50, 0, 200, 100, 50]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('decode png 1 channels', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_png_test.png')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodeImage(uint8array, 1);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([2, 2, 1]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(), [130, 50, 59, 124]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('decode png 3 channels', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_png_test.png')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodeImage(uint8array);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([2, 2, 3]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(),
|
||||
[238, 101, 0, 50, 50, 50, 100, 50, 0, 200, 100, 50]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('decode png 4 channels', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_png_4_channel_test.png')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodeImage(uint8array, 4);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([2, 2, 4]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(), [
|
||||
238, 101, 0, 255, 50, 50, 50, 255, 100, 50, 0, 255, 200, 100, 50, 255
|
||||
]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('decode bmp', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_bmp_test.bmp')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodeBmp(uint8array);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([2, 2, 3]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(),
|
||||
[238, 101, 0, 50, 50, 50, 100, 50, 0, 200, 100, 50]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('decode bmp through decodeImage', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_bmp_test.bmp')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodeImage(uint8array);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([2, 2, 3]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(),
|
||||
[238, 101, 0, 50, 50, 50, 100, 50, 0, 200, 100, 50]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('decode jpg', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_jpeg_test.jpeg')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodeJpeg(uint8array);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([2, 2, 3]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(),
|
||||
[239, 100, 0, 46, 48, 47, 92, 49, 0, 194, 98, 47]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('decode jpg 1 channel', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_jpeg_test.jpeg')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodeImage(uint8array, 1);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([2, 2, 1]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(), [130, 47, 56, 121]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('decode jpg 3 channels', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_jpeg_test.jpeg')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodeImage(uint8array, 3);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([2, 2, 3]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(),
|
||||
[239, 100, 0, 46, 48, 47, 92, 49, 0, 194, 98, 47]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('decode jpg with 0 channels, use the number of channels in the ' +
|
||||
'JPEG-encoded image', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_jpeg_test.jpeg')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodeImage(uint8array);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([2, 2, 3]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(),
|
||||
[239, 100, 0, 46, 48, 47, 92, 49, 0, 194, 98, 47]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('decode jpg with downscale', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_jpeg_test.jpeg')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodeJpeg(uint8array, 0, 2);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([1, 1, 3]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(), [147, 75, 25]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('decode gif', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/gif_test.gif')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodeImage(uint8array);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([2, 2, 2, 3]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(), [
|
||||
238, 101, 0, 50, 50, 50, 100, 50, 0, 200, 100, 50,
|
||||
200, 100, 50, 34, 68, 102, 170, 0, 102, 255, 255, 255
|
||||
]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('decode gif with no expandAnimation', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var beforeNumTensors, uint8array, imageTensor, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/gif_test.gif')];
|
||||
case 1:
|
||||
uint8array = _c.sent();
|
||||
imageTensor = tf.node.decodeImage(uint8array, 3, 'int32', false);
|
||||
expect(imageTensor.dtype).toBe('int32');
|
||||
expect(imageTensor.shape).toEqual([2, 2, 3]);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 2:
|
||||
_b.apply(_a, [_c.sent(),
|
||||
[238, 101, 0, 50, 50, 50, 100, 50, 0, 200, 100, 50]]);
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors + 1);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('throw error if request non int32 dtype', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var uint8array, error_1;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
_a.trys.push([0, 2, , 3]);
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_png_test.png')];
|
||||
case 1:
|
||||
uint8array = _a.sent();
|
||||
tf.node.decodeImage(uint8array, 0, 'uint8');
|
||||
done.fail();
|
||||
return [3 /*break*/, 3];
|
||||
case 2:
|
||||
error_1 = _a.sent();
|
||||
expect(error_1.message)
|
||||
.toBe('decodeImage could only return Tensor of type `int32` for now.');
|
||||
done();
|
||||
return [3 /*break*/, 3];
|
||||
case 3: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('throw error if decode invalid image type', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var uint8array, error_2;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
_a.trys.push([0, 2, , 3]);
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('package.json')];
|
||||
case 1:
|
||||
uint8array = _a.sent();
|
||||
tf.node.decodeImage(uint8array);
|
||||
done.fail();
|
||||
return [3 /*break*/, 3];
|
||||
case 2:
|
||||
error_2 = _a.sent();
|
||||
expect(error_2.message)
|
||||
.toBe('Expected image (BMP, JPEG, PNG, or GIF), ' +
|
||||
'but got unsupported image type');
|
||||
done();
|
||||
return [3 /*break*/, 3];
|
||||
case 3: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('throw error if backend is not tensorflow', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var testBackend_1, uint8array, err_1;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
_a.trys.push([0, 2, , 3]);
|
||||
testBackend_1 = new jasmine_util_1.TestKernelBackend();
|
||||
tfjs_1.registerBackend('fake', function () { return testBackend_1; });
|
||||
tfjs_1.setBackend('fake');
|
||||
return [4 /*yield*/, getUint8ArrayFromImage('test_objects/images/image_png_test.png')];
|
||||
case 1:
|
||||
uint8array = _a.sent();
|
||||
tf.node.decodeImage(uint8array);
|
||||
done.fail();
|
||||
return [3 /*break*/, 3];
|
||||
case 2:
|
||||
err_1 = _a.sent();
|
||||
expect(err_1.message)
|
||||
.toBe('Expect the current backend to be "tensorflow", but got "fake"');
|
||||
tfjs_1.setBackend('tensorflow');
|
||||
done();
|
||||
return [3 /*break*/, 3];
|
||||
case 3: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
});
|
||||
describe('encode images', function () {
|
||||
it('encodeJpeg', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var imageTensor, beforeNumTensors, jpegEncodedData;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
imageTensor = tf.tensor3d(new Uint8Array([239, 100, 0, 46, 48, 47, 92, 49, 0, 194, 98, 47]), [2, 2, 3]);
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, tf.node.encodeJpeg(imageTensor)];
|
||||
case 1:
|
||||
jpegEncodedData = _a.sent();
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors);
|
||||
expect(image_1.getImageType(jpegEncodedData)).toEqual(image_1.ImageType.JPEG);
|
||||
imageTensor.dispose();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('encodeJpeg grayscale', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var imageTensor, beforeNumTensors, jpegEncodedData;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
imageTensor = tf.tensor3d(new Uint8Array([239, 0, 47, 0]), [2, 2, 1]);
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, tf.node.encodeJpeg(imageTensor, 'grayscale')];
|
||||
case 1:
|
||||
jpegEncodedData = _a.sent();
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors);
|
||||
expect(image_1.getImageType(jpegEncodedData)).toEqual(image_1.ImageType.JPEG);
|
||||
imageTensor.dispose();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('encodeJpeg with parameters', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var imageTensor, format, quality, progressive, optimizeSize, chromaDownsampling, densityUnit, xDensity, yDensity, beforeNumTensors, jpegEncodedData;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
imageTensor = tf.tensor3d(new Uint8Array([239, 100, 0, 46, 48, 47, 92, 49, 0, 194, 98, 47]), [2, 2, 3]);
|
||||
format = 'rgb';
|
||||
quality = 50;
|
||||
progressive = true;
|
||||
optimizeSize = true;
|
||||
chromaDownsampling = false;
|
||||
densityUnit = 'cm';
|
||||
xDensity = 500;
|
||||
yDensity = 500;
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, tf.node.encodeJpeg(imageTensor, format, quality, progressive, optimizeSize, chromaDownsampling, densityUnit, xDensity, yDensity)];
|
||||
case 1:
|
||||
jpegEncodedData = _a.sent();
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors);
|
||||
expect(image_1.getImageType(jpegEncodedData)).toEqual(image_1.ImageType.JPEG);
|
||||
imageTensor.dispose();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('encodePng', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var imageTensor, beforeNumTensors, pngEncodedData, pngDecodedTensor, pngDecodedData, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
imageTensor = tf.tensor3d(new Uint8Array([239, 100, 0, 46, 48, 47, 92, 49, 0, 194, 98, 47]), [2, 2, 3]);
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, tf.node.encodePng(imageTensor)];
|
||||
case 1:
|
||||
pngEncodedData = _c.sent();
|
||||
return [4 /*yield*/, tf.node.decodePng(pngEncodedData)];
|
||||
case 2:
|
||||
pngDecodedTensor = _c.sent();
|
||||
return [4 /*yield*/, pngDecodedTensor.data()];
|
||||
case 3:
|
||||
pngDecodedData = _c.sent();
|
||||
pngDecodedTensor.dispose();
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors);
|
||||
expect(image_1.getImageType(pngEncodedData)).toEqual(image_1.ImageType.PNG);
|
||||
_b = (_a = tfjs_1.test_util).expectArraysEqual;
|
||||
return [4 /*yield*/, imageTensor.data()];
|
||||
case 4:
|
||||
_b.apply(_a, [_c.sent(), pngDecodedData]);
|
||||
imageTensor.dispose();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('encodePng grayscale', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var imageTensor, beforeNumTensors, pngEncodedData;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
imageTensor = tf.tensor3d(new Uint8Array([239, 0, 47, 0]), [2, 2, 1]);
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, tf.node.encodePng(imageTensor)];
|
||||
case 1:
|
||||
pngEncodedData = _a.sent();
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors);
|
||||
expect(image_1.getImageType(pngEncodedData)).toEqual(image_1.ImageType.PNG);
|
||||
imageTensor.dispose();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('encodePng with parameters', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var imageTensor, compression, beforeNumTensors, pngEncodedData;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
imageTensor = tf.tensor3d(new Uint8Array([239, 100, 0, 46, 48, 47, 92, 49, 0, 194, 98, 47]), [2, 2, 3]);
|
||||
compression = 4;
|
||||
beforeNumTensors = tfjs_1.memory().numTensors;
|
||||
return [4 /*yield*/, tf.node.encodePng(imageTensor, compression)];
|
||||
case 1:
|
||||
pngEncodedData = _a.sent();
|
||||
expect(tfjs_1.memory().numTensors).toBe(beforeNumTensors);
|
||||
expect(image_1.getImageType(pngEncodedData)).toEqual(image_1.ImageType.PNG);
|
||||
imageTensor.dispose();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
});
|
||||
function getUint8ArrayFromImage(path) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var image, buf;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, readFile(path)];
|
||||
case 1:
|
||||
image = _a.sent();
|
||||
buf = Buffer.from(image);
|
||||
return [2 /*return*/, new Uint8Array(buf)];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
Generated
Vendored
+55
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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 './register_all_kernels';
|
||||
import * as tf from '@tensorflow/tfjs';
|
||||
import * as nodeIo from './io/index';
|
||||
export declare const version: {
|
||||
'tfjs-node': string;
|
||||
'tfjs-core': string;
|
||||
'tfjs-backend-cpu': string;
|
||||
'tfjs-backend-webgl': string;
|
||||
'tfjs-data': string;
|
||||
'tfjs-layers': string;
|
||||
'tfjs-converter': string;
|
||||
'tfjs': string;
|
||||
};
|
||||
export declare const io: {
|
||||
fileSystem: typeof nodeIo.fileSystem;
|
||||
nodeHTTPRequest: typeof nodeIo.nodeHTTPRequest;
|
||||
copyModel: typeof import("@tensorflow/tfjs-core/dist/io/model_management").copyModel;
|
||||
listModels: typeof import("@tensorflow/tfjs-core/dist/io/model_management").listModels;
|
||||
moveModel: typeof import("@tensorflow/tfjs-core/dist/io/model_management").moveModel;
|
||||
removeModel: typeof import("@tensorflow/tfjs-core/dist/io/model_management").removeModel;
|
||||
browserFiles: typeof import("@tensorflow/tfjs-core/dist/io/browser_files").browserFiles;
|
||||
browserHTTPRequest: typeof import("@tensorflow/tfjs-core/dist/io/http").browserHTTPRequest;
|
||||
concatenateArrayBuffers: typeof import("@tensorflow/tfjs-core/dist/io/io_utils").concatenateArrayBuffers;
|
||||
decodeWeights: typeof import("@tensorflow/tfjs-core/dist/io/io_utils").decodeWeights;
|
||||
encodeWeights: typeof import("@tensorflow/tfjs-core/dist/io/io_utils").encodeWeights;
|
||||
fromMemory: typeof import("@tensorflow/tfjs-core/dist/io/passthrough").fromMemory;
|
||||
getLoadHandlers: (url: string | string[], loadOptions?: tf.io.LoadOptions) => tf.io.IOHandler[];
|
||||
getModelArtifactsInfoForJSON: typeof import("@tensorflow/tfjs-core/dist/io/io_utils").getModelArtifactsInfoForJSON;
|
||||
getSaveHandlers: (url: string | string[]) => tf.io.IOHandler[];
|
||||
http: typeof import("@tensorflow/tfjs-core/dist/io/http").http;
|
||||
isHTTPScheme: typeof import("@tensorflow/tfjs-core/dist/io/http").isHTTPScheme;
|
||||
loadWeights: typeof import("@tensorflow/tfjs-core/dist/io/weights_loader").loadWeights;
|
||||
registerLoadRouter: (loudRouter: import("@tensorflow/tfjs-core/dist/io/router_registry").IORouter) => void;
|
||||
registerSaveRouter: (loudRouter: import("@tensorflow/tfjs-core/dist/io/router_registry").IORouter) => void;
|
||||
weightsLoaderFactory: typeof import("@tensorflow/tfjs-core/dist/io/weights_loader").weightsLoaderFactory;
|
||||
withSaveHandler: typeof import("@tensorflow/tfjs-core/dist/io/passthrough").withSaveHandler;
|
||||
};
|
||||
export * from '@tensorflow/tfjs';
|
||||
export * from './node';
|
||||
Generated
Vendored
+81
@@ -0,0 +1,81 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
function __export(m) {
|
||||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
||||
}
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// Register all kernels.
|
||||
require("./register_all_kernels");
|
||||
var tf = require("@tensorflow/tfjs");
|
||||
var path = require("path");
|
||||
var callbacks_1 = require("./callbacks");
|
||||
var file_system_1 = require("./io/file_system");
|
||||
var nodeIo = require("./io/index");
|
||||
var nodejs_kernel_backend_1 = require("./nodejs_kernel_backend");
|
||||
var nodeVersion = require("./version");
|
||||
// tslint:disable-next-line:no-require-imports
|
||||
var binary = require('node-pre-gyp');
|
||||
var bindingPath = binary.find(path.resolve(path.join(__dirname, '/../package.json')));
|
||||
// Check if the node native addon module exists.
|
||||
// tslint:disable-next-line:no-require-imports
|
||||
var fs = require('fs');
|
||||
if (!fs.existsSync(bindingPath)) {
|
||||
throw new Error("The Node.js native addon module (tfjs_binding.node) can not " +
|
||||
"be found at path: " + String(bindingPath) + ". \nPlease run command " +
|
||||
"'npm rebuild @tensorflow/tfjs-node" +
|
||||
(String(bindingPath).indexOf('tfjs-node-gpu') > 0 ? "-gpu" : "") +
|
||||
" --build-addon-from-source' to " +
|
||||
"rebuild the native addon module. \nIf you have problem with building " +
|
||||
"the addon module, please check " +
|
||||
"https://github.com/tensorflow/tfjs/blob/master/tfjs-node/" +
|
||||
"WINDOWS_TROUBLESHOOTING.md or file an issue.");
|
||||
}
|
||||
// tslint:disable-next-line:no-require-imports
|
||||
var bindings = require(bindingPath);
|
||||
// Merge version and io namespaces.
|
||||
exports.version = __assign({}, tf.version, { 'tfjs-node': nodeVersion.version });
|
||||
exports.io = __assign({}, tf.io, nodeIo);
|
||||
// Export all union package symbols
|
||||
__export(require("@tensorflow/tfjs"));
|
||||
__export(require("./node"));
|
||||
// tslint:disable-next-line:no-require-imports
|
||||
var pjson = require('../package.json');
|
||||
// Side effects for default initialization of Node backend.
|
||||
tf.registerBackend('tensorflow', function () {
|
||||
return new nodejs_kernel_backend_1.NodeJSKernelBackend(bindings, pjson.name);
|
||||
}, 3 /* priority */);
|
||||
var success = tf.setBackend('tensorflow');
|
||||
if (!success) {
|
||||
throw new Error("Could not initialize TensorFlow backend.");
|
||||
}
|
||||
// Register the model saving and loading handlers for the 'file://' URL scheme.
|
||||
tf.io.registerLoadRouter(file_system_1.nodeFileSystemRouter);
|
||||
tf.io.registerSaveRouter(file_system_1.nodeFileSystemRouter);
|
||||
// Register the ProgbarLogger for Model.fit() at verbosity level 1.
|
||||
tf.registerCallbackConstructor(1, callbacks_1.ProgbarLogger);
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
export {};
|
||||
Generated
Vendored
+88
@@ -0,0 +1,88 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var _this = this;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tf = require("./index");
|
||||
describe('Ops are exported from index and work', function () {
|
||||
it('tf.mul works', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var a, b, _a, _b;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
a = tf.tensor1d([1, 2, 3]);
|
||||
b = tf.tensor1d([3, 4, 5]);
|
||||
_b = (_a = tf.test_util).expectArraysClose;
|
||||
return [4 /*yield*/, a.mul(b).data()];
|
||||
case 1:
|
||||
_b.apply(_a, [_c.sent(), [3, 8, 15]]);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
});
|
||||
describe('packages merge', function () {
|
||||
it('versions', function () {
|
||||
expect(tf.version['tfjs']).toBeDefined();
|
||||
expect(tf.version['tfjs-core']).toBeDefined();
|
||||
var expectedNodeVersion =
|
||||
// tslint:disable-next-line:no-require-imports
|
||||
require('../package.json').version;
|
||||
expect(tf.version['tfjs-node']).toBe(expectedNodeVersion);
|
||||
});
|
||||
it('symbols merge', function () {
|
||||
expect(tf.mul).toBeDefined();
|
||||
expect(tf.layers.dense).toBeDefined();
|
||||
expect(tf.io.listModels).toBeDefined();
|
||||
expect(tf.io.nodeHTTPRequest).toBeDefined();
|
||||
});
|
||||
});
|
||||
Generated
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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 { Shape } from '@tensorflow/tfjs';
|
||||
/**
|
||||
* Node.js-specific tensor type: int64-type scalar.
|
||||
*
|
||||
* This class is created for a specific purpose: to support
|
||||
* writing `step`s to TensorBoard via op-kernel bindings.
|
||||
* `step` is required to have an int64 dtype, but TensorFlow.js
|
||||
* (tfjs-core) doesn't have a built-in int64 dtype. This is
|
||||
* related to a lack of `Int64Array` or `Uint64Array` typed
|
||||
* array in basic JavaScript.
|
||||
*
|
||||
* This class is introduced as a workaround.
|
||||
*/
|
||||
export declare class Int64Scalar {
|
||||
readonly value: number;
|
||||
readonly dtype: string;
|
||||
readonly rank: number;
|
||||
private valueArray_;
|
||||
private static endiannessOkay_;
|
||||
constructor(value: number);
|
||||
readonly shape: Shape;
|
||||
/** Get the Int32Array that represents the int64 value. */
|
||||
readonly valueArray: Int32Array;
|
||||
}
|
||||
/**
|
||||
* This method encodes a Int32Array as Int64 layout in order to create TF_INT64
|
||||
* tensor through binding.
|
||||
*/
|
||||
export declare function encodeInt32ArrayAsInt64(value: Int32Array): Int32Array;
|
||||
Generated
Vendored
+98
@@ -0,0 +1,98 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tfjs_1 = require("@tensorflow/tfjs");
|
||||
var os_1 = require("os");
|
||||
var INT32_MAX = 2147483648;
|
||||
/**
|
||||
* Node.js-specific tensor type: int64-type scalar.
|
||||
*
|
||||
* This class is created for a specific purpose: to support
|
||||
* writing `step`s to TensorBoard via op-kernel bindings.
|
||||
* `step` is required to have an int64 dtype, but TensorFlow.js
|
||||
* (tfjs-core) doesn't have a built-in int64 dtype. This is
|
||||
* related to a lack of `Int64Array` or `Uint64Array` typed
|
||||
* array in basic JavaScript.
|
||||
*
|
||||
* This class is introduced as a workaround.
|
||||
*/
|
||||
var Int64Scalar = /** @class */ (function () {
|
||||
function Int64Scalar(value) {
|
||||
this.value = value;
|
||||
this.dtype = 'int64';
|
||||
this.rank = 1;
|
||||
// The reason why we need to check endianness of the machine here is
|
||||
// negative int64 values and the way in which we represent them
|
||||
// using Int32Arrays in JavaScript. We represent each int64 value with
|
||||
// two consecutive elements of an Int32Array. For positive values,
|
||||
// the high part is simply zero; for negative values, the high part
|
||||
// should be -1. The ordering of the low and high parts assumes
|
||||
// little endian (i.e., least significant digits appear first).
|
||||
// This assumption is checked by the lines below.
|
||||
if (Int64Scalar.endiannessOkay_ == null) {
|
||||
if (os_1.endianness() !== 'LE') {
|
||||
throw new Error("Int64Scalar does not support endianness of this machine: " +
|
||||
("" + os_1.endianness()));
|
||||
}
|
||||
Int64Scalar.endiannessOkay_ = true;
|
||||
}
|
||||
tfjs_1.util.assert(value > -INT32_MAX && value < INT32_MAX - 1, function () {
|
||||
return "Got a value outside of the bound of values supported for int64 " +
|
||||
("dtype ([-" + INT32_MAX + ", " + (INT32_MAX - 1) + "]): " + value);
|
||||
});
|
||||
tfjs_1.util.assert(Number.isInteger(value), function () { return "Expected value to be an integer, but got " + value; });
|
||||
// We use two int32 elements to represent a int64 value. This assumes
|
||||
// little endian, which is checked above.
|
||||
var highPart = value >= 0 ? 0 : -1;
|
||||
var lowPart = value % INT32_MAX;
|
||||
this.valueArray_ = new Int32Array([lowPart, highPart]);
|
||||
}
|
||||
Object.defineProperty(Int64Scalar.prototype, "shape", {
|
||||
get: function () {
|
||||
return [];
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(Int64Scalar.prototype, "valueArray", {
|
||||
/** Get the Int32Array that represents the int64 value. */
|
||||
get: function () {
|
||||
return this.valueArray_;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
return Int64Scalar;
|
||||
}());
|
||||
exports.Int64Scalar = Int64Scalar;
|
||||
/**
|
||||
* This method encodes a Int32Array as Int64 layout in order to create TF_INT64
|
||||
* tensor through binding.
|
||||
*/
|
||||
function encodeInt32ArrayAsInt64(value) {
|
||||
if (os_1.endianness() !== 'LE') {
|
||||
throw new Error("Int64Scalar does not support endianness of this machine: " +
|
||||
("" + os_1.endianness()));
|
||||
}
|
||||
var buffer = new Int32Array(value.length * 2);
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
buffer[i * 2] = value[i];
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
exports.encodeInt32ArrayAsInt64 = encodeInt32ArrayAsInt64;
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
export {};
|
||||
Generated
Vendored
+66
@@ -0,0 +1,66 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var int64_tensors_1 = require("./int64_tensors");
|
||||
describe('int64 tensors', function () {
|
||||
it('positive value', function () {
|
||||
var x = new int64_tensors_1.Int64Scalar(42);
|
||||
expect(x.dtype).toEqual('int64');
|
||||
var valueArray = x.valueArray;
|
||||
expect(valueArray.constructor.name).toEqual('Int32Array');
|
||||
expect(valueArray.length).toEqual(2);
|
||||
expect(valueArray[0]).toEqual(42);
|
||||
expect(valueArray[1]).toEqual(0);
|
||||
});
|
||||
it('zero value', function () {
|
||||
var x = new int64_tensors_1.Int64Scalar(0);
|
||||
expect(x.dtype).toEqual('int64');
|
||||
var valueArray = x.valueArray;
|
||||
expect(valueArray.constructor.name).toEqual('Int32Array');
|
||||
expect(valueArray.length).toEqual(2);
|
||||
expect(valueArray[0]).toEqual(0);
|
||||
expect(valueArray[1]).toEqual(0);
|
||||
});
|
||||
it('negative value', function () {
|
||||
var x = new int64_tensors_1.Int64Scalar(-3);
|
||||
expect(x.dtype).toEqual('int64');
|
||||
var valueArray = x.valueArray;
|
||||
expect(valueArray.constructor.name).toEqual('Int32Array');
|
||||
expect(valueArray.length).toEqual(2);
|
||||
expect(valueArray[0]).toEqual(-3);
|
||||
expect(valueArray[1]).toEqual(-1);
|
||||
});
|
||||
it('Non-integer value leads to error', function () {
|
||||
expect(function () { return new int64_tensors_1.Int64Scalar(0.4); }).toThrowError(/integer/);
|
||||
expect(function () { return new int64_tensors_1.Int64Scalar(-3.2); }).toThrowError(/integer/);
|
||||
});
|
||||
it('Out-of-bound value leads to error', function () {
|
||||
expect(function () { return new int64_tensors_1.Int64Scalar(2147483648); }).toThrowError(/bound/);
|
||||
expect(function () { return new int64_tensors_1.Int64Scalar(2147483648 * 2); }).toThrowError(/bound/);
|
||||
expect(function () { return new int64_tensors_1.Int64Scalar(-2147483648 - 1); }).toThrowError(/bound/);
|
||||
});
|
||||
it('encode int32array as int64 layout', function () {
|
||||
var input = Int32Array.from([2, 10]);
|
||||
var valueArray = int64_tensors_1.encodeInt32ArrayAsInt64(input);
|
||||
expect(valueArray.length).toEqual(4);
|
||||
expect(valueArray[0]).toEqual(2);
|
||||
expect(valueArray[1]).toEqual(0);
|
||||
expect(valueArray[2]).toEqual(10);
|
||||
expect(valueArray[3]).toEqual(0);
|
||||
});
|
||||
});
|
||||
Generated
Vendored
+74
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
import * as tf from '@tensorflow/tfjs';
|
||||
export declare class NodeFileSystem implements tf.io.IOHandler {
|
||||
static readonly URL_SCHEME = "file://";
|
||||
protected readonly path: string | string[];
|
||||
readonly MODEL_JSON_FILENAME = "model.json";
|
||||
readonly WEIGHTS_BINARY_FILENAME = "weights.bin";
|
||||
readonly MODEL_BINARY_FILENAME = "tensorflowjs.pb";
|
||||
/**
|
||||
* Constructor of the NodeFileSystem IOHandler.
|
||||
* @param path A single path or an Array of paths.
|
||||
* For saving: expects a single path pointing to an existing or nonexistent
|
||||
* directory. If the directory does not exist, it will be
|
||||
* created.
|
||||
* For loading:
|
||||
* - If the model has JSON topology (e.g., `tf.Model`), a single path
|
||||
* pointing to the JSON file (usually named `model.json`) is expected.
|
||||
* The JSON file is expected to contain `modelTopology` and/or
|
||||
* `weightsManifest`. If `weightManifest` exists, the values of the
|
||||
* weights will be loaded from relative paths (relative to the directory
|
||||
* of `model.json`) as contained in `weightManifest`.
|
||||
* - If the model has binary (protocol buffer GraphDef) topology,
|
||||
* an Array of two paths is expected: the first path should point to the
|
||||
* .pb file and the second path should point to the weight manifest
|
||||
* JSON file.
|
||||
*/
|
||||
constructor(path: string | string[]);
|
||||
save(modelArtifacts: tf.io.ModelArtifacts): Promise<tf.io.SaveResult>;
|
||||
load(): Promise<tf.io.ModelArtifacts>;
|
||||
protected loadBinaryModel(): Promise<tf.io.ModelArtifacts>;
|
||||
protected loadJSONModel(): Promise<tf.io.ModelArtifacts>;
|
||||
private loadWeights;
|
||||
/**
|
||||
* For each item in `this.path`, creates a directory at the path or verify
|
||||
* that the path exists as a directory.
|
||||
*/
|
||||
protected createOrVerifyDirectory(): Promise<void>;
|
||||
}
|
||||
export declare const nodeFileSystemRouter: (url: string | string[]) => NodeFileSystem;
|
||||
/**
|
||||
* Factory function for Node.js native file system IO Handler.
|
||||
*
|
||||
* @param path A single path or an Array of paths.
|
||||
* For saving: expects a single path pointing to an existing or nonexistent
|
||||
* directory. If the directory does not exist, it will be
|
||||
* created.
|
||||
* For loading:
|
||||
* - If the model has JSON topology (e.g., `tf.Model`), a single path
|
||||
* pointing to the JSON file (usually named `model.json`) is expected.
|
||||
* The JSON file is expected to contain `modelTopology` and/or
|
||||
* `weightsManifest`. If `weightManifest` exists, the values of the
|
||||
* weights will be loaded from relative paths (relative to the directory
|
||||
* of `model.json`) as contained in `weightManifest`.
|
||||
* - If the model has binary (protocol buffer GraphDef) topology,
|
||||
* an Array of two paths is expected: the first path should point to the
|
||||
* .pb file and the second path should point to the weight manifest
|
||||
* JSON file.
|
||||
*/
|
||||
export declare function fileSystem(path: string | string[]): NodeFileSystem;
|
||||
Generated
Vendored
+383
@@ -0,0 +1,383 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tf = require("@tensorflow/tfjs");
|
||||
var fs = require("fs");
|
||||
var path_1 = require("path");
|
||||
var util_1 = require("util");
|
||||
var io_utils_1 = require("./io_utils");
|
||||
var stat = util_1.promisify(fs.stat);
|
||||
var writeFile = util_1.promisify(fs.writeFile);
|
||||
var readFile = util_1.promisify(fs.readFile);
|
||||
var mkdir = util_1.promisify(fs.mkdir);
|
||||
function doesNotExistHandler(name) {
|
||||
return function (e) {
|
||||
switch (e.code) {
|
||||
case 'ENOENT':
|
||||
throw new Error(name + " " + e.path + " does not exist: loading failed");
|
||||
default:
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
}
|
||||
var NodeFileSystem = /** @class */ (function () {
|
||||
/**
|
||||
* Constructor of the NodeFileSystem IOHandler.
|
||||
* @param path A single path or an Array of paths.
|
||||
* For saving: expects a single path pointing to an existing or nonexistent
|
||||
* directory. If the directory does not exist, it will be
|
||||
* created.
|
||||
* For loading:
|
||||
* - If the model has JSON topology (e.g., `tf.Model`), a single path
|
||||
* pointing to the JSON file (usually named `model.json`) is expected.
|
||||
* The JSON file is expected to contain `modelTopology` and/or
|
||||
* `weightsManifest`. If `weightManifest` exists, the values of the
|
||||
* weights will be loaded from relative paths (relative to the directory
|
||||
* of `model.json`) as contained in `weightManifest`.
|
||||
* - If the model has binary (protocol buffer GraphDef) topology,
|
||||
* an Array of two paths is expected: the first path should point to the
|
||||
* .pb file and the second path should point to the weight manifest
|
||||
* JSON file.
|
||||
*/
|
||||
function NodeFileSystem(path) {
|
||||
this.MODEL_JSON_FILENAME = 'model.json';
|
||||
this.WEIGHTS_BINARY_FILENAME = 'weights.bin';
|
||||
this.MODEL_BINARY_FILENAME = 'tensorflowjs.pb';
|
||||
if (Array.isArray(path)) {
|
||||
tf.util.assert(path.length === 2, function () { return 'file paths must have a length of 2, ' +
|
||||
("(actual length is " + path.length + ")."); });
|
||||
this.path = path.map(function (p) { return path_1.resolve(p); });
|
||||
}
|
||||
else {
|
||||
this.path = path_1.resolve(path);
|
||||
}
|
||||
}
|
||||
NodeFileSystem.prototype.save = function (modelArtifacts) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var weightsBinPath, weightsManifest, modelJSON, modelJSONPath;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
if (Array.isArray(this.path)) {
|
||||
throw new Error('Cannot perform saving to multiple paths.');
|
||||
}
|
||||
return [4 /*yield*/, this.createOrVerifyDirectory()];
|
||||
case 1:
|
||||
_a.sent();
|
||||
if (!(modelArtifacts.modelTopology instanceof ArrayBuffer)) return [3 /*break*/, 2];
|
||||
throw new Error('NodeFileSystem.save() does not support saving model topology ' +
|
||||
'in binary format yet.');
|
||||
case 2:
|
||||
weightsBinPath = path_1.join(this.path, this.WEIGHTS_BINARY_FILENAME);
|
||||
weightsManifest = [{
|
||||
paths: [this.WEIGHTS_BINARY_FILENAME],
|
||||
weights: modelArtifacts.weightSpecs
|
||||
}];
|
||||
modelJSON = {
|
||||
modelTopology: modelArtifacts.modelTopology,
|
||||
weightsManifest: weightsManifest,
|
||||
format: modelArtifacts.format,
|
||||
generatedBy: modelArtifacts.generatedBy,
|
||||
convertedBy: modelArtifacts.convertedBy
|
||||
};
|
||||
if (modelArtifacts.trainingConfig != null) {
|
||||
modelJSON.trainingConfig = modelArtifacts.trainingConfig;
|
||||
}
|
||||
if (modelArtifacts.signature != null) {
|
||||
modelJSON.signature = modelArtifacts.signature;
|
||||
}
|
||||
if (modelArtifacts.userDefinedMetadata != null) {
|
||||
modelJSON.userDefinedMetadata = modelArtifacts.userDefinedMetadata;
|
||||
}
|
||||
modelJSONPath = path_1.join(this.path, this.MODEL_JSON_FILENAME);
|
||||
return [4 /*yield*/, writeFile(modelJSONPath, JSON.stringify(modelJSON), 'utf8')];
|
||||
case 3:
|
||||
_a.sent();
|
||||
return [4 /*yield*/, writeFile(weightsBinPath, Buffer.from(modelArtifacts.weightData), 'binary')];
|
||||
case 4:
|
||||
_a.sent();
|
||||
return [2 /*return*/, {
|
||||
// TODO(cais): Use explicit tf.io.ModelArtifactsInfo type below once it
|
||||
// is available.
|
||||
// tslint:disable-next-line:no-any
|
||||
modelArtifactsInfo: io_utils_1.getModelArtifactsInfoForJSON(modelArtifacts)
|
||||
}];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
NodeFileSystem.prototype.load = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
return [2 /*return*/, Array.isArray(this.path) ? this.loadBinaryModel() :
|
||||
this.loadJSONModel()];
|
||||
});
|
||||
});
|
||||
};
|
||||
NodeFileSystem.prototype.loadBinaryModel = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var topologyPath, weightManifestPath, topology, weightManifest, modelTopology, weightsManifest, _a, _b, modelArtifacts, _c, weightSpecs, weightData;
|
||||
return __generator(this, function (_d) {
|
||||
switch (_d.label) {
|
||||
case 0:
|
||||
topologyPath = this.path[0];
|
||||
weightManifestPath = this.path[1];
|
||||
return [4 /*yield*/, stat(topologyPath).catch(doesNotExistHandler('Topology Path'))];
|
||||
case 1:
|
||||
topology = _d.sent();
|
||||
return [4 /*yield*/, stat(weightManifestPath)
|
||||
.catch(doesNotExistHandler('Weight Manifest Path'))];
|
||||
case 2:
|
||||
weightManifest = _d.sent();
|
||||
// `this.path` can be either a directory or a file. If it is a file, assume
|
||||
// it is model.json file.
|
||||
if (!topology.isFile()) {
|
||||
throw new Error('File specified for topology is not a file!');
|
||||
}
|
||||
if (!weightManifest.isFile()) {
|
||||
throw new Error('File specified for the weight manifest is not a file!');
|
||||
}
|
||||
return [4 /*yield*/, readFile(this.path[0])];
|
||||
case 3:
|
||||
modelTopology = _d.sent();
|
||||
_b = (_a = JSON).parse;
|
||||
return [4 /*yield*/, readFile(this.path[1], 'utf8')];
|
||||
case 4:
|
||||
weightsManifest = _b.apply(_a, [_d.sent()]);
|
||||
modelArtifacts = {
|
||||
modelTopology: modelTopology,
|
||||
};
|
||||
return [4 /*yield*/, this.loadWeights(weightsManifest, this.path[1])];
|
||||
case 5:
|
||||
_c = _d.sent(), weightSpecs = _c[0], weightData = _c[1];
|
||||
modelArtifacts.weightSpecs = weightSpecs;
|
||||
modelArtifacts.weightData = weightData;
|
||||
return [2 /*return*/, modelArtifacts];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
NodeFileSystem.prototype.loadJSONModel = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var path, info, modelJSON, _a, _b, modelArtifacts, _c, weightSpecs, weightData;
|
||||
return __generator(this, function (_d) {
|
||||
switch (_d.label) {
|
||||
case 0:
|
||||
path = this.path;
|
||||
return [4 /*yield*/, stat(path).catch(doesNotExistHandler('Path'))];
|
||||
case 1:
|
||||
info = _d.sent();
|
||||
if (!info.isFile()) return [3 /*break*/, 5];
|
||||
_b = (_a = JSON).parse;
|
||||
return [4 /*yield*/, readFile(path, 'utf8')];
|
||||
case 2:
|
||||
modelJSON = _b.apply(_a, [_d.sent()]);
|
||||
modelArtifacts = {
|
||||
modelTopology: modelJSON.modelTopology,
|
||||
format: modelJSON.format,
|
||||
generatedBy: modelJSON.generatedBy,
|
||||
convertedBy: modelJSON.convertedBy
|
||||
};
|
||||
if (!(modelJSON.weightsManifest != null)) return [3 /*break*/, 4];
|
||||
return [4 /*yield*/, this.loadWeights(modelJSON.weightsManifest, path)];
|
||||
case 3:
|
||||
_c = _d.sent(), weightSpecs = _c[0], weightData = _c[1];
|
||||
modelArtifacts.weightSpecs = weightSpecs;
|
||||
modelArtifacts.weightData = weightData;
|
||||
_d.label = 4;
|
||||
case 4:
|
||||
if (modelJSON.trainingConfig != null) {
|
||||
modelArtifacts.trainingConfig = modelJSON.trainingConfig;
|
||||
}
|
||||
if (modelJSON.signature != null) {
|
||||
modelArtifacts.signature = modelJSON.signature;
|
||||
}
|
||||
if (modelJSON.userDefinedMetadata != null) {
|
||||
modelArtifacts.userDefinedMetadata = modelJSON.userDefinedMetadata;
|
||||
}
|
||||
return [2 /*return*/, modelArtifacts];
|
||||
case 5: throw new Error('The path to load from must be a file. Loading from a directory ' +
|
||||
'is not supported.');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
NodeFileSystem.prototype.loadWeights = function (weightsManifest, path) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var dirName, buffers, weightSpecs, _i, weightsManifest_1, group, _a, _b, path_2, weightFilePath, buffer;
|
||||
return __generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
dirName = path_1.dirname(path);
|
||||
buffers = [];
|
||||
weightSpecs = [];
|
||||
_i = 0, weightsManifest_1 = weightsManifest;
|
||||
_c.label = 1;
|
||||
case 1:
|
||||
if (!(_i < weightsManifest_1.length)) return [3 /*break*/, 7];
|
||||
group = weightsManifest_1[_i];
|
||||
_a = 0, _b = group.paths;
|
||||
_c.label = 2;
|
||||
case 2:
|
||||
if (!(_a < _b.length)) return [3 /*break*/, 5];
|
||||
path_2 = _b[_a];
|
||||
weightFilePath = path_1.join(dirName, path_2);
|
||||
return [4 /*yield*/, readFile(weightFilePath)
|
||||
.catch(doesNotExistHandler('Weight file'))];
|
||||
case 3:
|
||||
buffer = _c.sent();
|
||||
buffers.push(buffer);
|
||||
_c.label = 4;
|
||||
case 4:
|
||||
_a++;
|
||||
return [3 /*break*/, 2];
|
||||
case 5:
|
||||
weightSpecs.push.apply(weightSpecs, group.weights);
|
||||
_c.label = 6;
|
||||
case 6:
|
||||
_i++;
|
||||
return [3 /*break*/, 1];
|
||||
case 7: return [2 /*return*/, [weightSpecs, io_utils_1.toArrayBuffer(buffers)]];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* For each item in `this.path`, creates a directory at the path or verify
|
||||
* that the path exists as a directory.
|
||||
*/
|
||||
NodeFileSystem.prototype.createOrVerifyDirectory = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var paths, _i, paths_1, path, e_1;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
paths = Array.isArray(this.path) ? this.path : [this.path];
|
||||
_i = 0, paths_1 = paths;
|
||||
_a.label = 1;
|
||||
case 1:
|
||||
if (!(_i < paths_1.length)) return [3 /*break*/, 9];
|
||||
path = paths_1[_i];
|
||||
_a.label = 2;
|
||||
case 2:
|
||||
_a.trys.push([2, 4, , 8]);
|
||||
return [4 /*yield*/, mkdir(path)];
|
||||
case 3:
|
||||
_a.sent();
|
||||
return [3 /*break*/, 8];
|
||||
case 4:
|
||||
e_1 = _a.sent();
|
||||
if (!(e_1.code === 'EEXIST')) return [3 /*break*/, 6];
|
||||
return [4 /*yield*/, stat(path)];
|
||||
case 5:
|
||||
if ((_a.sent()).isFile()) {
|
||||
throw new Error("Path " + path + " exists as a file. The path must be " +
|
||||
"nonexistent or point to a directory.");
|
||||
}
|
||||
return [3 /*break*/, 7];
|
||||
case 6: throw e_1;
|
||||
case 7: return [3 /*break*/, 8];
|
||||
case 8:
|
||||
_i++;
|
||||
return [3 /*break*/, 1];
|
||||
case 9: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
NodeFileSystem.URL_SCHEME = 'file://';
|
||||
return NodeFileSystem;
|
||||
}());
|
||||
exports.NodeFileSystem = NodeFileSystem;
|
||||
exports.nodeFileSystemRouter = function (url) {
|
||||
if (Array.isArray(url)) {
|
||||
if (url.every(function (urlElement) { return urlElement.startsWith(NodeFileSystem.URL_SCHEME); })) {
|
||||
return new NodeFileSystem(url.map(function (urlElement) { return urlElement.slice(NodeFileSystem.URL_SCHEME.length); }));
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (url.startsWith(NodeFileSystem.URL_SCHEME)) {
|
||||
return new NodeFileSystem(url.slice(NodeFileSystem.URL_SCHEME.length));
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
// Registration of `nodeFileSystemRouter` is done in index.ts.
|
||||
/**
|
||||
* Factory function for Node.js native file system IO Handler.
|
||||
*
|
||||
* @param path A single path or an Array of paths.
|
||||
* For saving: expects a single path pointing to an existing or nonexistent
|
||||
* directory. If the directory does not exist, it will be
|
||||
* created.
|
||||
* For loading:
|
||||
* - If the model has JSON topology (e.g., `tf.Model`), a single path
|
||||
* pointing to the JSON file (usually named `model.json`) is expected.
|
||||
* The JSON file is expected to contain `modelTopology` and/or
|
||||
* `weightsManifest`. If `weightManifest` exists, the values of the
|
||||
* weights will be loaded from relative paths (relative to the directory
|
||||
* of `model.json`) as contained in `weightManifest`.
|
||||
* - If the model has binary (protocol buffer GraphDef) topology,
|
||||
* an Array of two paths is expected: the first path should point to the
|
||||
* .pb file and the second path should point to the weight manifest
|
||||
* JSON file.
|
||||
*/
|
||||
function fileSystem(path) {
|
||||
return new NodeFileSystem(path);
|
||||
}
|
||||
exports.fileSystem = fileSystem;
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
export {};
|
||||
Generated
Vendored
+578
@@ -0,0 +1,578 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var _this = this;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tf = require("@tensorflow/tfjs");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var rimraf = require("rimraf");
|
||||
var util_1 = require("util");
|
||||
var tfn = require("../index");
|
||||
var file_system_1 = require("./file_system");
|
||||
describe('File system IOHandler', function () {
|
||||
var mkdtemp = util_1.promisify(fs.mkdtemp);
|
||||
var readFile = util_1.promisify(fs.readFile);
|
||||
var writeFile = util_1.promisify(fs.writeFile);
|
||||
var rimrafPromise = util_1.promisify(rimraf);
|
||||
var modelTopology1 = {
|
||||
'class_name': 'Sequential',
|
||||
'keras_version': '2.1.6',
|
||||
'config': [{
|
||||
'class_name': 'Dense',
|
||||
'config': {
|
||||
'kernel_initializer': {
|
||||
'class_name': 'VarianceScaling',
|
||||
'config': {
|
||||
'distribution': 'uniform',
|
||||
'scale': 1.0,
|
||||
'seed': null,
|
||||
'mode': 'fan_avg'
|
||||
}
|
||||
},
|
||||
'name': 'dense',
|
||||
'kernel_constraint': null,
|
||||
'bias_regularizer': null,
|
||||
'bias_constraint': null,
|
||||
'dtype': 'float32',
|
||||
'activation': 'linear',
|
||||
'trainable': true,
|
||||
'kernel_regularizer': null,
|
||||
'bias_initializer': { 'class_name': 'Zeros', 'config': {} },
|
||||
'units': 1,
|
||||
'batch_input_shape': [null, 3],
|
||||
'use_bias': true,
|
||||
'activity_regularizer': null
|
||||
}
|
||||
}],
|
||||
'backend': 'tensorflow'
|
||||
};
|
||||
var weightSpecs1 = [
|
||||
{
|
||||
name: 'dense/kernel',
|
||||
shape: [3, 1],
|
||||
dtype: 'float32',
|
||||
},
|
||||
{
|
||||
name: 'dense/bias',
|
||||
shape: [1],
|
||||
dtype: 'float32',
|
||||
}
|
||||
];
|
||||
var weightData1 = new ArrayBuffer(16);
|
||||
var testDir;
|
||||
beforeEach(function (done) { return __awaiter(_this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, mkdtemp('tfjs_node_fs_test')];
|
||||
case 1:
|
||||
testDir = _a.sent();
|
||||
done();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
afterEach(function (done) { return __awaiter(_this, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, rimrafPromise(testDir)];
|
||||
case 1:
|
||||
_a.sent();
|
||||
done();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('save succeeds with newly created directory', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var t0, dir, handler;
|
||||
var _this = this;
|
||||
return __generator(this, function (_a) {
|
||||
t0 = new Date();
|
||||
dir = path.join(testDir, 'save-destination');
|
||||
handler = tf.io.getSaveHandlers("file://" + dir)[0];
|
||||
handler
|
||||
.save({
|
||||
modelTopology: modelTopology1,
|
||||
weightSpecs: weightSpecs1,
|
||||
weightData: weightData1,
|
||||
})
|
||||
.then(function (saveResult) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var modelJSONPath, weightsBinPath, modelJSON, _a, _b, weightData, _c;
|
||||
return __generator(this, function (_d) {
|
||||
switch (_d.label) {
|
||||
case 0:
|
||||
expect(saveResult.modelArtifactsInfo.dateSaved.getTime())
|
||||
.toBeGreaterThanOrEqual(t0.getTime());
|
||||
expect(saveResult.modelArtifactsInfo.modelTopologyType)
|
||||
.toEqual('JSON');
|
||||
modelJSONPath = path.join(dir, 'model.json');
|
||||
weightsBinPath = path.join(dir, 'weights.bin');
|
||||
_b = (_a = JSON).parse;
|
||||
return [4 /*yield*/, readFile(modelJSONPath, 'utf8')];
|
||||
case 1:
|
||||
modelJSON = _b.apply(_a, [_d.sent()]);
|
||||
expect(modelJSON.modelTopology).toEqual(modelTopology1);
|
||||
expect(modelJSON.weightsManifest.length).toEqual(1);
|
||||
expect(modelJSON.weightsManifest[0].paths).toEqual(['weights.bin']);
|
||||
expect(modelJSON.weightsManifest[0].weights).toEqual(weightSpecs1);
|
||||
_c = Uint8Array.bind;
|
||||
return [4 /*yield*/, readFile(weightsBinPath)];
|
||||
case 2:
|
||||
weightData = new (_c.apply(Uint8Array, [void 0, _d.sent()]))();
|
||||
expect(weightData.length).toEqual(16);
|
||||
weightData.forEach(function (value) { return expect(value).toEqual(0); });
|
||||
// Verify the content of the files.
|
||||
done();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); })
|
||||
.catch(function (err) { return done.fail(err.stack); });
|
||||
return [2 /*return*/];
|
||||
});
|
||||
}); });
|
||||
it('save fails if path exists as a file', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var dir, handler;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
dir = path.join(testDir, 'save-destination');
|
||||
// Create a file at the locatin.
|
||||
return [4 /*yield*/, writeFile(dir, 'foo')];
|
||||
case 1:
|
||||
// Create a file at the locatin.
|
||||
_a.sent();
|
||||
handler = tf.io.getSaveHandlers("file://" + dir)[0];
|
||||
handler
|
||||
.save({
|
||||
modelTopology: modelTopology1,
|
||||
weightSpecs: weightSpecs1,
|
||||
weightData: weightData1,
|
||||
})
|
||||
.then(function (saveResult) {
|
||||
done.fail('Saving to path of existing file succeeded unexpectedly.');
|
||||
})
|
||||
.catch(function (err) {
|
||||
expect(err.message).toMatch(/.*exists as a file.*directory.*/);
|
||||
done();
|
||||
});
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('save-load round trip: one weight file', function (done) {
|
||||
var handler1 = tf.io.getSaveHandlers("file://" + testDir)[0];
|
||||
handler1
|
||||
.save({
|
||||
modelTopology: modelTopology1,
|
||||
weightSpecs: weightSpecs1,
|
||||
weightData: weightData1,
|
||||
})
|
||||
.then(function (saveResult) {
|
||||
var modelJSONPath = path.join(testDir, 'model.json');
|
||||
var handler2 = tf.io.getLoadHandlers("file://" + modelJSONPath)[0];
|
||||
handler2.load()
|
||||
.then(function (modelArtifacts) {
|
||||
expect(modelArtifacts.modelTopology).toEqual(modelTopology1);
|
||||
expect(modelArtifacts.weightSpecs).toEqual(weightSpecs1);
|
||||
expect(new Float32Array(modelArtifacts.weightData))
|
||||
.toEqual(new Float32Array([0, 0, 0, 0]));
|
||||
done();
|
||||
})
|
||||
.catch(function (err) { return done.fail(err.stack); });
|
||||
})
|
||||
.catch(function (err) { return done.fail(err.stack); });
|
||||
});
|
||||
describe('load json model', function () {
|
||||
it('load: two weight files', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var weightsManifest, modelJSON, modelJSONPath, weightsData1, weightsData2, handler;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
weightsManifest = [
|
||||
{
|
||||
paths: ['weights.1.bin'],
|
||||
weights: [{
|
||||
name: 'dense/kernel',
|
||||
shape: [3, 1],
|
||||
dtype: 'float32',
|
||||
}],
|
||||
},
|
||||
{
|
||||
paths: ['weights.2.bin'],
|
||||
weights: [{
|
||||
name: 'dense/bias',
|
||||
shape: [1],
|
||||
dtype: 'float32',
|
||||
}]
|
||||
}
|
||||
];
|
||||
modelJSON = {
|
||||
modelTopology: modelTopology1,
|
||||
weightsManifest: weightsManifest,
|
||||
};
|
||||
modelJSONPath = path.join(testDir, 'model.json');
|
||||
return [4 /*yield*/, writeFile(modelJSONPath, JSON.stringify(modelJSON), 'utf8')];
|
||||
case 1:
|
||||
_a.sent();
|
||||
weightsData1 = Buffer.from(new Float32Array([-1.1, -3.3, -3.3]).buffer);
|
||||
return [4 /*yield*/, writeFile(path.join(testDir, 'weights.1.bin'), weightsData1, 'binary')];
|
||||
case 2:
|
||||
_a.sent();
|
||||
weightsData2 = Buffer.from(new Float32Array([-7.7]).buffer);
|
||||
return [4 /*yield*/, writeFile(path.join(testDir, 'weights.2.bin'), weightsData2, 'binary')];
|
||||
case 3:
|
||||
_a.sent();
|
||||
handler = tf.io.getLoadHandlers("file://" + modelJSONPath)[0];
|
||||
handler.load()
|
||||
.then(function (modelArtifacts) {
|
||||
expect(modelArtifacts.modelTopology).toEqual(modelTopology1);
|
||||
expect(modelArtifacts.weightSpecs).toEqual([
|
||||
{
|
||||
name: 'dense/kernel',
|
||||
shape: [3, 1],
|
||||
dtype: 'float32',
|
||||
},
|
||||
{
|
||||
name: 'dense/bias',
|
||||
shape: [1],
|
||||
dtype: 'float32',
|
||||
}
|
||||
]);
|
||||
tf.test_util.expectArraysClose(new Float32Array(modelArtifacts.weightData), new Float32Array([-1.1, -3.3, -3.3, -7.7]));
|
||||
done();
|
||||
})
|
||||
.catch(function (err) { return done.fail(err.stack); });
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('loading from nonexistent model.json path fails', function (done) {
|
||||
var handler = tf.io.getLoadHandlers("file://" + testDir + "/foo/model.json")[0];
|
||||
handler.load()
|
||||
.then(function (getModelArtifactsInfoForJSON) {
|
||||
done.fail('Loading from nonexisting model.json path succeeded ' +
|
||||
'unexpectedly.');
|
||||
})
|
||||
.catch(function (err) {
|
||||
expect(err.message)
|
||||
.toMatch(/model\.json.*does not exist.*loading failed/);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('loading from missing weights path fails', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var weightsManifest, modelJSON, modelJSONPath, weightsData1, handler;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
weightsManifest = [
|
||||
{
|
||||
paths: ['weights.1.bin'],
|
||||
weights: [{
|
||||
name: 'dense/kernel',
|
||||
shape: [3, 1],
|
||||
dtype: 'float32',
|
||||
}],
|
||||
},
|
||||
{
|
||||
paths: ['weights.2.bin'],
|
||||
weights: [{
|
||||
name: 'dense/bias',
|
||||
shape: [1],
|
||||
dtype: 'float32',
|
||||
}]
|
||||
}
|
||||
];
|
||||
modelJSON = {
|
||||
modelTopology: modelTopology1,
|
||||
weightsManifest: weightsManifest,
|
||||
};
|
||||
modelJSONPath = path.join(testDir, 'model.json');
|
||||
return [4 /*yield*/, writeFile(modelJSONPath, JSON.stringify(modelJSON), 'utf8')];
|
||||
case 1:
|
||||
_a.sent();
|
||||
weightsData1 = Buffer.from(new Float32Array([-1.1, -3.3, -3.3]).buffer);
|
||||
return [4 /*yield*/, writeFile(path.join(testDir, 'weights.1.bin'), weightsData1, 'binary')];
|
||||
case 2:
|
||||
_a.sent();
|
||||
handler = tf.io.getLoadHandlers("file://" + modelJSONPath)[0];
|
||||
handler.load()
|
||||
.then(function (modelArtifacts) {
|
||||
done.fail('Loading with missing weights file succeeded ' +
|
||||
'unexpectedly.');
|
||||
})
|
||||
.catch(function (err) {
|
||||
expect(err.message)
|
||||
.toMatch(/Weight file .*weights\.2\.bin does not exist/);
|
||||
done();
|
||||
});
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
});
|
||||
describe('load binary model', function () {
|
||||
it('load: two weight files', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var weightsManifest, modelPath, modelData, modelManifestJSONPath, weightsData1, weightsData2, handler;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
weightsManifest = [
|
||||
{
|
||||
paths: ['weights.1.bin'],
|
||||
weights: [{
|
||||
name: 'dense/kernel',
|
||||
shape: [3, 1],
|
||||
dtype: 'float32',
|
||||
}],
|
||||
},
|
||||
{
|
||||
paths: ['weights.2.bin'],
|
||||
weights: [{
|
||||
name: 'dense/bias',
|
||||
shape: [1],
|
||||
dtype: 'float32',
|
||||
}]
|
||||
}
|
||||
];
|
||||
modelPath = path.join(testDir, 'model.pb');
|
||||
modelData = Buffer.from(new Uint8Array([1, 2, 3]).buffer);
|
||||
return [4 /*yield*/, writeFile(modelPath, modelData, 'binary')];
|
||||
case 1:
|
||||
_a.sent();
|
||||
modelManifestJSONPath = path.join(testDir, 'manifest.json');
|
||||
return [4 /*yield*/, writeFile(modelManifestJSONPath, JSON.stringify(weightsManifest), 'utf8')];
|
||||
case 2:
|
||||
_a.sent();
|
||||
weightsData1 = Buffer.from(new Float32Array([-1.1, -3.3, -3.3]).buffer);
|
||||
return [4 /*yield*/, writeFile(path.join(testDir, 'weights.1.bin'), weightsData1, 'binary')];
|
||||
case 3:
|
||||
_a.sent();
|
||||
weightsData2 = Buffer.from(new Float32Array([-7.7]).buffer);
|
||||
return [4 /*yield*/, writeFile(path.join(testDir, 'weights.2.bin'), weightsData2, 'binary')];
|
||||
case 4:
|
||||
_a.sent();
|
||||
handler = new file_system_1.NodeFileSystem(["" + modelPath, "" + modelManifestJSONPath]);
|
||||
handler.load()
|
||||
.then(function (modelArtifacts) {
|
||||
tf.test_util.expectArraysClose(new Uint8Array(modelArtifacts.modelTopology), new Uint8Array(modelData));
|
||||
expect(modelArtifacts.weightSpecs).toEqual([
|
||||
{
|
||||
name: 'dense/kernel',
|
||||
shape: [3, 1],
|
||||
dtype: 'float32',
|
||||
},
|
||||
{
|
||||
name: 'dense/bias',
|
||||
shape: [1],
|
||||
dtype: 'float32',
|
||||
}
|
||||
]);
|
||||
tf.test_util.expectArraysClose(new Float32Array(modelArtifacts.weightData), new Float32Array([-1.1, -3.3, -3.3, -7.7]));
|
||||
done();
|
||||
})
|
||||
.catch(function (err) { return done.fail(err.stack); });
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('path length does not equal 2 fails', function () {
|
||||
expect(function () { return new file_system_1.NodeFileSystem([testDir + "/foo/model.pb"]); })
|
||||
.toThrowError(/file paths must have a length of 2.*actual length is 1.*/);
|
||||
});
|
||||
it('loading from nonexistent model.json path fails', function (done) {
|
||||
var handler = new file_system_1.NodeFileSystem([testDir + "/foo/model.pb", testDir + "/foo/manifest.json"]);
|
||||
handler.load()
|
||||
.then(function (getModelArtifactsInfoForJSON) {
|
||||
done.fail('Loading from nonexisting model.pb path succeeded ' +
|
||||
'unexpectedly.');
|
||||
})
|
||||
.catch(function (err) {
|
||||
expect(err.message)
|
||||
.toMatch(/model\.pb.*does not exist.*loading failed/);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('loading from missing weights path fails', function (done) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var weightsManifest, modelPath, modelData, modelManifestJSONPath, weightsData1, handler;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
weightsManifest = [
|
||||
{
|
||||
paths: ['weights.1.bin'],
|
||||
weights: [{
|
||||
name: 'dense/kernel',
|
||||
shape: [3, 1],
|
||||
dtype: 'float32',
|
||||
}],
|
||||
},
|
||||
{
|
||||
paths: ['weights.2.bin'],
|
||||
weights: [{
|
||||
name: 'dense/bias',
|
||||
shape: [1],
|
||||
dtype: 'float32',
|
||||
}]
|
||||
}
|
||||
];
|
||||
modelPath = path.join(testDir, 'model.pb');
|
||||
modelData = Buffer.from(new Uint8Array([1, 2, 3]).buffer);
|
||||
return [4 /*yield*/, writeFile(modelPath, modelData, 'binary')];
|
||||
case 1:
|
||||
_a.sent();
|
||||
modelManifestJSONPath = path.join(testDir, 'manifest.json');
|
||||
return [4 /*yield*/, writeFile(modelManifestJSONPath, JSON.stringify(weightsManifest), 'utf8')];
|
||||
case 2:
|
||||
_a.sent();
|
||||
weightsData1 = Buffer.from(new Float32Array([-1.1, -3.3, -3.3]).buffer);
|
||||
return [4 /*yield*/, writeFile(path.join(testDir, 'weights.1.bin'), weightsData1, 'binary')];
|
||||
case 3:
|
||||
_a.sent();
|
||||
handler = new file_system_1.NodeFileSystem(["" + modelPath, "" + modelManifestJSONPath]);
|
||||
handler.load()
|
||||
.then(function (modelArtifacts) {
|
||||
done.fail('Loading with missing weights file succeeded ' +
|
||||
'unexpectedly.');
|
||||
})
|
||||
.catch(function (err) {
|
||||
expect(err.message)
|
||||
.toMatch(/Weight file .*weights\.2\.bin does not exist/);
|
||||
done();
|
||||
});
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
});
|
||||
it('Exported file-system handler class exists', function () {
|
||||
var handler = tfn.io.fileSystem(testDir);
|
||||
expect(typeof handler.save).toEqual('function');
|
||||
expect(typeof handler.load).toEqual('function');
|
||||
});
|
||||
it('Save and load model with loss and optimizer', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var model, xs, ys, saveURL, loadURL, model2, optimizerConfig, history2;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
model = tf.sequential();
|
||||
model.add(tf.layers.dense({ units: 1, kernelInitializer: 'zeros', inputShape: [1] }));
|
||||
model.compile({ loss: 'meanSquaredError', optimizer: tf.train.adam(2.5e-2) });
|
||||
xs = tf.tensor2d([1, 2, 3, 4], [4, 1]);
|
||||
ys = tf.tensor2d([-1, -3, -5, -7], [4, 1]);
|
||||
return [4 /*yield*/, model.fit(xs, ys, { epochs: 2, shuffle: false, verbose: 0 })];
|
||||
case 1:
|
||||
_a.sent();
|
||||
saveURL = "file://" + testDir;
|
||||
loadURL = "file://" + testDir + "/model.json";
|
||||
return [4 /*yield*/, model.save(saveURL, { includeOptimizer: true })];
|
||||
case 2:
|
||||
_a.sent();
|
||||
return [4 /*yield*/, tf.loadLayersModel(loadURL)];
|
||||
case 3:
|
||||
model2 = _a.sent();
|
||||
optimizerConfig = model2.optimizer.getConfig();
|
||||
expect(model2.optimizer.getClassName()).toEqual('Adam');
|
||||
expect(optimizerConfig['learningRate']).toEqual(2.5e-2);
|
||||
return [4 /*yield*/, model2.fit(xs, ys, { epochs: 2, shuffle: false, verbose: 0 })];
|
||||
case 4:
|
||||
history2 = _a.sent();
|
||||
// The final loss value from training the model twice, 2 epochs
|
||||
// at a time, should be equal to the final loss of trainig the
|
||||
// model only once with 4 epochs.
|
||||
expect(history2.history.loss[1]).toBeCloseTo(18.603);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('Save and load model with user-defined metadata', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var model, saveURL, loadURL, model2;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
model = tf.sequential();
|
||||
model.add(tf.layers.dense({ units: 3, inputShape: [4] }));
|
||||
model.setUserDefinedMetadata({ 'outputLabels': ['Label1', 'Label2', 'Label3'] });
|
||||
saveURL = "file://" + testDir;
|
||||
loadURL = "file://" + testDir + "/model.json";
|
||||
return [4 /*yield*/, model.save(saveURL)];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [4 /*yield*/, tf.loadLayersModel(loadURL)];
|
||||
case 2:
|
||||
model2 = _a.sent();
|
||||
expect(model2.getUserDefinedMetadata()).toEqual({
|
||||
'outputLabels': ['Label1', 'Label2', 'Label3']
|
||||
});
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
describe('nodeFileSystemRouter', function () {
|
||||
it('should handle single path', function () {
|
||||
expect(file_system_1.nodeFileSystemRouter('file://model.json')).toBeDefined();
|
||||
});
|
||||
it('should handle multiple paths', function () {
|
||||
expect(file_system_1.nodeFileSystemRouter([
|
||||
'file://model.json', 'file://weights.json'
|
||||
])).toBeDefined();
|
||||
});
|
||||
it('should return null for non file path', function () {
|
||||
expect(file_system_1.nodeFileSystemRouter('http://model.json')).toBeNull();
|
||||
});
|
||||
it('should return null for multiple paths with mismatched scheme', function () {
|
||||
expect(file_system_1.nodeFileSystemRouter([
|
||||
'file://model.json', 'http://weights.json'
|
||||
])).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
Generated
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
/**
|
||||
* Public exports from the `io` module.
|
||||
*/
|
||||
export { fileSystem } from './file_system';
|
||||
export { nodeHTTPRequest } from './node_http';
|
||||
Generated
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/**
|
||||
* Public exports from the `io` module.
|
||||
*/
|
||||
var file_system_1 = require("./file_system");
|
||||
exports.fileSystem = file_system_1.fileSystem;
|
||||
var node_http_1 = require("./node_http");
|
||||
exports.nodeHTTPRequest = node_http_1.nodeHTTPRequest;
|
||||
Generated
Vendored
+41
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
/// <reference types="node" />
|
||||
import * as tf from '@tensorflow/tfjs';
|
||||
/**
|
||||
* Convert an ArrayBuffer to a Buffer.
|
||||
*/
|
||||
export declare function toBuffer(ab: ArrayBuffer): Buffer;
|
||||
/**
|
||||
* Convert a Buffer or an Array of Buffers to an ArrayBuffer.
|
||||
*
|
||||
* If the input is an Array of Buffers, they will be concatenated in the
|
||||
* specified order to form the output ArrayBuffer.
|
||||
*/
|
||||
export declare function toArrayBuffer(buf: Buffer | Buffer[]): ArrayBuffer;
|
||||
/**
|
||||
* Populate ModelArtifactsInfo fields for a model with JSON topology.
|
||||
* @param modelArtifacts
|
||||
* @returns A ModelArtifactsInfo object.
|
||||
*/
|
||||
export declare function getModelArtifactsInfoForJSON(modelArtifacts: tf.io.ModelArtifacts): {
|
||||
dateSaved: Date;
|
||||
modelTopologyType: string;
|
||||
modelTopologyBytes: number;
|
||||
weightSpecsBytes: number;
|
||||
weightDataBytes: number;
|
||||
};
|
||||
Generated
Vendored
+81
@@ -0,0 +1,81 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/**
|
||||
* Convert an ArrayBuffer to a Buffer.
|
||||
*/
|
||||
function toBuffer(ab) {
|
||||
var view = new Uint8Array(ab);
|
||||
return Buffer.from(view); // copies data
|
||||
}
|
||||
exports.toBuffer = toBuffer;
|
||||
/**
|
||||
* Convert a Buffer or an Array of Buffers to an ArrayBuffer.
|
||||
*
|
||||
* If the input is an Array of Buffers, they will be concatenated in the
|
||||
* specified order to form the output ArrayBuffer.
|
||||
*/
|
||||
function toArrayBuffer(buf) {
|
||||
if (Array.isArray(buf)) {
|
||||
// An Array of Buffers.
|
||||
var totalLength = 0;
|
||||
for (var _i = 0, buf_1 = buf; _i < buf_1.length; _i++) {
|
||||
var buffer = buf_1[_i];
|
||||
totalLength += buffer.length;
|
||||
}
|
||||
var ab = new ArrayBuffer(totalLength);
|
||||
var view = new Uint8Array(ab);
|
||||
var pos = 0;
|
||||
for (var _a = 0, buf_2 = buf; _a < buf_2.length; _a++) {
|
||||
var buffer = buf_2[_a];
|
||||
pos += buffer.copy(view, pos);
|
||||
}
|
||||
return ab;
|
||||
}
|
||||
else {
|
||||
// A single Buffer. Return a copy of the underlying ArrayBuffer slice.
|
||||
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
||||
}
|
||||
}
|
||||
exports.toArrayBuffer = toArrayBuffer;
|
||||
// TODO(cais): Use explicit tf.io.ModelArtifactsInfo return type below once it
|
||||
// is available.
|
||||
/**
|
||||
* Populate ModelArtifactsInfo fields for a model with JSON topology.
|
||||
* @param modelArtifacts
|
||||
* @returns A ModelArtifactsInfo object.
|
||||
*/
|
||||
function getModelArtifactsInfoForJSON(modelArtifacts) {
|
||||
if (modelArtifacts.modelTopology instanceof ArrayBuffer) {
|
||||
throw new Error('Expected JSON model topology, received ArrayBuffer.');
|
||||
}
|
||||
return {
|
||||
dateSaved: new Date(),
|
||||
modelTopologyType: 'JSON',
|
||||
modelTopologyBytes: modelArtifacts.modelTopology == null ?
|
||||
0 :
|
||||
Buffer.byteLength(JSON.stringify(modelArtifacts.modelTopology), 'utf8'),
|
||||
weightSpecsBytes: modelArtifacts.weightSpecs == null ?
|
||||
0 :
|
||||
Buffer.byteLength(JSON.stringify(modelArtifacts.weightSpecs), 'utf8'),
|
||||
weightDataBytes: modelArtifacts.weightData == null ?
|
||||
0 :
|
||||
modelArtifacts.weightData.byteLength,
|
||||
};
|
||||
}
|
||||
exports.getModelArtifactsInfoForJSON = getModelArtifactsInfoForJSON;
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
export {};
|
||||
Generated
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var io_utils_1 = require("./io_utils");
|
||||
describe('toBuffer', function () {
|
||||
it('Simple case', function () {
|
||||
var ab = new Uint8Array([3, 2, 1]).buffer;
|
||||
var buffer = io_utils_1.toBuffer(ab);
|
||||
expect(new Uint8Array(buffer)).toEqual(new Uint8Array([3, 2, 1]));
|
||||
});
|
||||
});
|
||||
describe('toArrayBuffer', function () {
|
||||
it('Single Buffer', function () {
|
||||
var buf = Buffer.from([10, 20, 30]);
|
||||
var ab = io_utils_1.toArrayBuffer(buf);
|
||||
expect(new Uint8Array(ab)).toEqual(new Uint8Array([10, 20, 30]));
|
||||
});
|
||||
it('Two Buffers', function () {
|
||||
var buf1 = Buffer.from([10, 20, 30]);
|
||||
var buf2 = Buffer.from([40, 50, 60]);
|
||||
var ab = io_utils_1.toArrayBuffer([buf1, buf2]);
|
||||
expect(new Uint8Array(ab)).toEqual(new Uint8Array([
|
||||
10, 20, 30, 40, 50, 60
|
||||
]));
|
||||
});
|
||||
it('Three Buffers', function () {
|
||||
var buf1 = Buffer.from([10, 20, 30]);
|
||||
var buf2 = Buffer.from([40, 50, 60]);
|
||||
var buf3 = Buffer.from([3, 2, 1]);
|
||||
var ab = io_utils_1.toArrayBuffer([buf1, buf2, buf3]);
|
||||
expect(new Uint8Array(ab)).toEqual(new Uint8Array([
|
||||
10, 20, 30, 40, 50, 60, 3, 2, 1
|
||||
]));
|
||||
});
|
||||
it('Zero buffers', function () {
|
||||
var ab = io_utils_1.toArrayBuffer([]);
|
||||
expect(new Uint8Array(ab)).toEqual(new Uint8Array([]));
|
||||
});
|
||||
});
|
||||
Generated
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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 { io } from '@tensorflow/tfjs';
|
||||
/**
|
||||
* Factory function for HTTP IO Handler in Node.js.
|
||||
*
|
||||
* @param path URL path or an array of them.
|
||||
* @param requestInit Request init for the HTTP IOHandler. May include fields
|
||||
* such as "credentials" and "cache". (Optional)
|
||||
* @param weightPathPrefix A path prefix for weight loading . (Optional).
|
||||
*/
|
||||
export declare function nodeHTTPRequest(path: string, requestInit?: RequestInit, weightPathPrefix?: string): io.IOHandler;
|
||||
export declare const nodeHTTPRequestRouter: (url: string) => io.IOHandler;
|
||||
Generated
Vendored
+44
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tfjs_1 = require("@tensorflow/tfjs");
|
||||
/**
|
||||
* Factory function for HTTP IO Handler in Node.js.
|
||||
*
|
||||
* @param path URL path or an array of them.
|
||||
* @param requestInit Request init for the HTTP IOHandler. May include fields
|
||||
* such as "credentials" and "cache". (Optional)
|
||||
* @param weightPathPrefix A path prefix for weight loading . (Optional).
|
||||
*/
|
||||
function nodeHTTPRequest(path, requestInit, weightPathPrefix) {
|
||||
return tfjs_1.io.browserHTTPRequest(path, { requestInit: requestInit, weightPathPrefix: weightPathPrefix });
|
||||
}
|
||||
exports.nodeHTTPRequest = nodeHTTPRequest;
|
||||
exports.nodeHTTPRequestRouter = function (url) {
|
||||
var isHTTP = true;
|
||||
if (Array.isArray(url)) {
|
||||
isHTTP = url.every(function (urlItem) { return tfjs_1.io.isHTTPScheme(urlItem); });
|
||||
}
|
||||
else {
|
||||
isHTTP = tfjs_1.io.isHTTPScheme(url);
|
||||
}
|
||||
if (isHTTP) {
|
||||
return nodeHTTPRequest(url);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
export {};
|
||||
Generated
Vendored
+202
@@ -0,0 +1,202 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 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.
|
||||
* =============================================================================
|
||||
*/
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var _this = this;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tf = require("@tensorflow/tfjs");
|
||||
var tfn = require("../index");
|
||||
// We still need node-fetch so that we can mock the core
|
||||
// tf.env().platform.fetch call and return a valid response.
|
||||
// tslint:disable-next-line:no-require-imports
|
||||
var fetch = require('node-fetch');
|
||||
var OCTET_STREAM_TYPE = 'application/octet-stream';
|
||||
var JSON_TYPE = 'application/json';
|
||||
// Test data;
|
||||
var modelTopology1 = {
|
||||
'class_name': 'Sequential',
|
||||
'keras_version': '2.1.4',
|
||||
'config': [{
|
||||
'class_name': 'Dense',
|
||||
'config': {
|
||||
'kernel_initializer': {
|
||||
'class_name': 'VarianceScaling',
|
||||
'config': {
|
||||
'distribution': 'uniform',
|
||||
'scale': 1.0,
|
||||
'seed': null,
|
||||
'mode': 'fan_avg'
|
||||
}
|
||||
},
|
||||
'name': 'dense',
|
||||
'kernel_constraint': null,
|
||||
'bias_regularizer': null,
|
||||
'bias_constraint': null,
|
||||
'dtype': 'float32',
|
||||
'activation': 'linear',
|
||||
'trainable': true,
|
||||
'kernel_regularizer': null,
|
||||
'bias_initializer': { 'class_name': 'Zeros', 'config': {} },
|
||||
'units': 1,
|
||||
'batch_input_shape': [null, 3],
|
||||
'use_bias': true,
|
||||
'activity_regularizer': null
|
||||
}
|
||||
}],
|
||||
'backend': 'tensorflow'
|
||||
};
|
||||
describe('nodeHTTPRequest-load', function () {
|
||||
var requestInits;
|
||||
var setupFakeWeightFiles = function (fileBufferMap) {
|
||||
spyOn(tf.env().platform, 'fetch')
|
||||
.and.callFake(function (path, init) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var contentType = '';
|
||||
if (path.endsWith('model.json')) {
|
||||
contentType = JSON_TYPE;
|
||||
}
|
||||
else if (path.endsWith('weightfile0') || path.endsWith('weightfile1')) {
|
||||
contentType = OCTET_STREAM_TYPE;
|
||||
}
|
||||
else {
|
||||
reject(new Error("Invalid path: " + path));
|
||||
}
|
||||
requestInits.push(init);
|
||||
resolve(new fetch.Response(fileBufferMap[path], { 'headers': { 'Content-Type': contentType } }));
|
||||
});
|
||||
});
|
||||
};
|
||||
beforeEach(function () {
|
||||
requestInits = [];
|
||||
});
|
||||
it('Constructor', function () {
|
||||
var handler = tfn.io.nodeHTTPRequest('./foo_model.json');
|
||||
expect(handler == null).toEqual(false);
|
||||
expect(typeof handler.load).toEqual('function');
|
||||
expect(typeof handler.save).toEqual('function');
|
||||
});
|
||||
it('Load through NodeHTTPRequest object', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var weightManifest1, floatData, handler, modelArtifacts;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
weightManifest1 = [{
|
||||
paths: ['weightfile0'],
|
||||
weights: [
|
||||
{
|
||||
name: 'dense/kernel',
|
||||
shape: [3, 1],
|
||||
dtype: 'float32',
|
||||
},
|
||||
{
|
||||
name: 'dense/bias',
|
||||
shape: [1],
|
||||
dtype: 'float32',
|
||||
}
|
||||
]
|
||||
}];
|
||||
floatData = new Float32Array([1, 3, 3, 7]);
|
||||
setupFakeWeightFiles({
|
||||
'http://localhost/model.json': JSON.stringify({ modelTopology: modelTopology1, weightsManifest: weightManifest1 }),
|
||||
'http://localhost/weightfile0': floatData,
|
||||
});
|
||||
handler = tfn.io.nodeHTTPRequest('http://localhost/model.json', { credentials: 'include', cache: 'no-cache' });
|
||||
return [4 /*yield*/, handler.load()];
|
||||
case 1:
|
||||
modelArtifacts = _a.sent();
|
||||
expect(modelArtifacts.modelTopology).toEqual(modelTopology1);
|
||||
expect(modelArtifacts.weightSpecs).toEqual(weightManifest1[0].weights);
|
||||
expect(new Float32Array(modelArtifacts.weightData)).toEqual(floatData);
|
||||
expect(requestInits).toEqual([
|
||||
{ credentials: 'include', cache: 'no-cache' },
|
||||
{ credentials: 'include', cache: 'no-cache' }
|
||||
]);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
it('Load through registered handler', function () { return __awaiter(_this, void 0, void 0, function () {
|
||||
var weightManifest1, floatData, model;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
weightManifest1 = [{
|
||||
paths: ['weightfile0'],
|
||||
weights: [
|
||||
{
|
||||
name: 'dense/kernel',
|
||||
shape: [3, 1],
|
||||
dtype: 'float32',
|
||||
},
|
||||
{
|
||||
name: 'dense/bias',
|
||||
shape: [1],
|
||||
dtype: 'float32',
|
||||
}
|
||||
]
|
||||
}];
|
||||
floatData = new Float32Array([1, 3, 3, 7]);
|
||||
setupFakeWeightFiles({
|
||||
'https://localhost/model.json': JSON.stringify({ modelTopology: modelTopology1, weightsManifest: weightManifest1 }),
|
||||
'https://localhost/weightfile0': floatData,
|
||||
});
|
||||
return [4 /*yield*/, tf.loadLayersModel('https://localhost/model.json')];
|
||||
case 1:
|
||||
model = _a.sent();
|
||||
expect(model.inputs.length).toEqual(1);
|
||||
expect(model.inputs[0].shape).toEqual([null, 3]);
|
||||
expect(model.outputs.length).toEqual(1);
|
||||
expect(model.outputs[0].shape).toEqual([null, 1]);
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
});
|
||||
Generated
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
import { KernelConfig } from '@tensorflow/tfjs';
|
||||
export declare const absConfig: KernelConfig;
|
||||
Generated
Vendored
+36
@@ -0,0 +1,36 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @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.
|
||||
* =============================================================================
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tfjs_1 = require("@tensorflow/tfjs");
|
||||
var nodejs_kernel_backend_1 = require("../nodejs_kernel_backend");
|
||||
exports.absConfig = {
|
||||
kernelName: tfjs_1.Abs,
|
||||
backendName: 'tensorflow',
|
||||
kernelFunc: function (args) {
|
||||
var x = args.inputs.x;
|
||||
var backend = args.backend;
|
||||
if (x.dtype === 'complex64') {
|
||||
var opAttrs = [
|
||||
nodejs_kernel_backend_1.createTensorsTypeOpAttr('T', x.dtype),
|
||||
nodejs_kernel_backend_1.createTensorsTypeOpAttr('Tout', 'float32')
|
||||
];
|
||||
return backend.executeSingleOutput('ComplexAbs', opAttrs, [x]);
|
||||
}
|
||||
return backend.executeSingleInput(tfjs_1.Abs, x);
|
||||
}
|
||||
};
|
||||
Generated
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
import { KernelConfig } from '@tensorflow/tfjs';
|
||||
export declare const acosConfig: KernelConfig;
|
||||
Generated
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @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.
|
||||
* =============================================================================
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tfjs_1 = require("@tensorflow/tfjs");
|
||||
exports.acosConfig = {
|
||||
kernelName: tfjs_1.Acos,
|
||||
backendName: 'tensorflow',
|
||||
kernelFunc: function (args) {
|
||||
var x = args.inputs.x;
|
||||
var backend = args.backend;
|
||||
return backend.executeSingleInput(tfjs_1.Acos, x);
|
||||
}
|
||||
};
|
||||
Generated
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
import { KernelConfig } from '@tensorflow/tfjs';
|
||||
export declare const acoshConfig: KernelConfig;
|
||||
Generated
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @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.
|
||||
* =============================================================================
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tfjs_1 = require("@tensorflow/tfjs");
|
||||
exports.acoshConfig = {
|
||||
kernelName: tfjs_1.Acosh,
|
||||
backendName: 'tensorflow',
|
||||
kernelFunc: function (args) {
|
||||
var x = args.inputs.x;
|
||||
var backend = args.backend;
|
||||
return backend.executeSingleInput(tfjs_1.Acosh, x);
|
||||
}
|
||||
};
|
||||
Generated
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
import { KernelConfig } from '@tensorflow/tfjs';
|
||||
export declare const addConfig: KernelConfig;
|
||||
Generated
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
"use strict";
|
||||
/**
|
||||
* @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.
|
||||
* =============================================================================
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tfjs_1 = require("@tensorflow/tfjs");
|
||||
var nodejs_kernel_backend_1 = require("../nodejs_kernel_backend");
|
||||
exports.addConfig = {
|
||||
kernelName: tfjs_1.Add,
|
||||
backendName: 'tensorflow',
|
||||
kernelFunc: function (args) {
|
||||
var _a = args.inputs, a = _a.a, b = _a.b;
|
||||
var backend = args.backend;
|
||||
var opAttrs = [nodejs_kernel_backend_1.createTensorsTypeOpAttr('T', tfjs_1.backend_util.upcastType(a.dtype, b.dtype))];
|
||||
return backend.executeSingleOutput(tfjs_1.Add, opAttrs, [a, b]);
|
||||
}
|
||||
};
|
||||
Generated
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
import { KernelConfig } from '@tensorflow/tfjs';
|
||||
export declare const addNConfig: KernelConfig;
|
||||
Loaded 100 of 189 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user