// // Copyright © 2017 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #include "QuantizationDataSet.hpp" #include #include #include #include namespace armnnQuantizer { QuantizationDataSet::QuantizationDataSet() { } QuantizationDataSet::QuantizationDataSet(const std::string csvFilePath): m_QuantizationInputs(), m_CsvFilePath(csvFilePath) { ParseCsvFile(); } void AddInputData(unsigned int passId, armnn::LayerBindingId bindingId, const std::string& inputFilePath, std::map& passIdToQuantizationInput) { auto iterator = passIdToQuantizationInput.find(passId); if (iterator == passIdToQuantizationInput.end()) { QuantizationInput input(passId, bindingId, inputFilePath); passIdToQuantizationInput.emplace(passId, input); } else { auto existingQuantizationInput = iterator->second; existingQuantizationInput.AddEntry(bindingId, inputFilePath); } } QuantizationDataSet::~QuantizationDataSet() { } /// Visitor class implementation to gather the TensorInfo for LayerBindingID for creation of ConstTensor for Refine. void InputLayerStrategy::ExecuteStrategy(const armnn::IConnectableLayer* layer, const armnn::BaseDescriptor& descriptor, const std::vector& constants, const char* name, const armnn::LayerBindingId id) { armnn::IgnoreUnused(name, descriptor, constants); m_TensorInfos.emplace(id, layer->GetOutputSlot(0).GetTensorInfo()); } armnn::TensorInfo InputLayerStrategy::GetTensorInfo(armnn::LayerBindingId layerBindingId) { auto iterator = m_TensorInfos.find(layerBindingId); if (iterator != m_TensorInfos.end()) { return m_TensorInfos.at(layerBindingId); } else { throw armnn::Exception("Could not retrieve tensor info for binding ID " + std::to_string(layerBindingId)); } } void InputLayerVisitor::VisitInputLayer(const armnn::IConnectableLayer* layer, armnn::LayerBindingId id, const char* name) { armnn::IgnoreUnused(name); m_TensorInfos.emplace(id, layer->GetOutputSlot(0).GetTensorInfo()); } armnn::TensorInfo InputLayerVisitor::GetTensorInfo(armnn::LayerBindingId layerBindingId) { auto iterator = m_TensorInfos.find(layerBindingId); if (iterator != m_TensorInfos.end()) { return m_TensorInfos.at(layerBindingId); } else { throw armnn::Exception("Could not retrieve tensor info for binding ID " + std::to_string(layerBindingId)); } } unsigned int GetPassIdFromCsvRow(std::vector tokens, unsigned int lineIndex) { unsigned int passId; try { passId = static_cast(std::stoi(tokens[0])); } catch (const std::invalid_argument&) { throw armnn::ParseException(fmt::format("Pass ID [{}] is not correct format on CSV row {}", tokens[0], lineIndex)); } return passId; } armnn::LayerBindingId GetBindingIdFromCsvRow(std::vector tokens, unsigned int lineIndex) { armnn::LayerBindingId bindingId; try { bindingId = std::stoi(tokens[1]); } catch (const std::invalid_argument&) { throw armnn::ParseException(fmt::format("Binding ID [{}] is not correct format on CSV row {}", tokens[1], lineIndex)); } return bindingId; } std::string GetFileNameFromCsvRow(std::vector tokens, unsigned int lineIndex) { std::string fileName = armnn::stringUtils::StringTrim(tokens[2]); if (!fs::exists(fileName)) { throw armnn::ParseException(fmt::format("File [{}] provided on CSV row {} does not exist.", fileName, lineIndex)); } if (fileName.empty()) { throw armnn::ParseException(fmt::format("Filename cannot be empty on CSV row {} ", lineIndex)); } return fileName; } void QuantizationDataSet::ParseCsvFile() { std::map passIdToQuantizationInput; if (m_CsvFilePath == "") { throw armnn::Exception("CSV file not specified."); } std::ifstream inf (m_CsvFilePath.c_str()); std::string line; std::vector tokens; unsigned int lineIndex = 0; if (!inf) { throw armnn::Exception(fmt::format("CSV file {} not found.", m_CsvFilePath)); } while (getline(inf, line)) { tokens = armnn::stringUtils::StringTokenizer(line, ","); if (tokens.size() != 3) { throw armnn::Exception(fmt::format("CSV file [{}] does not have correct number of entries" \ "on line {}. Expected 3 entries but was {}.", m_CsvFilePath, lineIndex, tokens.size())); } unsigned int passId = GetPassIdFromCsvRow(tokens, lineIndex); armnn::LayerBindingId bindingId = GetBindingIdFromCsvRow(tokens, lineIndex); std::string rawFileName = GetFileNameFromCsvRow(tokens, lineIndex); AddInputData(passId, bindingId, rawFileName, passIdToQuantizationInput); ++lineIndex; } if (passIdToQuantizationInput.empty()) { throw armnn::Exception("Could not parse CSV file."); } // Once all entries in CSV file are parsed successfully and QuantizationInput map is populated, populate // QuantizationInputs iterator for easier access and clear the map for (auto itr = passIdToQuantizationInput.begin(); itr != passIdToQuantizationInput.end(); ++itr) { m_QuantizationInputs.emplace_back(itr->second); } } }