-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #54 from InfiniTensor/dev
Dev
- Loading branch information
Showing
95 changed files
with
2,537 additions
and
967 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import argparse | ||
import numpy as np | ||
import os | ||
|
||
|
||
def parse_args(): | ||
parser = argparse.ArgumentParser(description="Compare output files.") | ||
parser.add_argument( | ||
"--expect", | ||
type=str, | ||
default="./onnx_outputs/", | ||
help="Path to the expected output files by onnx_runtime.", | ||
) | ||
parser.add_argument( | ||
"--actual", | ||
type=str, | ||
default="./if_outputs/", | ||
help="Path to the actual output files.", | ||
) | ||
args = parser.parse_args() | ||
return ( | ||
args.expect, | ||
args.actual, | ||
) | ||
|
||
def getDiff(base, test): | ||
absolute_diff = np.subtract(base, test) | ||
max_absolute_diff = np.max(np.abs(absolute_diff)) | ||
|
||
baseCopy = base.astype(np.float64).ravel() | ||
testCopy = test.astype(np.float64).ravel() | ||
upValue = np.sum(np.abs(baseCopy - testCopy)) | ||
downValue = np.sum(np.abs(baseCopy)) + np.float64(1e-9) | ||
max_relative_diff = upValue / downValue | ||
|
||
return max_absolute_diff, max_relative_diff | ||
|
||
def compare_npy(actual_path, expect_path, edge, node): | ||
actual = np.load(actual_path) | ||
expect = np.load(expect_path) | ||
if np.isnan(actual).any(): | ||
print(f"NAN value in node:{node} edge:{edge}") | ||
return | ||
|
||
max_absolute_diff, max_relative_diff = getDiff(expect, actual) | ||
if max_absolute_diff != 0.0: ## No need to print tensor with no diff | ||
print(f'{max_absolute_diff}\t{max_relative_diff}\t{node}\t{edge}') | ||
|
||
|
||
def main(): | ||
expect_dir, actual_dir = parse_args() | ||
meta_files = sorted([f for f in os.listdir(actual_dir) if f.endswith(".meta")]) | ||
for meta_file in meta_files: | ||
with open(os.path.join(actual_dir, meta_file), "r") as file: | ||
node_name = "" | ||
for line in file: | ||
elements = line.strip().split() | ||
if "node" == elements[0]: | ||
node_id, node_name = elements[1], elements[2] | ||
elif ("input" == elements[0] or "output" == elements[0]) and len( | ||
elements | ||
) == 4: | ||
edge_id, edge_name, actual_file_path = ( | ||
elements[1], | ||
elements[2], | ||
elements[3], | ||
) | ||
expect_file = edge_name.replace("/", "_") | ||
expect_file = expect_file.replace(".", "-") | ||
expect_file = expect_file + ".npy" | ||
expect_file_path = os.path.join(expect_dir, expect_file) | ||
if os.path.exists(expect_file_path): | ||
compare_npy( | ||
actual_file_path, expect_file_path, edge_name, node_name | ||
) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import numpy as np | ||
from pathlib import Path | ||
from onnx import load | ||
from refactor_graph.onnx import make_compiler | ||
import argparse | ||
import os | ||
import shutil | ||
|
||
input_dir_name = "inputs/" | ||
result_dir_name = "if_outputs/" | ||
|
||
|
||
def parse_args(): | ||
parser = argparse.ArgumentParser( | ||
description="Run with onnx_runtime, export all outputs to file." | ||
) | ||
parser.add_argument( | ||
"--model", type=str, required=True, help="Path to the ONNX model file." | ||
) | ||
parser.add_argument("--output", type=str, default="./", help="Working directory.") | ||
|
||
parser.add_argument( | ||
"--gen_input", action="store_true", help="Generate random input." | ||
) | ||
args = parser.parse_args() | ||
print("arg setting: ", args) | ||
return ( | ||
args.model, | ||
args.output, | ||
args.gen_input, | ||
) | ||
|
||
|
||
def create_dir(working_path, dir_name): | ||
dir_path = os.path.join(working_path, dir_name) | ||
if os.path.exists(dir_path): | ||
shutil.rmtree(dir_path) | ||
os.mkdir(dir_path) | ||
else: | ||
os.mkdir(dir_path) | ||
|
||
return dir_path | ||
|
||
|
||
def main(): | ||
model_path, work_path, gen_input = parse_args() | ||
if gen_input: | ||
create_dir(work_path, input_dir_name) | ||
create_dir(work_path, result_dir_name) | ||
|
||
model = load(model_path, load_external_data=False) | ||
compiler = make_compiler(model, Path(model_path).parent.__str__()) | ||
executor = compiler.compile("cuda", "default", []) | ||
inputs = compiler.zero_inputs() | ||
|
||
for i, input in enumerate(inputs): | ||
if gen_input: | ||
input[...] = np.random.random(input.shape).astype(input.dtype) | ||
executor.set_input(i, input) | ||
np.save(os.path.join(work_path, input_dir_name, f"input_{i}"), input) | ||
else: | ||
input = np.load(os.path.join(work_path, input_dir_name, f"input_{i}.npy")) | ||
executor.set_input(i, input) | ||
executor.trace(os.path.join(work_path, result_dir_name), "npy") | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
import argparse | ||
import onnx | ||
import numpy as np | ||
import onnxruntime | ||
import os | ||
import shutil | ||
from onnx.shape_inference import infer_shapes | ||
|
||
input_dir_name = "inputs/" | ||
onnx_result_dir_name = "onnx_outputs/" | ||
size_threshold = 1024 * 1024 * 1024 | ||
|
||
|
||
def parse_args(): | ||
parser = argparse.ArgumentParser( | ||
description="Run with onnx_runtime, export all outputs to file." | ||
) | ||
parser.add_argument( | ||
"--model", type=str, required=True, help="Path to the ONNX model file." | ||
) | ||
parser.add_argument("--output", type=str, default="./", help="Working directory.") | ||
parser.add_argument( | ||
"--gen_input", action="store_true", help="Generate random input." | ||
) | ||
args = parser.parse_args() | ||
print("arg setting: ", args) | ||
return ( | ||
args.model, | ||
args.output, | ||
args.gen_input, | ||
) | ||
|
||
|
||
def gen_inputs(model, working_path): | ||
inputs_info = model.graph.input | ||
dir_path = create_dir(working_path, input_dir_name) | ||
inputs = {} | ||
initializers = set(i.name for i in model.graph.initializer) | ||
|
||
for i, info in enumerate(inputs_info): | ||
if info.name not in initializers: | ||
shape = [ | ||
d.dim_value if d.HasField("dim_value") else 1 | ||
for d in info.type.tensor_type.shape.dim | ||
] | ||
|
||
if info.type.tensor_type.elem_type == 6: | ||
data = np.random.randint(0, 2, size=shape).astype(np.int32) | ||
elif info.type.tensor_type.elem_type == 7: | ||
data = np.random.randint(0, 2, size=shape) | ||
else: | ||
data = np.random.random(size=shape).astype(np.float32) | ||
inputs[info.name] = data | ||
np.save(os.path.join(dir_path, f"input_{i}"), data) | ||
|
||
return inputs | ||
|
||
|
||
def load_inputs(model, working_path): | ||
inputs_info = model.graph.input | ||
dir_path = os.path.join(working_path, input_dir_name) | ||
inputs = {} | ||
for i, info in enumerate(inputs_info): | ||
file_path = os.path.join(dir_path, f"input_{i}.npy") | ||
inputs[info.name] = np.load(file_path) | ||
return inputs | ||
|
||
|
||
def create_dir(working_path, dir_name): | ||
dir_path = os.path.join(working_path, dir_name) | ||
if os.path.exists(dir_path): | ||
shutil.rmtree(dir_path) | ||
os.mkdir(dir_path) | ||
else: | ||
os.mkdir(dir_path) | ||
|
||
return dir_path | ||
|
||
|
||
def get_extra_output_groups(model): | ||
output_groups = [] | ||
group = [] | ||
total_size = 0 | ||
for value_info in model.graph.value_info: | ||
group.append(value_info) | ||
shape = [ | ||
d.dim_value if d.HasField("dim_value") else 1 | ||
for d in value_info.type.tensor_type.shape.dim | ||
] | ||
size = 1 | ||
for i in shape: | ||
size *= i | ||
total_size += size | ||
|
||
if total_size > size_threshold: | ||
output_groups.append(group) | ||
group = [] | ||
total_size = 0 | ||
if total_size != 0: | ||
output_groups.append(group) | ||
output_groups.append([out for out in model.graph.output]) | ||
return output_groups | ||
|
||
|
||
def run_with_extra_outputs(model, extra_outputs, inputs, output_path): | ||
n = len(model.graph.output) | ||
for _ in range(n): | ||
model.graph.output.remove(model.graph.output[0]) | ||
model.graph.output.extend(extra_outputs) | ||
output_names = [info.name for info in extra_outputs] | ||
session = onnxruntime.InferenceSession(model.SerializeToString()) | ||
tensors = session.run(output_names=output_names, input_feed=inputs) | ||
|
||
for output_name, tensor in zip(output_names, tensors): | ||
output_name = output_name.replace("/", "_") | ||
output_name = output_name.replace(".", "-") | ||
file_path = os.path.join(output_path, output_name) | ||
print("Save output to " + file_path) | ||
np.save(file_path, tensor) | ||
|
||
|
||
def main(): | ||
model_path, working_path, gen_input = parse_args() | ||
create_dir(working_path, onnx_result_dir_name) | ||
model = onnx.load(model_path) | ||
model = infer_shapes(model) | ||
if gen_input: | ||
inputs = gen_inputs(model, working_path) | ||
else: | ||
inputs = load_inputs(model, working_path) | ||
|
||
output_groups = get_extra_output_groups(model) | ||
output_path = os.path.join(working_path, onnx_result_dir_name) | ||
|
||
for extra_outputs in output_groups: | ||
run_with_extra_outputs(model, extra_outputs, inputs, output_path) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#!/bin/bash | ||
|
||
# Save the current working directory | ||
original_directory=$(pwd) | ||
|
||
# Get the directory of the script | ||
script_directory=$(dirname "$(readlink -f "$0")") | ||
|
||
# Change to the script's directory | ||
cd "$script_directory" | ||
|
||
if [ "$#" -eq 1 ]; then | ||
echo "Validating model: $1. Random inputs will be generated." | ||
python run_actual.py --model $1 --gen_input | ||
python run_onnx.py --model $1 | ||
python compare.py > result.txt | ||
echo "Compare results saved in result.txt." | ||
else | ||
echo "Please provide an onnx file path as a single argument." | ||
fi | ||
|
||
# Change back to the original working directory | ||
cd "$original_directory" |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.