dawn-bench-models/pytorch/CIFAR10/benchmark/infer.py
Deepak Narayanan b7e1e0fa0f First commit
2017-08-17 11:43:17 -07:00

140 lines
4.6 KiB
Python

import os
import timeit
from glob import glob
from collections import OrderedDict
import click
import torch
import numpy as np
from torch.autograd import Variable
from torchvision import transforms
from torchvision import datasets
from benchmark.train import load, MEAN, STD, save_result, MODELS
class PyTorchEngine:
def __init__(self, filename, use_cuda=False, name=None):
self.filename = filename
self.use_cuda = use_cuda
self.name = name
model, epoch, accuracy = load(self.filename)
if self.use_cuda:
self.model = model.cuda()
else:
self.model = model.cpu()
self.epoch = epoch
self.accuracy = accuracy
def pred(self, inputs):
inputs = Variable(inputs, requires_grad=False, volatile=True)
if self.use_cuda:
inputs = inputs.cuda()
return self.model(inputs).data.cpu().numpy()
else:
return self.model(inputs).data.numpy()
def time_batch_size(dataset, batch_size, pred, use_cuda, repeat=100, bestof=3):
loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size,
shuffle=False, pin_memory=use_cuda)
inputs, targets = loader.__iter__().next()
assert inputs.size(0) == batch_size
times = timeit.repeat('pred(inputs)', globals=locals(),
repeat=repeat, number=1)
return times
def infer_cifar10(dataset, engine, start=1, end=128, repeat=100, log2=True,
output=None):
if log2:
start = int(np.floor(np.log2(start)))
end = int(np.ceil(np.log2(end)))
assert start >= 0
assert end >= start
batch_sizes = map(lambda x: 2**x, range(start, end + 1))
else:
batch_sizes = range(start, end + 1)
results = []
for batch_size in batch_sizes:
times = time_batch_size(dataset, batch_size, engine.pred,
engine.use_cuda, repeat=repeat)
result = OrderedDict()
result['nodename'] = os.uname().nodename
result['model'] = engine.name
result['use_cuda'] = engine.use_cuda
result['batch_size'] = batch_size
result['mean'] = np.mean(times)
result['std'] = np.std(times)
result['throughput'] = batch_size / np.mean(times)
result['filename'] = engine.filename
if output is not None:
save_result(result, output)
print('batch_size: {batch_size:4d}'
' - mean: {mean:.4f}'
' - std: {std:.4f}'
' - throughput: {throughput:.4f}'.format(**result))
results.append(result)
return results
@click.command()
@click.option('--dataset-dir', default='./data/cifar10')
@click.option('--run-dir', default='./run/')
@click.option('--output-file', default='inference.csv')
@click.option('--start', '-s', default=1)
@click.option('--end', '-e', default=128)
@click.option('--repeat', '-r', default=100)
@click.option('--log2/--no-log2', default=True)
@click.option('--cpu/--no-cpu', default=True)
@click.option('--gpu/--no-gpu', default=True)
@click.option('--append', is_flag=True)
@click.option('--models', '-m', type=click.Choice(MODELS.keys()),
multiple=True)
def infer(dataset_dir, run_dir, output_file, start, end, repeat, log2,
cpu, gpu, append, models):
transform_test = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(MEAN, STD)
])
testset = datasets.CIFAR10(root=dataset_dir, train=False, download=True,
transform=transform_test)
models = models or os.listdir(run_dir)
output_path = os.path.join(run_dir, output_file)
assert not os.path.exists(output_path) or append
for model in models:
model_dir = os.path.join(run_dir, model)
paths = glob(f"{model_dir}/*/checkpoint_best_model.t7")
assert len(paths) > 0
path = os.path.abspath(paths[0])
print(f'Model: {model}')
print(f'Path: {path}')
if cpu:
print('With CPU:')
engine = PyTorchEngine(path, use_cuda=False, name=model)
infer_cifar10(testset, engine, start=start, end=end, log2=log2,
repeat=repeat, output=output_path)
if gpu and torch.cuda.is_available():
print('With GPU:')
engine = PyTorchEngine(path, use_cuda=True, name=model)
# Warmup
time_batch_size(testset, 1, engine.pred, engine.use_cuda, repeat=1)
infer_cifar10(testset, engine, start=start, end=end, log2=log2,
repeat=repeat, output=output_path)
if __name__ == '__main__':
infer()