Skip to content
Snippets Groups Projects
Commit 02596df1 authored by Yifan Zhao's avatar Yifan Zhao
Browse files

Added a mode to generate 'inspected' binary in frontend

parent 0b239e5f
No related branches found
No related tags found
No related merge requests found
...@@ -6,10 +6,10 @@ import jinja2 ...@@ -6,10 +6,10 @@ import jinja2
from .graph_builder import DFG from .graph_builder import DFG
from .graph_ir import DFGNode, TensorNode, WeightTensor from .graph_ir import DFGNode, TensorNode, WeightTensor
TEMPLATE_FILE = "template_hpvm.cpp.in" PLAIN_TEMPLATE_FILE = "template_hpvm.cpp.in"
INSPECT_TEMPLATE_FILE = "template_hpvm_inspect.cpp.in"
loader = jinja2.FileSystemLoader(searchpath=Path(__file__).parent) loader = jinja2.FileSystemLoader(searchpath=Path(__file__).parent)
template_env = jinja2.Environment(loader=loader, trim_blocks=True) template_env = jinja2.Environment(loader=loader, trim_blocks=True)
template = template_env.get_template(TEMPLATE_FILE)
PathLike = Union[str, Path] PathLike = Union[str, Path]
...@@ -69,11 +69,14 @@ class HpvmCodeGen(CodeGen): ...@@ -69,11 +69,14 @@ class HpvmCodeGen(CodeGen):
# Variable indicator is always int for hpvm gen # Variable indicator is always int for hpvm gen
variables: Dict[DFGNode, Tuple[int, bool]] variables: Dict[DFGNode, Tuple[int, bool]]
def __init__(self, dfg: DFG, prefix: PathLike, input_size: int, target: str): def __init__(self, dfg: DFG, prefix: PathLike, input_size: int, target: str, inspectable: bool):
super().__init__(dfg, prefix, input_size) super().__init__(dfg, prefix, input_size)
if target not in ("tensor", "cudnn"): if target not in ("tensor", "cudnn"):
raise ValueError(f"Unsupported target {target}") raise ValueError(f"Unsupported target {target}")
self.target = target self.target = target
self.template = template_env.get_template(
INSPECT_TEMPLATE_FILE if inspectable else PLAIN_TEMPLATE_FILE
)
def _emit_hpvm_node_edges(self, input_vars: List[DFGNode]) -> List[dict]: def _emit_hpvm_node_edges(self, input_vars: List[DFGNode]) -> List[dict]:
ret = [] ret = []
...@@ -133,7 +136,7 @@ class HpvmCodeGen(CodeGen): ...@@ -133,7 +136,7 @@ class HpvmCodeGen(CodeGen):
weights = self.emit_weights(self.weights) weights = self.emit_weights(self.weights)
with Path(output).open("w") as f: with Path(output).open("w") as f:
f.write( f.write(
template.render( self.template.render(
nodes=nodes, nodes=nodes,
input_name=self.input_name, input_name=self.input_name,
input_size=self.input_size, input_size=self.input_size,
......
...@@ -62,12 +62,15 @@ class ModelExporter: ...@@ -62,12 +62,15 @@ class ModelExporter:
self.weight_dir = self.output_dir / self.weight_dir_name self.weight_dir = self.output_dir / self.weight_dir_name
self.weight_dir.mkdir(exist_ok=True) self.weight_dir.mkdir(exist_ok=True)
args3 = self.dfg, self.weight_dir, self.dataset_size
if target == "hpvm_tensor": if target == "hpvm_tensor":
self.codegen = HpvmCodeGen(self.dfg, self.weight_dir, self.dataset_size, "tensor") self.codegen = HpvmCodeGen(*args3, "tensor", False)
elif target == "hpvm_tensor_inspect":
self.codegen = HpvmCodeGen(*args3, "tensor", True)
elif target == "hpvm_cudnn": elif target == "hpvm_cudnn":
self.codegen = HpvmCodeGen(self.dfg, self.weight_dir, self.dataset_size, "cudnn") self.codegen = HpvmCodeGen(*args3, "cudnn", False)
elif target == "tensor": elif target == "tensor":
self.codegen = TensorCodeGen(self.dfg, self.weight_dir, self.dataset_size) self.codegen = TensorCodeGen(*args3)
else: else:
raise ValueError(f"Target {target} not recognized") raise ValueError(f"Target {target} not recognized")
......
#include <string>
#include <hpvm.h>
#include <tensorTypes.h>
#include <tensorUtils.h>
// Linux C API for FIFO files
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
/**** Routines for Handling Piped Execution ***/
bool fifo_wait(const std::string &filename) {
std::ifstream file{filename};
std::string line;
std::getline(file, line);
if (line == "next")
return true;
if (line == "stop")
return false;
std::cout << "Invalid fifo file content \"" << line << "\"\n";
abort();
}
void fifo_write_finished(const std::string &filename) {
std::ofstream file{filename};
file << "finished\n\0";
}
void make_fifo(const std::string &filename) {
if (mkfifo(filename.c_str(), 0666) == 0)
return;
if (errno == EEXIST) {
if (unlink(filename.c_str()) < 0) {
std::cout << "Error removing existing file: " << strerror(errno) << '\n';
abort();
}
make_fifo(filename);
}
std::cout << "Error making FIFO file: " << strerror(errno) << '\n';
abort();
}
{% for node in nodes %}
void var_{{node.idx}}_node(
{%- for n in range(node.input_size) -%}
void *t{{n}}, size_t bytes_t{{n}}{{", " if not loop.last}}
{%- endfor %}) {
__hpvm__hint(hpvm::{{target.upper()}}_TARGET);
__hpvm__attributes({{node.input_size}}, {% for n in range(node.input_size) -%}
t{{n}}{{", " if not loop.last}}
{%- endfor %}, 0);
__hpvm__node_id({{node.idx + 1}});
void *r = {{node.call_name}}({% for n in range(node.input_size) -%}
t{{n}}{{", " if not loop.last}}
{%- endfor %}{{", " if node.call_args}}{{node.call_args|join(", ")}});
__hpvm__return(2, r, (size_t) 0);
}
{% endfor -%}
void root({%- for n in root_inputs -%}
void *{{n}}, size_t {{n}}_bytes{{", " if not loop.last}}
{%- endfor %}) {
__hpvm__hint(hpvm::CPU_TARGET);
__hpvm__attributes({{root_inputs|length}}, {% for n in root_inputs -%}
{{n}}{{", " if not loop.last}}
{%- endfor %}, 0);
{% for node in nodes %}
void* var_{{node.idx}} = __hpvm__createNodeND(0, var_{{node.idx}}_node);
{% for edge in node.edges %}
{% if edge.is_bindin %}
__hpvm__bindIn(var_{{node.idx}}, {{edge.input_idx * 2}}, {{edge.edge_idx * 2}}, 0);
__hpvm__bindIn(var_{{node.idx}}, {{edge.input_idx * 2 + 1}}, {{edge.edge_idx * 2 + 1}}, 0);
{% else %}
__hpvm__edge(var_{{edge.input_node}}, var_{{node.idx}}, 1, 0, {{edge.edge_idx * 2}}, 0);
__hpvm__edge(var_{{edge.input_node}}, var_{{node.idx}}, 1, 1, {{edge.edge_idx * 2 + 1}}, 0);
{% endif %}
{% endfor %}
{% endfor %}
__hpvm__bindOut(var_{{root_output_idx}}, 0, 0, 0);
__hpvm__bindOut(var_{{root_output_idx}}, 1, 1, 0);
}
struct ret_t {
void* tensor;
size_t bytes;
};
typedef struct __attribute__((__packed__)) {
{% for n in root_inputs %}
void *{{n}};
size_t {{n}}_bytes;
{% endfor %}
struct ret_t r;
} RootIn;
const int batch_size = {{batch_size}}, input_size = {{input_size}}, batch_count = input_size / batch_size;
int main(int argc, char *argv[]){
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " {tune|test}\n";
return 1;
}
std::string arg1 = argv[1];
if (arg1 != "tune" && arg1 != "test") {
std::cout << "Usage: " << argv[0] << " {tune|test}\n";
return 1;
}
std::string dir_prefix = "{{prefix}}/";
std::string input_path = dir_prefix + arg1 + "_input.bin";
std::string labels_path = dir_prefix + arg1 + "_labels.bin";
{% for w in weights %}
std::string {{w.name}}_path = dir_prefix + "{{w.filename}}";
void* {{w.name}} = readTrainedWeights({{w.name}}_path.c_str(), 0, {{w.shape|join(', ')}});
{% endfor %}
RootIn* args = static_cast<RootIn*>(malloc(sizeof(RootIn)));
void* {{input_name}} = create4DTensor(0, nchw, batch_size, {{input_shape|join(', ')}});
{% for n in root_inputs %}
args->{{n}} = {{n}};
args->{{n}}_bytes = 0;
{% endfor %}
make_fifo("/tmp/hpvm_fifo");
while (fifo_wait("/tmp/hpvm_fifo")) {
__hpvm__init();
startMemTracking();
for (int i = 0; i < batch_count; i++){
int start = i * batch_size, end = start + batch_size;
copyInputBatch(input_path.c_str(), start, end, {{input_shape|join(', ')}}, {{input_name}});
void* dfg = __hpvm__launch(0, root, (void*) args);
__hpvm__wait(dfg);
void *result = static_cast<RootIn*>(args)->r.tensor;
hpvm_request_tensor(result, 0);
uint32_t* labels = readLabelsBatch3(labels_path.c_str(), start, end);
computeAccuracy3(labels, result);
freeBatchMemory();
}
__hpvm__cleanup();
fifo_write_finished("/tmp/hpvm_fifo");
}
return 0;
}
import shutil
from pathlib import Path
from subprocess import run
import torch
from torch2hpvm import BinDataset, ModelExporter
from torch.nn import Module
from predtuner.pipedbin import PipedBinaryApp
import os
import shutil
import site
from pathlib import Path
from subprocess import run
import torch
from torch2hpvm import BinDataset, ModelExporter
from torch.nn import Module
site.addsitedir(os.path.dirname(__file__))
import dnn
benchmarks = [
(dnn.LeNet, 1, 28, 5000, "lenet_mnist"),
(dnn.AlexNet, 3, 32, 5000, "alexnet_cifar10"),
(dnn.AlexNet2, 3, 32, 5000, "alexnet2_cifar10"),
(dnn.AlexNetImageNet, 3, 224, 500, "alexnet_imagenet"),
(dnn.MobileNet, 3, 32, 5000, "mobilenet_cifar10"),
(dnn.ResNet18, 3, 32, 5000, "resnet18_cifar10"),
(dnn.ResNet50, 3, 224, 100, "resnet50_imagenet"),
(dnn.VGG16Cifar10, 3, 32, 5000, "vgg16_cifar10"),
(dnn.VGG16Cifar100, 3, 32, 5000, "vgg16_cifar100"),
(dnn.VGG16ImageNet, 3, 224, 100, "vgg16_imagenet"),
]
self_folder = Path(__file__).parent
model_cls, nch, img_size, batch_size, pathname = benchmarks[0]
codegen_dir = Path(f"/tmp/{pathname}_tune")
print(f"Generating {pathname} to {codegen_dir}")
if codegen_dir.exists():
shutil.rmtree(codegen_dir)
params = self_folder / "../model_params" / pathname
dataset_shape = 5000, nch, img_size, img_size
bin_tuneset = BinDataset(
params / "tune_input.bin", params / "tune_labels.bin", dataset_shape
)
bin_testset = BinDataset(
params / "test_input.bin", params / "test_labels.bin", dataset_shape
)
model: Module = model_cls()
checkpoint = self_folder / "../model_params" / f"{pathname}.pth.tar"
model.load_state_dict(torch.load(checkpoint.as_posix()))
exporter = ModelExporter(model, bin_tuneset, bin_testset, codegen_dir, target="hpvm_tensor_inspect")
exporter.export_all(batch_size=batch_size)
conf_file = self_folder / "../hpvm-c/benchmarks" / pathname / "data/tuner_confs.txt"
build_dir = codegen_dir / "build"
target_binary = build_dir / pathname
run([
"approxhpvm.py", str(codegen_dir / ModelExporter.source_file_name), str(target_binary),
"-d", str(build_dir),
"-t", "tensor", "--conf-file", str(conf_file)
], check=True)
# run([str(target_binary), "test"], check=True)
# build_dir = codegen_dir / "build"
# print(PipedBinaryApp("test", codegen_dir / "ops.json", build_dir / "lenet_mnist", build_dir))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment