Add VP test in Stable diffusion pipeline (#19300)

### Description
1. Add visual parity test based on openai clip model
2. Add trigger rules

### Motivation and Context
1. check generated image is expected
2. reduce unnecessary triggers
This commit is contained in:
Yi Zhang 2024-01-30 01:33:58 +08:00 committed by GitHub
parent 82c1cb416b
commit e96a038f01
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 131 additions and 6 deletions

View file

@ -61,6 +61,7 @@ if __name__ == "__main__":
controlnet_scales=controlnet_scale,
show_latency=not warmup,
output_type="pil",
deterministic=args.deterministic,
)
if not args.disable_cuda_graph:

View file

@ -239,6 +239,7 @@ def parse_arguments(is_xl: bool, parser):
)
parser.add_argument("--nvtx-profile", action="store_true", help="Enable NVTX markers for performance profiling.")
parser.add_argument("--seed", type=int, default=None, help="Seed for random generator to get consistent results.")
parser.add_argument("--deterministic", action="store_true", help="use deterministic algorithms.")
parser.add_argument("-dc", "--disable-cuda-graph", action="store_true", help="Disable cuda graph.")
group = parser.add_argument_group("Options for ORT_CUDA engine only")

View file

@ -754,6 +754,7 @@ class StableDiffusionPipeline:
controlnet_scales: Optional[torch.Tensor] = None,
show_latency: bool = False,
output_type: str = "pil",
deterministic: bool = False,
):
"""
Run the diffusion pipeline.
@ -783,6 +784,9 @@ class StableDiffusionPipeline:
output_type (str):
It can be "latent", "pt" or "pil".
"""
if deterministic:
torch.use_deterministic_algorithms(True)
if self.is_backend_tensorrt():
import tensorrt as trt
from trt_utilities import TRT_LOGGER

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

View file

@ -0,0 +1,68 @@
import argparse
import os
import cv2
import open_clip
import torch
from PIL import Image
from sentence_transformers import util
def arg_parser():
parser = argparse.ArgumentParser(description="Options for Compare 2 image")
parser.add_argument("--image1", type=str, help="Path to image 1")
parser.add_argument("--image2", type=str, help="Path to image 2")
args = parser.parse_args()
return args
def image_encoder(img: Image.Image): # -> torch.Tensor:
device = "cuda" if torch.cuda.is_available() else "cpu"
model, _, preprocess = open_clip.create_model_and_transforms("ViT-B-16-plus-240", pretrained="laion400m_e32")
model.to(device)
img1 = Image.fromarray(img).convert("RGB")
img1 = preprocess(img1).unsqueeze(0).to(device)
img1 = model.encode_image(img1)
return img1
def load_image(image_path: str): # -> Image.Image:
# cv2.imread() can silently fail when the path is too long
# https://stackoverflow.com/questions/68716321/how-to-use-absolute-path-in-cv2-imread
if os.path.isabs(image_path):
directory = os.path.dirname(image_path)
current_directory = os.getcwd()
os.chdir(directory)
img = cv2.imread(os.path.basename(image_path), cv2.IMREAD_UNCHANGED)
os.chdir(current_directory)
else:
img = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)
return img
def generate_score(image1: str, image2: str): # -> float:
test_img = load_image(image1)
data_img = load_image(image2)
img1 = image_encoder(test_img)
img2 = image_encoder(data_img)
cos_scores = util.pytorch_cos_sim(img1, img2)
score = round(float(cos_scores[0][0]) * 100, 2)
return score
def main():
args = arg_parser()
image1 = args.image1
image2 = args.image2
score = round(generate_score(image1, image2), 2)
print("similarity Score: ", {score})
if score < 99:
print(f"{image1} and {image2} are different")
raise SystemExit(1)
else:
print(f"{image1} and {image2} are same")
if __name__ == "__main__":
main()

View file

@ -0,0 +1,4 @@
git+https://github.com/openai/CLIP.git
open_clip_torch
sentence_transformers
pillow

View file

@ -1,3 +1,32 @@
##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py ####
trigger:
branches:
include:
- main
- rel-*
paths:
exclude:
- docs/**
- README.md
- CONTRIBUTING.md
- BUILD.md
- 'js/web'
- 'onnxruntime/core/providers/js'
pr:
branches:
include:
- main
- rel-*
paths:
exclude:
- docs/**
- README.md
- CONTRIBUTING.md
- BUILD.md
- 'js/web'
- 'onnxruntime/core/providers/js'
#### end trigger ####parameters:
# reference: https://github.com/microsoft/onnxruntime/blob/main/onnxruntime/python/tools/transformers/models/stable_diffusion/README.md
parameters:
- name: specificArtifact
@ -143,7 +172,6 @@ stages:
- job: Stable_Diffusion
variables:
skipComponentGovernanceDetection: true
CCACHE_DIR: $(Pipeline.Workspace)/ccache
workspace:
clean: all
pool: onnxruntime-Linux-GPU-A10-12G
@ -162,7 +190,7 @@ stages:
- script: |
docker run --rm --gpus all -v $PWD:/workspace -v $(Build.BinariesDirectory)/Release:/Release nvcr.io/nvidia/pytorch:22.11-py3 \
bash -c "
bash -c '
set -ex; \
python3 --version; \
python3 -m pip install --upgrade pip; \
@ -171,12 +199,31 @@ stages:
python3 -m pip install -r requirements-cuda11.txt; \
python3 -m pip install --upgrade polygraphy onnx-graphsurgeon --extra-index-url https://pypi.ngc.nvidia.com; \
echo Generate an image guided by a text prompt; \
python3 demo_txt2img.py 'astronaut riding a horse on mars'; \
popd; \
"
python3 demo_txt2img.py --seed 1 --deterministic "astronaut riding a horse on mars" ; \
find $(pwd) -name "*.png" ; \
popd ; \
'
displayName: 'Run stable diffusion demo'
workingDirectory: $(Build.SourcesDirectory)
- script: |
docker run --rm --gpus all -v $PWD:/workspace nvcr.io/nvidia/pytorch:22.11-py3 \
bash -c '
set -ex; \
python3 --version; \
python3 -m pip install --upgrade pip; \
pushd /workspace/onnxruntime/python/tools/transformers/models/stable_diffusion/; \
image2=$(find $(pwd) -name "astronaut_riding_a_h*.png") ; \
pushd test; \
python3 -m pip install -r requirements.txt; \
echo check demo_txt2image.py generate image; \
python3 -u check_image.py --image1 astronaut_riding_txt2image-DDIM-50.png --image2 $image2; \
popd ; \
popd ; \
'
displayName: 'Check the generated image'
workingDirectory: $(Build.SourcesDirectory)
- stage: Llama2_ONNX_FP16
dependsOn:
- Build_Onnxruntime_Cuda

View file

@ -14,6 +14,7 @@ skip_doc_changes = ["web-ci-pipeline.yml"]
skip_js_changes = [
"android-arm64-v8a-QNN-crosscompile-ci-pipeline.yml",
"android-x86_64-crosscompile-ci-pipeline.yml",
"bigmodels-ci-pipeline.yml",
"linux-ci-pipeline.yml",
"linux-cpu-aten-pipeline.yml",
"linux-cpu-eager-pipeline.yml",
@ -31,7 +32,6 @@ skip_js_changes = [
"orttraining-linux-ci-pipeline.yml",
"orttraining-linux-gpu-ci-pipeline.yml",
"orttraining-linux-gpu-ortmodule-distributed-test-ci-pipeline.yml",
"orttraining-linux-gpu-training-apis.yml",
"orttraining-mac-ci-pipeline.yml",
"win-ci-pipeline.yml",
"win-gpu-ci-pipeline.yml",