Skip to content
Snippets Groups Projects
main.py 3.58 KiB
Newer Older
  • Learn to ignore specific revisions
  • import site
    from pathlib import Path
    
    from os import makedirs
    
    import numpy as np
    
    
    import torch
    from torch2hpvm import BinDataset, ModelExporter
    
    self_folder = Path(__file__).parent.absolute()
    
    site.addsitedir(self_folder.as_posix())
    
    Yifan Zhao's avatar
    Yifan Zhao committed
    from torch_dnn import MiniERA, quantize, CIFAR
    
    
    # Consts (don't change)
    BUFFER_NAME = "hpvm-mod.nvdla"
    
    
    def split_and_scp(
        local_srcs: list, host: str, remote_dst: str, password: str, options: str
    ):
        import pexpect
    
        print(f"Copying files to remote host {host}...")
        args = options.split(" ")
        local_srcs = [str(s) for s in local_srcs]
        args += ["-r", *local_srcs, f"{host}:{remote_dst}"]
        child = pexpect.spawn("scp", args)
        child.expect(r"password:")
        child.sendline(password)
        # A rough approach to at least print something when scp is alive
        for line in child:
            print(line.decode())
    
    
    def run_test_over_ssh(host: str, password: str, working_dir: str, image_dir: Path, options: str):
        import pexpect
    
        print(f"Running test on remote host {host}...")
        args = options.split(" ") + [host]
    
    Yifan Zhao's avatar
    Yifan Zhao committed
        child = pexpect.spawn("ssh", args, timeout=None)
    
        child.expect(r"password:")
        child.sendline(password)
        child.expect("# ")  # The bash prompt
        child.sendline(f"cd {working_dir}")
        child.expect("# ")
        child.delimiter = "# "
        for image in image_dir.glob("*"):
            remote_path = f"{image_dir.name}/{image.name}"
            print(f"Sending {image.name} to run")
            child.sendline(f"./nvdla_runtime --loadable {BUFFER_NAME} --image {remote_path} --rawdump")
    
    Yifan Zhao's avatar
    Yifan Zhao committed
            child.expect("Test pass")
    
            child.sendline("cat output.dimg")
            child.expect("# ")
            result_lines = child.before.decode().splitlines()
            # Should have 2 lines. First line is the command we keyed in.
            output = [int(s) for s in result_lines[1].strip().split()]
            yield image, output
    
    
    # Local configs
    
    ASSET_DIR = self_folder / "assets/miniera"
    QUANT_STRAT = "NONE"  # Quantization method
    WORKING_DIR = Path("/tmp/miniera")
    
    Yifan Zhao's avatar
    Yifan Zhao committed
    N_IMAGES = 50
    
    # Remote configs
    SCP_OPTS = "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P 5506"
    SSH_OPTS = "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 5506"
    SCP_HOST = "root@espgate.cs.columbia.edu"
    SCP_PWD = "openesp"
    SCP_DST = "~/NV_NVDLA"
    
    
    Yifan Zhao's avatar
    Yifan Zhao committed
    # Reproducibility
    np.random.seed(42)
    
    Yifan Zhao's avatar
    Yifan Zhao committed
    makedirs(WORKING_DIR, exist_ok=False)
    
    
    # Calculate quantization scales
    ckpt = (ASSET_DIR / "miniera.pth").as_posix()
    
    model = MiniERA()
    
    model.load_state_dict(torch.load(ckpt))
    
    Yifan Zhao's avatar
    Yifan Zhao committed
    dataset = CIFAR.from_file(ASSET_DIR / "input.bin", ASSET_DIR / "labels.bin")
    scale_output = quantize(model, dataset, QUANT_STRAT, WORKING_DIR)
    
    
    # Code generation (into /tmp/miniera/hpvm-mod.nvdla)
    
    nvdla_buffer = WORKING_DIR / BUFFER_NAME
    print(f"Generating NVDLA buffer into {nvdla_buffer}")
    
    bin_dataset = BinDataset(
        ASSET_DIR / "input.bin", ASSET_DIR / "labels.bin", (5000, 3, 32, 32)
    )
    
    Yifan Zhao's avatar
    Yifan Zhao committed
    exporter = ModelExporter(model, bin_dataset, WORKING_DIR, ASSET_DIR / "scales/calib_NONE.txt")
    
    exporter.generate(n_images=N_IMAGES).compile(WORKING_DIR / "miniera", WORKING_DIR)
    
    
    # SCP essential files to remote device
    input_images = exporter.dataset_dir
    
    split_and_scp([nvdla_buffer, input_images], SCP_HOST, SCP_DST, SCP_PWD, SCP_OPTS)
    
    # SSH to run test remotely
    
    Yifan Zhao's avatar
    Yifan Zhao committed
    n_total, correct = 0, 0
    
    for image_path, output in run_test_over_ssh(SCP_HOST, SCP_PWD, SCP_DST, input_images, SSH_OPTS):
    
    Yifan Zhao's avatar
    Yifan Zhao committed
        idx, label = [int(s) for s in image_path.stem.split("_")]
        output = np.array(output)
        print(idx, output.argmax(), label, output)
        n_total += 1
        correct += int(output.argmax() == label)
    print(f"Accuracy: {correct / n_total * 100}% ({n_total} images)")