Accelerate Inference of Sparse Transformer Models with OpenVINO™ and 4th Gen Intel® Xeon® Scalable Processors#

This Jupyter notebook can be launched on-line, opening an interactive environment in a browser window. You can also make a local installation. Choose one of the following options:

Google ColabGithub

This tutorial demonstrates how to improve performance of sparse Transformer models with OpenVINO on 4th Gen Intel® Xeon® Scalable processors.

The tutorial downloads a BERT-base model which has been quantized, sparsified, and tuned for SST2 datasets using Optimum-Intel. It demonstrates the inference performance advantage on 4th Gen Intel® Xeon® Scalable Processors by running it with Sparse Weight Decompression, a runtime option that seizes model sparsity for efficiency. The notebook consists of the following steps:

  • Install prerequisites

  • Download and quantize sparse public BERT model, using the OpenVINO integration with Hugging Face Optimum.

  • Compare sparse 8-bit vs. dense 8-bit inference performance.

Table of contents:

Installation Instructions#

This is a self-contained example that relies solely on its own code.

We recommend running the notebook in a virtual environment. You only need a Jupyter server to start. For details, please refer to Installation Guide.

Prerequisites#

%pip install -q "openvino>=2023.1.0"
%pip install -q "git+https://github.com/huggingface/optimum-intel.git" "torch>=2.1" datasets "onnx<1.16.2" transformers>=4.33.0 --extra-index-url https://download.pytorch.org/whl/cpu

Imports#

import shutil
from pathlib import Path

from optimum.intel.openvino import OVModelForSequenceClassification
from transformers import AutoTokenizer, pipeline
from huggingface_hub import hf_hub_download

Download, quantize and sparsify the model, using Hugging Face Optimum API#

The first step is to download a quantized sparse transformers which has been translated to OpenVINO IR. Then, it will be put through a classification as a simple validation of a working downloaded model. To find out how the model is being quantized and sparsified, refer to the OpenVINO/bert-base-uncased-sst2-int8-unstructured80 model card on Hugging Face.

# The following model has been quantized, sparsified using Optimum-Intel 1.7 which is enabled by OpenVINO and NNCF
# for reproducibility, refer https://huggingface.co/OpenVINO/bert-base-uncased-sst2-int8-unstructured80
model_id = "OpenVINO/bert-base-uncased-sst2-int8-unstructured80"

# The following two steps will set up the model and download them to HF Cache folder
ov_model = OVModelForSequenceClassification.from_pretrained(model_id)
tokenizer = AutoTokenizer.from_pretrained(model_id)

# Let's take the model for a spin!
sentiment_classifier = pipeline("text-classification", model=ov_model, tokenizer=tokenizer)

text = "He's a dreadful magician."
outputs = sentiment_classifier(text)

print(outputs)

For benchmarking, we will use OpenVINO’s benchmark application and put the IRs into a single folder.

# create a folder
quantized_sparse_dir = Path("bert_80pc_sparse_quantized_ir")
quantized_sparse_dir.mkdir(parents=True, exist_ok=True)

# following return path to specified filename in cache folder (which we've with the
ov_ir_xml_path = hf_hub_download(repo_id=model_id, filename="openvino_model.xml")
ov_ir_bin_path = hf_hub_download(repo_id=model_id, filename="openvino_model.bin")

# copy IRs to the folder
shutil.copy(ov_ir_xml_path, quantized_sparse_dir)
shutil.copy(ov_ir_bin_path, quantized_sparse_dir)

Benchmark quantized dense inference performance#

Benchmark dense inference performance using parallel execution on four CPU cores to simulate a small instance in the cloud infrastructure. Sequence length is dependent on use cases, 16 is common for conversational AI while 160 for question answering task. It is set to 64 as an example. It is recommended to tune based on your applications.

# Dump benchmarking config for dense inference
with (quantized_sparse_dir / "perf_config.json").open("w") as outfile:
    outfile.write(
        """
        {
            "CPU": {"NUM_STREAMS": 4, "INFERENCE_NUM_THREADS": 4}
        }
        """
    )
!benchmark_app -m $quantized_sparse_dir/openvino_model.xml -shape "input_ids[1,64],attention_mask[1,64],token_type_ids[1,64]" -load_config $quantized_sparse_dir/perf_config.json

Benchmark quantized sparse inference performance#

To enable sparse weight decompression feature, users can add it to runtime config like below. CPU_SPARSE_WEIGHTS_DECOMPRESSION_RATE takes values between 0.5 and 1.0. It is a layer-level sparsity threshold for which a layer will be enabled.

# Dump benchmarking config for dense inference
# "CPU_SPARSE_WEIGHTS_DECOMPRESSION_RATE" controls minimum sparsity rate for weights to consider
# for sparse optimization at the runtime.
with (quantized_sparse_dir / "perf_config_sparse.json").open("w") as outfile:
    outfile.write(
        """
        {
            "CPU": {"NUM_STREAMS": 4, "INFERENCE_NUM_THREADS": 4, "CPU_SPARSE_WEIGHTS_DECOMPRESSION_RATE": "0.75"}
        }
        """
    )
!benchmark_app -m $quantized_sparse_dir/openvino_model.xml -shape "input_ids[1,64],attention_mask[1,64],token_type_ids[1,64]" -load_config $quantized_sparse_dir/perf_config_sparse.json

When this might be helpful#

This feature can improve inference performance for models with sparse weights in the scenarios when the model is deployed to handle multiple requests in parallel asynchronously. It is especially helpful with a small sequence length, for example, 32 and lower.

For more details about asynchronous inference with OpenVINO, refer to the following documentation: