sh_commands.py 47.9 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
def strip_invalid_utf8(str):
L
Liangliang He 已提交
49 50
    return sh.iconv(str, "-c", "-t", "UTF-8")

51

52 53 54 55 56 57
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]


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

    return process_output

65

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
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


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


87 88 89 90 91 92 93 94 95
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 已提交
96 97 98
################################
# clear data
################################
99 100 101 102 103
def clear_phone_data_dir(serialno, phone_data_dir):
    sh.adb("-s",
           serialno,
           "shell",
           "rm -rf %s" % phone_data_dir)
104 105 106


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


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

145

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
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


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

174

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


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

186

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

L
Liangliang He 已提交
194

Y
yejianwu 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207
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)


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

Y
yejianwu 已提交
241 242
        stdout_buff = []
        process_output = make_output_processor(stdout_buff)
L
liuqi 已提交
243
        sh.adb(
Y
yejianwu 已提交
244 245 246
            "-s",
            serialno,
            "shell",
247 248 249 250
            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,
251 252 253
            device_bin_full_path,
            args,
            _tty_in=True,
Y
yejianwu 已提交
254
            _out=process_output,
255
            _err_to_out=True)
Y
yejianwu 已提交
256
        return "".join(stdout_buff)
257 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
################################
# 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))
285 286


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


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

338 339

def bazel_target_to_bin(target):
L
Liangliang He 已提交
340 341 342 343 344 345 346 347
    # 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

348 349 350 351 352

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

357

Y
yejianwu 已提交
358
def gen_mace_engine_factory_source(model_tags,
359
                                   model_load_type,
Y
yejianwu 已提交
360
                                   codegen_path="mace/codegen"):
361 362 363 364
    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)
365
    gen_mace_engine_factory(
366 367
        model_tags,
        "mace/python/tools",
368
        model_load_type,
369 370 371 372 373
        codegen_tools_dir)
    print("Genearte mace engine creator source done!\n")


def pull_binaries(abi, serialno, model_output_dirs,
374
                  cl_built_kernel_file_name):
375
    compiled_opencl_dir = "/data/local/tmp/mace_run/interior/"
376
    mace_run_param_file = "mace_run.config"
Y
yejianwu 已提交
377 378 379 380 381

    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)
382
    if cl_bin_dirs:
Y
yejianwu 已提交
383 384 385 386 387
        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":
388 389
            adb_pull(compiled_opencl_dir + cl_built_kernel_file_name,
                     cl_bin_dir, serialno)
390
            adb_pull("/data/local/tmp/mace_run/%s" % mace_run_param_file,
Y
yejianwu 已提交
391 392 393
                     cl_bin_dir, serialno)


394 395 396 397
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 已提交
398
    cl_bin_dirs = []
399
    for d in binaries_dirs:
Y
yejianwu 已提交
400
        cl_bin_dirs.append(os.path.join(d, "opencl_bin"))
401 402
    # create opencl binary output dir
    opencl_binary_dir = os.path.dirname(output_file_path)
L
liuqi 已提交
403 404
    if not os.path.exists(opencl_binary_dir):
        sh.mkdir("-p", opencl_binary_dir)
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 442 443 444 445 446 447 448
    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 已提交
449 450


W
wuchenghui 已提交
451
def gen_tuning_param_code(model_output_dirs,
Y
yejianwu 已提交
452
                          codegen_path="mace/codegen"):
453
    mace_run_param_file = "mace_run.config"
Y
yejianwu 已提交
454 455 456 457
    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)
458 459 460 461 462

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

463 464 465 466 467
    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 已提交
468 469


470
def gen_mace_version(codegen_path="mace/codegen"):
L
Liangliang He 已提交
471 472 473 474
    sh.mkdir("-p", "%s/version" % codegen_path)
    sh.bash("mace/tools/git/gen_version_source.sh",
            "%s/version/version.cc" % codegen_path)

475

Y
yejianwu 已提交
476 477 478 479 480
def gen_model_code(model_codegen_dir,
                   platform,
                   model_file_path,
                   weight_file_path,
                   model_sha256_checksum,
481
                   weight_sha256_checksum,
Y
yejianwu 已提交
482 483 484 485 486 487 488
                   input_nodes,
                   output_nodes,
                   runtime,
                   model_tag,
                   input_shapes,
                   dsp_mode,
                   embed_model_data,
489
                   winograd,
Y
yejianwu 已提交
490
                   obfuscate,
491
                   model_build_type,
李寅 已提交
492 493
                   data_type,
                   transformers):
Y
yejianwu 已提交
494
    bazel_build_common("//mace/python/tools:converter")
Y
yejianwu 已提交
495

Y
yejianwu 已提交
496 497 498
    if os.path.exists(model_codegen_dir):
        sh.rm("-rf", model_codegen_dir)
    sh.mkdir("-p", model_codegen_dir)
Y
yejianwu 已提交
499

L
liuqi 已提交
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
    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,
515
              "--winograd=%s" % winograd,
L
liuqi 已提交
516 517 518 519
              "--obfuscate=%s" % obfuscate,
              "--output_dir=%s" % model_codegen_dir,
              "--model_build_type=%s" % model_build_type,
              "--data_type=%s" % data_type,
李寅 已提交
520
              "--transformers=%s" % transformers,
L
liuqi 已提交
521
              _fg=True)
Y
yejianwu 已提交
522 523 524 525 526 527


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

    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 已提交
550 551
        if isinstance(input_nodes, list):
            input_name_list.extend(input_nodes)
Y
yejianwu 已提交
552
        else:
W
wuchenghui 已提交
553
            input_name_list.append(input_nodes)
Y
yejianwu 已提交
554 555 556 557 558 559
        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 已提交
560 561
                        common.formatted_file_name(input_file_name,
                                                   input_name_list[i])
Y
yejianwu 已提交
562 563 564 565
                if input_file_list[i].startswith("http://") or \
                        input_file_list[i].startswith("https://"):
                    urllib.urlretrieve(input_file_list[i], dst_input_file)
                else:
566
                    sh.cp("-f", input_file_list[i], dst_input_file)
Y
yejianwu 已提交
567 568


Y
yejianwu 已提交
569 570 571 572 573 574
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 已提交
575 576
    if os.path.exists(mace_run_filepath):
        sh.rm("-rf", mace_run_filepath)
Y
yejianwu 已提交
577 578
    if linkshared == 0:
        sh.cp("-f", "bazel-bin/mace/tools/validation/mace_run_static",
Y
yejianwu 已提交
579 580
              build_tmp_binary_dir)
    else:
Y
yejianwu 已提交
581 582
        sh.cp("-f", "bazel-bin/mace/tools/validation/mace_run_shared",
              build_tmp_binary_dir)
583 584 585 586 587 588 589 590


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 已提交
591 592


593 594 595 596
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
597 598


Y
yejianwu 已提交
599 600 601 602 603 604 605 606
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 已提交
607
    if os.path.exists(library_dir):
Y
yejianwu 已提交
608 609 610
        sh.rm("-rf", library_dir)
    sh.mkdir("-p", library_dir)
    sh.cp("-f", "bazel-bin/mace/libmace.so", library_dir)
Y
yejianwu 已提交
611 612
    sh.cp("-f",
          "%s/sources/cxx-stl/gnu-libstdc++/4.9/libs/%s/libgnustl_shared.so" %
613
          (os.environ["ANDROID_NDK_HOME"], abi),
Y
yejianwu 已提交
614 615
          library_dir)

Y
yejianwu 已提交
616 617 618 619
    if os.path.exists("mace/libmace.so"):
        sh.rm("-f", "mace/libmace.so")
    sh.cp("-f", "bazel-bin/mace/libmace.so", "mace/")

Y
yejianwu 已提交
620

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

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

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

713 714 715 716
        if device_type == common.DeviceType.GPU\
                and os.path.exists(opencl_binary_file):
            adb_push(opencl_binary_file, phone_data_dir, serialno)

W
wuchenghui 已提交
717
        adb_push("third_party/nnlib/libhexagon_controller.so",
Y
yejianwu 已提交
718 719
                 phone_data_dir, serialno)

720 721 722 723 724
        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 已提交
725
                     serialno)
726

Y
yejianwu 已提交
727
        if linkshared == 1:
Y
yejianwu 已提交
728 729 730 731 732 733
            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 已提交
734
        adb_push("%s/%s" % (mace_run_dir, mace_run_target), phone_data_dir,
735
                 serialno)
Y
yejianwu 已提交
736

Y
yejianwu 已提交
737 738
        stdout_buff = []
        process_output = make_output_processor(stdout_buff)
739
        adb_cmd = [
W
wuchenghui 已提交
740 741 742 743
            "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,
744
            "MACE_RUN_PARAMETER_PATH=%s/mace_run.config" % phone_data_dir,
745
            "MACE_INTERNAL_STORAGE_PATH=%s" % internal_storage_dir,
746
            "MACE_LIMIT_OPENCL_KERNEL_TIME=%s" % limit_opencl_kernel_time,
李寅 已提交
747
            "MACE_RUNTIME_FAILURE_RATIO=%f" % runtime_failure_ratio,
748
        ]
749
        if address_sanitizer:
750
            adb_cmd.extend([
751 752
                "LD_PRELOAD=%s/%s" % (phone_data_dir,
                                      asan_rt_library_names(abi))
753 754
            ])
        adb_cmd.extend([
Y
yejianwu 已提交
755
            "%s/%s" % (phone_data_dir, mace_run_target),
756
            "--model_name=%s" % model_tag,
W
wuchenghui 已提交
757 758 759 760 761 762 763 764 765 766 767 768 769 770
            "--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,
771
            "--model_file=%s" % mace_model_phone_path,
772 773
            "--opencl_binary_file=%s/%s" %
            (phone_data_dir, os.path.basename(opencl_binary_file)),
774 775
        ])
        adb_cmd = ' '.join(adb_cmd)
李寅 已提交
776 777 778 779 780
        adb_cmd_file = "%s/%s" % (phone_data_dir, 'cmd_file')
        with open('/tmp/mace_cmd_file', 'w') as cmd_file:
            cmd_file.write(adb_cmd)
        adb_push('/tmp/mace_cmd_file', adb_cmd_file, serialno)

L
liuqi 已提交
781
        sh.adb(
782 783 784
            "-s",
            serialno,
            "shell",
李寅 已提交
785 786
            "sh",
            adb_cmd_file,
787
            _tty_in=True,
W
wuchenghui 已提交
788
            _out=process_output,
789
            _err_to_out=True)
790 791 792
        stdout = "".join(stdout_buff)
        if not stdout_success(stdout):
            common.MaceLogger.error("Mace Run", "Mace run failed.")
Y
yejianwu 已提交
793
        print("Running finished!\n")
794
        return stdout
Y
yejianwu 已提交
795 796


W
wuchenghui 已提交
797 798
def validate_model(abi,
                   serialno,
Y
yejianwu 已提交
799 800 801
                   model_file_path,
                   weight_file_path,
                   platform,
802
                   device_type,
Y
yejianwu 已提交
803 804 805 806 807
                   input_nodes,
                   output_nodes,
                   input_shapes,
                   output_shapes,
                   model_output_dir,
808
                   phone_data_dir,
L
liuqi 已提交
809
                   caffe_env,
Y
yejianwu 已提交
810 811 812
                   input_file_name="model_input",
                   output_file_name="model_out"):
    print("* Validate with %s" % platform)
L
liuqi 已提交
813 814 815 816 817 818 819 820 821
    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 已提交
822 823

    if platform == "tensorflow":
824 825
        validate(platform, model_file_path, "",
                 "%s/%s" % (model_output_dir, input_file_name),
826
                 "%s/%s" % (model_output_dir, output_file_name), device_type,
827 828
                 ":".join(input_shapes), ":".join(output_shapes),
                 ",".join(input_nodes), ",".join(output_nodes))
Y
yejianwu 已提交
829 830 831 832
    elif platform == "caffe":
        image_name = "mace-caffe:latest"
        container_name = "mace_caffe_validator"

L
liuqi 已提交
833 834 835 836 837 838 839 840
        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),
841 842
                     "%s/%s" % (model_output_dir, output_file_name),
                     device_type,
L
liuqi 已提交
843 844 845 846 847 848 849
                     ":".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 已提交
850
                          "third_party/caffe")
L
liuqi 已提交
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876

            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 已提交
877 878

            for output_name in output_nodes:
L
liuqi 已提交
879 880 881 882 883 884 885 886
                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 已提交
887
            sh.docker("cp", "tools/common.py", "%s:/mace" % container_name)
L
liuqi 已提交
888 889 890 891
            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 已提交
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908
            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 已提交
909 910 911 912

    print("Validation done!\n")


913 914 915
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 已提交
916 917
    bazel_build("//mace/codegen:generated_opencl", abi=abi)
    bazel_build("//mace/codegen:generated_tuning_params", abi=abi)
918 919 920 921 922 923 924 925 926
    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 已提交
927 928 929


def merge_libs(target_soc,
L
liuqi 已提交
930
               serial_num,
Y
yejianwu 已提交
931 932
               abi,
               project_name,
933 934 935 936
               build_output_dir,
               library_output_dir,
               model_build_type,
               hexagon_mode):
Y
yejianwu 已提交
937
    print("* Merge mace lib")
938
    project_output_dir = "%s/%s" % (build_output_dir, project_name)
L
Liangliang He 已提交
939
    hexagon_lib_file = "third_party/nnlib/libhexagon_controller.so"
L
liuqi 已提交
940 941
    library_dir = "%s/%s" % (project_output_dir, library_output_dir)
    model_bin_dir = "%s/%s/" % (library_dir, abi)
942

L
liuqi 已提交
943 944
    if not os.path.exists(model_bin_dir):
        sh.mkdir("-p", model_bin_dir)
Y
yejianwu 已提交
945
    if hexagon_mode:
L
liuqi 已提交
946
        sh.cp("-f", hexagon_lib_file, library_dir)
Y
yejianwu 已提交
947

948
    # make static library
Y
yejianwu 已提交
949 950
    mri_stream = ""
    if abi == "host":
951 952
        mri_stream += "create %s/libmace_%s.a\n" % \
                      (model_bin_dir, project_name)
Y
yejianwu 已提交
953
        mri_stream += (
954 955
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_opencl.pic.a\n")
Y
yejianwu 已提交
956
        mri_stream += (
957 958
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_tuning_params.pic.a\n")
959 960 961 962 963
        mri_stream += (
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_version.pic.a\n")
        mri_stream += (
            "addlib "
Y
yejianwu 已提交
964
            "bazel-bin/mace/core/libcore.pic.lo\n")
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980
        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:
981 982 983
            mri_stream += (
                "addlib "
                "bazel-bin/mace/codegen/libgenerated_models.pic.a\n")
Y
yejianwu 已提交
984
    else:
985 986 987 988
        if not target_soc:
            mri_stream += "create %s/libmace_%s.a\n" % \
                          (model_bin_dir, project_name)
        else:
L
liuqi 已提交
989 990 991 992
            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)
993
        if model_build_type == BuildType.code:
994 995 996
            mri_stream += (
                "addlib "
                "bazel-bin/mace/codegen/libgenerated_models.a\n")
Y
yejianwu 已提交
997
        mri_stream += (
998 999
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_opencl.a\n")
Y
yejianwu 已提交
1000
        mri_stream += (
1001 1002
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_tuning_params.a\n")
Y
yejianwu 已提交
1003
        mri_stream += (
1004 1005
            "addlib "
            "bazel-bin/mace/codegen/libgenerated_version.a\n")
Y
yejianwu 已提交
1006
        mri_stream += (
1007
            "addlib "
Y
yejianwu 已提交
1008
            "bazel-bin/mace/core/libcore.lo\n")
Y
yejianwu 已提交
1009
        mri_stream += (
1010 1011
            "addlib "
            "bazel-bin/mace/kernels/libkernels.a\n")
Y
yejianwu 已提交
1012
        mri_stream += (
1013 1014
            "addlib "
            "bazel-bin/mace/utils/libutils.a\n")
1015 1016 1017 1018 1019 1020
        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 已提交
1021
        mri_stream += (
1022 1023
            "addlib "
            "bazel-bin/mace/ops/libops.lo\n")
Y
yejianwu 已提交
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046

    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 已提交
1047 1048 1049 1050 1051 1052 1053
    sh.tar(
        "cvzf",
        "%s" % tar_package_path,
        glob.glob("%s/*" % project_dir),
        "--exclude",
        "%s/_tmp" % project_dir,
        _fg=True)
Y
yejianwu 已提交
1054 1055 1056
    print("Packaging Done!\n")


1057 1058
def build_benchmark_model(abi,
                          model_output_dir,
Y
yejianwu 已提交
1059
                          hexagon_mode,
L
liuqi 已提交
1060
                          enable_openmp,
Y
yejianwu 已提交
1061
                          linkshared=False):
L
liuqi 已提交
1062
    if not linkshared:
Y
yejianwu 已提交
1063
        target_name = "benchmark_model_static"
Y
yejianwu 已提交
1064
    else:
Y
yejianwu 已提交
1065 1066 1067
        target_name = "benchmark_model_shared"
    benchmark_target = "//mace/benchmark:%s" % target_name

1068 1069
    bazel_build(benchmark_target,
                abi=abi,
L
liuqi 已提交
1070
                enable_openmp=enable_openmp,
1071 1072
                hexagon_mode=hexagon_mode)

Y
yejianwu 已提交
1073 1074 1075 1076
    benchmark_binary_file = "%s/%s" % (model_output_dir, target_name)
    if os.path.exists(benchmark_binary_file):
        sh.rm("-rf", benchmark_binary_file)

1077
    target_bin = "/".join(bazel_target_to_bin(benchmark_target))
Y
yejianwu 已提交
1078
    sh.cp("-f", target_bin, model_output_dir)
1079 1080


W
wuchenghui 已提交
1081 1082
def benchmark_model(abi,
                    serialno,
1083
                    benchmark_binary_dir,
Y
yejianwu 已提交
1084 1085 1086
                    vlog_level,
                    embed_model_data,
                    model_output_dir,
Y
yejianwu 已提交
1087
                    mace_model_dir,
Y
yejianwu 已提交
1088 1089 1090 1091 1092 1093
                    input_nodes,
                    output_nodes,
                    input_shapes,
                    output_shapes,
                    model_tag,
                    device_type,
1094
                    phone_data_dir,
1095
                    build_type,
1096
                    opencl_binary_file,
Y
yejianwu 已提交
1097
                    shared_library_dir,
W
wuchenghui 已提交
1098 1099 1100 1101
                    omp_num_threads=-1,
                    cpu_affinity_policy=1,
                    gpu_perf_hint=3,
                    gpu_priority_hint=3,
Y
yejianwu 已提交
1102
                    input_file_name="model_input",
Y
yejianwu 已提交
1103
                    linkshared=0):
Y
yejianwu 已提交
1104 1105
    print("* Benchmark for %s" % model_tag)

Y
yejianwu 已提交
1106 1107 1108 1109 1110
    if linkshared == 0:
        benchmark_model_target = "benchmark_model_static"
    else:
        benchmark_model_target = "benchmark_model_shared"

1111 1112 1113
    mace_model_path = ""
    if build_type == BuildType.proto:
        mace_model_path = "%s/%s.pb" % (mace_model_dir, model_tag)
Y
yejianwu 已提交
1114
    if abi == "host":
W
wuchenghui 已提交
1115 1116
        p = subprocess.Popen(
            [
Y
yejianwu 已提交
1117 1118
                "env",
                "MACE_CPP_MIN_VLOG_LEVEL=%s" % vlog_level,
Y
yejianwu 已提交
1119
                "%s/%s" % (benchmark_binary_dir, benchmark_model_target),
1120
                "--model_name=%s" % model_tag,
Y
yejianwu 已提交
1121 1122 1123 1124 1125
                "--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),
1126
                "--model_data_file=%s/%s.data" % (mace_model_dir, model_tag),
Y
yejianwu 已提交
1127
                "--device=%s" % device_type,
W
wuchenghui 已提交
1128 1129 1130 1131
                "--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 已提交
1132
                "--model_file=%s" % mace_model_path,
W
wuchenghui 已提交
1133
            ])
Y
yejianwu 已提交
1134 1135 1136
        p.wait()
    else:
        sh.adb("-s", serialno, "shell", "mkdir", "-p", phone_data_dir)
1137 1138
        internal_storage_dir = create_internal_storage_dir(
            serialno, phone_data_dir)
Y
yejianwu 已提交
1139 1140

        for input_name in input_nodes:
L
liuqi 已提交
1141 1142
            formatted_name = common.formatted_file_name(input_file_name,
                                                        input_name)
Y
yejianwu 已提交
1143 1144 1145
            adb_push("%s/%s" % (model_output_dir, formatted_name),
                     phone_data_dir, serialno)
        if not embed_model_data:
1146
            adb_push("%s/%s.data" % (mace_model_dir, model_tag),
Y
yejianwu 已提交
1147
                     phone_data_dir, serialno)
1148 1149 1150
        if device_type == common.DeviceType.GPU \
                and os.path.exists(opencl_binary_file):
            adb_push(opencl_binary_file, phone_data_dir, serialno)
1151 1152 1153 1154 1155
        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 已提交
1156
                     serialno)
Y
yejianwu 已提交
1157

Y
yejianwu 已提交
1158
        if linkshared == 1:
Y
yejianwu 已提交
1159 1160 1161 1162 1163
            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 已提交
1164 1165
        adb_push("%s/%s" % (benchmark_binary_dir, benchmark_model_target),
                 phone_data_dir,
1166
                 serialno)
Y
yejianwu 已提交
1167

李寅 已提交
1168
        adb_cmd = [
W
wuchenghui 已提交
1169 1170 1171 1172
            "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,
1173
            "MACE_INTERNAL_STORAGE_PATH=%s" % internal_storage_dir,
W
wuchenghui 已提交
1174
            "MACE_OPENCL_PROFILING=1",
Y
yejianwu 已提交
1175
            "%s/%s" % (phone_data_dir, benchmark_model_target),
1176
            "--model_name=%s" % model_tag,
W
wuchenghui 已提交
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
            "--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,
1188
            "--model_file=%s" % mace_model_phone_path,
1189 1190
            "--opencl_binary_file=%s/%s" %
            (phone_data_dir, os.path.basename(opencl_binary_file)),
李寅 已提交
1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
        ]
        adb_cmd = ' '.join(adb_cmd)
        adb_cmd_file = "%s/%s" % (phone_data_dir, 'cmd_file')
        with open('/tmp/mace_cmd_file', 'w') as cmd_file:
            cmd_file.write(adb_cmd)
        adb_push('/tmp/mace_cmd_file', adb_cmd_file, serialno)

        sh.adb(
            "-s",
            serialno,
            "shell",
            "sh",
            adb_cmd_file,
L
liuqi 已提交
1204
            _fg=True)
Y
yejianwu 已提交
1205 1206 1207 1208

    print("Benchmark done!\n")


W
wuchenghui 已提交
1209 1210
def build_run_throughput_test(abi,
                              serialno,
Y
yejianwu 已提交
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
                              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,
1223
                              phone_data_dir,
Y
yejianwu 已提交
1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
                              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

1239
    sh.cp("-f", merged_lib_file, "mace/benchmark/libmace_merged.a")
L
liuqi 已提交
1240
    sh.bazel(
Y
yejianwu 已提交
1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
        "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 已提交
1260
        _fg=True)
Y
yejianwu 已提交
1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285

    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 已提交
1286
    adb_push("third_party/nnlib/libhexagon_controller.so",
Y
yejianwu 已提交
1287 1288 1289
             phone_data_dir,
             serialno)

L
liuqi 已提交
1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
    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 已提交
1312 1313 1314 1315

    print("throughput_test done!\n")


1316 1317 1318
################################
# falcon
################################
L
Liangliang He 已提交
1319
def falcon_tags(tags_dict):
L
Liangliang He 已提交
1320 1321 1322 1323 1324 1325 1326
    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 已提交
1327

1328

L
Liangliang He 已提交
1329 1330
def falcon_push_metrics(server, metrics, endpoint="mace_dev", tags={}):
    cli = falcon_cli.FalconCli.connect(server=server, port=8433, debug=False)
L
Liangliang He 已提交
1331 1332 1333 1334 1335 1336 1337
    ts = int(time.time())
    falcon_metrics = [{
        "endpoint": endpoint,
        "metric": key,
        "tags": falcon_tags(tags),
        "timestamp": ts,
        "value": value,
L
Liangliang He 已提交
1338
        "step": 600,
L
Liangliang He 已提交
1339 1340 1341
        "counterType": "GAUGE"
    } for key, value in metrics.iteritems()]
    cli.update(falcon_metrics)