sh_commands.py 45.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
28
from enum import Enum
29

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

32 33 34 35 36 37
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
38
    from mace_engine_factory_codegen import gen_mace_engine_factory
Y
yejianwu 已提交
39 40
except Exception as e:
    print("Import error:\n%s" % e)
41 42
    exit(1)

43 44 45
################################
# common
################################
L
liuqi 已提交
46 47 48
logger = logging.getLogger('MACE')


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'


Y
yejianwu 已提交
88 89 90
################################
# clear data
################################
91 92 93 94 95
def clear_phone_data_dir(serialno, phone_data_dir):
    sh.adb("-s",
           serialno,
           "shell",
           "rm -rf %s" % phone_data_dir)
96 97 98


def clear_model_codegen(model_codegen_dir="mace/codegen/models"):
Y
yejianwu 已提交
99 100 101 102
    if os.path.exists(model_codegen_dir):
        sh.rm("-rf", model_codegen_dir)


103 104 105
################################
# adb commands
################################
W
wuchenghui 已提交
106 107
def adb_devices():
    serialnos = []
108
    p = re.compile(r'(\w+)\s+device')
109
    for line in split_stdout(sh.adb("devices")):
110 111
        m = p.match(line)
        if m:
W
wuchenghui 已提交
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
            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 已提交
136

137

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
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


155
def adb_getprop_by_serialno(serialno):
L
Liangliang He 已提交
156
    outputs = sh.adb("-s", serialno, "shell", "getprop")
157
    raw_props = split_stdout(outputs)
L
Liangliang He 已提交
158
    props = {}
159
    p = re.compile(r'\[(.+)\]: \[(.+)\]')
L
Liangliang He 已提交
160 161 162 163 164 165
    for raw_prop in raw_props:
        m = p.match(raw_prop)
        if m:
            props[m.group(1)] = m.group(2)
    return props

166

W
wuchenghui 已提交
167 168
def adb_get_device_name_by_serialno(serialno):
    props = adb_getprop_by_serialno(serialno)
L
liuqi 已提交
169
    return props.get("ro.product.model", "").replace(' ', '')
W
wuchenghui 已提交
170 171


172
def adb_supported_abis(serialno):
L
Liangliang He 已提交
173 174 175 176 177
    props = adb_getprop_by_serialno(serialno)
    abilist_str = props["ro.product.cpu.abilist"]
    abis = [abi.strip() for abi in abilist_str.split(',')]
    return abis

178

179
def adb_get_all_socs():
L
Liangliang He 已提交
180 181 182 183 184
    socs = []
    for d in adb_devices():
        props = adb_getprop_by_serialno(d)
        socs.append(props["ro.board.platform"])
    return set(socs)
185

L
Liangliang He 已提交
186

Y
yejianwu 已提交
187 188 189 190 191 192 193 194 195 196 197 198 199
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)


200 201
def adb_run(abi,
            serialno,
L
Liangliang He 已提交
202 203
            host_bin_path,
            bin_name,
204
            args="",
L
liuqi 已提交
205
            opencl_profiling=True,
206
            vlog_level=0,
207
            device_bin_path="/data/local/tmp/mace",
L
liuqi 已提交
208
            out_of_range_check=True,
209
            address_sanitizer=False):
L
Liangliang He 已提交
210 211 212 213 214 215
    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 已提交
216
    print("Trying to lock device %s" % serialno)
217 218 219 220
    with device_lock(serialno):
        print("Run on device: %s, %s, %s" %
              (serialno, props["ro.board.platform"],
               props["ro.product.model"]))
Y
yejianwu 已提交
221 222
        sh.adb("-s", serialno, "shell", "rm -rf %s" % device_bin_path)
        sh.adb("-s", serialno, "shell", "mkdir -p %s" % device_bin_path)
Y
yejianwu 已提交
223
        adb_push(host_bin_full_path, device_bin_full_path, serialno)
224 225 226 227 228
        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 已提交
229 230
        opencl_profiling = 1 if opencl_profiling else 0
        out_of_range_check = 1 if out_of_range_check else 0
Y
yejianwu 已提交
231
        print("Run %s" % device_bin_full_path)
232

Y
yejianwu 已提交
233 234
        stdout_buff = []
        process_output = make_output_processor(stdout_buff)
L
liuqi 已提交
235
        sh.adb(
Y
yejianwu 已提交
236 237 238
            "-s",
            serialno,
            "shell",
239 240 241 242
            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,
243 244 245
            device_bin_full_path,
            args,
            _tty_in=True,
Y
yejianwu 已提交
246
            _out=process_output,
247
            _err_to_out=True)
Y
yejianwu 已提交
248
        return "".join(stdout_buff)
249 250


251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
################################
# 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))
277 278


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


def bazel_build_common(target, build_args=""):
L
Liangliang He 已提交
320 321
    stdout_buff = []
    process_output = make_output_processor(stdout_buff)
L
liuqi 已提交
322
    sh.bazel(
L
Liangliang He 已提交
323
        "build",
Y
yejianwu 已提交
324
        target + build_args,
325
        _tty_in=True,
L
Liangliang He 已提交
326
        _out=process_output,
327
        _err_to_out=True)
L
Liangliang He 已提交
328 329
    return "".join(stdout_buff)

330 331

def bazel_target_to_bin(target):
L
Liangliang He 已提交
332 333 334 335 336 337 338 339
    # 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

340 341 342 343 344

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

349

Y
yejianwu 已提交
350
def gen_mace_engine_factory_source(model_tags,
351
                                   model_load_type,
Y
yejianwu 已提交
352
                                   codegen_path="mace/codegen"):
353 354 355 356
    print("* Genearte mace engine creator source")
    codegen_tools_dir = "%s/engine" % codegen_path
    sh.rm("-rf", codegen_tools_dir)
    sh.mkdir("-p", codegen_tools_dir)
357
    gen_mace_engine_factory(
358 359
        model_tags,
        "mace/python/tools",
360
        model_load_type,
361 362 363 364 365
        codegen_tools_dir)
    print("Genearte mace engine creator source done!\n")


def pull_binaries(abi, serialno, model_output_dirs,
366
                  cl_built_kernel_file_name):
367
    compiled_opencl_dir = "/data/local/tmp/mace_run/interior/"
368
    mace_run_param_file = "mace_run.config"
Y
yejianwu 已提交
369 370 371 372 373

    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)
374
    if cl_bin_dirs:
Y
yejianwu 已提交
375 376 377 378 379
        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":
380 381
            adb_pull(compiled_opencl_dir + cl_built_kernel_file_name,
                     cl_bin_dir, serialno)
382
            adb_pull("/data/local/tmp/mace_run/%s" % mace_run_param_file,
Y
yejianwu 已提交
383 384 385
                     cl_bin_dir, serialno)


386 387 388 389
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 已提交
390
    cl_bin_dirs = []
391
    for d in binaries_dirs:
Y
yejianwu 已提交
392
        cl_bin_dirs.append(os.path.join(d, "opencl_bin"))
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 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
    # create opencl binary output dir
    opencl_binary_dir = os.path.dirname(output_file_path)
    if os.path.exists(opencl_binary_dir):
        sh.rm("-rf", opencl_binary_dir)
    sh.mkdir("-p", opencl_binary_dir)
    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 已提交
442 443


W
wuchenghui 已提交
444
def gen_tuning_param_code(model_output_dirs,
Y
yejianwu 已提交
445
                          codegen_path="mace/codegen"):
446
    mace_run_param_file = "mace_run.config"
Y
yejianwu 已提交
447 448 449 450
    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)
451 452 453 454 455

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

456 457 458 459 460
    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 已提交
461 462


463
def gen_mace_version(codegen_path="mace/codegen"):
L
Liangliang He 已提交
464 465 466 467
    sh.mkdir("-p", "%s/version" % codegen_path)
    sh.bash("mace/tools/git/gen_version_source.sh",
            "%s/version/version.cc" % codegen_path)

468

Y
yejianwu 已提交
469 470 471 472 473
def gen_model_code(model_codegen_dir,
                   platform,
                   model_file_path,
                   weight_file_path,
                   model_sha256_checksum,
474
                   weight_sha256_checksum,
Y
yejianwu 已提交
475 476 477 478 479 480 481 482
                   input_nodes,
                   output_nodes,
                   runtime,
                   model_tag,
                   input_shapes,
                   dsp_mode,
                   embed_model_data,
                   fast_conv,
Y
yejianwu 已提交
483
                   obfuscate,
484 485
                   model_build_type,
                   data_type):
Y
yejianwu 已提交
486
    bazel_build_common("//mace/python/tools:converter")
Y
yejianwu 已提交
487

Y
yejianwu 已提交
488 489 490
    if os.path.exists(model_codegen_dir):
        sh.rm("-rf", model_codegen_dir)
    sh.mkdir("-p", model_codegen_dir)
Y
yejianwu 已提交
491

L
liuqi 已提交
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
    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,
              "--winograd=%s" % fast_conv,
              "--obfuscate=%s" % obfuscate,
              "--output_dir=%s" % model_codegen_dir,
              "--model_build_type=%s" % model_build_type,
              "--data_type=%s" % data_type,
              _fg=True)
Y
yejianwu 已提交
513 514 515 516 517 518 519 520


def gen_random_input(model_output_dir,
                     input_nodes,
                     input_shapes,
                     input_files,
                     input_file_name="model_input"):
    for input_name in input_nodes:
L
liuqi 已提交
521 522
        formatted_name = common.formatted_file_name(
            input_file_name, input_name)
523 524
        if os.path.exists("%s/%s" % (model_output_dir, formatted_name)):
            sh.rm("%s/%s" % (model_output_dir, formatted_name))
Y
yejianwu 已提交
525 526
    input_nodes_str = ",".join(input_nodes)
    input_shapes_str = ":".join(input_shapes)
527 528 529
    generate_input_data("%s/%s" % (model_output_dir, input_file_name),
                        input_nodes_str,
                        input_shapes_str)
Y
yejianwu 已提交
530 531 532 533 534 535 536 537

    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 已提交
538 539
        if isinstance(input_nodes, list):
            input_name_list.extend(input_nodes)
Y
yejianwu 已提交
540
        else:
W
wuchenghui 已提交
541
            input_name_list.append(input_nodes)
Y
yejianwu 已提交
542 543 544 545 546 547
        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 已提交
548 549
                        common.formatted_file_name(input_file_name,
                                                   input_name_list[i])
Y
yejianwu 已提交
550 551 552 553
                if input_file_list[i].startswith("http://") or \
                        input_file_list[i].startswith("https://"):
                    urllib.urlretrieve(input_file_list[i], dst_input_file)
                else:
554
                    sh.cp("-f", input_file_list[i], dst_input_file)
Y
yejianwu 已提交
555 556


557 558
def update_mace_run_lib(build_tmp_binary_dir):
    mace_run_filepath = build_tmp_binary_dir + "/mace_run"
Y
yejianwu 已提交
559 560
    if os.path.exists(mace_run_filepath):
        sh.rm("-rf", mace_run_filepath)
561 562 563 564 565 566 567 568 569 570
    sh.cp("-f", "bazel-bin/mace/tools/validation/mace_run",
          build_tmp_binary_dir)


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 已提交
571 572


573 574 575 576 577 578 579 580 581 582 583 584
def mv_model_file_to_output_dir(
        model_build_type,
        model_codegen_dir,
        model_name,
        output_dir):
    if model_build_type == BuildType.proto:
        sh.mv("-f",
              '%s/%s.pb' % (model_codegen_dir, model_name),
              output_dir)
    sh.mv("-f",
          '%s/%s.data' % (model_codegen_dir, model_name),
          output_dir)
Y
yejianwu 已提交
585 586


587 588 589 590
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
591 592


W
wuchenghui 已提交
593 594
def tuning_run(abi,
               serialno,
595
               mace_run_dir,
Y
yejianwu 已提交
596 597 598 599 600 601 602
               vlog_level,
               embed_model_data,
               model_output_dir,
               input_nodes,
               output_nodes,
               input_shapes,
               output_shapes,
Y
yejianwu 已提交
603
               mace_model_dir,
Y
yejianwu 已提交
604 605 606 607 608 609 610
               model_tag,
               device_type,
               running_round,
               restart_round,
               limit_opencl_kernel_time,
               tuning,
               out_of_range_check,
611
               phone_data_dir,
612
               build_type,
613
               opencl_binary_file,
W
wuchenghui 已提交
614 615 616 617
               omp_num_threads=-1,
               cpu_affinity_policy=1,
               gpu_perf_hint=3,
               gpu_priority_hint=3,
Y
yejianwu 已提交
618
               input_file_name="model_input",
619 620 621
               output_file_name="model_out",
               runtime_failure_ratio=0.0,
               address_sanitizer=False):
622
    print("* Run '%s' with round=%s, restart_round=%s, tuning=%s, "
W
wuchenghui 已提交
623 624
          "out_of_range_check=%s, omp_num_threads=%s, cpu_affinity_policy=%s, "
          "gpu_perf_hint=%s, gpu_priority_hint=%s" %
625
          (model_tag, running_round, restart_round, str(tuning),
W
wuchenghui 已提交
626 627
           str(out_of_range_check), omp_num_threads, cpu_affinity_policy,
           gpu_perf_hint, gpu_priority_hint))
628 629 630
    mace_model_path = ""
    if build_type == BuildType.proto:
        mace_model_path = "%s/%s.pb" % (mace_model_dir, model_tag)
Y
yejianwu 已提交
631
    if abi == "host":
W
wuchenghui 已提交
632 633
        p = subprocess.Popen(
            [
Y
yejianwu 已提交
634 635
                "env",
                "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level,
李寅 已提交
636
                "MACE_RUNTIME_FAILURE_RATIO=%f" % runtime_failure_ratio,
637
                "%s/mace_run" % mace_run_dir,
638
                "--model_name=%s" % model_tag,
Y
yejianwu 已提交
639 640 641 642 643 644
                "--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),
645
                "--model_data_file=%s/%s.data" % (mace_model_dir, model_tag),
Y
yejianwu 已提交
646 647 648
                "--device=%s" % device_type,
                "--round=%s" % running_round,
                "--restart_round=%s" % restart_round,
W
wuchenghui 已提交
649 650 651 652
                "--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 已提交
653
                "--model_file=%s" % mace_model_path,
W
wuchenghui 已提交
654 655 656
            ],
            stderr=subprocess.PIPE,
            stdout=subprocess.PIPE)
Y
yejianwu 已提交
657 658 659 660 661
        out, err = p.communicate()
        stdout = err + out
        print stdout
        print("Running finished!\n")
        return stdout
Y
yejianwu 已提交
662 663
    else:
        sh.adb("-s", serialno, "shell", "mkdir", "-p", phone_data_dir)
664 665
        internal_storage_dir = create_internal_storage_dir(
            serialno, phone_data_dir)
Y
yejianwu 已提交
666 667

        for input_name in input_nodes:
L
liuqi 已提交
668 669
            formatted_name = common.formatted_file_name(input_file_name,
                                                        input_name)
Y
yejianwu 已提交
670 671
            adb_push("%s/%s" % (model_output_dir, formatted_name),
                     phone_data_dir, serialno)
672 673 674
        if address_sanitizer:
            adb_push(find_asan_rt_library(abi), phone_data_dir, serialno)

Y
yejianwu 已提交
675
        if not embed_model_data:
676
            adb_push("%s/%s.data" % (mace_model_dir, model_tag),
Y
yejianwu 已提交
677
                     phone_data_dir, serialno)
678

679 680 681 682
        if device_type == common.DeviceType.GPU\
                and os.path.exists(opencl_binary_file):
            adb_push(opencl_binary_file, phone_data_dir, serialno)

W
wuchenghui 已提交
683
        adb_push("third_party/nnlib/libhexagon_controller.so",
Y
yejianwu 已提交
684 685
                 phone_data_dir, serialno)

686 687 688 689 690
        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 已提交
691
                     serialno)
692 693 694

        adb_push("%s/mace_run" % mace_run_dir, phone_data_dir,
                 serialno)
Y
yejianwu 已提交
695

Y
yejianwu 已提交
696 697
        stdout_buff = []
        process_output = make_output_processor(stdout_buff)
698
        adb_cmd = [
W
wuchenghui 已提交
699 700 701 702
            "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,
703
            "MACE_RUN_PARAMETER_PATH=%s/mace_run.config" % phone_data_dir,
704
            "MACE_INTERNAL_STORAGE_PATH=%s" % internal_storage_dir,
705
            "MACE_LIMIT_OPENCL_KERNEL_TIME=%s" % limit_opencl_kernel_time,
李寅 已提交
706
            "MACE_RUNTIME_FAILURE_RATIO=%f" % runtime_failure_ratio,
707
        ]
708
        if address_sanitizer:
709
            adb_cmd.extend([
710 711
                "LD_PRELOAD=%s/%s" % (phone_data_dir,
                                      asan_rt_library_names(abi))
712 713
            ])
        adb_cmd.extend([
W
wuchenghui 已提交
714
            "%s/mace_run" % phone_data_dir,
715
            "--model_name=%s" % model_tag,
W
wuchenghui 已提交
716 717 718 719 720 721 722 723 724 725 726 727 728 729
            "--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,
730
            "--model_file=%s" % mace_model_phone_path,
731 732
            "--opencl_binary_file=%s/%s" %
            (phone_data_dir, os.path.basename(opencl_binary_file)),
733 734
        ])
        adb_cmd = ' '.join(adb_cmd)
L
liuqi 已提交
735
        sh.adb(
736 737 738 739
            "-s",
            serialno,
            "shell",
            adb_cmd,
740
            _tty_in=True,
W
wuchenghui 已提交
741
            _out=process_output,
742
            _err_to_out=True)
Y
yejianwu 已提交
743 744
        print("Running finished!\n")
        return "".join(stdout_buff)
Y
yejianwu 已提交
745 746


W
wuchenghui 已提交
747 748
def validate_model(abi,
                   serialno,
Y
yejianwu 已提交
749 750 751
                   model_file_path,
                   weight_file_path,
                   platform,
752
                   device_type,
Y
yejianwu 已提交
753 754 755 756 757
                   input_nodes,
                   output_nodes,
                   input_shapes,
                   output_shapes,
                   model_output_dir,
758
                   phone_data_dir,
L
liuqi 已提交
759
                   caffe_env,
Y
yejianwu 已提交
760 761 762
                   input_file_name="model_input",
                   output_file_name="model_out"):
    print("* Validate with %s" % platform)
L
liuqi 已提交
763 764 765 766 767 768 769 770 771
    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 已提交
772 773

    if platform == "tensorflow":
774 775
        validate(platform, model_file_path, "",
                 "%s/%s" % (model_output_dir, input_file_name),
776
                 "%s/%s" % (model_output_dir, output_file_name), device_type,
777 778
                 ":".join(input_shapes), ":".join(output_shapes),
                 ",".join(input_nodes), ",".join(output_nodes))
Y
yejianwu 已提交
779 780 781 782
    elif platform == "caffe":
        image_name = "mace-caffe:latest"
        container_name = "mace_caffe_validator"

L
liuqi 已提交
783 784 785 786 787 788 789 790
        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),
791 792
                     "%s/%s" % (model_output_dir, output_file_name),
                     device_type,
L
liuqi 已提交
793 794 795 796 797 798 799
                     ":".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 已提交
800
                          "third_party/caffe")
L
liuqi 已提交
801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826

            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 已提交
827 828

            for output_name in output_nodes:
L
liuqi 已提交
829 830 831 832 833 834 835 836
                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 已提交
837
            sh.docker("cp", "tools/common.py", "%s:/mace" % container_name)
L
liuqi 已提交
838 839 840 841
            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 已提交
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
            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 已提交
859 860 861 862

    print("Validation done!\n")


863 864 865
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 已提交
866 867
    bazel_build("//mace/codegen:generated_opencl", abi=abi)
    bazel_build("//mace/codegen:generated_tuning_params", abi=abi)
868 869 870 871 872 873 874 875 876
    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 已提交
877 878 879


def merge_libs(target_soc,
L
liuqi 已提交
880
               serial_num,
Y
yejianwu 已提交
881 882
               abi,
               project_name,
883 884 885 886
               build_output_dir,
               library_output_dir,
               model_build_type,
               hexagon_mode):
Y
yejianwu 已提交
887
    print("* Merge mace lib")
888
    project_output_dir = "%s/%s" % (build_output_dir, project_name)
Y
yejianwu 已提交
889
    model_header_dir = "%s/include/mace/public" % project_output_dir
L
Liangliang He 已提交
890
    hexagon_lib_file = "third_party/nnlib/libhexagon_controller.so"
L
liuqi 已提交
891 892
    library_dir = "%s/%s" % (project_output_dir, library_output_dir)
    model_bin_dir = "%s/%s/" % (library_dir, abi)
893 894 895 896 897 898 899 900

    if os.path.exists(model_bin_dir):
        sh.rm("-rf", model_bin_dir)
    sh.mkdir("-p", model_bin_dir)
    if os.path.exists(model_header_dir):
        sh.rm("-rf", model_header_dir)
    sh.mkdir("-p", model_header_dir)
    # copy header files
901
    sh.cp("-f", glob.glob("mace/public/*.h"), model_header_dir)
Y
yejianwu 已提交
902
    if hexagon_mode:
L
liuqi 已提交
903
        sh.cp("-f", hexagon_lib_file, library_dir)
Y
yejianwu 已提交
904

905
    if model_build_type == BuildType.code:
Y
yejianwu 已提交
906
        sh.cp("-f", glob.glob("mace/codegen/engine/*.h"), model_header_dir)
907
        sh.cp("-f", glob.glob("mace/codegen/models/*/*.h"), model_header_dir)
Y
yejianwu 已提交
908

909
    # make static library
Y
yejianwu 已提交
910 911
    mri_stream = ""
    if abi == "host":
912 913
        mri_stream += "create %s/libmace_%s.a\n" % \
                      (model_bin_dir, project_name)
Y
yejianwu 已提交
914
        mri_stream += (
915 916
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_opencl.pic.a\n")
Y
yejianwu 已提交
917
        mri_stream += (
918 919
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_tuning_params.pic.a\n")
920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941
        mri_stream += (
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_version.pic.a\n")
        mri_stream += (
            "addlib "
            "bazel-bin/mace/core/libcore.pic.a\n")
        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:
942 943 944
            mri_stream += (
                "addlib "
                "bazel-bin/mace/codegen/libgenerated_models.pic.a\n")
Y
yejianwu 已提交
945
    else:
946 947 948 949
        if not target_soc:
            mri_stream += "create %s/libmace_%s.a\n" % \
                          (model_bin_dir, project_name)
        else:
L
liuqi 已提交
950 951 952 953
            device_name = adb_get_device_name_by_serialno(serial_num)
            mri_stream += "create %s/libmace_%s.%s.%s.a\n" % \
                          (model_bin_dir, project_name,
                           device_name, target_soc)
954
        if model_build_type == BuildType.code:
955 956 957
            mri_stream += (
                "addlib "
                "bazel-bin/mace/codegen/libgenerated_models.a\n")
Y
yejianwu 已提交
958
        mri_stream += (
959 960
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_opencl.a\n")
Y
yejianwu 已提交
961
        mri_stream += (
962 963
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_tuning_params.a\n")
Y
yejianwu 已提交
964
        mri_stream += (
965 966
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_version.a\n")
Y
yejianwu 已提交
967
        mri_stream += (
968 969
            "addlib "
            "bazel-bin/mace/core/libcore.a\n")
Y
yejianwu 已提交
970
        mri_stream += (
971 972
            "addlib "
            "bazel-bin/mace/kernels/libkernels.a\n")
Y
yejianwu 已提交
973
        mri_stream += (
974 975
            "addlib "
            "bazel-bin/mace/utils/libutils.a\n")
976 977 978 979 980 981
        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 已提交
982
        mri_stream += (
983 984
            "addlib "
            "bazel-bin/mace/ops/libops.lo\n")
Y
yejianwu 已提交
985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007

    mri_stream += "save\n"
    mri_stream += "end\n"

    cmd = sh.Command("%s/toolchains/" % os.environ["ANDROID_NDK_HOME"] +
                     "aarch64-linux-android-4.9/prebuilt/linux-x86_64/" +
                     "bin/aarch64-linux-android-ar")

    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))
L
liuqi 已提交
1008 1009 1010 1011 1012 1013 1014
    sh.tar(
        "cvzf",
        "%s" % tar_package_path,
        glob.glob("%s/*" % project_dir),
        "--exclude",
        "%s/_tmp" % project_dir,
        _fg=True)
Y
yejianwu 已提交
1015 1016 1017
    print("Packaging Done!\n")


1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
def build_benchmark_model(abi,
                          model_output_dir,
                          hexagon_mode):
    benchmark_binary_file = "%s/benchmark_model" % model_output_dir
    if os.path.exists(benchmark_binary_file):
        sh.rm("-rf", benchmark_binary_file)

    benchmark_target = "//mace/benchmark:benchmark_model"
    bazel_build(benchmark_target,
                abi=abi,
                hexagon_mode=hexagon_mode)

    target_bin = "/".join(bazel_target_to_bin(benchmark_target))
    sh.cp("-f", target_bin, model_output_dir)


W
wuchenghui 已提交
1034 1035
def benchmark_model(abi,
                    serialno,
1036
                    benchmark_binary_dir,
Y
yejianwu 已提交
1037 1038 1039
                    vlog_level,
                    embed_model_data,
                    model_output_dir,
Y
yejianwu 已提交
1040
                    mace_model_dir,
Y
yejianwu 已提交
1041 1042 1043 1044 1045 1046
                    input_nodes,
                    output_nodes,
                    input_shapes,
                    output_shapes,
                    model_tag,
                    device_type,
1047
                    phone_data_dir,
1048
                    build_type,
1049
                    opencl_binary_file,
W
wuchenghui 已提交
1050 1051 1052 1053
                    omp_num_threads=-1,
                    cpu_affinity_policy=1,
                    gpu_perf_hint=3,
                    gpu_priority_hint=3,
1054
                    input_file_name="model_input"):
Y
yejianwu 已提交
1055 1056
    print("* Benchmark for %s" % model_tag)

1057 1058 1059
    mace_model_path = ""
    if build_type == BuildType.proto:
        mace_model_path = "%s/%s.pb" % (mace_model_dir, model_tag)
Y
yejianwu 已提交
1060
    if abi == "host":
W
wuchenghui 已提交
1061 1062
        p = subprocess.Popen(
            [
Y
yejianwu 已提交
1063 1064
                "env",
                "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level,
1065
                "%s/benchmark_model" % benchmark_binary_dir,
1066
                "--model_name=%s" % model_tag,
Y
yejianwu 已提交
1067 1068 1069 1070 1071
                "--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),
1072
                "--model_data_file=%s/%s.data" % (mace_model_dir, model_tag),
Y
yejianwu 已提交
1073
                "--device=%s" % device_type,
W
wuchenghui 已提交
1074 1075 1076 1077
                "--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 已提交
1078
                "--model_file=%s" % mace_model_path,
W
wuchenghui 已提交
1079
            ])
Y
yejianwu 已提交
1080 1081 1082
        p.wait()
    else:
        sh.adb("-s", serialno, "shell", "mkdir", "-p", phone_data_dir)
1083 1084
        internal_storage_dir = create_internal_storage_dir(
            serialno, phone_data_dir)
Y
yejianwu 已提交
1085 1086

        for input_name in input_nodes:
L
liuqi 已提交
1087 1088
            formatted_name = common.formatted_file_name(input_file_name,
                                                        input_name)
Y
yejianwu 已提交
1089 1090 1091
            adb_push("%s/%s" % (model_output_dir, formatted_name),
                     phone_data_dir, serialno)
        if not embed_model_data:
1092
            adb_push("%s/%s.data" % (mace_model_dir, model_tag),
Y
yejianwu 已提交
1093
                     phone_data_dir, serialno)
1094 1095 1096
        if device_type == common.DeviceType.GPU \
                and os.path.exists(opencl_binary_file):
            adb_push(opencl_binary_file, phone_data_dir, serialno)
1097 1098 1099 1100 1101
        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 已提交
1102
                     serialno)
1103 1104
        adb_push("%s/benchmark_model" % benchmark_binary_dir, phone_data_dir,
                 serialno)
Y
yejianwu 已提交
1105

L
liuqi 已提交
1106
        sh.adb(
W
wuchenghui 已提交
1107 1108 1109 1110 1111 1112 1113
            "-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,
1114
            "MACE_INTERNAL_STORAGE_PATH=%s" % internal_storage_dir,
W
wuchenghui 已提交
1115 1116
            "MACE_OPENCL_PROFILING=1",
            "%s/benchmark_model" % phone_data_dir,
1117
            "--model_name=%s" % model_tag,
W
wuchenghui 已提交
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
            "--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,
1129
            "--model_file=%s" % mace_model_phone_path,
1130 1131
            "--opencl_binary_file=%s/%s" %
            (phone_data_dir, os.path.basename(opencl_binary_file)),
L
liuqi 已提交
1132
            _fg=True)
Y
yejianwu 已提交
1133 1134 1135 1136

    print("Benchmark done!\n")


W
wuchenghui 已提交
1137 1138
def build_run_throughput_test(abi,
                              serialno,
Y
yejianwu 已提交
1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
                              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,
1151
                              phone_data_dir,
Y
yejianwu 已提交
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
                              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

1167
    sh.cp("-f", merged_lib_file, "mace/benchmark/libmace_merged.a")
L
liuqi 已提交
1168
    sh.bazel(
Y
yejianwu 已提交
1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
        "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 已提交
1188
        _fg=True)
Y
yejianwu 已提交
1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213

    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 已提交
1214
    adb_push("third_party/nnlib/libhexagon_controller.so",
Y
yejianwu 已提交
1215 1216 1217
             phone_data_dir,
             serialno)

L
liuqi 已提交
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
    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 已提交
1240 1241 1242 1243

    print("throughput_test done!\n")


1244 1245 1246
################################
# falcon
################################
L
Liangliang He 已提交
1247
def falcon_tags(tags_dict):
L
Liangliang He 已提交
1248 1249 1250 1251 1252 1253 1254
    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 已提交
1255

1256

L
Liangliang He 已提交
1257 1258
def falcon_push_metrics(server, metrics, endpoint="mace_dev", tags={}):
    cli = falcon_cli.FalconCli.connect(server=server, port=8433, debug=False)
L
Liangliang He 已提交
1259 1260 1261 1262 1263 1264 1265
    ts = int(time.time())
    falcon_metrics = [{
        "endpoint": endpoint,
        "metric": key,
        "tags": falcon_tags(tags),
        "timestamp": ts,
        "value": value,
L
Liangliang He 已提交
1266
        "step": 600,
L
Liangliang He 已提交
1267 1268 1269
        "counterType": "GAUGE"
    } for key, value in metrics.iteritems()]
    cli.update(falcon_metrics)