blob: 8503c178a3a3313a1d2f4b1413a1310e7a55ae6c [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
from __future__ import print_function
import itertools
import mxnet as mx
import sys
import time
class MetricDataGen(object):
""" Base class for generating random data for metric benchmarking """
def __init__(self, n, c, pred_ctx, label_ctx):
self.n = n
self.c = c
self.pred_ctx = pred_ctx
self.label_ctx = label_ctx
def data(self):
mx.random.seed(0)
pred = mx.nd.random_uniform(0.0, 1.0, (self.n, self.c), ctx=self.pred_ctx)
label = mx.nd.random_uniform(0.0, self.c - 1, (self.n,), ctx=self.label_ctx).round()
return label, pred
@property
def batch_size(self):
return self.n
@property
def output_dim(self):
return self.c
class F1MetricDataGen(MetricDataGen):
""" Class for generating random data for F1 metric benchmarking """
def __init__(self, n, c, pred_ctx, label_ctx):
super(F1MetricDataGen, self).__init__(n, 2, pred_ctx, label_ctx)
class PearsonMetricDataGen(MetricDataGen):
""" Class for generating random data for Pearson Correlation metric benchmarking """
def __init__(self, n, c, pred_ctx, label_ctx):
super(PearsonMetricDataGen, self).__init__(n, c, pred_ctx, label_ctx)
def data(self):
mx.random.seed(0)
pred = mx.nd.random_uniform(0.0, 1.0, (self.n, self.c), ctx=self.pred_ctx)
label = mx.nd.random_uniform(0.0, 1.0, (self.n, self.c), ctx=self.label_ctx)
return label, pred
def run_metric(name, data_gen_cls, i, n, c, pred_ctx, label_ctx, **kwargs):
""" Helper function for running one metric benchmark """
metric = mx.gluon.metric.create(name, **kwargs)
data_gen = data_gen_cls(n, c, pred_ctx, label_ctx)
try:
label, pred = data_gen.data()
mx.nd.waitall()
before = time.time()
metric.update([label] * i, [pred] * i)
mx.nd.waitall()
elapsed = time.time() - before
elapsed_str = f"{elapsed:<.5}"
except mx.MXNetError:
elapsed_str = "FAILED"
print(f"{name:<15}{pred_ctx:<10}{label_ctx:<12}{i * n:<12}{data_gen.batch_size:<15}{data_gen.output_dim:<15}{elapsed_str:<}", file=sys.stderr)
def test_metric_performance():
""" unittest entry for metric performance benchmarking """
# Each dictionary entry is (metric_name:(kwargs, DataGenClass))
metrics = [
('acc', ({}, MetricDataGen)),
('top_k_acc', ({'top_k': 5}, MetricDataGen)),
('F1', ({}, F1MetricDataGen)),
('Perplexity', ({'ignore_label': -1}, MetricDataGen)),
('MAE', ({}, MetricDataGen)),
('MSE', ({}, MetricDataGen)),
('RMSE', ({}, MetricDataGen)),
('ce', ({}, MetricDataGen)),
('nll_loss', ({}, MetricDataGen)),
('pearsonr', ({}, PearsonMetricDataGen)),
]
data_size = 1024 * 128
batch_sizes = [16, 64, 256, 1024]
output_dims = [128, 1024, 8192]
ctxs = [mx.cpu(), mx.gpu()]
print("\nmx.gluon.metric benchmarks", file=sys.stderr)
print(
f"{'Metric':15}{'Data-Ctx':10}{'Label-Ctx':12}{'Data Size':12}{'Batch Size':15}{'Output Dim':15}{'Elapsed Time'}",
file=sys.stderr)
print(f"{'':-^90}", file=sys.stderr)
for k, v in metrics:
for c in output_dims:
for n in batch_sizes:
for pred_ctx, label_ctx in itertools.product(ctxs, ctxs):
run_metric(k, v[1], (data_size * 128), (n * c), n, c, pred_ctx, label_ctx, **v[0])
print(f"{'':-^90}", file=sys.stderr)