提交 33d4454d 编写于 作者: L liuqi

Add gcn validation tools.

上级 1635046e
......@@ -100,8 +100,10 @@ int main(int argc, char **argv) {
in_file.close();
}
VLOG(0) << "Before Init";
// Init model
auto net = CreateNet(net_def, &ws, device_type, NetMode::INIT);
VLOG(0) << "Before Run";
net->Run();
// run model
......
......@@ -28,6 +28,11 @@ extern void Conv2dOpenclK3x3S2(const Tensor *input, const Tensor *filter,
const int *padding, const DataType dt,
Tensor *output);
extern void Conv2dOpencl(const Tensor *input, const Tensor *filter,
const Tensor *bias, const bool fused_relu,
const uint32_t stride, const int *padding,
const DataType dt, Tensor *output);
template<typename T>
void FusedConv2dFunctor<DeviceType::OPENCL, T>::operator()(const Tensor *input,
const Tensor *filter,
......@@ -44,20 +49,15 @@ void FusedConv2dFunctor<DeviceType::OPENCL, T>::operator()(const Tensor *input,
{Conv2dOpenclK3x3S1, Conv2dOpenclK3x3S2},
{nullptr, nullptr},
{nullptr, nullptr}};
index_t kernel_h = filter->dim(0);
index_t kernel_w = filter->dim(1);
if (kernel_h != kernel_w || kernel_h > 5 || strides_[0] != strides_[1] ||
strides_[0] > 2 || dilations_[0] != 1 || dilations_[1] != 1 ||
selector[kernel_h - 1][strides_[0] - 1] == nullptr) {
if (!input->is_image() || strides_[0] != strides_[1] ||
strides_[0] > 2 || dilations_[0] != 1 || dilations_[1] != 1) {
LOG(WARNING) << "OpenCL conv2d kernel with "
<< "filter" << kernel_h << "x" << kernel_w << ","
<< " stride " << strides_[0] << "x" << strides_[1]
<< " is not implemented yet, using slow version";
// TODO(heliangliang) The CPU/NEON kernel should map the buffer
FusedConv2dFunctor<DeviceType::CPU, T>(strides_, paddings_, dilations_)(
input, filter, bias, output);
return;
MACE_NOT_IMPLEMENTED;
}
std::vector<index_t> output_shape(4);
......@@ -66,16 +66,17 @@ void FusedConv2dFunctor<DeviceType::OPENCL, T>::operator()(const Tensor *input,
input->shape().data(), filter->shape().data(), dilations_,
strides_, paddings_, output_shape.data(), paddings.data());
if (input->is_image()) {
std::vector<size_t> output_image_shape;
CalImage2DShape(output_shape, BufferType::IN_OUT, output_image_shape);
output->ResizeImage(output_shape, output_image_shape);
std::vector<size_t> output_image_shape;
CalImage2DShape(output_shape, BufferType::IN_OUT, output_image_shape);
output->ResizeImage(output_shape, output_image_shape);
if (kernel_h == kernel_w && kernel_h <= 5 &&
selector[kernel_h - 1][strides_[0] - 1] != nullptr) {
auto conv2d_func = selector[kernel_h - 1][strides_[0] - 1];
conv2d_func(input, filter, bias, false, paddings.data(), DataTypeToEnum<T>::value, output);
} else {
output->Resize(output_shape);
Conv2dOpencl(input, filter, bias, false, strides_[0], paddings.data(), DataTypeToEnum<T>::value, output);
}
auto conv2d_func = selector[kernel_h - 1][strides_[0] - 1];
conv2d_func(input, filter, bias, true, paddings.data(), DataTypeToEnum<T>::value, output);
}
template
......
......@@ -24,7 +24,7 @@ def main(unused_args):
input_graph_def, FLAGS.input_node, FLAGS.output_node, FLAGS.prequantize)
else:
output_graph_def = tf_converter_lib.convert_to_mace_pb(
input_graph_def, FLAGS.runtime)
input_graph_def, FLAGS.input_node, FLAGS.output_node, FLAGS.runtime)
with gfile.GFile(FLAGS.output, "wb") as f:
f.write(output_graph_def.SerializeToString())
......
......@@ -45,9 +45,11 @@ def get_input_tensor(op, index):
def add_buffer_to_image(input_name, input_type, net_def):
output_name = input_name[:-2] + "_b2i" + input_name[-2:]
op_def = net_def.op.add()
op_def.name = output_name
op_def.name = output_name[:-2]
op_def.type = 'BufferToImage'
op_def.input.extend([input_name])
op_def.output.extend([output_name])
epsilon_arg = op_def.arg.add()
epsilon_arg.name = 'buffer_type'
epsilon_arg.i = buffer_type_map[input_type]
......@@ -56,6 +58,30 @@ def add_buffer_to_image(input_name, input_type, net_def):
epsilon_arg.i = 0
return output_name
def add_input_transform(name, net_def):
new_input_name = "mace_input_node:0"
op_def = net_def.op.add()
op_def.name = name
op_def.type = 'BufferToImage'
op_def.input.extend([new_input_name])
op_def.output.extend([name+':0'])
epsilon_arg = op_def.arg.add()
epsilon_arg.name = 'buffer_type'
epsilon_arg.i = buffer_type_map['IN_OUT']
def add_output_transform(name, net_def):
output_name = "mace_output_node:0"
op_def = net_def.op.add()
op_def.name = output_name[:-2]
op_def.type = 'ImageToBuffer'
op_def.input.extend([name+':0'])
op_def.output.extend([output_name])
epsilon_arg = op_def.arg.add()
epsilon_arg.name = 'buffer_type'
epsilon_arg.i = buffer_type_map['IN_OUT']
def convert_ops(unresolved_ops, net_def, device):
ops_count = len(unresolved_ops)
resolved_count = 1
......@@ -257,7 +283,7 @@ def convert_ops(unresolved_ops, net_def, device):
size_arg.ints.extend(get_input_tensor(first_op, 1).eval().astype(np.int32).flat)
size_arg = op_def.arg.add()
size_arg.name = 'align_corners'
size_arg.ints.extend(first_op.get_attr('align_corners'))
size_arg.i = first_op.get_attr('align_corners')
output_shapes = []
for output in first_op.outputs:
output_shape = mace_pb2.OutputShape()
......@@ -284,7 +310,7 @@ def convert_ops(unresolved_ops, net_def, device):
del unresolved_ops[0]
def convert_to_mace_pb(input_graph_def, device):
def convert_to_mace_pb(input_graph_def, input_node, output_node, device):
net_def = mace_pb2.NetDef()
with tf.Session() as session:
......@@ -292,8 +318,12 @@ def convert_to_mace_pb(input_graph_def, device):
tf.import_graph_def(input_graph_def, name="")
ops = graph.get_operations()
unresolved_ops = ops
if device == 'gpu':
add_input_transform(input_node, net_def)
while len(unresolved_ops) > 0:
convert_ops(unresolved_ops, net_def, device)
if device == 'gpu':
add_output_transform(output_node, net_def)
print "PB Parsed."
......
import argparse
import sys
import tensorflow as tf
import numpy as np
from tensorflow import gfile
# Validation Flow:
# 1. Generate input data
# python validate_icnet.py --generate_data 1 \
# --random_seed 1
# 2. Use mace_run to run icnet on phone.
# 3. adb pull the result.
# 4. Compare output data of mace and tf
# python validate_icnet.py --model_file opt_icnet.pb \
# --input_file input_file \
# --mace_out_file icnet.out
def generate_data(shape):
np.random.seed(FLAGS.random_seed)
data = np.random.random(shape)
print FLAGS.input_file
data.astype(np.float32).tofile(FLAGS.input_file)
print "Generate input file done."
def load_data(file):
return np.fromfile(file=file, dtype=np.float32)
def valid_output(out_shape, mace_out_file, tf_out_value):
mace_out_value = load_data(mace_out_file)
mace_out_value = mace_out_value.reshape(out_shape)
res = np.allclose(tf_out_value, mace_out_value, rtol=0, atol=1e-5)
print 'Passed! Haha' if res else 'Failed! Oops'
def run_model(input_shape):
if not gfile.Exists(FLAGS.model_file):
print("Input graph file '" + FLAGS.model_file + "' does not exist!")
return -1
input_graph_def = tf.GraphDef()
with gfile.Open(FLAGS.model_file, "rb") as f:
data = f.read()
input_graph_def.ParseFromString(data)
tf.import_graph_def(input_graph_def, name="")
with tf.Session() as session:
with session.graph.as_default() as graph:
tf.import_graph_def(input_graph_def, name="")
input_node = graph.get_tensor_by_name(FLAGS.input_node + ':0')
output_node = graph.get_tensor_by_name(FLAGS.output_node + ':0')
input_value = load_data(FLAGS.input_file)
input_value = input_value.reshape(input_shape)
output_value = session.run(output_node, feed_dict={input_node: [input_value]})
return output_value
def main(unused_args):
input_shape = [int(x) for x in FLAGS.input_shape.split(',')]
output_shape = [int(x) for x in FLAGS.output_shape.split(',')]
if FLAGS.generate_data:
generate_data(input_shape)
else:
output_value = run_model(input_shape)
valid_output(output_shape, FLAGS.mace_out_file, output_value)
def parse_args():
"""Parses command line arguments."""
parser = argparse.ArgumentParser()
parser.register("type", "bool", lambda v: v.lower() == "true")
parser.add_argument(
"--model_file",
type=str,
default="",
help="TensorFlow \'GraphDef\' file to load.")
parser.add_argument(
"--input_file",
type=str,
default="",
help="input file.")
parser.add_argument(
"--mace_out_file",
type=str,
default="",
help="mace output file to load.")
parser.add_argument(
"--input_shape",
type=str,
default="512,512,3",
help="input shape.")
parser.add_argument(
"--output_shape",
type=str,
default="1,512,512,2",
help="output shape.")
parser.add_argument(
"--input_node",
type=str,
default="input_node",
help="input node")
parser.add_argument(
"--output_node",
type=str,
default="output_node",
help="output node")
parser.add_argument(
"--generate_data",
type='bool',
default="false",
help="Random seed for generate test case.")
parser.add_argument(
"--random_seed",
type=int,
default="0",
help="Random seed for generate test case.")
return parser.parse_known_args()
if __name__ == '__main__':
FLAGS, unparsed = parse_args()
main(unused_args=[sys.argv[0]] + unparsed)
#!/bin/bash
# Must run at root dir of mace project.
set -e
Usage() {
echo 'Usage: bash tools/validate_gcn.sh tf_model_file'
}
if [ $# != 1 ];then
Usage
exit -1
fi
TF_MODEL_FILE_PATH=$1
MODEL_DIR=$(dirname ${TF_MODEL_FILE_PATH})
MACE_MODEL_NAME='mace_model.pb'
INPUT_FILE_NAME='model_input'
OUTPUT_FILE_NAME='gcn.out'
PHONE_DATA_DIR="/data/local/tmp/${MACE_MODEL_NAME}"
KERNEL_DIR="${PHONE_DATA_DIR}/cl/"
# Step 1: convert tf model to mace model
#echo "Step 1: convert tf model to mace model"
#bazel build //mace/python/tools:tf_converter
#bazel-bin/mace/python/tools/tf_converter --input=${TF_MODEL_FILE_PATH} \
# --output=${MODEL_DIR}/${MACE_MODEL_NAME} \
# --input_node=input \
# --output_node=GCN/br_result_2/fcn_br \
# --runtime=gpu
#
## Step 2: Generate input data
#echo "Step 2: Generate input data"
#python tools/validate.py --generate_data true --random_seed 1 \
# --input_file=${MODEL_DIR}/${INPUT_FILE_NAME} \
# --input_shape=512,512,3
# Step 3: Run model on the phone
echo "Step 3: Run model on the phone"
bazel build -c opt --strip always mace/examples:mace_run \
--crosstool_top=//external:android/crosstool \
--host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
--cpu=arm64-v8a
adb shell "mkdir -p ${PHONE_DATA_DIR}"
adb shell "mkdir -p ${KERNEL_DIR}"
adb push mace/kernels/opencl/cl/* ${KERNEL_DIR}
adb push ${MODEL_DIR}/${MACE_MODEL_NAME} ${PHONE_DATA_DIR}
adb push ${MODEL_DIR}/${INPUT_FILE_NAME} ${PHONE_DATA_DIR}
adb push bazel-bin/mace/examples/mace_run ${PHONE_DATA_DIR}
num_threads=${1:-1}
adb shell MACE_RUN_PARAMETER_PATH=${PHONE_DATA_DIR}/mace_run.config \
MACE_KERNEL_PATH=$KERNEL_DIR \
OMP_NUM_THREADS=$num_threads \
${PHONE_DATA_DIR}/mace_run \
--model=${PHONE_DATA_DIR}/${MACE_MODEL_NAME} \
--input=mace_input_node \
--output=mace_output_node \
--input_shape=1,512,512,3\
--input_file=${PHONE_DATA_DIR}/${MACE_INPUT_FILE_NAME} \
--output_file=${PHONE_DATA_DIR}/${OUTPUT_FILE_NAME} \
--device=OPENCL
# Step 4: pull the mace run result.
echo "Step 4: pull the mace run result."
adb pull ${PHONE_DATA_DIR}/${OUTPUT_FILE_NAME} ${MODEL_DIR}
# Step 5: validate the result
echo "Step 5: validate the result"
python tools/validate.py --model_file ${TF_MODEL_FILE_PATH} \
--input_file ${MODEL_DIR}/${INPUT_FILE_NAME} \
--mace_out_file ${MODEL_DIR}/${OUTPUT_FILE_NAME} \
--input_node input \
--output_node GCN/br_result_2/fcn_br
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册