Skip to content

Commit 73d7ca2

Browse files
YuningQiudevpramod
andauthored
Add new sample for TensorFlow AMX BF16 Inference (#1549)
Signed-off-by: devpramod-intel <[email protected]> Co-authored-by: devpramod-intel <[email protected]>
1 parent dfb03a0 commit 73d7ca2

14 files changed

+746
-0
lines changed

AI-and-Analytics/Features-and-Functionality/IntelTensorFlow_AMX_BF16_Inference/IntelTensorFlow_AMX_BF16_Inference.ipynb

+409
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# details about this Python script
2+
# - Enable auto-mixed precision with few code changes for faster inference.
3+
# - Image Classification task using TensorFlow Hub's ResNet50v1.5 pretrained model.
4+
# - Export the optimized model in the SavedModel format.
5+
6+
# Importing libraries
7+
import os
8+
import numpy as np
9+
import time
10+
import PIL.Image as Image
11+
import tensorflow as tf
12+
import tensorflow_hub as hub
13+
from datetime import datetime
14+
import requests
15+
from copy import deepcopy
16+
print("We are using Tensorflow version: ", tf.__version__)
17+
18+
# Check if hardware supports AMX
19+
20+
from cpuinfo import get_cpu_info
21+
info = get_cpu_info()
22+
flags = info['flags']
23+
amx_supported = False
24+
for flag in flags:
25+
if "amx" in flag:
26+
amx_supported = True
27+
print("AMX is supported on current hardware. Code sample can be run.\n")
28+
if not amx_supported:
29+
print("AMX is not supported on current hardware. Code sample cannot be run.\n")
30+
sys.exit("AMX is not supported on current hardware. Code sample cannot be run.\n")
31+
32+
33+
tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
34+
data_root = tf.keras.utils.get_file(
35+
'flower_photos',
36+
'https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',
37+
untar=True)
38+
39+
batch_size = 512
40+
img_height = 224
41+
img_width = 224
42+
43+
train_ds = tf.keras.utils.image_dataset_from_directory(
44+
str(data_root),
45+
validation_split=0.2,
46+
subset="training",
47+
seed=123,
48+
image_size=(img_height, img_width),
49+
batch_size=batch_size
50+
)
51+
52+
val_ds = tf.keras.utils.image_dataset_from_directory(
53+
str(data_root),
54+
validation_split=0.2,
55+
subset="validation",
56+
seed=123,
57+
image_size=(img_height, img_width),
58+
batch_size=batch_size
59+
)
60+
61+
class_names = np.array(train_ds.class_names)
62+
print("The flower dataset has " + str(len(class_names)) + " classes: ", class_names)
63+
64+
# import pre-trained fp_32 model
65+
fp32_model = tf.keras.models.load_model('models/my_saved_model_fp32')
66+
67+
normalization_layer = tf.keras.layers.Rescaling(1./255)
68+
train_ds = train_ds.map(lambda x, y: (normalization_layer(x), y)) # Where x—images, y—labels.
69+
val_ds = val_ds.map(lambda x, y: (normalization_layer(x), y)) # Where x—images, y—labels.
70+
71+
AUTOTUNE = tf.data.AUTOTUNE
72+
train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
73+
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
74+
75+
import time
76+
start = time.time()
77+
fp32_history = fp32_model.evaluate(val_ds)
78+
fp32_inference_time = time.time() - start
79+
80+
81+
82+
# Reload the model as the bf16 model with AVX512 to compare inference time
83+
os.environ["ONEDNN_MAX_CPU_ISA"] = "AVX512_BF16"
84+
tf.config.optimizer.set_experimental_options({'auto_mixed_precision_onednn_bfloat16':True})
85+
bf16_model_noAmx = tf.keras.models.load_model('models/my_saved_model_fp32')
86+
87+
bf16_model_noAmx_export_path = "models/my_saved_model_bf16_noAmx"
88+
bf16_model_noAmx.save(bf16_model_noAmx_export_path)
89+
90+
start = time.time()
91+
bf16_noAmx_history = bf16_model_noAmx.evaluate(val_ds)
92+
bf16_noAmx_inference_time = time.time() - start
93+
94+
95+
# Reload the model as the bf16 model with AMX to compare inference time
96+
os.environ["ONEDNN_MAX_CPU_ISA"] = "AMX_BF16"
97+
tf.config.optimizer.set_experimental_options({'auto_mixed_precision_onednn_bfloat16':True})
98+
bf16_model_withAmx = tf.keras.models.load_model('models/my_saved_model_fp32')
99+
100+
bf16_model_withAmx_export_path = "models/my_saved_model_bf16_with_amx"
101+
bf16_model_withAmx.save(bf16_model_withAmx_export_path)
102+
103+
start = time.time()
104+
bf16_withAmx_history = bf16_model_withAmx.evaluate(val_ds)
105+
bf16_withAmx_inference_time = time.time() - start
106+
107+
108+
# Summary of results
109+
print("Summary")
110+
print("FP32 inference time: %.3f" %fp32_inference_time)
111+
print("BF16 with AVX512 inference time: %.3f" %bf16_noAmx_inference_time)
112+
print("BF16 with AMX inference time: %.3f" %bf16_withAmx_inference_time)
113+
114+
import matplotlib.pyplot as plt
115+
plt.figure()
116+
plt.title("Resnet50 Inference Time")
117+
plt.xlabel("Test Case")
118+
plt.ylabel("Inference Time (seconds)")
119+
plt.bar(["FP32", "BF16 with AVX512", "BF16 with AMX"], [fp32_inference_time, bf16_noAmx_inference_time, bf16_withAmx_inference_time])
120+
121+
fp32_inference_accuracy = fp32_history[1]
122+
bf16_noAmx_inference_accuracy = bf16_noAmx_history[1]
123+
bf16_withAmx_inference_accuracy = bf16_withAmx_history[1]
124+
plt.figure()
125+
plt.title("Resnet50 Inference Accuracy")
126+
plt.xlabel("Test Case")
127+
plt.ylabel("Inference Accuracy")
128+
plt.bar(["FP32", "BF16 with AVX512", "BF16 with AMX"], [fp32_inference_accuracy, bf16_noAmx_inference_accuracy, bf16_withAmx_inference_accuracy])
129+
130+
print('[CODE_SAMPLE_COMPLETED_SUCCESFULLY]')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Copyright Intel Corporation
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4+
5+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Enabling Auto-Mixed Precision for Transfer Learning with TensorFlow
2+
This tutorial guides you through the process of enabling auto-mixed precision to use low-precision datatypes, like bfloat16, for model inference with TensorFlow* (TF).
3+
4+
The Intel® Optimization for TensorFlow* enables TensorFlow* with optimizations for performance boost on Intel® hardware. For example, newer optimizations include AVX-512 Vector Neural Network Instructions (AVX512 VNNI) and Intel® Advanced Matrix Extensions (Intel® AMX).
5+
6+
| Area | Description
7+
|:--- |:---
8+
| What you will learn | Inference performance improvements with Intel® AMX BF16
9+
| Time to complete | 10 minutes
10+
| Category | Code Optimization
11+
12+
13+
## Purpose
14+
15+
The Intel® Optimization for TensorFlow* gives users the ability to speed up inference on Intel® Xeon Scalable processors with lower precision data formats and specialized computer instructions. The bfloat16 (BF16) data format uses half the bit width of floating-point-32 (FP32), lowering the amount of memory needed and execution time to process. You should notice performance optimization with the AMX instruction set when compared to AVX-512.
16+
17+
## Prerequisites
18+
19+
| Optimized for | Description
20+
|:--- |:---
21+
| OS | Ubuntu* 18.04 or newer
22+
| Hardware | Intel® Xeon® Scalable processor family or newer
23+
| Software | Intel® AI Analytics Toolkit (AI Kit)
24+
25+
### For Local Development Environments
26+
27+
You will need to download and install the following toolkits, tools, and components to use the sample.
28+
29+
- **Create a virtual environment venv-tf using Python 3.8**
30+
31+
```
32+
pip install virtualenv
33+
# use `whereis python` to find the `python3.8` path in the system and specify it. Please install `Python3.8` if not installed on your system.
34+
virtualenv -p /usr/bin/python3.8 venv-tf
35+
source venv-tf/bin/activate
36+
37+
# If git, numactl and wget were not installed, please install them using
38+
yum update -y && yum install -y git numactl wget
39+
```
40+
41+
- **Install [Intel optimized TensorFlow](https://pypi.org/project/intel-tensorflow/2.11.dev202242/)**
42+
```
43+
# Install Intel Optimized TensorFlow
44+
pip install intel-tensorflow==2.11.dev202242
45+
pip install keras-nightly==2.11.0.dev2022092907
46+
```
47+
48+
- **Jupyter Notebook**
49+
50+
Install using PIP: `$pip install notebook`. <br> Alternatively, see [*Installing Jupyter*](https://jupyter.org/install) for detailed installation instructions.
51+
52+
- **Other dependencies**
53+
54+
You will need to install the additional packages in requirements.txt and **Py-cpuinfo**.
55+
```
56+
pip install -r requirements.txt
57+
python -m pip install py-cpuinfo
58+
```
59+
60+
### For Intel® DevCloud
61+
62+
The necessary tools and components are already installed in the environment. You do not need to install additional components. See [Intel® DevCloud for oneAPI](https://devcloud.intel.com/oneapi/get_started/) for information.
63+
64+
## Key Implementation Details
65+
66+
This code sample uses a pre-trained on ResNet50v1.5 pretrained model, trained on the ImageNet dataset and fine-tuned on TensorFlow Flower dataset. The FP32 model is validated using FP32 and BF16 precision, including the use of Intel® Advanced Matrix Extensions (AMX) on BF16. AMX is supported on BF16 and INT8 data types starting with 4th Gen Xeon Scalable Processors. The inference time will be compared, showcasing the speedup of BF16 and AMX.
67+
The sample tutorial contains one Jupyter Notebook and one Python script. You can use either.
68+
69+
### Jupyter Notebook
70+
71+
| Notebook | Description
72+
|:--- |:---
73+
|`IntelTensorFlow_AMX_BF16_Inference.ipynb` | TensorFlow Inference Optimizations with Advanced Matrix Extensions Bfloat16
74+
75+
### Python Scripts
76+
77+
| Script | Description
78+
|:--- |:---
79+
|`IntelTensorFlow_AMX_BF16_Inference.py` | The script performs inference with AMX BF16 and compares the performance against the baseline
80+
81+
82+
## Run the Sample on Linux*
83+
1. Launch Jupyter Notebook.
84+
```
85+
jupyter notebook --ip=0.0.0.0
86+
```
87+
2. Follow the instructions to open the URL with the token in your browser.
88+
3. Locate and select the Notebook.
89+
```
90+
enabling_automixed_precision_transfer_learning_tensorflow.ipynb
91+
````
92+
4. Change your Jupyter Notebook kernel to **tensorflow** or **intel-tensorflow**.
93+
5. Run every cell in the Notebook in sequence.
94+
95+
96+
### Run the Sample on Intel® DevCloud
97+
98+
1. If you do not already have an account, request an Intel® DevCloud account at [*Create an Intel® DevCloud Account*](https://intelsoftwaresites.secure.force.com/DevCloud/oneapi).
99+
2. On a Linux* system, open a terminal.
100+
3. SSH into Intel® DevCloud.
101+
```
102+
ssh DevCloud
103+
```
104+
> **Note**: You can find information about configuring your Linux system and connecting to Intel DevCloud at Intel® DevCloud for oneAPI [Get Started](https://devcloud.intel.com/oneapi/get_started).
105+
4. Follow the instructions to open the URL with the token in your browser.
106+
5. Locate and select the Notebook.
107+
```
108+
enabling_automixed_precision_transfer_learning_tensorflow.ipynb
109+
````
110+
6. Change the kernel to **tensorflow** or **intel-tensorflow**.
111+
7. Run every cell in the Notebook in sequence.
112+
113+
114+
#### Troubleshooting
115+
116+
If you receive an error message, troubleshoot the problem using the **Diagnostics Utility for Intel® oneAPI Toolkits**. The diagnostic utility provides configuration and system checks to help find missing dependencies, permissions errors, and other issues. See the [Diagnostics Utility for Intel® oneAPI Toolkits User Guide](https://www.intel.com/content/www/us/en/develop/documentation/diagnostic-utility-user-guide/top.html) for more information on using the utility.
117+
118+
119+
## Example Output
120+
If successful, the sample displays [CODE_SAMPLE_COMPLETED_SUCCESSFULLY]. Additionally, the sample generates performance and analysis diagrams for comparison.
121+
122+
The following image shows approximate performance speed increases using AMX BF16 with auto-mixed precision during inference. To see more performance improvement between AVX-512 BF16 and AMX BF16, increase the number of required computations in one batch.
123+
124+
![Inference Speedup](images/inference-perf-comp.png)
125+
126+
With the imporovement on model inference speed, using AMX BF16 with auto-mixed precision during inference will not influence the inference accuracy.
127+
128+
![Inference Speedup](images/inference-acc-comp.png)
129+
130+
131+
## License
132+
133+
Code samples are licensed under the MIT license. See
134+
[License.txt](https://github.com/oneapi-src/oneAPI-samples/blob/master/License.txt) for details.
135+
136+
Third party program Licenses can be found here: [third-party-programs.txt](https://github.com/oneapi-src/oneAPI-samples/blob/master/third-party-programs.txt).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import os
2+
3+
def runJupyterNotebook(input_notebook_filename, output_notebook_filename, conda_env, fdpath='./'):
4+
import nbformat
5+
import os
6+
from nbconvert.preprocessors import ExecutePreprocessor
7+
from nbconvert.preprocessors import CellExecutionError
8+
if os.path.isfile(input_notebook_filename) is False:
9+
print("No Jupyter notebook found : ",input_notebook_filename)
10+
try:
11+
with open(input_notebook_filename) as f:
12+
nb = nbformat.read(f, as_version=4)
13+
ep = ExecutePreprocessor(timeout=6000, kernel_name=conda_env, allow_errors=True)
14+
ep.preprocess(nb, {'metadata': {'path': fdpath}})
15+
with open(output_notebook_filename, 'w', encoding='utf-8') as f:
16+
nbformat.write(nb, f)
17+
return 0
18+
except CellExecutionError:
19+
print("Exception!")
20+
return -1
21+
22+
23+
runJupyterNotebook(os.path.join(os.path.dirname(os.path.realpath(__file__)),
24+
'IntelTensorFlow_AMX_BF16_Inference.ipynb'),
25+
'IntelTensorFlow_AMX_BF16_Inference_result.ipynb',
26+
'tensorflow')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
�root"_tf_keras_sequential*�{"name": "sequential_1", "trainable": true, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": null, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": false, "class_name": "Sequential", "config": {"name": "sequential_1", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 224, 224, 3]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "keras_layer_input"}}, {"class_name": "KerasLayer", "config": {"name": "keras_layer", "trainable": false, "dtype": "float32", "batch_input_shape": {"class_name": "__tuple__", "items": [null, 224, 224, 3]}, "handle": "https://tfhub.dev/google/imagenet/resnet_v1_50/feature_vector/5"}}, {"class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 5, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}]}, "shared_object_id": 5, "input_spec": [{"class_name": "InputSpec", "config": {"dtype": null, "shape": {"class_name": "__tuple__", "items": [null, 224, 224, 3]}, "ndim": 4, "max_ndim": null, "min_ndim": null, "axes": {}}}], "build_input_shape": {"class_name": "TensorShape", "items": [null, 224, 224, 3]}, "is_graph_network": true, "full_save_spec": {"class_name": "__tuple__", "items": [[{"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 224, 224, 3]}, "float32", "keras_layer_input"]}], {}]}, "save_spec": {"class_name": "TypeSpec", "type_spec": "tf.TensorSpec", "serialized": [{"class_name": "TensorShape", "items": [null, 224, 224, 3]}, "float32", "keras_layer_input"]}, "keras_version": "2.11.0", "backend": "tensorflow", "model_config": {"class_name": "Sequential", "config": {"name": "sequential_1", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": {"class_name": "__tuple__", "items": [null, 224, 224, 3]}, "dtype": "float32", "sparse": false, "ragged": false, "name": "keras_layer_input"}, "shared_object_id": 0}, {"class_name": "KerasLayer", "config": {"name": "keras_layer", "trainable": false, "dtype": "float32", "batch_input_shape": {"class_name": "__tuple__", "items": [null, 224, 224, 3]}, "handle": "https://tfhub.dev/google/imagenet/resnet_v1_50/feature_vector/5"}, "shared_object_id": 1}, {"class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 5, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 2}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 3}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 4}]}}, "training_config": {"loss": {"class_name": "SparseCategoricalCrossentropy", "config": {"reduction": "auto", "name": "sparse_categorical_crossentropy", "from_logits": true, "ignore_class": null}, "shared_object_id": 7}, "metrics": [[{"class_name": "MeanMetricWrapper", "config": {"name": "acc", "dtype": "float32", "fn": "sparse_categorical_accuracy"}, "shared_object_id": 8}]], "weighted_metrics": null, "loss_weights": null, "optimizer_config": {"class_name": "Custom>SGD", "config": {"name": "SGD", "weight_decay": null, "clipnorm": null, "global_clipnorm": null, "clipvalue": null, "use_ema": false, "ema_momentum": 0.99, "ema_overwrite_frequency": null, "jit_compile": false, "is_legacy_optimizer": false, "learning_rate": 0.009999999776482582, "momentum": 0.0, "nesterov": false}}}}2
3+
�root.layer_with_weights-0"_tf_keras_layer*�{"name": "keras_layer", "trainable": false, "expects_training_arg": true, "dtype": "float32", "batch_input_shape": {"class_name": "__tuple__", "items": [null, 224, 224, 3]}, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "KerasLayer", "config": {"name": "keras_layer", "trainable": false, "dtype": "float32", "batch_input_shape": {"class_name": "__tuple__", "items": [null, 224, 224, 3]}, "handle": "https://tfhub.dev/google/imagenet/resnet_v1_50/feature_vector/5"}, "shared_object_id": 1, "build_input_shape": {"class_name": "TensorShape", "items": [512, 224, 224, 3]}}2
4+
�root.layer_with_weights-1"_tf_keras_layer*�{"name": "dense_1", "trainable": true, "expects_training_arg": false, "dtype": "float32", "batch_input_shape": null, "stateful": false, "must_restore_from_config": false, "preserve_input_structure_in_config": false, "autocast": true, "class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 5, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}, "shared_object_id": 2}, "bias_initializer": {"class_name": "Zeros", "config": {}, "shared_object_id": 3}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "shared_object_id": 4, "input_spec": {"class_name": "InputSpec", "config": {"dtype": null, "shape": null, "ndim": null, "max_ndim": null, "min_ndim": 2, "axes": {"-1": 2048}}, "shared_object_id": 9}, "build_input_shape": {"class_name": "TensorShape", "items": [null, 2048]}}2
5+
��root.keras_api.metrics.0"_tf_keras_metric*�{"class_name": "Mean", "name": "loss", "dtype": "float32", "config": {"name": "loss", "dtype": "float32"}, "shared_object_id": 10}2
6+
��root.keras_api.metrics.1"_tf_keras_metric*�{"class_name": "MeanMetricWrapper", "name": "acc", "dtype": "float32", "config": {"name": "acc", "dtype": "float32", "fn": "sparse_categorical_accuracy"}, "shared_object_id": 8}2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
notebook
2+
Pillow
3+
tensorflow_hub
4+
requests
5+

0 commit comments

Comments
 (0)