Loading a Model from a File (C++)

The following walkthrough is a C++ example demonstrating how to load a model from a file.

#include "rml/RadeonML.hpp"

#include <cstring>
#include <fstream>
#include <iostream>
#include <sstream>
#include <set>
#include <stdexcept>
#include <string>
#include <vector>

/*
 * Read input from file
 *
 * @param input_file - name of input file
 * @return - string content of file
 */
std::string ReadInput(const std::string& input_file)
{
        std::istream* input_stream;
        std::ifstream input_file_stream;

        if (input_file.empty())
        {
                freopen(nullptr, "rb", stdin);
                input_stream = &std::cin;
                std::cout << "Reading data from stdin...\n";
        }
        else
        {
                input_file_stream.open(input_file, std::ios_base::binary);
                if (input_file_stream.fail())
                {
                        throw std::runtime_error(std::string("Error reading ") + input_file);
                }
                input_stream = &input_file_stream;
                std::cout << "Reading data from file: " << input_file << "\n";
        }

        std::ostringstream stream;
        stream << input_stream->rdbuf();

        auto input = stream.str();
        std::cout << "Input data size: " << input.size() << " bytes\n";
        return input;
}

/*
 * Write output to file
 *
 * @param output_file - name of output file
 * @param output - output data
 */
void WriteOutput(const std::string& output_file, const std::string& output)
{
        std::cout << "Output data size: " << output.size() << " bytes\n";

        std::ostream* output_stream;
        std::ofstream output_file_stream;

        if (output_file.empty())
        {
                freopen(nullptr, "wb", stdout);
                output_stream = &std::cout;
                std::cout << "Writing result to stdout\n";
        }
        else
        {
                output_file_stream.open(output_file, std::ios_base::binary);
                if (output_file_stream.fail())
                {
                        throw std::runtime_error(std::string("Error writing ") + output_file);
                }
                output_stream = &output_file_stream;
                std::cout << "Writing result to file: " << output_file << "\n";
        }

        output_stream->write(output.data(), output.size());
}

int main() try
{
        // Create a context
        rml::Context context = rml::CreateDefaultContext();

        // Set model path
#if defined(_WIN32)
        std::wstring model_path(L"path/model");
#else
        std::string model_path("path/model");
#endif

        // Set input file
        const std::string input_file = "path/input";

        // Set output file
        const std::string output_file = "path/output";

        // Load model
        rml::Graph graph = rml::LoadGraphFromFile(model_path);
        rml::Model model = context.CreateModel(graph);

        // Get initial input tensor information
        std::vector<const char*> input_names = graph.GetInputNames();
        if (input_names.empty())
        {
                throw std::runtime_error("No model inputs were found");
        }

        // Set unspecified input tensor dimensions if required
        rml_tensor_info input_info = model.GetInputInfo(input_names[0]);
        if (input_info.layout == RML_LAYOUT_NHWC)
        {
                input_info.shape[0] = 1;
                input_info.shape[1] = 600;
                input_info.shape[2] = 800;
        }
        else if (input_info.layout == RML_LAYOUT_NCHW)
        {
                input_info.shape[0] = 1;
                input_info.shape[2] = 600;
                input_info.shape[3] = 800;
        }
        else
        {
                throw std::runtime_error("Only NCHW or NHWC data layout is supported");
        }
        model.SetInputInfo(input_names[0], input_info);

        // Create the input tensor
        // The handle is released automatically upon scope exit
        rml::Tensor input_tensor = context.CreateTensor(input_info, RML_ACCESS_MODE_WRITE_ONLY);
        input_tensor.Write(ReadInput(input_file));

        // Set up inputs
        model.SetInput(input_names[0], input_tensor);

        // Get output tensor information
        rml_tensor_info output_info = model.GetOutputInfo();

        // Create the output tensor
        // The handle is released automatically upon scope exit
        rml::Tensor output_tensor = context.CreateTensor(output_info, RML_ACCESS_MODE_READ_ONLY);

        // Set model output
        model.SetOutput(output_tensor);

        // Run inference
        model.Infer();

        // Get data from output tensor
        size_t output_size;
        void* output_data = output_tensor.Map(&output_size);

        // Unmap output data
        const std::string output(static_cast<char*>(output_data), output_size);
        output_tensor.Unmap(output_data);

        // Write the output
        WriteOutput(output_file, output);
}
catch (const std::exception& e)
{
        std::cerr << e.what() << std::endl;
        return 1;
}