blob: 99fc021a514c4e9d7c7ae934b999c143243ba4c4 [file] [log] [blame]
//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//
#include "QuantizationDataSet.hpp"
#include <fmt/format.h>
#include <armnn/utility/StringUtils.hpp>
#include <armnn/utility/IgnoreUnused.hpp>
#include <Filesystem.hpp>
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<unsigned int, QuantizationInput>& 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<armnn::ConstTensor>& 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<std::string> tokens, unsigned int lineIndex)
{
unsigned int passId;
try
{
passId = static_cast<unsigned int>(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<std::string> 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<std::string> 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<unsigned int, QuantizationInput> passIdToQuantizationInput;
if (m_CsvFilePath == "")
{
throw armnn::Exception("CSV file not specified.");
}
std::ifstream inf (m_CsvFilePath.c_str());
std::string line;
std::vector<std::string> 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);
}
}
}