Extend and fix input/output precisions support in functional tests (#3933)
* Use actual blobs type to get nGraph element type, when generating inputs and calculating reference results. It will allow to run tests with `undefined` preset and use real type, returned from the device to generate and process input. It also fixes the case with several inputs with different type. * Extend `convertOutputPrecision` function to fully support conversions from/to fp16/bf16 types. The device might return blobs in that formats, so they need to be supported by the testing framework.
This commit is contained in:
parent
d4488b9dfc
commit
bad4e97d9b
@ -351,15 +351,14 @@ void LayerTestsCommon::Infer() {
|
||||
}
|
||||
|
||||
std::vector<std::vector<std::uint8_t>> LayerTestsCommon::CalculateRefs() {
|
||||
// nGraph interpreter does not support f16
|
||||
// IE converts f16 to f32
|
||||
ngraph::pass::ConvertPrecision<ngraph::element::Type_t::f16, ngraph::element::Type_t::f32>().run_on_function(
|
||||
function);
|
||||
|
||||
// The same idea for bf16
|
||||
// nGraph interpreter does not support f16/bf16
|
||||
ngraph::pass::ConvertPrecision<ngraph::element::Type_t::f16, ngraph::element::Type_t::f32>().run_on_function(function);
|
||||
ngraph::pass::ConvertPrecision<ngraph::element::Type_t::bf16, ngraph::element::Type_t::f32>().run_on_function(function);
|
||||
|
||||
function->validate_nodes_and_infer_types();
|
||||
|
||||
auto referenceInputs = std::vector<std::vector<std::uint8_t>>(inputs.size());
|
||||
auto refInputsTypes = std::vector<ngraph::element::Type>(inputs.size());
|
||||
for (std::size_t i = 0; i < inputs.size(); ++i) {
|
||||
const auto &input = inputs[i];
|
||||
const auto &inputSize = input->byteSize();
|
||||
@ -372,29 +371,27 @@ std::vector<std::vector<std::uint8_t>> LayerTestsCommon::CalculateRefs() {
|
||||
const auto lockedMemory = memory->wmap();
|
||||
const auto buffer = lockedMemory.as<const std::uint8_t *>();
|
||||
std::copy(buffer, buffer + inputSize, referenceInput.data());
|
||||
|
||||
refInputsTypes[i] = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(memory->getTensorDesc().getPrecision());
|
||||
}
|
||||
|
||||
auto ieOutPrc = outPrc;
|
||||
const auto &&outputsInfo = executableNetwork.GetOutputsInfo();
|
||||
std::vector<ngraph::element::Type_t> convertType(outputsInfo.size(),
|
||||
FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(ieOutPrc));
|
||||
if (ieOutPrc == InferenceEngine::Precision::UNSPECIFIED) {
|
||||
size_t i = 0;
|
||||
std::vector<ngraph::element::Type_t> convertType;
|
||||
convertType.reserve(outputsInfo.size());
|
||||
for (const auto &output : outputsInfo) {
|
||||
convertType[i++] = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(
|
||||
output.second->getTensorDesc().getPrecision());
|
||||
convertType.push_back(
|
||||
FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(
|
||||
output.second->getTensorDesc().getPrecision()));
|
||||
}
|
||||
}
|
||||
|
||||
const auto& inType = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(inPrc);
|
||||
std::vector<std::vector<std::uint8_t>> expectedOutputs;
|
||||
switch (refMode) {
|
||||
case INTERPRETER: {
|
||||
expectedOutputs = ngraph::helpers::interpreterFunction(function, referenceInputs, inType, convertType);
|
||||
expectedOutputs = ngraph::helpers::interpreterFunction(function, referenceInputs, refInputsTypes, convertType);
|
||||
break;
|
||||
}
|
||||
case CONSTANT_FOLDING: {
|
||||
const auto &foldedFunc = ngraph::helpers::foldFunction(function, referenceInputs, inType);
|
||||
const auto &foldedFunc = ngraph::helpers::foldFunction(function, referenceInputs, refInputsTypes);
|
||||
expectedOutputs = ngraph::helpers::getConstData(foldedFunc, convertType);
|
||||
break;
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ inline ngraph::NodeVector castOps2Nodes(const std::vector<std::shared_ptr<opType
|
||||
|
||||
std::vector<std::vector<std::uint8_t>> interpreterFunction(const std::shared_ptr<Function> &function,
|
||||
const std::vector<std::vector<std::uint8_t>> &inputs,
|
||||
element::Type_t inType = element::Type_t::undefined,
|
||||
const std::vector<ngraph::element::Type> &inputTypes = {},
|
||||
const std::vector<ngraph::element::Type_t> convertType = {});
|
||||
|
||||
//
|
||||
@ -253,7 +253,7 @@ void CompareFunctions(const Function &actual, const Function &expected);
|
||||
|
||||
std::shared_ptr<Function> foldFunction(const std::shared_ptr<Function> &function,
|
||||
const std::vector<std::vector<std::uint8_t>> &inputs,
|
||||
element::Type_t inpType = element::Type_t::undefined);
|
||||
const std::vector<ngraph::element::Type> &inputTypes = {});
|
||||
|
||||
std::vector<std::vector<std::uint8_t>> getConstData(const std::shared_ptr<Function> &function,
|
||||
std::vector<ngraph::element::Type_t> convertType = {});
|
||||
|
@ -81,7 +81,7 @@ OutputVector convert2OutputVector(const std::vector<std::shared_ptr<Node>> &node
|
||||
|
||||
std::vector<std::vector<std::uint8_t>> interpreterFunction(const std::shared_ptr<Function> &function,
|
||||
const std::vector<std::vector<std::uint8_t>> &inputs,
|
||||
element::Type_t inType,
|
||||
const std::vector<ngraph::element::Type> &inputTypes,
|
||||
const std::vector<ngraph::element::Type_t> convertType) {
|
||||
runtime::Backend::set_backend_shared_library_search_directory("");
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
@ -92,18 +92,25 @@ std::vector<std::vector<std::uint8_t>> interpreterFunction(const std::shared_ptr
|
||||
NGRAPH_CHECK(parametersNumber == inputsNumber,
|
||||
"Got function (", function->get_friendly_name(), ") with ", parametersNumber, " parameters, but ",
|
||||
inputsNumber, " input blobs");
|
||||
if (!inputTypes.empty()) {
|
||||
NGRAPH_CHECK(inputTypes.size() == inputsNumber,
|
||||
"Got function (", function->get_friendly_name(), ") with ", inputsNumber, " inputs, but ",
|
||||
inputTypes.size(), " types");
|
||||
}
|
||||
|
||||
auto inputTensors = std::vector<std::shared_ptr<runtime::Tensor>>{};
|
||||
for (const auto ¶meter : parameters) {
|
||||
for (size_t i = 0; i < parametersNumber; ++i) {
|
||||
const auto ¶meter = parameters[i];
|
||||
const auto ¶meterIndex = function->get_parameter_index(parameter);
|
||||
const auto ¶meterShape = parameter->get_shape();
|
||||
const auto ¶meterType = parameter->get_element_type();
|
||||
const auto ¶meterSize = shape_size(parameterShape) * parameterType.size();
|
||||
|
||||
auto input = inputs[parameterIndex];
|
||||
const auto inType = inputTypes.empty() ? element::undefined : inputTypes[i];
|
||||
|
||||
if (inType != element::undefined && inType != parameterType) {
|
||||
input = convertOutputPrecision(input, inType, parameter->get_element_type(), shape_size(parameter->get_shape()));
|
||||
input = convertOutputPrecision(input, inType, parameterType, shape_size(parameterShape));
|
||||
}
|
||||
|
||||
const auto &inputSize = input.size();
|
||||
@ -144,7 +151,20 @@ std::vector<std::vector<std::uint8_t>> interpreterFunction(const std::shared_ptr
|
||||
}
|
||||
|
||||
std::shared_ptr<Function> foldFunction(const std::shared_ptr<Function> &function,
|
||||
const std::vector<std::vector<std::uint8_t>> &inputs, element::Type_t inpType) {
|
||||
const std::vector<std::vector<std::uint8_t>> &inputs,
|
||||
const std::vector<ngraph::element::Type> &inputTypes) {
|
||||
const auto ¶meters = function->get_parameters();
|
||||
const auto ¶metersNumber = parameters.size();
|
||||
const auto &inputsNumber = inputs.size();
|
||||
NGRAPH_CHECK(parametersNumber == inputsNumber,
|
||||
"Got function (", function->get_friendly_name(), ") with ", parametersNumber, " parameters, but ",
|
||||
inputsNumber, " input blobs");
|
||||
if (!inputTypes.empty()) {
|
||||
NGRAPH_CHECK(inputTypes.size() == inputsNumber,
|
||||
"Got function (", function->get_friendly_name(), ") with ", inputsNumber, " inputs, but ",
|
||||
inputTypes.size(), " types");
|
||||
}
|
||||
|
||||
std::vector<element::Type> paramElementTypes;
|
||||
std::vector<PartialShape> paramShapes;
|
||||
std::vector<std::vector<std::uint8_t>> vecTmpConvertedInputs;
|
||||
@ -153,12 +173,15 @@ std::shared_ptr<Function> foldFunction(const std::shared_ptr<Function> &function
|
||||
std::vector<void *> inBuffers;
|
||||
inBuffers.reserve(inputs.size());
|
||||
|
||||
for (const auto ¶m : function->get_parameters()) {
|
||||
for (size_t i = 0; i < parametersNumber; ++i) {
|
||||
const auto ¶m = parameters[i];
|
||||
paramElementTypes.emplace_back(param->get_element_type());
|
||||
paramShapes.emplace_back(param->get_shape());
|
||||
auto parameterIndex = function->get_parameter_index(param);
|
||||
auto& input = inputs[parameterIndex];
|
||||
|
||||
const auto inpType = inputTypes.empty() ? element::undefined : inputTypes[i];
|
||||
|
||||
if (inpType != element::undefined && inpType != paramElementTypes.back()) {
|
||||
vecTmpConvertedInputs.emplace_back(convertOutputPrecision(input, inpType, param->get_element_type(), shape_size(param->get_shape())));
|
||||
inBuffers.push_back(vecTmpConvertedInputs.back().data());
|
||||
@ -314,6 +337,12 @@ std::vector<std::uint8_t> convertOutputPrecision(const std::vector<std::uint8_t>
|
||||
case element::Type_t::f32: {
|
||||
return convertPrecision<uint8_t, float>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::f16: {
|
||||
return convertPrecision<uint8_t, ngraph::float16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::bf16: {
|
||||
return convertPrecision<uint8_t, ngraph::bfloat16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u64: {
|
||||
return convertPrecision<uint8_t, uint64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
@ -345,6 +374,12 @@ std::vector<std::uint8_t> convertOutputPrecision(const std::vector<std::uint8_t>
|
||||
case element::Type_t::f32: {
|
||||
return convertPrecision<uint16_t, float>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::f16: {
|
||||
return convertPrecision<uint16_t, ngraph::float16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::bf16: {
|
||||
return convertPrecision<uint16_t, ngraph::bfloat16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u64: {
|
||||
return convertPrecision<uint16_t, uint64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
@ -376,6 +411,12 @@ std::vector<std::uint8_t> convertOutputPrecision(const std::vector<std::uint8_t>
|
||||
case element::Type_t::f32: {
|
||||
return convertPrecision<int8_t, float>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::f16: {
|
||||
return convertPrecision<int8_t, ngraph::float16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::bf16: {
|
||||
return convertPrecision<int8_t, ngraph::bfloat16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u64: {
|
||||
return convertPrecision<int8_t, uint64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
@ -407,6 +448,12 @@ std::vector<std::uint8_t> convertOutputPrecision(const std::vector<std::uint8_t>
|
||||
case element::Type_t::f32: {
|
||||
return convertPrecision<int16_t, float>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::f16: {
|
||||
return convertPrecision<int16_t, ngraph::float16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::bf16: {
|
||||
return convertPrecision<int16_t, ngraph::bfloat16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u64: {
|
||||
return convertPrecision<int16_t, uint64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
@ -438,6 +485,12 @@ std::vector<std::uint8_t> convertOutputPrecision(const std::vector<std::uint8_t>
|
||||
case element::Type_t::f32: {
|
||||
return convertPrecision<int32_t, float>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::f16: {
|
||||
return convertPrecision<int32_t, ngraph::float16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::bf16: {
|
||||
return convertPrecision<int32_t, ngraph::bfloat16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u64: {
|
||||
return convertPrecision<int32_t, uint64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
@ -469,6 +522,12 @@ std::vector<std::uint8_t> convertOutputPrecision(const std::vector<std::uint8_t>
|
||||
case element::Type_t::f32: {
|
||||
return convertPrecision<int64_t, float>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::f16: {
|
||||
return convertPrecision<int64_t, ngraph::float16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::bf16: {
|
||||
return convertPrecision<int64_t, ngraph::bfloat16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u64: {
|
||||
return convertPrecision<int64_t, uint64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
@ -500,6 +559,12 @@ std::vector<std::uint8_t> convertOutputPrecision(const std::vector<std::uint8_t>
|
||||
case element::Type_t::f32: {
|
||||
return convertPrecision<uint64_t, float>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::f16: {
|
||||
return convertPrecision<uint64_t, ngraph::float16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::bf16: {
|
||||
return convertPrecision<uint64_t, ngraph::bfloat16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u64: {
|
||||
return convertPrecision<uint64_t, uint64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
@ -532,15 +597,14 @@ std::vector<std::uint8_t> convertOutputPrecision(const std::vector<std::uint8_t>
|
||||
return convertPrecision<float, float>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::f16: {
|
||||
// ngraph float16 has single ctor from float
|
||||
return convertPrecision<float, ngraph::float16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u64: {
|
||||
return convertPrecision<float, uint64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::bf16: {
|
||||
return convertPrecision<float, ngraph::bfloat16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u64: {
|
||||
return convertPrecision<float, uint64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::boolean: {
|
||||
return convertPrecision<float, char>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
@ -572,6 +636,9 @@ std::vector<std::uint8_t> convertOutputPrecision(const std::vector<std::uint8_t>
|
||||
case element::Type_t::f32: {
|
||||
return convertPrecision<char, float>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::f16: {
|
||||
return convertPrecision<char, ngraph::float16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::bf16: {
|
||||
return convertPrecision<char, ngraph::bfloat16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
@ -583,6 +650,46 @@ std::vector<std::uint8_t> convertOutputPrecision(const std::vector<std::uint8_t>
|
||||
element::Type(toPrecision).get_type_name());
|
||||
}
|
||||
}
|
||||
case element::Type_t::f16: {
|
||||
switch (toPrecision) {
|
||||
case element::Type_t::u8: {
|
||||
return convertPrecision<ngraph::float16, uint8_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u16: {
|
||||
return convertPrecision<ngraph::float16, uint16_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::i8: {
|
||||
return convertPrecision<ngraph::float16, int8_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::i16: {
|
||||
return convertPrecision<ngraph::float16, int16_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::i32: {
|
||||
return convertPrecision<ngraph::float16, int32_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::i64: {
|
||||
return convertPrecision<ngraph::float16, int64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::f32: {
|
||||
return convertPrecision<ngraph::float16, float>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::f16: {
|
||||
return convertPrecision<ngraph::float16, ngraph::float16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::bf16: {
|
||||
return convertPrecision<ngraph::float16, ngraph::bfloat16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u64: {
|
||||
return convertPrecision<ngraph::float16, uint64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::boolean: {
|
||||
return convertPrecision<ngraph::float16, char>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("convertOutputPrecision can't convert from: " + element::Type(fromPrecision).get_type_name() + " to: " +
|
||||
element::Type(toPrecision).get_type_name());
|
||||
}
|
||||
}
|
||||
case element::Type_t::bf16: {
|
||||
switch (toPrecision) {
|
||||
case element::Type_t::u8: {
|
||||
@ -606,12 +713,15 @@ std::vector<std::uint8_t> convertOutputPrecision(const std::vector<std::uint8_t>
|
||||
case element::Type_t::f32: {
|
||||
return convertPrecision<ngraph::bfloat16, float>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u64: {
|
||||
return convertPrecision<ngraph::bfloat16, uint64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
case element::Type_t::f16: {
|
||||
return convertPrecision<ngraph::bfloat16, ngraph::float16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::bf16: {
|
||||
return convertPrecision<ngraph::bfloat16, ngraph::bfloat16>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::u64: {
|
||||
return convertPrecision<ngraph::bfloat16, uint64_t>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
case element::Type_t::boolean: {
|
||||
return convertPrecision<ngraph::bfloat16, char>(output, elementsCount, element::Type(toPrecision).size());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user