add analyze_ovir.py
Browse files
scripts/ADDITIONAL/analyze_ovir.py
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from openvino.runtime import Core
|
2 |
+
from tqdm import tqdm
|
3 |
+
import torch
|
4 |
+
from collections import OrderedDict
|
5 |
+
from pathlib import Path
|
6 |
+
import numpy as np
|
7 |
+
from collections import Counter
|
8 |
+
import os
|
9 |
+
|
10 |
+
QDTYPE_SPECIAL_VALUES={
|
11 |
+
'u4': [0, 1, 2, 4, 8],
|
12 |
+
'u8': [0, 1, 2, 4, 8, 16, 32, 64, 128],
|
13 |
+
'int8': [-1, -2, -4, -8, -16, -32, -64, -128, 0, 1, 2, 4, 8, 16, 32, 64]
|
14 |
+
}
|
15 |
+
|
16 |
+
zero_point_map = {
|
17 |
+
'u4': 8,
|
18 |
+
'u8': 128,
|
19 |
+
'int8': 0,
|
20 |
+
}
|
21 |
+
|
22 |
+
def get_uniq_value_stats(tensor, q_dtype):
|
23 |
+
if q_dtype not in QDTYPE_SPECIAL_VALUES.keys():
|
24 |
+
raise NotImplementedError(f"Unsupported q_dtype {q_dtype}")
|
25 |
+
|
26 |
+
value_counts = Counter(tensor.flatten())
|
27 |
+
total_elements = sum(value_counts.values())
|
28 |
+
|
29 |
+
top1_val, top1_count = value_counts.most_common(1)[0]
|
30 |
+
top1_tuple = (top1_val, top1_count/total_elements)
|
31 |
+
|
32 |
+
# Calculate ratio for each value
|
33 |
+
count_ratio_dict = {value: {'count': count, 'ratio': count / total_elements}
|
34 |
+
for value, count in value_counts.items()}
|
35 |
+
|
36 |
+
# # Find unique elements and their counts
|
37 |
+
# unique_values, counts = np.unique(tensor, return_counts=True)
|
38 |
+
# # Calculate the total number of elements in the tensor
|
39 |
+
# total_elements = tensor.size
|
40 |
+
# # Calculate the relative ratio for each unique value
|
41 |
+
# ratios = counts / total_elements
|
42 |
+
|
43 |
+
special_value_count = 0
|
44 |
+
special_value_ratio = 0
|
45 |
+
sparsity = 0
|
46 |
+
zero_count = 0
|
47 |
+
|
48 |
+
# for value, count, ratio in zip(unique_values, counts, ratios):
|
49 |
+
for value, vdict in count_ratio_dict.items():
|
50 |
+
count = vdict['count']
|
51 |
+
ratio = vdict['ratio']
|
52 |
+
if value == zero_point_map[q_dtype]:
|
53 |
+
sparsity = ratio
|
54 |
+
zero_count = count
|
55 |
+
|
56 |
+
# zero will enter both above and below
|
57 |
+
if value in QDTYPE_SPECIAL_VALUES[q_dtype]:
|
58 |
+
special_value_count += count
|
59 |
+
special_value_ratio += ratio
|
60 |
+
|
61 |
+
return dict(
|
62 |
+
numel=total_elements,
|
63 |
+
sparsity=sparsity,
|
64 |
+
special_value_ratio=special_value_ratio,
|
65 |
+
top1=top1_tuple,
|
66 |
+
raw=count_ratio_dict
|
67 |
+
)
|
68 |
+
|
69 |
+
|
70 |
+
def get_ir_pair(model_dir):
|
71 |
+
p = Path(model_dir)
|
72 |
+
return p/"openvino_model.xml", p/"openvino_model.bin"
|
73 |
+
|
74 |
+
|
75 |
+
# fc_numel = {
|
76 |
+
# 'llama-2-chat-7b ': {'min': 16777216, 'max': 45088768},
|
77 |
+
# 'mistral-7b ': {'min': 4194304, 'max': 58720256},
|
78 |
+
# 'gemma-2b-it': {'min': 524288, 'max': 33554432},
|
79 |
+
# }
|
80 |
+
|
81 |
+
fc_numel = {
|
82 |
+
'llama-2-chat-7b': [16777216, 45088768],
|
83 |
+
'mistral-7b': [4194304, 16777216, 58720256],
|
84 |
+
'gemma-2b-it': [524288, 4194304, 33554432],
|
85 |
+
}
|
86 |
+
|
87 |
+
ovir_folder = "stable-diffusion-pokemons-1-5-quantized/unet"
|
88 |
+
|
89 |
+
# model_key = compressed_weight_folder.split("/")[2]
|
90 |
+
|
91 |
+
ir_xml, ir_bin = get_ir_pair(ovir_folder)
|
92 |
+
|
93 |
+
ie = Core()
|
94 |
+
ir_model = ie.read_model(ir_xml)
|
95 |
+
|
96 |
+
model_params = OrderedDict()
|
97 |
+
|
98 |
+
csv_path = os.path.join(ovir_folder, "weight_dist.csv")
|
99 |
+
|
100 |
+
with open(csv_path, "w") as outfile:
|
101 |
+
outfile.write("layer,dtype,w_ndim,shape,numel,sparsity,special_val_ratio,top1_val_ratio,top1_val\n")
|
102 |
+
|
103 |
+
# for op in tqdm(ir_model.get_ordered_ops()):
|
104 |
+
for op in ir_model.get_ordered_ops():
|
105 |
+
if 'constant' in str(op.get_type_info()).lower():
|
106 |
+
shape = tuple(op.get_output_shape(0))
|
107 |
+
numel = np.prod(shape)
|
108 |
+
|
109 |
+
|
110 |
+
if op.data.dtype.name == "int8":
|
111 |
+
# print(f"{numel:15} | {str(shape):20} | {op.get_name():20} | {op.data.dtype.name}")
|
112 |
+
layer = op.get_name()
|
113 |
+
q_dtype = op.data.dtype.name
|
114 |
+
|
115 |
+
# model_params[layer] = {}
|
116 |
+
|
117 |
+
statdict = get_uniq_value_stats(op.data, op.data.dtype.name)
|
118 |
+
|
119 |
+
# print("joto")
|
120 |
+
# q_mode = "sym" if attr['q_zero_point'][0] == zero_point_map[attr['q_dtype']] else "asym"
|
121 |
+
# is_top1_zero_point = "zero_point" if statdict['top1'][0] == zero_point_map[attr['q_dtype']] else statdict['top1'][0] # zero point is per channel per group
|
122 |
+
# print(f"{layer:30} | {attr['q_dtype']} ({q_mode:>5}) | orig. shape: {str(attr['original_shape']):15} | numel: {statdict['numel']:>15,} | sparsity: {statdict['sparsity']:.2f} | special ratio: {statdict['special_value_ratio']:.2f} | top1 ratio: {statdict['top1'][1]:.2f} ({is_top1_zero_point:>10}) |")
|
123 |
+
print(f"{layer:30} | {q_dtype} | orig. shape: {str(shape):20} | numel: {statdict['numel']:>15,} | sparsity: {statdict['sparsity']:.2f} | special ratio: {statdict['special_value_ratio']:.2f} | top1 ratio: {statdict['top1'][1]:.2f} (val: {statdict['top1'][0]})")
|
124 |
+
|
125 |
+
shape_str = str(shape).replace(", "," x ")
|
126 |
+
outfile.write(f"{layer:>25},{q_dtype},{len(shape)},{shape_str:20},{statdict['numel']:>15},{statdict['sparsity']:.4f},{statdict['special_value_ratio']:.4f},{statdict['top1'][1]:.4f},{statdict['top1'][0]}\n")
|
127 |
+
|
128 |
+
print('Done!')
|
scripts/ADDITIONAL/readme.md
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
The whole repo was based on the objectives of evaluating how much a certain value (power of twos) in quantized weights. But there wasn't a script here to do that.
|
2 |
+
|
3 |
+
Later in July 24, found an old script `analyze_ovir.py` that does that for unet of `OpenVINO/stable-diffusion-pokemons-1-5-quantized`.
|