sh_commands.py 51.3 KB
Newer Older
Y
yejianwu 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# Copyright 2018 Xiaomi, Inc.  All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Y
yejianwu 已提交
15 16
import falcon_cli
import filelock
Y
yejianwu 已提交
17
import glob
L
liuqi 已提交
18
import logging
19
import numpy as np
Y
yejianwu 已提交
20
import os
21
import re
Y
yejianwu 已提交
22
import sh
23
import struct
Y
yejianwu 已提交
24
import subprocess
25
import sys
26
import time
W
wuchenghui 已提交
27
import urllib
A
Allen 已提交
28
import platform
29
from enum import Enum
30

L
liuqi 已提交
31
import common
L
Liangliang He 已提交
32

33 34 35 36 37 38
sys.path.insert(0, "mace/python/tools")
try:
    from encrypt_opencl_codegen import encrypt_opencl_codegen
    from binary_codegen import tuning_param_codegen
    from generate_data import generate_input_data
    from validate import validate
39
    from mace_engine_factory_codegen import gen_mace_engine_factory
Y
yejianwu 已提交
40 41
except Exception as e:
    print("Import error:\n%s" % e)
42 43
    exit(1)

44 45 46
################################
# common
################################
L
liuqi 已提交
47 48


49
def strip_invalid_utf8(str):
L
Liangliang He 已提交
50 51
    return sh.iconv(str, "-c", "-t", "UTF-8")

52

53 54 55 56 57 58
def split_stdout(stdout_str):
    stdout_str = strip_invalid_utf8(stdout_str)
    # Filter out last empty line
    return [l.strip() for l in stdout_str.split('\n') if len(l.strip()) > 0]


59
def make_output_processor(buff):
L
Liangliang He 已提交
60
    def process_output(line):
L
Liangliang He 已提交
61
        print(line.rstrip())
L
Liangliang He 已提交
62 63 64 65
        buff.append(line)

    return process_output

66

67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
def device_lock_path(serialno):
    return "/tmp/device-lock-%s" % serialno


def device_lock(serialno, timeout=3600):
    return filelock.FileLock(device_lock_path(serialno), timeout=timeout)


def is_device_locked(serialno):
    try:
        with device_lock(serialno, timeout=0.000001):
            return False
    except filelock.Timeout:
        return True


83 84 85 86 87
class BuildType(object):
    proto = 'proto'
    code = 'code'


88 89 90 91 92 93 94 95 96
def stdout_success(stdout):
    stdout_lines = stdout.split("\n")
    for line in stdout_lines:
        if "Aborted" in line or "FAILED" in line or \
                        "Segmentation fault" in line:
            return False
    return True


Y
yejianwu 已提交
97 98 99
################################
# clear data
################################
100 101 102 103 104
def clear_phone_data_dir(serialno, phone_data_dir):
    sh.adb("-s",
           serialno,
           "shell",
           "rm -rf %s" % phone_data_dir)
105 106 107


def clear_model_codegen(model_codegen_dir="mace/codegen/models"):
Y
yejianwu 已提交
108 109 110 111
    if os.path.exists(model_codegen_dir):
        sh.rm("-rf", model_codegen_dir)


112 113 114
################################
# adb commands
################################
W
wuchenghui 已提交
115 116
def adb_devices():
    serialnos = []
117
    p = re.compile(r'(\w+)\s+device')
118
    for line in split_stdout(sh.adb("devices")):
119 120
        m = p.match(line)
        if m:
W
wuchenghui 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
            serialnos.append(m.group(1))

    return serialnos


def get_soc_serialnos_map():
    serialnos = adb_devices()
    soc_serialnos_map = {}
    for serialno in serialnos:
        props = adb_getprop_by_serialno(serialno)
        soc_serialnos_map.setdefault(props["ro.board.platform"], [])\
            .append(serialno)

    return soc_serialnos_map


def get_target_socs_serialnos(target_socs=None):
    soc_serialnos_map = get_soc_serialnos_map()
    serialnos = []
    if target_socs is None:
        target_socs = soc_serialnos_map.keys()
    for target_soc in target_socs:
        serialnos.extend(soc_serialnos_map[target_soc])
    return serialnos
L
Liangliang He 已提交
145

146

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
def get_soc_serial_number_map():
    serial_numbers = adb_devices()
    soc_serial_number_map = {}
    for num in serial_numbers:
        props = adb_getprop_by_serialno(num)
        soc_serial_number_map[props["ro.board.platform"]] = num
    return soc_serial_number_map


def get_target_soc_serial_number(target_soc):
    soc_serial_number_map = get_soc_serial_number_map()
    serial_number = None
    if target_soc in soc_serial_number_map:
        serial_number = soc_serial_number_map[target_soc]
    return serial_number


164
def adb_getprop_by_serialno(serialno):
L
Liangliang He 已提交
165
    outputs = sh.adb("-s", serialno, "shell", "getprop")
166
    raw_props = split_stdout(outputs)
L
Liangliang He 已提交
167
    props = {}
168
    p = re.compile(r'\[(.+)\]: \[(.+)\]')
L
Liangliang He 已提交
169 170 171 172 173 174
    for raw_prop in raw_props:
        m = p.match(raw_prop)
        if m:
            props[m.group(1)] = m.group(2)
    return props

175

W
wuchenghui 已提交
176 177
def adb_get_device_name_by_serialno(serialno):
    props = adb_getprop_by_serialno(serialno)
L
liuqi 已提交
178
    return props.get("ro.product.model", "").replace(' ', '')
W
wuchenghui 已提交
179 180


181
def adb_supported_abis(serialno):
L
Liangliang He 已提交
182 183 184 185 186
    props = adb_getprop_by_serialno(serialno)
    abilist_str = props["ro.product.cpu.abilist"]
    abis = [abi.strip() for abi in abilist_str.split(',')]
    return abis

187

188
def adb_get_all_socs():
L
Liangliang He 已提交
189 190 191 192 193
    socs = []
    for d in adb_devices():
        props = adb_getprop_by_serialno(d)
        socs.append(props["ro.board.platform"])
    return set(socs)
194

L
Liangliang He 已提交
195

Y
yejianwu 已提交
196 197 198 199 200 201 202 203 204 205 206 207 208
def adb_push(src_path, dst_path, serialno):
    print("Push %s to %s" % (src_path, dst_path))
    sh.adb("-s", serialno, "push", src_path, dst_path)


def adb_pull(src_path, dst_path, serialno):
    print("Pull %s to %s" % (src_path, dst_path))
    try:
        sh.adb("-s", serialno, "pull", src_path, dst_path)
    except Exception as e:
        print("Error msg: %s" % e.stderr)


209 210
def adb_run(abi,
            serialno,
L
Liangliang He 已提交
211 212
            host_bin_path,
            bin_name,
213
            args="",
L
liuqi 已提交
214
            opencl_profiling=True,
215
            vlog_level=0,
216
            device_bin_path="/data/local/tmp/mace",
L
liuqi 已提交
217
            out_of_range_check=True,
218
            address_sanitizer=False):
L
Liangliang He 已提交
219 220 221 222 223 224
    host_bin_full_path = "%s/%s" % (host_bin_path, bin_name)
    device_bin_full_path = "%s/%s" % (device_bin_path, bin_name)
    props = adb_getprop_by_serialno(serialno)
    print(
        "====================================================================="
    )
L
Liangliang He 已提交
225
    print("Trying to lock device %s" % serialno)
226 227 228 229
    with device_lock(serialno):
        print("Run on device: %s, %s, %s" %
              (serialno, props["ro.board.platform"],
               props["ro.product.model"]))
Y
yejianwu 已提交
230 231
        sh.adb("-s", serialno, "shell", "rm -rf %s" % device_bin_path)
        sh.adb("-s", serialno, "shell", "mkdir -p %s" % device_bin_path)
Y
yejianwu 已提交
232
        adb_push(host_bin_full_path, device_bin_full_path, serialno)
233 234 235 236 237
        ld_preload = ""
        if address_sanitizer:
            adb_push(find_asan_rt_library(abi), device_bin_path, serialno)
            ld_preload = "LD_PRELOAD=%s/%s" % (device_bin_path,
                                               asan_rt_library_names(abi)),
L
liuqi 已提交
238 239
        opencl_profiling = 1 if opencl_profiling else 0
        out_of_range_check = 1 if out_of_range_check else 0
Y
yejianwu 已提交
240
        print("Run %s" % device_bin_full_path)
241

Y
yejianwu 已提交
242 243
        stdout_buff = []
        process_output = make_output_processor(stdout_buff)
L
liuqi 已提交
244
        sh.adb(
Y
yejianwu 已提交
245 246 247
            "-s",
            serialno,
            "shell",
248 249 250 251
            ld_preload,
            "MACE_OUT_OF_RANGE_CHECK=%d" % out_of_range_check,
            "MACE_OPENCL_PROFILING=%d" % opencl_profiling,
            "MACE_CPP_MIN_VLOG_LEVEL=%d" % vlog_level,
252 253 254
            device_bin_full_path,
            args,
            _tty_in=True,
Y
yejianwu 已提交
255
            _out=process_output,
256
            _err_to_out=True)
Y
yejianwu 已提交
257
        return "".join(stdout_buff)
258 259


260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
################################
# Toolchain
################################
def asan_rt_library_names(abi):
    asan_rt_names = {
        "armeabi-v7a": "libclang_rt.asan-arm-android.so",
        "arm64-v8a": "libclang_rt.asan-aarch64-android.so",
    }
    return asan_rt_names[abi]


def find_asan_rt_library(abi, asan_rt_path=''):
    if not asan_rt_path:
        find_path = os.environ['ANDROID_NDK_HOME']
        candidates = split_stdout(sh.find(find_path, "-name",
                                          asan_rt_library_names(abi)))
        if len(candidates) == 0:
            common.MaceLogger.error(
                "Toolchain",
                "Can't find AddressSanitizer runtime library in % s" %
                find_path)
        elif len(candidates) > 1:
            common.MaceLogger.info(
                "More than one AddressSanitizer runtime library, use the 1st")
        return candidates[0]
    return "%s/%s" % (asan_rt_path, asan_rt_library_names(abi))
286 287


288 289 290
################################
# bazel commands
################################
Y
yejianwu 已提交
291 292 293
def bazel_build(target,
                abi="armeabi-v7a",
                hexagon_mode=False,
李寅 已提交
294
                enable_openmp=True,
295
                enable_neon=True,
L
liuqi 已提交
296 297
                address_sanitizer=False,
                extra_args=""):
Y
yejianwu 已提交
298 299
    print("* Build %s with ABI %s" % (target, abi))
    if abi == "host":
W
wuchenghui 已提交
300
        bazel_args = (
Y
yejianwu 已提交
301 302
            "build",
            "--define",
W
wuchenghui 已提交
303
            "openmp=%s" % str(enable_openmp).lower(),
304
            target,
W
wuchenghui 已提交
305
        )
Y
yejianwu 已提交
306 307 308 309
    else:
        bazel_args = (
            "build",
            target,
310 311
            "--config",
            "android",
Y
yejianwu 已提交
312 313
            "--cpu=%s" % abi,
            "--define",
李寅 已提交
314
            "neon=%s" % str(enable_neon).lower(),
Y
yejianwu 已提交
315
            "--define",
W
wuchenghui 已提交
316
            "openmp=%s" % str(enable_openmp).lower(),
Y
yejianwu 已提交
317 318
            "--define",
            "hexagon=%s" % str(hexagon_mode).lower())
319 320 321 322
    if address_sanitizer:
        bazel_args += ("--config", "asan")
    else:
        bazel_args += ("--config", "optimization")
L
liuqi 已提交
323 324
    if extra_args:
        bazel_args += (extra_args, )
L
liuqi 已提交
325 326
    sh.bazel(
        _fg=True,
327 328
        *bazel_args)
    print("Build done!\n")
Y
yejianwu 已提交
329 330 331


def bazel_build_common(target, build_args=""):
L
Liangliang He 已提交
332 333
    stdout_buff = []
    process_output = make_output_processor(stdout_buff)
L
liuqi 已提交
334
    sh.bazel(
L
Liangliang He 已提交
335
        "build",
Y
yejianwu 已提交
336
        target + build_args,
337
        _tty_in=True,
L
Liangliang He 已提交
338
        _out=process_output,
339
        _err_to_out=True)
L
Liangliang He 已提交
340 341
    return "".join(stdout_buff)

342 343

def bazel_target_to_bin(target):
L
Liangliang He 已提交
344 345 346 347 348 349 350 351
    # change //mace/a/b:c to bazel-bin/mace/a/b/c
    prefix, bin_name = target.split(':')
    prefix = prefix.replace('//', '/')
    if prefix.startswith('/'):
        prefix = prefix[1:]
    host_bin_path = "bazel-bin/%s" % prefix
    return host_bin_path, bin_name

352 353 354 355 356

################################
# mace commands
################################
def gen_encrypted_opencl_source(codegen_path="mace/codegen"):
L
Liangliang He 已提交
357
    sh.mkdir("-p", "%s/opencl" % codegen_path)
358 359
    encrypt_opencl_codegen("./mace/kernels/opencl/cl/",
                           "mace/codegen/opencl/opencl_encrypt_program.cc")
L
Liangliang He 已提交
360

361

Y
yejianwu 已提交
362
def gen_mace_engine_factory_source(model_tags,
363
                                   model_load_type,
B
Bin Li 已提交
364
                                   embed_model_data,
Y
yejianwu 已提交
365
                                   codegen_path="mace/codegen"):
B
Bin Li 已提交
366
    print("* Generate mace engine creator source")
367 368 369
    codegen_tools_dir = "%s/engine" % codegen_path
    sh.rm("-rf", codegen_tools_dir)
    sh.mkdir("-p", codegen_tools_dir)
370
    gen_mace_engine_factory(
371 372
        model_tags,
        "mace/python/tools",
373
        model_load_type,
B
Bin Li 已提交
374
        embed_model_data,
375
        codegen_tools_dir)
B
Bin Li 已提交
376
    print("Generate mace engine creator source done!\n")
377 378 379


def pull_binaries(abi, serialno, model_output_dirs,
380
                  cl_built_kernel_file_name):
381
    compiled_opencl_dir = "/data/local/tmp/mace_run/interior/"
382
    mace_run_param_file = "mace_run.config"
Y
yejianwu 已提交
383 384 385 386 387

    cl_bin_dirs = []
    for d in model_output_dirs:
        cl_bin_dirs.append(os.path.join(d, "opencl_bin"))
    cl_bin_dirs_str = ",".join(cl_bin_dirs)
388
    if cl_bin_dirs:
Y
yejianwu 已提交
389 390 391 392 393
        cl_bin_dir = cl_bin_dirs_str
        if os.path.exists(cl_bin_dir):
            sh.rm("-rf", cl_bin_dir)
        sh.mkdir("-p", cl_bin_dir)
        if abi != "host":
394 395
            adb_pull(compiled_opencl_dir + cl_built_kernel_file_name,
                     cl_bin_dir, serialno)
396
            adb_pull("/data/local/tmp/mace_run/%s" % mace_run_param_file,
Y
yejianwu 已提交
397 398 399
                     cl_bin_dir, serialno)


400 401 402 403
def merge_opencl_binaries(binaries_dirs,
                          cl_compiled_program_file_name,
                          output_file_path):
    platform_info_key = 'mace_opencl_precompiled_platform_info_key'
Y
yejianwu 已提交
404
    cl_bin_dirs = []
405
    for d in binaries_dirs:
Y
yejianwu 已提交
406
        cl_bin_dirs.append(os.path.join(d, "opencl_bin"))
407 408
    # create opencl binary output dir
    opencl_binary_dir = os.path.dirname(output_file_path)
L
liuqi 已提交
409 410
    if not os.path.exists(opencl_binary_dir):
        sh.mkdir("-p", opencl_binary_dir)
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
    kvs = {}
    for binary_dir in cl_bin_dirs:
        binary_path = os.path.join(binary_dir, cl_compiled_program_file_name)
        if not os.path.exists(binary_path):
            continue

        print 'generate opencl code from', binary_path
        with open(binary_path, "rb") as f:
            binary_array = np.fromfile(f, dtype=np.uint8)

        idx = 0
        size, = struct.unpack("Q", binary_array[idx:idx + 8])
        idx += 8
        for _ in xrange(size):
            key_size, = struct.unpack("i", binary_array[idx:idx + 4])
            idx += 4
            key, = struct.unpack(
                str(key_size) + "s", binary_array[idx:idx + key_size])
            idx += key_size
            value_size, = struct.unpack("i", binary_array[idx:idx + 4])
            idx += 4
            if key == platform_info_key and key in kvs:
                common.mace_check(
                    (kvs[key] == binary_array[idx:idx + value_size]).all(),
                    "",
                    "There exists more than one OpenCL version for models:"
                    " %s vs %s " %
                    (kvs[key], binary_array[idx:idx + value_size]))
            else:
                kvs[key] = binary_array[idx:idx + value_size]
            idx += value_size

    output_byte_array = bytearray()
    data_size = len(kvs)
    output_byte_array.extend(struct.pack("Q", data_size))
    for key, value in kvs.iteritems():
        key_size = len(key)
        output_byte_array.extend(struct.pack("i", key_size))
        output_byte_array.extend(struct.pack(str(key_size) + "s", key))
        value_size = len(value)
        output_byte_array.extend(struct.pack("i", value_size))
        output_byte_array.extend(value)

    np.array(output_byte_array).tofile(output_file_path)
Y
yejianwu 已提交
455 456


W
wuchenghui 已提交
457
def gen_tuning_param_code(model_output_dirs,
Y
yejianwu 已提交
458
                          codegen_path="mace/codegen"):
459
    mace_run_param_file = "mace_run.config"
Y
yejianwu 已提交
460 461 462 463
    cl_bin_dirs = []
    for d in model_output_dirs:
        cl_bin_dirs.append(os.path.join(d, "opencl_bin"))
    cl_bin_dirs_str = ",".join(cl_bin_dirs)
464 465 466 467 468

    tuning_codegen_dir = "%s/tuning/" % codegen_path
    if not os.path.exists(tuning_codegen_dir):
        sh.mkdir("-p", tuning_codegen_dir)

469 470 471 472 473
    tuning_param_variable_name = "kTuningParamsData"
    tuning_param_codegen(cl_bin_dirs_str,
                         mace_run_param_file,
                         "%s/tuning_params.cc" % tuning_codegen_dir,
                         tuning_param_variable_name)
Y
yejianwu 已提交
474 475


476
def gen_mace_version(codegen_path="mace/codegen"):
L
Liangliang He 已提交
477 478 479 480
    sh.mkdir("-p", "%s/version" % codegen_path)
    sh.bash("mace/tools/git/gen_version_source.sh",
            "%s/version/version.cc" % codegen_path)

481

Y
yejianwu 已提交
482 483 484 485 486
def gen_model_code(model_codegen_dir,
                   platform,
                   model_file_path,
                   weight_file_path,
                   model_sha256_checksum,
487
                   weight_sha256_checksum,
Y
yejianwu 已提交
488 489 490 491 492 493 494
                   input_nodes,
                   output_nodes,
                   runtime,
                   model_tag,
                   input_shapes,
                   dsp_mode,
                   embed_model_data,
495
                   winograd,
Y
yejianwu 已提交
496
                   obfuscate,
497
                   model_build_type,
李寅 已提交
498
                   data_type,
李寅 已提交
499
                   graph_optimize_options):
Y
yejianwu 已提交
500
    bazel_build_common("//mace/python/tools:converter")
Y
yejianwu 已提交
501

Y
yejianwu 已提交
502 503 504
    if os.path.exists(model_codegen_dir):
        sh.rm("-rf", model_codegen_dir)
    sh.mkdir("-p", model_codegen_dir)
Y
yejianwu 已提交
505

L
liuqi 已提交
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
    sh.python("bazel-bin/mace/python/tools/converter",
              "-u",
              "--platform=%s" % platform,
              "--model_file=%s" % model_file_path,
              "--weight_file=%s" % weight_file_path,
              "--model_checksum=%s" % model_sha256_checksum,
              "--weight_checksum=%s" % weight_sha256_checksum,
              "--input_node=%s" % input_nodes,
              "--output_node=%s" % output_nodes,
              "--runtime=%s" % runtime,
              "--template=%s" % "mace/python/tools",
              "--model_tag=%s" % model_tag,
              "--input_shape=%s" % input_shapes,
              "--dsp_mode=%s" % dsp_mode,
              "--embed_model_data=%s" % embed_model_data,
521
              "--winograd=%s" % winograd,
L
liuqi 已提交
522 523 524 525
              "--obfuscate=%s" % obfuscate,
              "--output_dir=%s" % model_codegen_dir,
              "--model_build_type=%s" % model_build_type,
              "--data_type=%s" % data_type,
李寅 已提交
526
              "--graph_optimize_options=%s" % graph_optimize_options,
L
liuqi 已提交
527
              _fg=True)
Y
yejianwu 已提交
528 529 530 531 532 533


def gen_random_input(model_output_dir,
                     input_nodes,
                     input_shapes,
                     input_files,
534 535
                     input_ranges,
                     input_file_name="model_input"):
Y
yejianwu 已提交
536
    for input_name in input_nodes:
L
liuqi 已提交
537 538
        formatted_name = common.formatted_file_name(
            input_file_name, input_name)
539 540
        if os.path.exists("%s/%s" % (model_output_dir, formatted_name)):
            sh.rm("%s/%s" % (model_output_dir, formatted_name))
Y
yejianwu 已提交
541 542
    input_nodes_str = ",".join(input_nodes)
    input_shapes_str = ":".join(input_shapes)
543
    input_ranges_str = ":".join(input_ranges)
544 545
    generate_input_data("%s/%s" % (model_output_dir, input_file_name),
                        input_nodes_str,
李寅 已提交
546 547
                        input_shapes_str,
                        input_ranges_str)
Y
yejianwu 已提交
548 549 550 551 552 553 554 555

    input_file_list = []
    if isinstance(input_files, list):
        input_file_list.extend(input_files)
    else:
        input_file_list.append(input_files)
    if len(input_file_list) != 0:
        input_name_list = []
W
wuchenghui 已提交
556 557
        if isinstance(input_nodes, list):
            input_name_list.extend(input_nodes)
Y
yejianwu 已提交
558
        else:
W
wuchenghui 已提交
559
            input_name_list.append(input_nodes)
Y
yejianwu 已提交
560 561 562 563 564 565
        if len(input_file_list) != len(input_name_list):
            raise Exception('If input_files set, the input files should '
                            'match the input names.')
        for i in range(len(input_file_list)):
            if input_file_list[i] is not None:
                dst_input_file = model_output_dir + '/' + \
L
liuqi 已提交
566 567
                        common.formatted_file_name(input_file_name,
                                                   input_name_list[i])
Y
yejianwu 已提交
568 569 570 571
                if input_file_list[i].startswith("http://") or \
                        input_file_list[i].startswith("https://"):
                    urllib.urlretrieve(input_file_list[i], dst_input_file)
                else:
572
                    sh.cp("-f", input_file_list[i], dst_input_file)
Y
yejianwu 已提交
573 574


Y
yejianwu 已提交
575 576 577 578 579 580
def update_mace_run_lib(build_tmp_binary_dir, linkshared=0):
    if linkshared == 0:
        mace_run_filepath = build_tmp_binary_dir + "/mace_run_static"
    else:
        mace_run_filepath = build_tmp_binary_dir + "/mace_run_shared"

Y
yejianwu 已提交
581 582
    if os.path.exists(mace_run_filepath):
        sh.rm("-rf", mace_run_filepath)
Y
yejianwu 已提交
583 584
    if linkshared == 0:
        sh.cp("-f", "bazel-bin/mace/tools/validation/mace_run_static",
Y
yejianwu 已提交
585 586
              build_tmp_binary_dir)
    else:
Y
yejianwu 已提交
587 588
        sh.cp("-f", "bazel-bin/mace/tools/validation/mace_run_shared",
              build_tmp_binary_dir)
589 590 591 592 593 594 595 596


def touch_tuned_file_flag(build_tmp_binary_dir):
    sh.touch(build_tmp_binary_dir + '/tuned')


def is_binary_tuned(build_tmp_binary_dir):
    return os.path.exists(build_tmp_binary_dir + '/tuned')
Y
yejianwu 已提交
597 598


599 600 601 602
def create_internal_storage_dir(serialno, phone_data_dir):
    internal_storage_dir = "%s/interior/" % phone_data_dir
    sh.adb("-s", serialno, "shell", "mkdir", "-p", internal_storage_dir)
    return internal_storage_dir
603 604


Y
yejianwu 已提交
605 606 607 608 609 610 611 612
def update_libmace_shared_library(serial_num,
                                  abi,
                                  project_name,
                                  build_output_dir,
                                  library_output_dir):
    library_dir = "%s/%s/%s/%s" % (
            build_output_dir, project_name, library_output_dir, abi)

Y
yejianwu 已提交
613
    if os.path.exists(library_dir):
Y
yejianwu 已提交
614 615 616
        sh.rm("-rf", library_dir)
    sh.mkdir("-p", library_dir)
    sh.cp("-f", "bazel-bin/mace/libmace.so", library_dir)
Y
yejianwu 已提交
617 618
    sh.cp("-f",
          "%s/sources/cxx-stl/gnu-libstdc++/4.9/libs/%s/libgnustl_shared.so" %
619
          (os.environ["ANDROID_NDK_HOME"], abi),
Y
yejianwu 已提交
620 621
          library_dir)

Y
yejianwu 已提交
622 623 624 625
    if os.path.exists("mace/libmace.so"):
        sh.rm("-f", "mace/libmace.so")
    sh.cp("-f", "bazel-bin/mace/libmace.so", "mace/")

Y
yejianwu 已提交
626

W
wuchenghui 已提交
627 628
def tuning_run(abi,
               serialno,
L
liuqi 已提交
629 630
               target_dir,
               target_name,
Y
yejianwu 已提交
631 632 633 634 635 636 637
               vlog_level,
               embed_model_data,
               model_output_dir,
               input_nodes,
               output_nodes,
               input_shapes,
               output_shapes,
Y
yejianwu 已提交
638
               mace_model_dir,
Y
yejianwu 已提交
639 640 641 642 643 644 645
               model_tag,
               device_type,
               running_round,
               restart_round,
               limit_opencl_kernel_time,
               tuning,
               out_of_range_check,
646
               phone_data_dir,
647
               build_type,
648
               opencl_binary_file,
Y
yejianwu 已提交
649
               shared_library_dir,
W
wuchenghui 已提交
650 651 652 653
               omp_num_threads=-1,
               cpu_affinity_policy=1,
               gpu_perf_hint=3,
               gpu_priority_hint=3,
Y
yejianwu 已提交
654
               input_file_name="model_input",
655 656
               output_file_name="model_out",
               runtime_failure_ratio=0.0,
Y
yejianwu 已提交
657
               address_sanitizer=False,
Y
yejianwu 已提交
658
               linkshared=0):
659
    print("* Run '%s' with round=%s, restart_round=%s, tuning=%s, "
W
wuchenghui 已提交
660 661
          "out_of_range_check=%s, omp_num_threads=%s, cpu_affinity_policy=%s, "
          "gpu_perf_hint=%s, gpu_priority_hint=%s" %
662
          (model_tag, running_round, restart_round, str(tuning),
W
wuchenghui 已提交
663 664
           str(out_of_range_check), omp_num_threads, cpu_affinity_policy,
           gpu_perf_hint, gpu_priority_hint))
665 666 667
    mace_model_path = ""
    if build_type == BuildType.proto:
        mace_model_path = "%s/%s.pb" % (mace_model_dir, model_tag)
Y
yejianwu 已提交
668
    if abi == "host":
W
wuchenghui 已提交
669 670
        p = subprocess.Popen(
            [
Y
yejianwu 已提交
671 672
                "env",
                "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level,
李寅 已提交
673
                "MACE_RUNTIME_FAILURE_RATIO=%f" % runtime_failure_ratio,
L
liuqi 已提交
674
                "%s/%s" % (target_dir, target_name),
675
                "--model_name=%s" % model_tag,
Y
yejianwu 已提交
676 677 678 679 680 681
                "--input_node=%s" % ",".join(input_nodes),
                "--output_node=%s" % ",".join(output_nodes),
                "--input_shape=%s" % ":".join(input_shapes),
                "--output_shape=%s" % ":".join(output_shapes),
                "--input_file=%s/%s" % (model_output_dir, input_file_name),
                "--output_file=%s/%s" % (model_output_dir, output_file_name),
682
                "--model_data_file=%s/%s.data" % (mace_model_dir, model_tag),
Y
yejianwu 已提交
683 684 685
                "--device=%s" % device_type,
                "--round=%s" % running_round,
                "--restart_round=%s" % restart_round,
W
wuchenghui 已提交
686 687 688 689
                "--omp_num_threads=%s" % omp_num_threads,
                "--cpu_affinity_policy=%s" % cpu_affinity_policy,
                "--gpu_perf_hint=%s" % gpu_perf_hint,
                "--gpu_priority_hint=%s" % gpu_priority_hint,
Y
yejianwu 已提交
690
                "--model_file=%s" % mace_model_path,
W
wuchenghui 已提交
691 692 693
            ],
            stderr=subprocess.PIPE,
            stdout=subprocess.PIPE)
Y
yejianwu 已提交
694 695 696 697 698
        out, err = p.communicate()
        stdout = err + out
        print stdout
        print("Running finished!\n")
        return stdout
Y
yejianwu 已提交
699 700
    else:
        sh.adb("-s", serialno, "shell", "mkdir", "-p", phone_data_dir)
701 702
        internal_storage_dir = create_internal_storage_dir(
            serialno, phone_data_dir)
Y
yejianwu 已提交
703 704

        for input_name in input_nodes:
L
liuqi 已提交
705 706
            formatted_name = common.formatted_file_name(input_file_name,
                                                        input_name)
Y
yejianwu 已提交
707 708
            adb_push("%s/%s" % (model_output_dir, formatted_name),
                     phone_data_dir, serialno)
709 710 711
        if address_sanitizer:
            adb_push(find_asan_rt_library(abi), phone_data_dir, serialno)

Y
yejianwu 已提交
712
        if not embed_model_data:
713
            adb_push("%s/%s.data" % (mace_model_dir, model_tag),
Y
yejianwu 已提交
714
                     phone_data_dir, serialno)
715

716 717 718 719
        if device_type == common.DeviceType.GPU\
                and os.path.exists(opencl_binary_file):
            adb_push(opencl_binary_file, phone_data_dir, serialno)

W
wuchenghui 已提交
720
        adb_push("third_party/nnlib/libhexagon_controller.so",
Y
yejianwu 已提交
721 722
                 phone_data_dir, serialno)

723 724 725 726 727
        mace_model_phone_path = ""
        if build_type == BuildType.proto:
            mace_model_phone_path = "%s/%s.pb" % (phone_data_dir, model_tag)
            adb_push(mace_model_path,
                     mace_model_phone_path,
Y
yejianwu 已提交
728
                     serialno)
729

Y
yejianwu 已提交
730
        if linkshared == 1:
Y
yejianwu 已提交
731 732 733 734 735 736
            adb_push("%s/libmace.so" % shared_library_dir, phone_data_dir,
                     serialno)
            adb_push("%s/libgnustl_shared.so" % shared_library_dir,
                     phone_data_dir,
                     serialno)

L
liuqi 已提交
737
        adb_push("%s/%s" % (target_dir, target_name), phone_data_dir,
738
                 serialno)
Y
yejianwu 已提交
739

Y
yejianwu 已提交
740 741
        stdout_buff = []
        process_output = make_output_processor(stdout_buff)
742
        adb_cmd = [
W
wuchenghui 已提交
743 744 745 746
            "LD_LIBRARY_PATH=%s" % phone_data_dir,
            "MACE_TUNING=%s" % int(tuning),
            "MACE_OUT_OF_RANGE_CHECK=%s" % int(out_of_range_check),
            "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level,
747
            "MACE_RUN_PARAMETER_PATH=%s/mace_run.config" % phone_data_dir,
748
            "MACE_INTERNAL_STORAGE_PATH=%s" % internal_storage_dir,
749
            "MACE_LIMIT_OPENCL_KERNEL_TIME=%s" % limit_opencl_kernel_time,
李寅 已提交
750
            "MACE_RUNTIME_FAILURE_RATIO=%f" % runtime_failure_ratio,
751
        ]
752
        if address_sanitizer:
753
            adb_cmd.extend([
754 755
                "LD_PRELOAD=%s/%s" % (phone_data_dir,
                                      asan_rt_library_names(abi))
756 757
            ])
        adb_cmd.extend([
L
liuqi 已提交
758
            "%s/%s" % (phone_data_dir, target_name),
759
            "--model_name=%s" % model_tag,
W
wuchenghui 已提交
760 761 762 763 764 765 766 767 768 769 770 771 772 773
            "--input_node=%s" % ",".join(input_nodes),
            "--output_node=%s" % ",".join(output_nodes),
            "--input_shape=%s" % ":".join(input_shapes),
            "--output_shape=%s" % ":".join(output_shapes),
            "--input_file=%s/%s" % (phone_data_dir, input_file_name),
            "--output_file=%s/%s" % (phone_data_dir, output_file_name),
            "--model_data_file=%s/%s.data" % (phone_data_dir, model_tag),
            "--device=%s" % device_type,
            "--round=%s" % running_round,
            "--restart_round=%s" % restart_round,
            "--omp_num_threads=%s" % omp_num_threads,
            "--cpu_affinity_policy=%s" % cpu_affinity_policy,
            "--gpu_perf_hint=%s" % gpu_perf_hint,
            "--gpu_priority_hint=%s" % gpu_priority_hint,
774
            "--model_file=%s" % mace_model_phone_path,
775 776
            "--opencl_binary_file=%s/%s" %
            (phone_data_dir, os.path.basename(opencl_binary_file)),
777 778
        ])
        adb_cmd = ' '.join(adb_cmd)
李滨 已提交
779 780 781 782
        cmd_file_name = "%s-%s-%s" % ('cmd_file', model_tag, str(time.time()))
        adb_cmd_file = "%s/%s" % (phone_data_dir, cmd_file_name)
        tmp_cmd_file = "%s/%s" % ('/tmp', cmd_file_name)
        with open(tmp_cmd_file, 'w') as cmd_file:
李寅 已提交
783
            cmd_file.write(adb_cmd)
李滨 已提交
784 785
        adb_push(tmp_cmd_file, adb_cmd_file, serialno)
        os.remove(tmp_cmd_file)
李寅 已提交
786

L
liuqi 已提交
787
        sh.adb(
788 789 790
            "-s",
            serialno,
            "shell",
李寅 已提交
791 792
            "sh",
            adb_cmd_file,
793
            _tty_in=True,
W
wuchenghui 已提交
794
            _out=process_output,
795
            _err_to_out=True)
796 797 798
        stdout = "".join(stdout_buff)
        if not stdout_success(stdout):
            common.MaceLogger.error("Mace Run", "Mace run failed.")
李滨 已提交
799 800 801 802 803 804 805 806 807

        sh.adb(
            "-s",
            serialno,
            "shell",
            "rm",
            adb_cmd_file,
            _fg=True)

Y
yejianwu 已提交
808
        print("Running finished!\n")
李滨 已提交
809

810
        return stdout
Y
yejianwu 已提交
811 812


W
wuchenghui 已提交
813 814
def validate_model(abi,
                   serialno,
Y
yejianwu 已提交
815 816 817
                   model_file_path,
                   weight_file_path,
                   platform,
818
                   device_type,
Y
yejianwu 已提交
819 820 821 822 823
                   input_nodes,
                   output_nodes,
                   input_shapes,
                   output_shapes,
                   model_output_dir,
824
                   phone_data_dir,
L
liuqi 已提交
825
                   caffe_env,
Y
yejianwu 已提交
826 827 828
                   input_file_name="model_input",
                   output_file_name="model_out"):
    print("* Validate with %s" % platform)
L
liuqi 已提交
829 830 831 832 833 834 835 836 837
    if abi != "host":
        for output_name in output_nodes:
            formatted_name = common.formatted_file_name(
                output_file_name, output_name)
            if os.path.exists("%s/%s" % (model_output_dir,
                                         formatted_name)):
                sh.rm("-rf", "%s/%s" % (model_output_dir, formatted_name))
            adb_pull("%s/%s" % (phone_data_dir, formatted_name),
                     model_output_dir, serialno)
Y
yejianwu 已提交
838 839

    if platform == "tensorflow":
840 841
        validate(platform, model_file_path, "",
                 "%s/%s" % (model_output_dir, input_file_name),
842
                 "%s/%s" % (model_output_dir, output_file_name), device_type,
843 844
                 ":".join(input_shapes), ":".join(output_shapes),
                 ",".join(input_nodes), ",".join(output_nodes))
Y
yejianwu 已提交
845 846 847 848
    elif platform == "caffe":
        image_name = "mace-caffe:latest"
        container_name = "mace_caffe_validator"

L
liuqi 已提交
849 850 851 852 853 854 855 856
        if caffe_env == common.CaffeEnvType.LOCAL:
            import imp
            try:
                imp.find_module('caffe')
            except ImportError:
                logger.error('There is no caffe python module.')
            validate(platform, model_file_path, weight_file_path,
                     "%s/%s" % (model_output_dir, input_file_name),
857 858
                     "%s/%s" % (model_output_dir, output_file_name),
                     device_type,
L
liuqi 已提交
859 860 861 862 863 864 865
                     ":".join(input_shapes), ":".join(output_shapes),
                     ",".join(input_nodes), ",".join(output_nodes))
        elif caffe_env == common.CaffeEnvType.DOCKER:
            docker_image_id = sh.docker("images", "-q", image_name)
            if not docker_image_id:
                print("Build caffe docker")
                sh.docker("build", "-t", image_name,
L
Liangliang He 已提交
866
                          "third_party/caffe")
L
liuqi 已提交
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892

            container_id = sh.docker("ps", "-qa", "-f",
                                     "name=%s" % container_name)
            if container_id and not sh.docker("ps", "-qa", "--filter",
                                              "status=running", "-f",
                                              "name=%s" % container_name):
                sh.docker("rm", "-f", container_name)
                container_id = ""
            if not container_id:
                print("Run caffe container")
                sh.docker(
                        "run",
                        "-d",
                        "-it",
                        "--name",
                        container_name,
                        image_name,
                        "/bin/bash")

            for input_name in input_nodes:
                formatted_input_name = common.formatted_file_name(
                        input_file_name, input_name)
                sh.docker(
                        "cp",
                        "%s/%s" % (model_output_dir, formatted_input_name),
                        "%s:/mace" % container_name)
Y
yejianwu 已提交
893 894

            for output_name in output_nodes:
L
liuqi 已提交
895 896 897 898 899 900 901 902
                formatted_output_name = common.formatted_file_name(
                        output_file_name, output_name)
                sh.docker(
                        "cp",
                        "%s/%s" % (model_output_dir, formatted_output_name),
                        "%s:/mace" % container_name)
            model_file_name = os.path.basename(model_file_path)
            weight_file_name = os.path.basename(weight_file_path)
L
liuqi 已提交
903
            sh.docker("cp", "tools/common.py", "%s:/mace" % container_name)
L
liuqi 已提交
904 905 906 907
            sh.docker("cp", "tools/validate.py", "%s:/mace" % container_name)
            sh.docker("cp", model_file_path, "%s:/mace" % container_name)
            sh.docker("cp", weight_file_path, "%s:/mace" % container_name)

L
liuqi 已提交
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
            sh.docker(
                "exec",
                container_name,
                "python",
                "-u",
                "/mace/validate.py",
                "--platform=caffe",
                "--model_file=/mace/%s" % model_file_name,
                "--weight_file=/mace/%s" % weight_file_name,
                "--input_file=/mace/%s" % input_file_name,
                "--mace_out_file=/mace/%s" % output_file_name,
                "--device_type=%s" % device_type,
                "--input_node=%s" % ",".join(input_nodes),
                "--output_node=%s" % ",".join(output_nodes),
                "--input_shape=%s" % ":".join(input_shapes),
                "--output_shape=%s" % ":".join(output_shapes),
                _fg=True)
Y
yejianwu 已提交
925 926 927 928

    print("Validation done!\n")


929 930 931
def build_host_libraries(model_build_type, abi):
    bazel_build("@com_google_protobuf//:protobuf_lite", abi=abi)
    bazel_build("//mace/proto:mace_cc", abi=abi)
Y
yejianwu 已提交
932 933
    bazel_build("//mace/codegen:generated_opencl", abi=abi)
    bazel_build("//mace/codegen:generated_tuning_params", abi=abi)
934 935 936 937 938 939 940 941 942
    bazel_build("//mace/codegen:generated_version", abi=abi)
    bazel_build("//mace/utils:utils", abi=abi)
    bazel_build("//mace/core:core", abi=abi)
    bazel_build("//mace/kernels:kernels", abi=abi)
    bazel_build("//mace/ops:ops", abi=abi)
    if model_build_type == BuildType.code:
        bazel_build(
            "//mace/codegen:generated_models",
            abi=abi)
Y
yejianwu 已提交
943 944


L
liuqi 已提交
945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
################################
# library
################################
def get_lib_path(target_soc, serial_num, abi, project_name, build_output_dir,
                 library_output_dir):
    project_output_dir = "%s/%s" % (build_output_dir, project_name)
    library_dir = "%s/%s" % (project_output_dir, library_output_dir)
    model_bin_dir = "%s/%s/" % (library_dir, abi)
    if abi == "host":
        lib_path = "%s/libmace_%s.a" % \
                   (model_bin_dir, project_name)
    else:
        if not target_soc:
            lib_path = "%s/libmace_%s.a" % \
                       (model_bin_dir, project_name)
        else:
            device_name = adb_get_device_name_by_serialno(serial_num)
            lib_path = "%s/libmace_%s.%s.%s.a" % \
                       (model_bin_dir, project_name,
                        device_name, target_soc)
    return lib_path


Y
yejianwu 已提交
968
def merge_libs(target_soc,
L
liuqi 已提交
969
               serial_num,
Y
yejianwu 已提交
970 971
               abi,
               project_name,
972 973 974 975
               build_output_dir,
               library_output_dir,
               model_build_type,
               hexagon_mode):
Y
yejianwu 已提交
976
    print("* Merge mace lib")
977
    project_output_dir = "%s/%s" % (build_output_dir, project_name)
L
Liangliang He 已提交
978
    hexagon_lib_file = "third_party/nnlib/libhexagon_controller.so"
L
liuqi 已提交
979 980
    library_dir = "%s/%s" % (project_output_dir, library_output_dir)
    model_bin_dir = "%s/%s/" % (library_dir, abi)
981

L
liuqi 已提交
982 983
    if not os.path.exists(model_bin_dir):
        sh.mkdir("-p", model_bin_dir)
Y
yejianwu 已提交
984
    if hexagon_mode:
L
liuqi 已提交
985
        sh.cp("-f", hexagon_lib_file, library_dir)
Y
yejianwu 已提交
986

L
liuqi 已提交
987 988
    lib_path = get_lib_path(target_soc, serial_num, abi,
                            project_name, build_output_dir, library_output_dir)
989
    # make static library
Y
yejianwu 已提交
990 991
    mri_stream = ""
    if abi == "host":
L
liuqi 已提交
992
        mri_stream += "create %s\n" % lib_path
Y
yejianwu 已提交
993
        mri_stream += (
994 995
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_opencl.pic.a\n")
Y
yejianwu 已提交
996
        mri_stream += (
997 998
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_tuning_params.pic.a\n")
999 1000 1001 1002 1003
        mri_stream += (
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_version.pic.a\n")
        mri_stream += (
            "addlib "
Y
yejianwu 已提交
1004
            "bazel-bin/mace/core/libcore.pic.lo\n")
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
        mri_stream += (
            "addlib "
            "bazel-bin/mace/kernels/libkernels.pic.a\n")
        mri_stream += (
            "addlib "
            "bazel-bin/mace/utils/libutils.pic.a\n")
        mri_stream += (
            "addlib "
            "bazel-bin/mace/proto/libmace_cc.pic.a\n")
        mri_stream += (
            "addlib "
            "bazel-bin/external/com_google_protobuf/libprotobuf_lite.pic.a\n")
        mri_stream += (
            "addlib "
            "bazel-bin/mace/ops/libops.pic.lo\n")
        if model_build_type == BuildType.code:
1021 1022 1023
            mri_stream += (
                "addlib "
                "bazel-bin/mace/codegen/libgenerated_models.pic.a\n")
Y
yejianwu 已提交
1024
    else:
L
liuqi 已提交
1025
        mri_stream += "create %s\n" % lib_path
1026
        if model_build_type == BuildType.code:
1027 1028 1029
            mri_stream += (
                "addlib "
                "bazel-bin/mace/codegen/libgenerated_models.a\n")
Y
yejianwu 已提交
1030
        mri_stream += (
1031 1032
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_opencl.a\n")
Y
yejianwu 已提交
1033
        mri_stream += (
1034 1035
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_tuning_params.a\n")
Y
yejianwu 已提交
1036
        mri_stream += (
1037 1038
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_version.a\n")
Y
yejianwu 已提交
1039
        mri_stream += (
1040
            "addlib "
Y
yejianwu 已提交
1041
            "bazel-bin/mace/core/libcore.lo\n")
Y
yejianwu 已提交
1042
        mri_stream += (
1043 1044
            "addlib "
            "bazel-bin/mace/kernels/libkernels.a\n")
Y
yejianwu 已提交
1045
        mri_stream += (
1046 1047
            "addlib "
            "bazel-bin/mace/utils/libutils.a\n")
1048 1049 1050 1051 1052 1053
        mri_stream += (
            "addlib "
            "bazel-bin/mace/proto/libmace_cc.a\n")
        mri_stream += (
            "addlib "
            "bazel-bin/external/com_google_protobuf/libprotobuf_lite.a\n")
Y
yejianwu 已提交
1054
        mri_stream += (
1055 1056
            "addlib "
            "bazel-bin/mace/ops/libops.lo\n")
Y
yejianwu 已提交
1057 1058 1059

    mri_stream += "save\n"
    mri_stream += "end\n"
A
Allen 已提交
1060 1061 1062 1063 1064 1065 1066 1067 1068
    which_sys = platform.system()
    if which_sys == "Linux":
        cmd = sh.Command("%s/toolchains/" % os.environ["ANDROID_NDK_HOME"] +
                        "aarch64-linux-android-4.9/prebuilt/linux-x86_64/" +
                        "bin/aarch64-linux-android-ar")
    elif which_sys == "Darwin":
        cmd = sh.Command("%s/toolchains/" % os.environ["ANDROID_NDK_HOME"] +
                        "aarch64-linux-android-4.9/prebuilt/darwin-x86_64/" +
                        "bin/aarch64-linux-android-ar")
Y
yejianwu 已提交
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084

    cmd("-M", _in=mri_stream)

    print("Libs merged!\n")


def packaging_lib(libmace_output_dir, project_name):
    print("* Package libs for %s" % project_name)
    tar_package_name = "libmace_%s.tar.gz" % project_name
    project_dir = "%s/%s" % (libmace_output_dir, project_name)
    tar_package_path = "%s/%s" % (project_dir, tar_package_name)
    if os.path.exists(tar_package_path):
        sh.rm("-rf", tar_package_path)

    print("Start packaging '%s' libs into %s" % (project_name,
                                                 tar_package_path))
A
Allen 已提交
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
    which_sys = platform.system()
    if which_sys == "Linux":
        sh.tar(
            "cvzf",
            "%s" % tar_package_path,
            glob.glob("%s/*" % project_dir),
            "--exclude",
            "%s/_tmp" % project_dir,
            _fg=True)
    elif which_sys == "Darwin":
        sh.tar(
A
Allen 已提交
1096 1097 1098 1099 1100 1101
            "--exclude",
            "%s/_tmp" % project_dir,
            "-cvzf",
            "%s" % tar_package_path,
            glob.glob("%s/*" % project_dir),
            _fg=True)
Y
yejianwu 已提交
1102 1103 1104
    print("Packaging Done!\n")


L
liuqi 已提交
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
################################
# example
################################
def build_example(target_soc,
                  serial_num,
                  abi,
                  project_name,
                  build_output_dir,
                  library_output_dir,
                  model_output_dir,
                  build_type,
                  hexagon_mode,
                  enable_openmp,
                  linkshared=False):
    static_lib_name = "mace/libmace.a"
    if not linkshared:
        target_name = "example_static"
        lib_path = get_lib_path(target_soc, serial_num, abi, project_name,
                                build_output_dir, library_output_dir)
        sh.cp("-f", lib_path, static_lib_name)
    else:
        target_name = "example_shared"
    example_target = "//mace/examples/cli:%s" % target_name

    if build_type == BuildType.code:
        build_arg = "--per_file_copt=//mace/examples/cli:example.cc@-DCODE_TYPE"  # noqa
    else:
        build_arg = ""

    bazel_build(example_target,
                abi=abi,
                enable_openmp=enable_openmp,
                hexagon_mode=hexagon_mode,
                extra_args=build_arg)

    example_binary_file = "%s/%s" % (model_output_dir, target_name)
    if os.path.exists(example_binary_file):
        sh.rm("-rf", example_binary_file)

    target_bin = "/".join(bazel_target_to_bin(example_target))
    sh.cp("-f", target_bin, model_output_dir)
    sh.rm("-rf", static_lib_name)


################################
# benchmark
################################
1152 1153
def build_benchmark_model(abi,
                          model_output_dir,
Y
yejianwu 已提交
1154
                          hexagon_mode,
L
liuqi 已提交
1155
                          enable_openmp,
Y
yejianwu 已提交
1156
                          linkshared=False):
L
liuqi 已提交
1157
    if not linkshared:
Y
yejianwu 已提交
1158
        target_name = "benchmark_model_static"
Y
yejianwu 已提交
1159
    else:
Y
yejianwu 已提交
1160 1161 1162
        target_name = "benchmark_model_shared"
    benchmark_target = "//mace/benchmark:%s" % target_name

1163 1164
    bazel_build(benchmark_target,
                abi=abi,
L
liuqi 已提交
1165
                enable_openmp=enable_openmp,
1166 1167
                hexagon_mode=hexagon_mode)

Y
yejianwu 已提交
1168 1169 1170 1171
    benchmark_binary_file = "%s/%s" % (model_output_dir, target_name)
    if os.path.exists(benchmark_binary_file):
        sh.rm("-rf", benchmark_binary_file)

1172
    target_bin = "/".join(bazel_target_to_bin(benchmark_target))
Y
yejianwu 已提交
1173
    sh.cp("-f", target_bin, model_output_dir)
1174 1175


W
wuchenghui 已提交
1176 1177
def benchmark_model(abi,
                    serialno,
1178
                    benchmark_binary_dir,
Y
yejianwu 已提交
1179 1180 1181
                    vlog_level,
                    embed_model_data,
                    model_output_dir,
Y
yejianwu 已提交
1182
                    mace_model_dir,
Y
yejianwu 已提交
1183 1184 1185 1186 1187 1188
                    input_nodes,
                    output_nodes,
                    input_shapes,
                    output_shapes,
                    model_tag,
                    device_type,
1189
                    phone_data_dir,
1190
                    build_type,
1191
                    opencl_binary_file,
Y
yejianwu 已提交
1192
                    shared_library_dir,
W
wuchenghui 已提交
1193 1194 1195 1196
                    omp_num_threads=-1,
                    cpu_affinity_policy=1,
                    gpu_perf_hint=3,
                    gpu_priority_hint=3,
Y
yejianwu 已提交
1197
                    input_file_name="model_input",
Y
yejianwu 已提交
1198
                    linkshared=0):
Y
yejianwu 已提交
1199 1200
    print("* Benchmark for %s" % model_tag)

Y
yejianwu 已提交
1201 1202 1203 1204 1205
    if linkshared == 0:
        benchmark_model_target = "benchmark_model_static"
    else:
        benchmark_model_target = "benchmark_model_shared"

1206 1207 1208
    mace_model_path = ""
    if build_type == BuildType.proto:
        mace_model_path = "%s/%s.pb" % (mace_model_dir, model_tag)
Y
yejianwu 已提交
1209
    if abi == "host":
W
wuchenghui 已提交
1210 1211
        p = subprocess.Popen(
            [
Y
yejianwu 已提交
1212 1213
                "env",
                "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level,
Y
yejianwu 已提交
1214
                "%s/%s" % (benchmark_binary_dir, benchmark_model_target),
1215
                "--model_name=%s" % model_tag,
Y
yejianwu 已提交
1216 1217 1218 1219 1220
                "--input_node=%s" % ",".join(input_nodes),
                "--output_node=%s" % ",".join(output_nodes),
                "--input_shape=%s" % ":".join(input_shapes),
                "--output_shape=%s" % ":".join(output_shapes),
                "--input_file=%s/%s" % (model_output_dir, input_file_name),
1221
                "--model_data_file=%s/%s.data" % (mace_model_dir, model_tag),
Y
yejianwu 已提交
1222
                "--device=%s" % device_type,
W
wuchenghui 已提交
1223 1224 1225 1226
                "--omp_num_threads=%s" % omp_num_threads,
                "--cpu_affinity_policy=%s" % cpu_affinity_policy,
                "--gpu_perf_hint=%s" % gpu_perf_hint,
                "--gpu_priority_hint=%s" % gpu_priority_hint,
Y
yejianwu 已提交
1227
                "--model_file=%s" % mace_model_path,
W
wuchenghui 已提交
1228
            ])
Y
yejianwu 已提交
1229 1230 1231
        p.wait()
    else:
        sh.adb("-s", serialno, "shell", "mkdir", "-p", phone_data_dir)
1232 1233
        internal_storage_dir = create_internal_storage_dir(
            serialno, phone_data_dir)
Y
yejianwu 已提交
1234 1235

        for input_name in input_nodes:
L
liuqi 已提交
1236 1237
            formatted_name = common.formatted_file_name(input_file_name,
                                                        input_name)
Y
yejianwu 已提交
1238 1239 1240
            adb_push("%s/%s" % (model_output_dir, formatted_name),
                     phone_data_dir, serialno)
        if not embed_model_data:
1241
            adb_push("%s/%s.data" % (mace_model_dir, model_tag),
Y
yejianwu 已提交
1242
                     phone_data_dir, serialno)
1243 1244 1245
        if device_type == common.DeviceType.GPU \
                and os.path.exists(opencl_binary_file):
            adb_push(opencl_binary_file, phone_data_dir, serialno)
1246 1247 1248 1249 1250
        mace_model_phone_path = ""
        if build_type == BuildType.proto:
            mace_model_phone_path = "%s/%s.pb" % (phone_data_dir, model_tag)
            adb_push(mace_model_path,
                     mace_model_phone_path,
Y
yejianwu 已提交
1251
                     serialno)
Y
yejianwu 已提交
1252

Y
yejianwu 已提交
1253
        if linkshared == 1:
Y
yejianwu 已提交
1254 1255 1256 1257 1258
            adb_push("%s/libmace.so" % shared_library_dir, phone_data_dir,
                     serialno)
            adb_push("%s/libgnustl_shared.so" % shared_library_dir,
                     phone_data_dir,
                     serialno)
Y
yejianwu 已提交
1259 1260
        adb_push("%s/%s" % (benchmark_binary_dir, benchmark_model_target),
                 phone_data_dir,
1261
                 serialno)
Y
yejianwu 已提交
1262

李寅 已提交
1263
        adb_cmd = [
W
wuchenghui 已提交
1264 1265 1266 1267
            "LD_LIBRARY_PATH=%s" % phone_data_dir,
            "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level,
            "MACE_RUN_PARAMETER_PATH=%s/mace_run.config" %
            phone_data_dir,
1268
            "MACE_INTERNAL_STORAGE_PATH=%s" % internal_storage_dir,
W
wuchenghui 已提交
1269
            "MACE_OPENCL_PROFILING=1",
Y
yejianwu 已提交
1270
            "%s/%s" % (phone_data_dir, benchmark_model_target),
1271
            "--model_name=%s" % model_tag,
W
wuchenghui 已提交
1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
            "--input_node=%s" % ",".join(input_nodes),
            "--output_node=%s" % ",".join(output_nodes),
            "--input_shape=%s" % ":".join(input_shapes),
            "--output_shape=%s" % ":".join(output_shapes),
            "--input_file=%s/%s" % (phone_data_dir, input_file_name),
            "--model_data_file=%s/%s.data" % (phone_data_dir, model_tag),
            "--device=%s" % device_type,
            "--omp_num_threads=%s" % omp_num_threads,
            "--cpu_affinity_policy=%s" % cpu_affinity_policy,
            "--gpu_perf_hint=%s" % gpu_perf_hint,
            "--gpu_priority_hint=%s" % gpu_priority_hint,
1283
            "--model_file=%s" % mace_model_phone_path,
1284 1285
            "--opencl_binary_file=%s/%s" %
            (phone_data_dir, os.path.basename(opencl_binary_file)),
李寅 已提交
1286 1287
        ]
        adb_cmd = ' '.join(adb_cmd)
李滨 已提交
1288 1289 1290 1291
        cmd_file_name = "%s-%s-%s" % ('cmd_file', model_tag, str(time.time()))
        adb_cmd_file = "%s/%s" % (phone_data_dir, cmd_file_name)
        tmp_cmd_file = "%s/%s" % ('/tmp', cmd_file_name)
        with open(tmp_cmd_file, 'w') as cmd_file:
李寅 已提交
1292
            cmd_file.write(adb_cmd)
李滨 已提交
1293 1294
        adb_push(tmp_cmd_file, adb_cmd_file, serialno)
        os.remove(tmp_cmd_file)
李寅 已提交
1295 1296 1297 1298 1299 1300 1301

        sh.adb(
            "-s",
            serialno,
            "shell",
            "sh",
            adb_cmd_file,
L
liuqi 已提交
1302
            _fg=True)
Y
yejianwu 已提交
1303

李滨 已提交
1304 1305 1306 1307 1308 1309 1310 1311
        sh.adb(
            "-s",
            serialno,
            "shell",
            "rm",
            adb_cmd_file,
            _fg=True)

Y
yejianwu 已提交
1312 1313 1314
    print("Benchmark done!\n")


W
wuchenghui 已提交
1315 1316
def build_run_throughput_test(abi,
                              serialno,
Y
yejianwu 已提交
1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328
                              vlog_level,
                              run_seconds,
                              merged_lib_file,
                              model_input_dir,
                              embed_model_data,
                              input_nodes,
                              output_nodes,
                              input_shapes,
                              output_shapes,
                              cpu_model_tag,
                              gpu_model_tag,
                              dsp_model_tag,
1329
                              phone_data_dir,
Y
yejianwu 已提交
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344
                              strip="always",
                              input_file_name="model_input"):
    print("* Build and run throughput_test")

    model_tag_build_flag = ""
    if cpu_model_tag:
        model_tag_build_flag += "--copt=-DMACE_CPU_MODEL_TAG=%s " % \
                                cpu_model_tag
    if gpu_model_tag:
        model_tag_build_flag += "--copt=-DMACE_GPU_MODEL_TAG=%s " % \
                                gpu_model_tag
    if dsp_model_tag:
        model_tag_build_flag += "--copt=-DMACE_DSP_MODEL_TAG=%s " % \
                                dsp_model_tag

1345
    sh.cp("-f", merged_lib_file, "mace/benchmark/libmace_merged.a")
L
liuqi 已提交
1346
    sh.bazel(
Y
yejianwu 已提交
1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
        "build",
        "-c",
        "opt",
        "--strip",
        strip,
        "--verbose_failures",
        "//mace/benchmark:model_throughput_test",
        "--crosstool_top=//external:android/crosstool",
        "--host_crosstool_top=@bazel_tools//tools/cpp:toolchain",
        "--cpu=%s" % abi,
        "--copt=-std=c++11",
        "--copt=-D_GLIBCXX_USE_C99_MATH_TR1",
        "--copt=-Werror=return-type",
        "--copt=-O3",
        "--define",
        "neon=true",
        "--define",
        "openmp=true",
        model_tag_build_flag,
L
liuqi 已提交
1366
        _fg=True)
Y
yejianwu 已提交
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391

    sh.rm("mace/benchmark/libmace_merged.a")
    sh.adb("-s",
           serialno,
           "shell",
           "mkdir",
           "-p",
           phone_data_dir)
    adb_push("%s/%s_%s" % (model_input_dir, input_file_name,
                           ",".join(input_nodes)),
             phone_data_dir,
             serialno)
    adb_push("bazel-bin/mace/benchmark/model_throughput_test",
             phone_data_dir,
             serialno)
    if not embed_model_data:
        adb_push("codegen/models/%s/%s.data" % cpu_model_tag,
                 phone_data_dir,
                 serialno)
        adb_push("codegen/models/%s/%s.data" % gpu_model_tag,
                 phone_data_dir,
                 serialno)
        adb_push("codegen/models/%s/%s.data" % dsp_model_tag,
                 phone_data_dir,
                 serialno)
L
Liangliang He 已提交
1392
    adb_push("third_party/nnlib/libhexagon_controller.so",
Y
yejianwu 已提交
1393 1394 1395
             phone_data_dir,
             serialno)

L
liuqi 已提交
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417
    sh.adb(
        "-s",
        serialno,
        "shell",
        "LD_LIBRARY_PATH=%s" % phone_data_dir,
        "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level,
        "MACE_RUN_PARAMETER_PATH=%s/mace_run.config" %
        phone_data_dir,
        "%s/model_throughput_test" % phone_data_dir,
        "--input_node=%s" % ",".join(input_nodes),
        "--output_node=%s" % ",".join(output_nodes),
        "--input_shape=%s" % ":".join(input_shapes),
        "--output_shape=%s" % ":".join(output_shapes),
        "--input_file=%s/%s" % (phone_data_dir, input_file_name),
        "--cpu_model_data_file=%s/%s.data" % (phone_data_dir,
                                              cpu_model_tag),
        "--gpu_model_data_file=%s/%s.data" % (phone_data_dir,
                                              gpu_model_tag),
        "--dsp_model_data_file=%s/%s.data" % (phone_data_dir,
                                              dsp_model_tag),
        "--run_seconds=%s" % run_seconds,
        _fg=True)
Y
yejianwu 已提交
1418 1419 1420 1421

    print("throughput_test done!\n")


1422 1423 1424
################################
# falcon
################################
L
Liangliang He 已提交
1425
def falcon_tags(tags_dict):
L
Liangliang He 已提交
1426 1427 1428 1429 1430 1431 1432
    tags = ""
    for k, v in tags_dict.iteritems():
        if tags == "":
            tags = "%s=%s" % (k, v)
        else:
            tags = tags + ",%s=%s" % (k, v)
    return tags
L
Liangliang He 已提交
1433

1434

L
Liangliang He 已提交
1435 1436
def falcon_push_metrics(server, metrics, endpoint="mace_dev", tags={}):
    cli = falcon_cli.FalconCli.connect(server=server, port=8433, debug=False)
L
Liangliang He 已提交
1437 1438 1439 1440 1441 1442 1443
    ts = int(time.time())
    falcon_metrics = [{
        "endpoint": endpoint,
        "metric": key,
        "tags": falcon_tags(tags),
        "timestamp": ts,
        "value": value,
L
Liangliang He 已提交
1444
        "step": 600,
L
Liangliang He 已提交
1445 1446 1447
        "counterType": "GAUGE"
    } for key, value in metrics.iteritems()]
    cli.update(falcon_metrics)