|
- #!/usr/bin/env python3
- # coding: utf-8
- # Copyright 2019 Huawei Technologies Co., Ltd
- #
- # 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.
-
- """result compare function"""
- import logging
- import numpy as np
- import akg.tvm as tvm
-
- def result_compare(actual, bench_mark, r_tol=5e-3):
- """function for compare result."""
- error = 0
- count = 0
- last_err = -2
- continue_err = 0
- max_continue = -1
- max_end = 0
- logging.debug(actual.shape)
- logging.debug(bench_mark.shape)
-
- actual = actual.reshape((actual.size,))
- len_a = actual.size
- bench_mark = bench_mark.reshape((bench_mark.size,))
- len_b = bench_mark.size
- if len_a != len_b:
- return False
-
- for i in range(len_a):
- a = actual[i]
- b = bench_mark[i]
- if abs(a - b) > abs(b) * r_tol:
- error += 1
-
- if last_err + 1 == count:
- continue_err += 1
- else:
- if continue_err > max_continue:
- max_continue = continue_err
- max_end = last_err
- continue_err = 1
- last_err = count
-
- elif np.isnan(a):
- error += 1
-
- if last_err + 1 == count:
- continue_err += 1
- else:
- if continue_err > max_continue:
- max_continue = continue_err
- max_end = last_err
- continue_err = 1
- last_err = count
- count += 1
- if continue_err > max_continue:
- max_continue = continue_err
- max_end = last_err
- logging.debug("error num: %d/%d (%.2f%%)", error, count, 100.0 * error / count)
- logging.debug("longest error range: [%d, %d]", max_end - max_continue + 1, max_end)
- if max_continue >= 16:
- return False
- logging.debug("\n\n******************** test ok *****************\n\n")
- return True
-
-
- def akg_fp16_mean(inputs, axis=None, keepdims=True):
- size = 1
- for dim in axis:
- size = size * inputs.shape[dim]
- expect = np_bisect_sum(inputs, axis=axis, keepdims=keepdims) * np.float16(1 / size)
- return expect
-
-
- def np_bisect_sum(inputs, axis=None, keepdims=True):
- """numpy bisection summation."""
- shape = inputs.shape
- size = 1
- for dim in axis:
- size = size * shape[dim]
- if size <= 2:
- expect = np_bisect_sum_fp16(inputs, axis=tuple(axis), keepdims=keepdims)
- else:
- expect = np.sum(inputs.astype("float32"), axis=tuple(axis), keepdims=keepdims).astype("float16")
- return expect
-
-
- def np_bisect_sum_fp16(inputs, axis=None, keepdims=True):
- """
- Function for expected result of bisect sum operation.
-
- Note:
- For fp16 data, np.sum doesn't have enough accuracy, so use bisect sum instead.
- """
- if axis is None:
- axis = []
- if isinstance(axis, int):
- expect = bisect_sum(inputs, axis, keepdims)
- elif isinstance(axis, (list, tuple)):
- axis = sorted(axis)
- expect = inputs
- i = 0
- for x in axis:
- expect = bisect_sum(expect, x if keepdims else x - i, keepdims)
- i = i + 1
- return expect
-
-
- def bisect_sum(a, axis=0, keepdims=True):
- """Axis transformations for bisect sum operation."""
- import math
- shape = a.shape
- if not len(shape) <= 8:
- raise AssertionError("the dimension of input cannot be larger than 6!")
- if axis < 0:
- axis = len(shape) + axis
- dimlen = shape[axis]
- reduce_num = int(math.pow(2, int(math.log(dimlen, 2))))
- tail_num = dimlen - reduce_num
-
- s1 = np.array(a)
- s = s1
-
- if axis == len(shape) - 1:
- s[..., 0:tail_num] = s1[..., 0:tail_num] + s1[..., reduce_num:reduce_num + tail_num]
- while reduce_num != 1:
- s = s[..., 0:reduce_num // 2] + s[..., reduce_num // 2:reduce_num]
- reduce_num = reduce_num // 2
- elif axis == 0:
- s[0:tail_num, :] = s1[0:tail_num, :] + s1[reduce_num:reduce_num + tail_num, :]
- while reduce_num != 1:
- s = s[0:reduce_num // 2, :] + s[reduce_num // 2:reduce_num, :]
- reduce_num = reduce_num // 2
- elif axis == 1:
- s[:, 0:tail_num, :] = s1[:, 0:tail_num, :] + s1[:, reduce_num:reduce_num + tail_num, :]
- while reduce_num != 1:
- s = s[:, 0:reduce_num // 2, :] + s[:, reduce_num // 2:reduce_num, :]
- reduce_num = reduce_num // 2
- elif axis == 2:
- s[:, :, 0:tail_num, :] = s1[:, :, 0:tail_num, :] + s1[:, :, reduce_num:reduce_num + tail_num, :]
- while reduce_num != 1:
- s = s[:, :, 0:reduce_num // 2, :] + s[:, :, reduce_num // 2:reduce_num, :]
- reduce_num = reduce_num // 2
- elif axis == 3:
- s[:, :, :, 0:tail_num, :] = s1[:, :, :, 0:tail_num, :] + s1[:, :, :, reduce_num:reduce_num + tail_num, :]
- while reduce_num != 1:
- s = s[:, :, :, 0:reduce_num // 2, :] + s[:, :, :, reduce_num // 2:reduce_num, :]
- reduce_num = reduce_num // 2
- elif axis == 4:
- s[:, :, :, :, 0:tail_num, :] = s1[:, :, :, :, 0:tail_num, :] + \
- s1[:, :, :, :, reduce_num:reduce_num + tail_num, :]
- while reduce_num != 1:
- s = s[:, :, :, :, 0:reduce_num // 2, :] + s[:, :, :, :, reduce_num // 2:reduce_num, :]
- reduce_num = reduce_num // 2
- elif axis == 5:
- s[:, :, :, :, :, 0:tail_num, :] = s1[:, :, :, :, :, 0:tail_num, :] +\
- s1[:, :, :, :, :, reduce_num:reduce_num + tail_num, :]
- while reduce_num != 1:
- s = s[:, :, :, :, :, 0:reduce_num // 2, :] + s[:, :, :, :, :, reduce_num // 2:reduce_num, :]
- reduce_num = reduce_num // 2
- elif axis == 6:
- s[:, :, :, :, :, :, 0:tail_num, :] = s1[:, :, :, :, :, :, 0:tail_num, :] + \
- s1[:, :, :, :, :, :, reduce_num:reduce_num + tail_num, :]
- while reduce_num != 1:
- s = s[:, :, :, :, :, :, 0:reduce_num // 2, :] + s[:, :, :, :, :, :, reduce_num // 2:reduce_num, :]
- reduce_num = reduce_num // 2
- elif axis == 7:
- s[:, :, :, :, :, :, :, 0:tail_num, :] = s1[:, :, :, :, :, :, :, 0:tail_num, :] + \
- s1[:, :, :, :, :, :, :, reduce_num:reduce_num + tail_num, :]
- while reduce_num != 1:
- s = s[:, :, :, :, :, :, :, 0:reduce_num // 2, :] + s[:, :, :, :, :, :, :, reduce_num // 2:reduce_num, :]
- reduce_num = reduce_num // 2
- if not keepdims:
- s = np.squeeze(s, axis)
- return s
-
-
- def get_ticks(stat_info):
- """get ticks from statistic info."""
- aic_out_path = "aic_out"
- calog_path = aic_out_path + "/calog"
- ticks_log_file = calog_path + '/core0_instr_popped_log.dump'
- with open(ticks_log_file, "r") as file:
- line = file.readlines()[-2]
- ticks = int(line.split(",")[1].split('tick:')[1])
- stat_info['run_time'] = ticks
-
-
- def flattened_index_to_real_index(idx, shape):
- index = []
- index_per_dim = idx
- for i in reversed(range(len(shape))):
- dim_index = index_per_dim % shape[i]
- index_per_dim //= shape[i]
- index.append(dim_index)
-
- index.reverse()
- return index
-
- def count_unequal_element(data_expected, data_actual, rtol, atol):
- """Function for asserting unequal elements in data_actual and data_expected."""
- if not data_expected.shape == data_actual.shape:
- raise AssertionError("'data_expected' and 'data_actual' should have the same shape")
- list_a = data_expected.flatten()
- list_b = data_actual.flatten()
- count = 0
- eps = 1e-10
- all_printed = True
- for i, aa in enumerate(list_a):
- a = list_b[i]
- b = aa
- is_bool = isinstance(a, np.bool_) or isinstance(b, np.bool_)
- is_nan = np.isnan(a) or np.isnan(b)
- is_numeric = not (is_bool or is_nan)
- if (is_bool and a != b) or (is_numeric and abs(a - b) > (atol + rtol * abs(b))) or is_nan:
- if count < 100:
- index = flattened_index_to_real_index(i, data_expected.shape)
- if is_numeric:
- b_1 = b + eps if b == 0.0 else b
- logging.error("%s: Actual[%s] Expected[%s] Ratio[%s]",
- str(index), str(a), str(b), str(abs(a - b) / abs(b_1)))
- else:
- logging.error("%s: Actual[%s] Expected[%s]", str(index), str(a), str(b))
- else:
- all_printed = False
- count += 1
-
- if count != 0:
- if not all_printed:
- logging.error("...")
- logging.error("Total %s mismatch detected!!!, Only print 100...", str(count))
- else:
- logging.error("Total %s mismatch detected!!!", str(count))
-
- if not count <= int(len(list_a)):
- raise AssertionError
-
-
- def allclose_nparray(data_expected, data_actual, rtol, atol=1e-08):
- """Compare whether arrays are element-wise equal within tolerances."""
- if not np.allclose(data_expected, data_actual, rtol, atol):
- count_unequal_element(data_expected, data_actual, rtol, atol)
-
- def gpu_profiling(mod, *args, repeat_time=1, device_id=0):
- """Do profiling on gpu for cuda op"""
- ctx = tvm.context("cuda", device_id)
- ftimer = mod.time_evaluator(mod.entry_name, ctx, number=repeat_time)
- tcost = ftimer(*args).mean
- print("{}: exec={} sec/op".format(ctx, tcost))
|