X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=examples%2Fgraph_resnet50.cpp;h=bafa9a58527540c878da9be555c5d44cb0920277;hb=HEAD;hp=1bd76f0ad6a1ea2401f2c22e6023005a037ecd60;hpb=67c8c91522e5be8156b77f57e63c0253535c902a;p=platform%2Fupstream%2Farmcl.git diff --git a/examples/graph_resnet50.cpp b/examples/graph_resnet50.cpp index 1bd76f0..bafa9a5 100644 --- a/examples/graph_resnet50.cpp +++ b/examples/graph_resnet50.cpp @@ -21,8 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "arm_compute/graph/Graph.h" -#include "arm_compute/graph/Nodes.h" +#include "arm_compute/graph.h" #include "support/ToolchainSupport.h" #include "utils/GraphUtils.h" #include "utils/Utils.h" @@ -30,13 +29,13 @@ #include using namespace arm_compute::utils; -using namespace arm_compute::graph; +using namespace arm_compute::graph::frontend; using namespace arm_compute::graph_utils; -/** Example demonstrating how to implement Microsoft's ResNet50 network using the Compute Library's graph API +/** Example demonstrating how to implement ResNet50 network using the Compute Library's graph API * * @param[in] argc Number of arguments - * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels ) + * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL, 2 = OpenCL with Tuner), [optional] Path to the weights folder, [optional] image, [optional] labels, [optional] Fast math for convolution layer (0 = DISABLED, 1 = ENABLED) ) */ class GraphResNet50Example : public Example { @@ -53,76 +52,93 @@ public: false /* Do not convert to BGR */); // Set target. 0 (NEON), 1 (OpenCL), 2 (OpenCL with Tuner). By default it is NEON - const int int_target_hint = argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0; - TargetHint target_hint = set_target_hint(int_target_hint); + const int target = argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0; + Target target_hint = set_target_hint(target); + FastMathHint fast_math_hint = FastMathHint::DISABLED; // Parse arguments if(argc < 2) { // Print help - std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n"; + std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels] [fast_math_hint]\n\n"; std::cout << "No data folder provided: using random values\n\n"; } else if(argc == 2) { - std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n"; + std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels] [fast_math_hint]\n\n"; std::cout << "No data folder provided: using random values\n\n"; } else if(argc == 3) { data_path = argv[2]; - std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n"; + std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels] [fast_math_hint]\n\n"; std::cout << "No image provided: using random values\n\n"; } else if(argc == 4) { data_path = argv[2]; image = argv[3]; - std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n"; + std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels] [fast_math_hint]\n\n"; std::cout << "No text file with labels provided: skipping output accessor\n\n"; } - else + else if(argc == 5) { data_path = argv[2]; image = argv[3]; label = argv[4]; + std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " " << argv[4] << " [fast_math_hint]\n\n"; + std::cout << "No fast math info provided: disabling fast math\n\n"; + } + else + { + data_path = argv[2]; + image = argv[3]; + label = argv[4]; + fast_math_hint = (std::strtol(argv[5], nullptr, 1) == 0) ? FastMathHint::DISABLED : FastMathHint::ENABLED; } graph << target_hint - << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32), - get_input_accessor(image, std::move(preprocessor), false /* Do not convert to BGR */)) + << fast_math_hint + << InputLayer(TensorDescriptor(TensorShape(224U, 224U, 3U, 1U), DataType::F32), + get_input_accessor(image, std::move(preprocessor), false /* Do not convert to BGR */)) << ConvolutionLayer( 7U, 7U, 64U, get_weights_accessor(data_path, "/cnn_data/resnet50_model/conv1_weights.npy"), std::unique_ptr(nullptr), PadStrideInfo(2, 2, 3, 3)) + .set_name("conv1/convolution") << BatchNormalizationLayer( get_weights_accessor(data_path, "/cnn_data/resnet50_model/conv1_BatchNorm_moving_mean.npy"), get_weights_accessor(data_path, "/cnn_data/resnet50_model/conv1_BatchNorm_moving_variance.npy"), get_weights_accessor(data_path, "/cnn_data/resnet50_model/conv1_BatchNorm_gamma.npy"), get_weights_accessor(data_path, "/cnn_data/resnet50_model/conv1_BatchNorm_beta.npy"), 0.0000100099996416f) - << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)) - << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR))); + .set_name("conv1/BatchNorm") + << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)).set_name("conv1/Relu") + << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR))).set_name("pool1/MaxPool"); add_residual_block(data_path, "block1", 64, 3, 2); add_residual_block(data_path, "block2", 128, 4, 2); add_residual_block(data_path, "block3", 256, 6, 2); add_residual_block(data_path, "block4", 512, 3, 1); - graph << PoolingLayer(PoolingLayerInfo(PoolingType::AVG)) + graph << PoolingLayer(PoolingLayerInfo(PoolingType::AVG)).set_name("pool5") << ConvolutionLayer( 1U, 1U, 1000U, get_weights_accessor(data_path, "/cnn_data/resnet50_model/logits_weights.npy"), get_weights_accessor(data_path, "/cnn_data/resnet50_model/logits_biases.npy"), PadStrideInfo(1, 1, 0, 0)) - << FlattenLayer() - << SoftmaxLayer() - << Tensor(get_output_accessor(label, 5)); + .set_name("logits/convolution") + << FlattenLayer().set_name("predictions/Reshape") + << SoftmaxLayer().set_name("predictions/Softmax") + << OutputLayer(get_output_accessor(label, 5)); - // In order to enable the OpenCL tuner, graph_init() has to be called only when all nodes have been instantiated - graph.graph_init(int_target_hint == 2); + // Finalize graph + GraphConfig config; + config.use_tuner = (target == 2); + graph.finalize(target_hint, config); } + void do_run() override { // Run graph @@ -130,15 +146,19 @@ public: } private: - Graph graph{}; + Stream graph{ 0, "ResNet50" }; void add_residual_block(const std::string &data_path, const std::string &name, unsigned int base_depth, unsigned int num_units, unsigned int stride) { for(unsigned int i = 0; i < num_units; ++i) { - std::stringstream unit; - unit << "/cnn_data/resnet50_model/" << name << "_unit_" << (i + 1) << "_bottleneck_v1_"; - std::string unit_name = unit.str(); + std::stringstream unit_path_ss; + unit_path_ss << "/cnn_data/resnet50_model/" << name << "_unit_" << (i + 1) << "_bottleneck_v1_"; + std::stringstream unit_name_ss; + unit_name_ss << name << "/unit" << (i + 1) << "/bottleneck_v1/"; + + std::string unit_path = unit_path_ss.str(); + std::string unit_name = unit_name_ss.str(); unsigned int middle_stride = 1; @@ -147,76 +167,84 @@ private: middle_stride = stride; } - SubGraph right; + SubStream right(graph); right << ConvolutionLayer( 1U, 1U, base_depth, - get_weights_accessor(data_path, unit_name + "conv1_weights.npy"), + get_weights_accessor(data_path, unit_path + "conv1_weights.npy"), std::unique_ptr(nullptr), PadStrideInfo(1, 1, 0, 0)) + .set_name(unit_name + "conv1/convolution") << BatchNormalizationLayer( - get_weights_accessor(data_path, unit_name + "conv1_BatchNorm_moving_mean.npy"), - get_weights_accessor(data_path, unit_name + "conv1_BatchNorm_moving_variance.npy"), - get_weights_accessor(data_path, unit_name + "conv1_BatchNorm_gamma.npy"), - get_weights_accessor(data_path, unit_name + "conv1_BatchNorm_beta.npy"), + get_weights_accessor(data_path, unit_path + "conv1_BatchNorm_moving_mean.npy"), + get_weights_accessor(data_path, unit_path + "conv1_BatchNorm_moving_variance.npy"), + get_weights_accessor(data_path, unit_path + "conv1_BatchNorm_gamma.npy"), + get_weights_accessor(data_path, unit_path + "conv1_BatchNorm_beta.npy"), 0.0000100099996416f) - << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)) + .set_name(unit_name + "conv1/BatchNorm") + << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)).set_name(unit_name + "conv1/Relu") << ConvolutionLayer( 3U, 3U, base_depth, - get_weights_accessor(data_path, unit_name + "conv2_weights.npy"), + get_weights_accessor(data_path, unit_path + "conv2_weights.npy"), std::unique_ptr(nullptr), PadStrideInfo(middle_stride, middle_stride, 1, 1)) + .set_name(unit_name + "conv2/convolution") << BatchNormalizationLayer( - get_weights_accessor(data_path, unit_name + "conv2_BatchNorm_moving_mean.npy"), - get_weights_accessor(data_path, unit_name + "conv2_BatchNorm_moving_variance.npy"), - get_weights_accessor(data_path, unit_name + "conv2_BatchNorm_gamma.npy"), - get_weights_accessor(data_path, unit_name + "conv2_BatchNorm_beta.npy"), + get_weights_accessor(data_path, unit_path + "conv2_BatchNorm_moving_mean.npy"), + get_weights_accessor(data_path, unit_path + "conv2_BatchNorm_moving_variance.npy"), + get_weights_accessor(data_path, unit_path + "conv2_BatchNorm_gamma.npy"), + get_weights_accessor(data_path, unit_path + "conv2_BatchNorm_beta.npy"), 0.0000100099996416f) - << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)) + .set_name(unit_name + "conv2/BatchNorm") + << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)).set_name(unit_name + "conv1/Relu") << ConvolutionLayer( 1U, 1U, base_depth * 4, - get_weights_accessor(data_path, unit_name + "conv3_weights.npy"), + get_weights_accessor(data_path, unit_path + "conv3_weights.npy"), std::unique_ptr(nullptr), PadStrideInfo(1, 1, 0, 0)) + .set_name(unit_name + "conv3/convolution") << BatchNormalizationLayer( - get_weights_accessor(data_path, unit_name + "conv3_BatchNorm_moving_mean.npy"), - get_weights_accessor(data_path, unit_name + "conv3_BatchNorm_moving_variance.npy"), - get_weights_accessor(data_path, unit_name + "conv3_BatchNorm_gamma.npy"), - get_weights_accessor(data_path, unit_name + "conv3_BatchNorm_beta.npy"), - 0.0000100099996416f); + get_weights_accessor(data_path, unit_path + "conv3_BatchNorm_moving_mean.npy"), + get_weights_accessor(data_path, unit_path + "conv3_BatchNorm_moving_variance.npy"), + get_weights_accessor(data_path, unit_path + "conv3_BatchNorm_gamma.npy"), + get_weights_accessor(data_path, unit_path + "conv3_BatchNorm_beta.npy"), + 0.0000100099996416f) + .set_name(unit_name + "conv2/BatchNorm"); if(i == 0) { - SubGraph left; + SubStream left(graph); left << ConvolutionLayer( 1U, 1U, base_depth * 4, - get_weights_accessor(data_path, unit_name + "shortcut_weights.npy"), + get_weights_accessor(data_path, unit_path + "shortcut_weights.npy"), std::unique_ptr(nullptr), PadStrideInfo(1, 1, 0, 0)) + .set_name(unit_name + "shortcut/convolution") << BatchNormalizationLayer( - get_weights_accessor(data_path, unit_name + "shortcut_BatchNorm_moving_mean.npy"), - get_weights_accessor(data_path, unit_name + "shortcut_BatchNorm_moving_variance.npy"), - get_weights_accessor(data_path, unit_name + "shortcut_BatchNorm_gamma.npy"), - get_weights_accessor(data_path, unit_name + "shortcut_BatchNorm_beta.npy"), - 0.0000100099996416f); + get_weights_accessor(data_path, unit_path + "shortcut_BatchNorm_moving_mean.npy"), + get_weights_accessor(data_path, unit_path + "shortcut_BatchNorm_moving_variance.npy"), + get_weights_accessor(data_path, unit_path + "shortcut_BatchNorm_gamma.npy"), + get_weights_accessor(data_path, unit_path + "shortcut_BatchNorm_beta.npy"), + 0.0000100099996416f) + .set_name(unit_name + "shortcut/BatchNorm"); - graph << ResidualLayer(std::move(left), std::move(right)); + graph << BranchLayer(BranchMergeMethod::ADD, std::move(left), std::move(right)).set_name(unit_name + "add"); } else if(middle_stride > 1) { - SubGraph left; - left << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 1, PadStrideInfo(middle_stride, middle_stride, 0, 0), true)) - << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LINEAR, 1.f, 0.f)); + SubStream left(graph); + left << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 1, PadStrideInfo(middle_stride, middle_stride, 0, 0), true)).set_name(unit_name + "shortcut/MaxPool"); - graph << ResidualLayer(std::move(left), std::move(right)); + graph << BranchLayer(BranchMergeMethod::ADD, std::move(left), std::move(right)).set_name(unit_name + "add"); } else { - graph << ResidualLayer(std::move(right)); + SubStream left(graph); + graph << BranchLayer(BranchMergeMethod::ADD, std::move(left), std::move(right)).set_name(unit_name + "add"); } - graph << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)); + graph << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)).set_name(unit_name + "Relu"); } } }; @@ -224,7 +252,7 @@ private: /** Main program for ResNet50 * * @param[in] argc Number of arguments - * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels ) + * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL, 2 = OpenCL with Tuner), [optional] Path to the weights folder, [optional] image, [optional] labels, [optional] Fast math for convolution layer (0 = DISABLED, 1 = ENABLED) ) */ int main(int argc, char **argv) {