/* * SPDX-FileCopyrightText: Copyright (c) 1993-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * * 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. */ #include #include #include #include #include #include #include #include #include #include #include "NvInfer.h" #include "logger.h" #include "sampleOptions.h" #include "sampleUtils.h" using namespace nvinfer1; namespace sample { namespace { using namespace std::string_view_literals; std::map> const kUNIT_MULTIPLIERS{ {'B', {1LL, "Bytes"}}, {'K', {1LL << 10, "Kibibytes"}}, {'M', {1LL << 20, "Mebibytes"}}, {'G', {1LL << 30, "Gibibytes"}}, }; std::string addDefaultUnitSuffixIfNotSpecified(std::string const& option, char defaultUnit) { char lastChar = option.at(option.size() - 1); return std::isdigit(lastChar) ? option + defaultUnit : option; } // Returns "B (Bytes), K (Kilobytes), ..." std::string getAvailableUnitSuffixes() { std::ostringstream ss; for (auto it = kUNIT_MULTIPLIERS.begin(); it != kUNIT_MULTIPLIERS.end(); ++it) { if (it != kUNIT_MULTIPLIERS.begin()) { ss << ", "; } ss << it->first << " (" << it->second.second << ")"; } return ss.str(); } // Numeric trtexec arguments can have unit specifiers in similar to polygraphy. // E.g. --weightStreamingBudget=20M would be 20 Mebibytes (base 2). int64_t getUnitMultiplier(std::string const& option) { char lastChar = option.at(option.size() - 1); if (!std::isdigit(lastChar)) { char unit = std::toupper(lastChar); auto found = kUNIT_MULTIPLIERS.find(unit); if (found == kUNIT_MULTIPLIERS.end()) { std::ostringstream ss; ss << "Error parsing \"" << option << "\": invalid unit specifier '" << unit << "'. Valid base-2 unit suffixes include: "; ss << getAvailableUnitSuffixes() << "."; throw std::invalid_argument(ss.str()); } return found->second.first; } // Return bytes by default return kUNIT_MULTIPLIERS.at('B').first; } template T stringToValue(std::string const& option) { return T{option}; } template <> int32_t stringToValue(std::string const& option) { return std::stoi(option); } template <> int64_t stringToValue(std::string const& option) { return std::stoi(option); } template <> size_t stringToValue(std::string const& option) { return std::stoi(option) * getUnitMultiplier(option); } template <> float stringToValue(std::string const& option) { return std::stof(option); } template <> double stringToValue(std::string const& option) { return std::stod(option) * getUnitMultiplier(option); } template <> bool stringToValue(std::string const& option) { return true; } template <> std::vector stringToValue>(std::string const& option) { std::vector shape; if (option == "scalar") { return shape; } std::vector dimsStrings = splitToStringVec(option, 'x'); for (auto const& d : dimsStrings) { shape.push_back(stringToValue(d)); } return shape; } template <> nvinfer1::DeviceType stringToValue(std::string const& option) { std::unordered_map const strToDevice = { {"GPU", nvinfer1::DeviceType::kGPU}, {"DLA", nvinfer1::DeviceType::kDLA}, }; auto const& device = strToDevice.find(option); if (device == strToDevice.end()) { throw std::invalid_argument("Invalid Device Type " + option); } return device->second; } template <> nvinfer1::TensorFormats stringToValue(std::string const& option) { std::vector optionStrings = splitToStringVec(option, '+'); const std::unordered_map strToFmt{{"chw", nvinfer1::TensorFormat::kLINEAR}, {"chw2", nvinfer1::TensorFormat::kCHW2}, {"chw4", nvinfer1::TensorFormat::kCHW4}, {"hwc8", nvinfer1::TensorFormat::kHWC8}, {"chw16", nvinfer1::TensorFormat::kCHW16}, {"chw32", nvinfer1::TensorFormat::kCHW32}, {"dhwc8", nvinfer1::TensorFormat::kDHWC8}, {"cdhw32", nvinfer1::TensorFormat::kCDHW32}, {"hwc", nvinfer1::TensorFormat::kHWC}, {"dhwc", nvinfer1::TensorFormat::kDHWC}, {"dla_linear", nvinfer1::TensorFormat::kDLA_LINEAR}, {"hwc16", nvinfer1::TensorFormat::kHWC16}, {"dla_hwc4", nvinfer1::TensorFormat::kDLA_HWC4}}; nvinfer1::TensorFormats formats{}; for (auto f : optionStrings) { auto const& tf = strToFmt.find(f); if (tf == strToFmt.end()) { throw std::invalid_argument(std::string("Invalid TensorFormat ") + f); } formats |= 1U << static_cast(tf->second); } return formats; } template <> IOFormat stringToValue(std::string const& option) { return IOFormat{stringToValue(option)}; } template <> SparsityFlag stringToValue(std::string const& option) { std::unordered_map const table{ {"disable", SparsityFlag::kDISABLE}, {"enable", SparsityFlag::kENABLE}, { "force", SparsityFlag::kFORCE } }; auto search = table.find(option); if (search == table.end()) { throw std::invalid_argument(std::string("Unknown sparsity mode: ") + option); } if (search->second == SparsityFlag::kFORCE) { sample::gLogWarning << "--sparsity=force has been deprecated. " << "Please use to rewrite the weights to a sparsity pattern " << "and then run with --sparsity=enable" << std::endl; } return search->second; } template <> WeightStreamingBudget stringToValue(std::string const& option) { WeightStreamingBudget budget; if (option.find('%') != std::string::npos) { double percent = std::stod(option); if (!(percent >= 0 && percent <= 100.0)) { std::ostringstream err; err << "The weight streaming percent must be between 0 and 100."; throw std::invalid_argument(err.str()); } budget.percent = percent; } else { double bytes = stringToValue(option); if (!(bytes == WeightStreamingBudget::kAUTOMATIC || bytes == WeightStreamingBudget::kDISABLE || bytes >= 0)) { std::ostringstream err; err << "The weight streaming budget must be " << WeightStreamingBudget::kDISABLE << ", " << WeightStreamingBudget::kAUTOMATIC << ", or at least 0."; throw std::invalid_argument(err.str()); } budget.bytes = static_cast(bytes); } return budget; } #if ENABLE_UNIFIED_BUILDER template <> samplesSafeCommon::SafetyPluginLibraryArgument stringToValue( std::string const& option) { samplesSafeCommon::SafetyPluginLibraryArgument argument; auto status = parseSafetyPluginArgument(option, argument); if (!status) { throw std::invalid_argument(std::string("Invalid Safety plugin library option: " + option)); } return argument; } #endif template std::pair splitNameAndValue(std::string const& s) { std::string tensorName; std::string valueString; // Support 'inputName':Path format for --loadInputs flag when dealing with Windows paths. // i.e. 'inputName':c:\inputData std::vector quoteNameRange{splitToStringVec(s, '\'')}; // splitToStringVec returns the entire string when delimiter is not found, so it's size is always at least 1 if (quoteNameRange.size() != 1) { if (quoteNameRange.size() != 3) { std::string errorMsg = std::string("Found invalid number of \'s when parsing ") + s + std::string(". Expected: 2, received: ") + std::to_string(quoteNameRange.size() -1) + ". Please ensure that a singular comma is used within each comma-separated key-value pair for options like --inputIOFormats, --optShapes, etc."; throw std::invalid_argument(errorMsg); } // Everything before the second "'" is the name. tensorName = quoteNameRange[0] + quoteNameRange[1]; // Path is the last string - ignoring leading ":" so slice it with [1:] valueString = quoteNameRange[2].substr(1); return std::pair(tensorName, stringToValue(valueString)); } // Split on the last : std::vector nameRange{splitToStringVec(s, ':')}; // Everything before the last : is the name tensorName = nameRange[0]; for (size_t i = 1; i < nameRange.size() - 1; i++) { tensorName += ":" + nameRange[i]; } // Value is the string element after the last : valueString = nameRange[nameRange.size() - 1]; return std::pair(tensorName, stringToValue(valueString)); } template void splitInsertKeyValue(std::vector const& kvList, T& map) { for (auto const& kv : kvList) { map.insert(splitNameAndValue(kv)); } } char const* boolToEnabled(bool enable) { return enable ? "Enabled" : "Disabled"; } //! A helper function similar to sep.join(list) in Python. template std::string joinValuesToString(std::vector const& list, std::string const& sep) { std::ostringstream os; for (int32_t i = 0, n = list.size(); i < n; ++i) { os << list[i]; if (i != n - 1) { os << sep; } } return os.str(); } template std::string joinValuesToString(std::array const& list, std::string const& sep) { return joinValuesToString(std::vector(list.begin(), list.end()), sep); } //! Check if input option exists in input arguments. //! If it does: set its value, and return true //! If it does not: return false. template bool getOption(Arguments& arguments, std::string const& option, T& value) { auto const match = arguments.find(option); if (match != arguments.end()) { value = stringToValue(match->second.first); return true; } return false; } //! Check if input option exists in input arguments. //! If it does: set its value, erase the argument and return true. //! If it does not: return false. template bool getAndDelOption(Arguments& arguments, std::string const& option, T& value) { bool found = getOption(arguments, option, value); if (found) { auto const match = arguments.find(option); arguments.erase(match); } return found; } //! Check if input option exists in input arguments. //! If it does: set its value and position, erase the argument and return true. //! If it does not: return false. template bool getAndDelOptionWithPosition(Arguments& arguments, std::string const& option, T& value, int32_t& pos) { auto const match = arguments.find(option); if (match != arguments.end()) { value = stringToValue(match->second.first); pos = match->second.second; arguments.erase(match); return true; } return false; } //! Check if input option exists in input arguments behind the position spcecified by pos. //! If it does: set its value, erase the argument and return true. //! If it does not: return false. template bool getAndDelOptionBehind(Arguments& arguments, std::string const& option, int32_t pos, T& value) { auto const match = arguments.equal_range(option); if (match.first == match.second) { return false; } for (auto i = match.first; i != match.second; ++i) { if (i->second.second - pos == 1) { value = stringToValue(i->second.first); arguments.erase(i); return true; } } return false; } //! Check if input option exists in input arguments. //! If it does: set false in value, erase the argument and return true. //! If it does not: return false. bool getAndDelNegOption(Arguments& arguments, std::string const& option, bool& value) { bool dummy; if (getAndDelOption(arguments, option, dummy)) { value = false; return true; } return false; } //! Check if input option exists in input arguments. //! If it does: add all the matched arg values to values vector, erase the argument and return true. //! If it does not: return false. template bool getAndDelRepeatedOption(Arguments& arguments, std::string const& option, std::vector& values) { auto const match = arguments.equal_range(option); if (match.first == match.second) { return false; } auto addToValues = [&values](Arguments::value_type& argValue) { values.emplace_back(stringToValue(argValue.second.first)); }; std::for_each(match.first, match.second, addToValues); arguments.erase(match.first, match.second); return true; } void insertShapesBuild(BuildOptions::ShapeProfile& shapes, nvinfer1::OptProfileSelector selector, std::string const& name, std::vector const& dims) { shapes[name][static_cast(selector)] = dims; } void insertShapesInference( InferenceOptions::ShapeProfile& shapes, std::string const& name, std::vector const& dims) { shapes[name] = dims; } std::string removeSingleQuotationMarks(std::string& str) { std::vector strList{splitToStringVec(str, '\'')}; // Remove all the escaped single quotation marks std::string retVal; // Do not really care about unterminated sequences for (size_t i = 0; i < strList.size(); i++) { retVal += strList[i]; } return retVal; } void getLayerDeviceTypes(Arguments& arguments, char const* argument, LayerDeviceTypes& layerDeviceTypes) { std::string list; if (!getAndDelOption(arguments, argument, list)) { return; } // The layerDeviceTypes flag contains comma-separated layerName:deviceType pairs. std::vector deviceList{splitToStringVec(list, ',')}; for (auto const& s : deviceList) { auto nameDevicePair = splitNameAndValue(s); auto const layerName = removeSingleQuotationMarks(nameDevicePair.first); layerDeviceTypes[layerName] = stringToValue(nameDevicePair.second); } } void getDecomposableAttentions( Arguments& arguments, char const* argument, DecomposableAttentions& decomposableAttentions) { std::string list; if (!getAndDelOption(arguments, argument, list)) { return; } std::vector attentionList{splitToStringVec(list, ',')}; for (auto& s : attentionList) { auto const attentionName = removeSingleQuotationMarks(s); decomposableAttentions[attentionName] = true; } } void getAndDelStringsSet(Arguments& arguments, char const* argument, StringSet& stringSet) { std::string list; if (!getAndDelOption(arguments, argument, list)) { return; } // The layerPrecisions flag contains comma-separated layerName:precision pairs. std::vector strings{splitToStringVec(list, ',')}; for (auto const& s : strings) { stringSet.insert(s); } } bool getShapesBuild(Arguments& arguments, BuildOptions::ShapeProfile& shapes, char const* argument, nvinfer1::OptProfileSelector selector) { std::string list; bool retVal = getAndDelOption(arguments, argument, list); std::vector shapeList{splitToStringVec(list, ',')}; for (auto const& s : shapeList) { auto nameDimsPair = splitNameAndValue>(s); auto tensorName = removeSingleQuotationMarks(nameDimsPair.first); auto dims = nameDimsPair.second; insertShapesBuild(shapes, selector, tensorName, dims); } return retVal; } bool getShapesInference(Arguments& arguments, InferenceOptions::ShapeProfile& shapes, char const* argument) { std::string list; bool retVal = getAndDelOption(arguments, argument, list); std::vector shapeList{splitToStringVec(list, ',')}; for (auto const& s : shapeList) { auto nameDimsPair = splitNameAndValue>(s); auto tensorName = removeSingleQuotationMarks(nameDimsPair.first); auto dims = nameDimsPair.second; insertShapesInference(shapes, tensorName, dims); } return retVal; } void fillShapes(BuildOptions::ShapeProfile& shapes, std::string const& name, ShapeRange const& sourceShapeRange, nvinfer1::OptProfileSelector minDimsSource, nvinfer1::OptProfileSelector optDimsSource, nvinfer1::OptProfileSelector maxDimsSource) { insertShapesBuild( shapes, nvinfer1::OptProfileSelector::kMIN, name, sourceShapeRange[static_cast(minDimsSource)]); insertShapesBuild( shapes, nvinfer1::OptProfileSelector::kOPT, name, sourceShapeRange[static_cast(optDimsSource)]); insertShapesBuild( shapes, nvinfer1::OptProfileSelector::kMAX, name, sourceShapeRange[static_cast(maxDimsSource)]); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) void processShapes(BuildOptions::ShapeProfile& shapes, bool minShapes, bool optShapes, bool maxShapes) { if (!minShapes && !optShapes && !maxShapes) { return; } BuildOptions::ShapeProfile newShapes; for (auto& s : shapes) { nvinfer1::OptProfileSelector minDimsSource, optDimsSource, maxDimsSource; minDimsSource = nvinfer1::OptProfileSelector::kMIN; optDimsSource = nvinfer1::OptProfileSelector::kOPT; maxDimsSource = nvinfer1::OptProfileSelector::kMAX; // Populate missing minShapes if (!minShapes) { if (optShapes) { minDimsSource = optDimsSource; sample::gLogWarning << "optShapes is being broadcasted to minShapes for tensor " << s.first << std::endl; } else { minDimsSource = maxDimsSource; sample::gLogWarning << "maxShapes is being broadcasted to minShapes for tensor " << s.first << std::endl; } } // Populate missing optShapes if (!optShapes) { if (maxShapes) { optDimsSource = maxDimsSource; sample::gLogWarning << "maxShapes is being broadcasted to optShapes for tensor " << s.first << std::endl; } else { optDimsSource = minDimsSource; sample::gLogWarning << "minShapes is being broadcasted to optShapes for tensor " << s.first << std::endl; } } // Populate missing maxShapes if (!maxShapes) { if (optShapes) { maxDimsSource = optDimsSource; sample::gLogWarning << "optShapes is being broadcasted to maxShapes for tensor " << s.first << std::endl; } else { maxDimsSource = minDimsSource; sample::gLogWarning << "minShapes is being broadcasted to maxShapes for tensor " << s.first << std::endl; } } fillShapes(newShapes, s.first, s.second, minDimsSource, optDimsSource, maxDimsSource); } shapes = newShapes; } bool getOptimizationProfiles( Arguments& arguments, std::vector& optProfiles, char const* argument) { bool retValue{false}; int32_t pos{}; size_t profileIndex{}; auto getShapes = [](BuildOptions::ShapeProfile& shapes, std::string const& list, nvinfer1::OptProfileSelector selector) { std::vector shapeList{splitToStringVec(list, ',')}; for (auto const& s : shapeList) { auto nameDimsPair = splitNameAndValue>(s); auto tensorName = removeSingleQuotationMarks(nameDimsPair.first); auto dims = nameDimsPair.second; insertShapesBuild(shapes, selector, tensorName, dims); } }; while (getAndDelOptionWithPosition(arguments, argument, profileIndex, pos)) { BuildOptions::ShapeProfile optProfile{}; bool minShapes{false}, maxShapes{false}, optShapes{false}; for (int32_t i = 0; i < nvinfer1::EnumMax(); i++, pos++) { std::string value; if (!minShapes && getAndDelOptionBehind(arguments, "--minShapes", pos, value)) { minShapes = true; getShapes(optProfile, value, nvinfer1::OptProfileSelector::kMIN); } else if (!maxShapes && getAndDelOptionBehind(arguments, "--maxShapes", pos, value)) { maxShapes = true; getShapes(optProfile, value, nvinfer1::OptProfileSelector::kMAX); } else if (!optShapes && getAndDelOptionBehind(arguments, "--optShapes", pos, value)) { optShapes = true; getShapes(optProfile, value, nvinfer1::OptProfileSelector::kOPT); } else { break; } } processShapes(optProfile, minShapes, optShapes, maxShapes); if (profileIndex >= optProfiles.size()) { optProfiles.resize(profileIndex + 1); } if (!optProfiles[profileIndex].empty()) { throw std::invalid_argument("Optimization profile index cannot be the same."); } optProfiles[profileIndex] = optProfile; retValue = true; } profileIndex = 0; for (auto const& optProfile : optProfiles) { if (optProfile.empty()) { throw std::invalid_argument(std::string("Found invalid or missing shape spec at profile index ") + std::to_string(profileIndex) + std::string(". ")); } ++profileIndex; } return retValue; } // Helper function to output a map as "name1:file1, name2:file2, ..." std::string mapToString(std::unordered_map const& m) { std::string result; char const* delim = ""; for (auto const& kv : m) { result += delim; delim = ", "; result += kv.first + ":" + kv.second; } return result; } // NOLINTNEXTLINE(readability-function-cognitive-complexity) bool getRefPairs(Arguments& arguments, std::vector& refPairs) { bool retValue{false}; int32_t pos{}; constexpr int32_t kNUM_REF_PAIR_FOLLOW_OPTIONS = 2; // Number of options that can follow --refPair: --loadInputs and --loadRefOutputs size_t pairIndex{}; auto parseIntoMap = [](std::string const& value, std::unordered_map& map) { std::vector kvList{splitToStringVec(value, ',')}; splitInsertKeyValue(kvList, map); }; while (getAndDelOptionWithPosition(arguments, "--refPair", pairIndex, pos)) { InferenceOptions::RefPair pair; for (int32_t i = 0; i < kNUM_REF_PAIR_FOLLOW_OPTIONS; ++i, ++pos) { std::string value; if (getAndDelOptionBehind(arguments, "--loadInputs", pos, value)) { parseIntoMap(value, pair.first); // Parse into input map } else if (getAndDelOptionBehind(arguments, "--loadRefOutputs", pos, value)) { parseIntoMap(value, pair.second); // Parse into output map } else { break; } } if (pairIndex >= refPairs.size()) { refPairs.resize(pairIndex + 1); } if (!refPairs[pairIndex].first.empty() || !refPairs[pairIndex].second.empty()) { throw std::invalid_argument("Reference pair index cannot be the same."); } refPairs[pairIndex] = pair; retValue = true; } // Validate refPairs when --refPair is used if (retValue) { // Rule: Need at least 2 pairs when using --refPair if (refPairs.size() < 2) { throw std::invalid_argument("When using --refPair, you need at least two pairs of I/O."); } size_t idx = 0; for (auto const& pair : refPairs) { // Rule: Each pair must have both --loadInputs and --loadRefOutputs if (pair.first.empty()) { throw std::invalid_argument(std::string("Missing --loadInputs for reference pair at index ") + std::to_string(idx) + std::string(". Each --refPair must have both --loadInputs and --loadRefOutputs.")); } if (pair.second.empty()) { throw std::invalid_argument(std::string("Missing --loadRefOutputs for reference pair at index ") + std::to_string(idx) + std::string(". Each --refPair must have both --loadInputs and --loadRefOutputs.")); } ++idx; } // Output parsed refPairs for verification sample::gLogVerbose << "Parsed refPairs:" << std::endl; for (size_t i = 0; i < refPairs.size(); ++i) { sample::gLogVerbose << " refPair[" << i << "]:" << std::endl; sample::gLogVerbose << " loadInputs: {" << mapToString(refPairs[i].first) << "}" << std::endl; sample::gLogVerbose << " loadRefOutputs: {" << mapToString(refPairs[i].second) << "}" << std::endl; } } return retValue; } template void printShapes(std::ostream& os, char const* phase, T const& shapes, int32_t profileIndex) { using namespace std::string_view_literals; if (shapes.empty()) { os << "Input " << phase << " shapes: model" << std::endl; } else { std::string profileString = (profileIndex != -1 && phase == "build"sv) ? "(profile " + std::to_string(profileIndex) + ")" : ""; for (auto const& s : shapes) { os << "Input " << phase << " shape " << profileString << ": " << s.first << "=" << s.second << std::endl; } } } std::ostream& printTacticSources( std::ostream& os, nvinfer1::TacticSources enabledSources, nvinfer1::TacticSources disabledSources) { if (!enabledSources && !disabledSources) { os << "Using default tactic sources"; } else { auto const addSource = [&](uint32_t source, std::string const& name) { if (enabledSources & source) { os << name << " [ON], "; } else if (disabledSources & source) { os << name << " [OFF], "; } }; addSource( 1U << static_cast(nvinfer1::TacticSource::kEDGE_MASK_CONVOLUTIONS), "edge mask convolutions"); addSource(1U << static_cast(nvinfer1::TacticSource::kJIT_CONVOLUTIONS), "JIT convolutions"); } return os; } std::ostream& printPrecision(std::ostream& os, BuildOptions const& options) { os << "Strongly Typed"; return os; } std::ostream& printTempfileControls(std::ostream& os, TempfileControlFlags const tempfileControls) { auto getFlag = [&](TempfileControlFlag f) -> char const* { bool allowed = !!(tempfileControls & (1U << static_cast(f))); return allowed ? "allow" : "deny"; }; auto const inMemory = getFlag(TempfileControlFlag::kALLOW_IN_MEMORY_FILES); auto const temporary = getFlag(TempfileControlFlag::kALLOW_TEMPORARY_FILES); os << "{ in_memory: " << inMemory << ", temporary: " << temporary << " }"; return os; } std::ostream& printTimingCache(std::ostream& os, TimingCacheMode const& timingCacheMode) { switch (timingCacheMode) { case TimingCacheMode::kGLOBAL: os << "global"; break; case TimingCacheMode::kLOCAL: os << "local"; break; case TimingCacheMode::kDISABLE: os << "disable"; break; } return os; } std::ostream& printSparsity(std::ostream& os, BuildOptions const& options) { switch (options.sparsity) { case SparsityFlag::kDISABLE: os << "Disabled"; break; case SparsityFlag::kENABLE: os << "Enabled"; break; case SparsityFlag::kFORCE: os << "Forced"; break; } return os; } std::ostream& printMemoryPools(std::ostream& os, BuildOptions const& options) { auto const printValueOrDefault = [&os](double const val, char const* unit = "MiB") { if (val >= 0) { os << val << " " << unit; } else { os << "default"; } }; os << "workspace: "; printValueOrDefault(options.workspace); os << ", "; os << "dlaSRAM: "; printValueOrDefault(options.dlaSRAM); os << ", "; os << "dlaLocalDRAM: "; printValueOrDefault(options.dlaLocalDRAM); os << ", "; os << "dlaGlobalDRAM: "; printValueOrDefault(options.dlaGlobalDRAM); os << ", "; os << "tacticSharedMem: "; printValueOrDefault(options.tacticSharedMem, "KiB"); return os; } std::string previewFeatureToString(PreviewFeature feature) { // clang-format off switch (feature) { case PreviewFeature::kALIASED_PLUGIN_IO_10_03: return "kALIASED_PLUGIN_IO_10_03"; case PreviewFeature::kRUNTIME_ACTIVATION_RESIZE_10_10: return "kRUNTIME_ACTIVATION_RESIZE_10_10"; } return "Invalid Preview Feature"; // clang-format on } std::ostream& printPreviewFlags(std::ostream& os, BuildOptions const& options) { if (options.previewFeatures.empty()) { os << "Use default preview flags."; return os; } auto const addFlag = [&](PreviewFeature feat) { int32_t featVal = static_cast(feat); if (options.previewFeatures.find(featVal) != options.previewFeatures.end()) { os << previewFeatureToString(feat) << (options.previewFeatures.at(featVal) ? " [ON], " : " [OFF], "); } }; addFlag(PreviewFeature::kALIASED_PLUGIN_IO_10_03); addFlag(PreviewFeature::kRUNTIME_ACTIVATION_RESIZE_10_10); return os; } } // namespace Arguments argsToArgumentsMap(int32_t argc, char* argv[]) { Arguments arguments; for (int32_t i = 1; i < argc; ++i) { auto valuePtr = strchr(argv[i], '='); if (valuePtr) { std::string value{valuePtr + 1}; arguments.emplace(std::string(argv[i], valuePtr - argv[i]), std::make_pair(value, i)); } else { arguments.emplace(argv[i], std::make_pair(std::string(""), i)); } } return arguments; } namespace { std::string resolveHomeDirectoryOnLinux(std::string const& model) { std::string filePath{model}; #ifndef _WIN32 if (filePath[0] == '~') { char const* home = std::getenv("HOME"); if (home) { filePath.replace(0, 1, home); } } #endif return filePath; } } // namespace void BaseModelOptions::parse(Arguments& arguments) { if (getAndDelOption(arguments, "--onnx", model)) { format = ModelFormat::kONNX; model = resolveHomeDirectoryOnLinux(model); } } void ModelOptions::parse(Arguments& arguments) { baseModel.parse(arguments); switch (baseModel.format) { case ModelFormat::kONNX: case ModelFormat::kANY: { break; } } if (baseModel.format == ModelFormat::kONNX) { if (!outputs.empty()) { throw std::invalid_argument("The --output flag should not be used with ONNX models."); } } } void getTempfileControls(Arguments& arguments, char const* argument, TempfileControlFlags& tempfileControls) { std::string list; if (!getAndDelOption(arguments, argument, list)) { return; } std::vector controlList{splitToStringVec(list, ',')}; for (auto const& s : controlList) { auto const [control, allow] = splitNameAndValue(s); if (!(allow == "allow"sv || allow == "deny"sv)) { throw std::invalid_argument("--tempfileControls value should be `deny` or `allow`"); } if (!(control == "in_memory"sv || control == "temporary"sv)) { throw std::invalid_argument(std::string{"Unknown --tempfileControls key "} + control); } bool const allowed = (allow == "allow"sv); int32_t const offset = (control == "in_memory"sv) ? static_cast(TempfileControlFlag::kALLOW_IN_MEMORY_FILES) : static_cast(TempfileControlFlag::kALLOW_TEMPORARY_FILES); if (allowed) { tempfileControls |= (1U << offset); } else { tempfileControls &= ~(1U << offset); } } } // NOLINTNEXTLINE(readability-function-cognitive-complexity,readability-function-size) void BuildOptions::parse(Arguments& arguments) { getAndDelOption(arguments, "--cpuOnly", cpuOnly); auto getFormats = [&arguments](std::vector& formatsVector, char const* argument) { std::string list; getAndDelOption(arguments, argument, list); std::vector formats{splitToStringVec(list, ',')}; for (const auto& f : formats) { formatsVector.push_back(stringToValue(f)); } }; getFormats(inputFormats, "--inputIOFormats"); getFormats(outputFormats, "--outputIOFormats"); if (!getOptimizationProfiles(arguments, optProfiles, "--profile")) { ShapeProfile shapes; bool minShapes{false}, optShapes{false}, maxShapes{false}; try { minShapes = getShapesBuild(arguments, shapes, "--minShapes", nvinfer1::OptProfileSelector::kMIN); optShapes = getShapesBuild(arguments, shapes, "--optShapes", nvinfer1::OptProfileSelector::kOPT); maxShapes = getShapesBuild(arguments, shapes, "--maxShapes", nvinfer1::OptProfileSelector::kMAX); } catch (std::invalid_argument const& arg) { throw std::invalid_argument(arg.what() + std::string(" conversion failure: failed to parse minShapes/optShapes/maxShapes. Please double check " "your input string.")); } processShapes(shapes, minShapes, optShapes, maxShapes); optProfiles.emplace_back(shapes); } BuildOptions::ShapeProfile dummyShapes; bool remainingMinShapes = getShapesBuild(arguments, dummyShapes, "--minShapes", nvinfer1::OptProfileSelector::kMIN); bool remainingOptShapes = getShapesBuild(arguments, dummyShapes, "--optShapes", nvinfer1::OptProfileSelector::kOPT); bool remainingMaxShapes = getShapesBuild(arguments, dummyShapes, "--maxShapes", nvinfer1::OptProfileSelector::kMAX); if (remainingMinShapes || remainingOptShapes || remainingMaxShapes) { throw std::invalid_argument("Multiple --minShapes/--optShapes/--maxShapes without --profile are not allowed. "); } std::string memPoolSizes; getAndDelOption(arguments, "--memPoolSize", memPoolSizes); std::vector memPoolSpecs{splitToStringVec(memPoolSizes, ',')}; for (auto const& memPoolSpec : memPoolSpecs) { std::string memPoolName; double memPoolSize; try { std::string strPoolSize; std::tie(memPoolName, strPoolSize) = splitNameAndValue(memPoolSpec); memPoolSize = stringToValue(addDefaultUnitSuffixIfNotSpecified(strPoolSize, 'M')); } catch (std::invalid_argument const& arg) { throw std::invalid_argument(arg.what() + std::string( " conversion failure: failed to parse --memPoolSize. Please double check your input string.")); } if (memPoolSize < 0) { throw std::invalid_argument(std::string("Negative memory pool size: ") + std::to_string(memPoolSize)); } if (memPoolName == "workspace") { // use unit in MB. workspace = memPoolSize / 1.0_MiB; } else if (memPoolName == "dlaSRAM") { // use unit in MB. dlaSRAM = memPoolSize / 1.0_MiB; } else if (memPoolName == "dlaLocalDRAM") { // use unit in MB. dlaLocalDRAM = memPoolSize / 1.0_MiB; } else if (memPoolName == "dlaGlobalDRAM") { // use unit in MB. dlaGlobalDRAM = memPoolSize / 1.0_MiB; } else if (memPoolName == "tacticSharedMem") { // use unit in KB. tacticSharedMem = memPoolSize / 1.0_KiB; } else if (!memPoolName.empty()) { throw std::invalid_argument(std::string("Unknown memory pool: ") + memPoolName); } } getAndDelOption(arguments, "--avgTiming", avgTiming); getAndDelOption(arguments, "--refit", refittable); getAndDelOption(arguments, "--stripWeights", stripWeights); bool stripAllWeights{}; getAndDelOption(arguments, "--stripAllWeights", stripAllWeights); if (stripAllWeights) { refittable = true; stripWeights = true; } // --vc and --versionCompatible are synonyms getAndDelOption(arguments, "--vc", versionCompatible); if (!versionCompatible) { getAndDelOption(arguments, "--versionCompatible", versionCompatible); } // --pi and --pluginInstanceNorm are synonyms getAndDelOption(arguments, "--pi", pluginInstanceNorm); if (!pluginInstanceNorm) { getAndDelOption(arguments, "--pluginInstanceNorm", pluginInstanceNorm); } getAndDelOption(arguments, "--uint8AsymmetricQuantizationDLA", enableUInt8AsymmetricQuantizationDLA); getAndDelOption(arguments, "--reportCapabilityDLA", reportCapabilityDLA); getAndDelOption(arguments, "--adjustForDLA", adjustForDLA); getAndDelOption(arguments, "--enablePluginOverride", enablePluginOverride); getAndDelOption(arguments, "--excludeLeanRuntime", excludeLeanRuntime); getAndDelOption(arguments, "--noCompilationCache", disableCompilationCache); getAndDelOption(arguments, "--monitorMemory", enableMonitorMemory); getAndDelNegOption(arguments, "--noTF32", tf32); getAndDelOption(arguments, "--stronglyTyped", stronglyTyped); getAndDelOption(arguments, "--distributiveIndependence", distributiveIndependence); getAndDelOption(arguments, "--safe", safe); getAndDelOption(arguments, "--dumpKernelText", dumpKernelText); if (dumpKernelText && !safe) { throw std::invalid_argument("--dumpKernelText requires --safe to be enabled."); } getAndDelOption(arguments, "--buildDLAStandalone", buildDLAStandalone); getAndDelOption(arguments, "--allowGPUFallback", allowGPUFallback); getAndDelOption(arguments, "--consistency", consistency); getAndDelOption(arguments, "--skipInference", skipInference); if (getAndDelOption(arguments, "--directIO", directIO)) { sample::gLogWarning << "--directIO flag has been deprecated" << std::endl; } getLayerDeviceTypes(arguments, "--layerDeviceTypes", layerDeviceTypes); getDecomposableAttentions(arguments, "--decomposableAttentions", decomposableAttentions); getAndDelStringsSet(arguments, "--markDebug", debugTensors); getAndDelOption(arguments, "--markUnfusedTensorsAsDebugTensors", markUnfusedTensorsAsDebugTensors); getAndDelOption(arguments, "--sparsity", sparsity); std::string profilingVerbosityString; getAndDelOption(arguments, "--profilingVerbosity", profilingVerbosityString); if (profilingVerbosityString == "layer_names_only") { profilingVerbosity = nvinfer1::ProfilingVerbosity::kLAYER_NAMES_ONLY; } else if (profilingVerbosityString == "none") { profilingVerbosity = nvinfer1::ProfilingVerbosity::kNONE; } else if (profilingVerbosityString == "detailed") { profilingVerbosity = nvinfer1::ProfilingVerbosity::kDETAILED; } else if (profilingVerbosityString == "default") { sample::gLogWarning << "--profilingVerbosity=default has been deprecated by " "--profilingVerbosity=layer_names_only." << std::endl; profilingVerbosity = nvinfer1::ProfilingVerbosity::kLAYER_NAMES_ONLY; } else if (profilingVerbosityString == "verbose") { sample::gLogWarning << "--profilingVerbosity=verbose has been deprecated by --profilingVerbosity=detailed." << std::endl; profilingVerbosity = nvinfer1::ProfilingVerbosity::kDETAILED; } else if (!profilingVerbosityString.empty()) { throw std::invalid_argument(std::string("Unknown profilingVerbosity: ") + profilingVerbosityString); } if (getAndDelOption(arguments, "--loadEngine", engine)) { load = true; } getAndDelOption(arguments, "--asyncFileReader", asyncFileReader); getAndDelOption(arguments, "--getPlanVersionOnly", getPlanVersionOnly); if (getAndDelOption(arguments, "--saveEngine", engine)) { save = true; } getAndDelOption(arguments, "--saveAllEngines", saveAllEngines); if (load && save) { throw std::invalid_argument("Incompatible load and save engine options selected"); } if (saveAllEngines && !save) { throw std::invalid_argument("--saveAllEngines requires --saveEngine to be specified."); } std::string tacticSourceArgs; if (getAndDelOption(arguments, "--tacticSources", tacticSourceArgs)) { std::vector tacticList = splitToStringVec(tacticSourceArgs, ','); for (auto& t : tacticList) { bool enable{false}; if (t.front() == '+') { enable = true; } else if (t.front() != '-') { throw std::invalid_argument( "Tactic source must be prefixed with + or -, indicating whether it should be enabled or disabled " "respectively."); } t.erase(0, 1); auto const toUpper = [](std::string& sourceName) { std::transform( sourceName.begin(), sourceName.end(), sourceName.begin(), [](char c) { return std::toupper(c); }); return sourceName; }; nvinfer1::TacticSource source{}; t = toUpper(t); if (t == "EDGE_MASK_CONVOLUTIONS") { source = nvinfer1::TacticSource::kEDGE_MASK_CONVOLUTIONS; } else if (t == "JIT_CONVOLUTIONS") { source = nvinfer1::TacticSource::kJIT_CONVOLUTIONS; } else { throw std::invalid_argument(std::string("Unknown tactic source: ") + t); } uint32_t sourceBit = 1U << static_cast(source); if (enable) { enabledTactics |= sourceBit; } else { disabledTactics |= sourceBit; } if (enabledTactics & disabledTactics) { throw std::invalid_argument(std::string("Cannot enable and disable ") + t); } } } bool noBuilderCache{false}; getAndDelOption(arguments, "--noBuilderCache", noBuilderCache); getAndDelOption(arguments, "--timingCacheFile", timingCacheFile); if (noBuilderCache) { timingCacheMode = TimingCacheMode::kDISABLE; } else if (!timingCacheFile.empty()) { timingCacheMode = TimingCacheMode::kGLOBAL; } else { timingCacheMode = TimingCacheMode::kLOCAL; } getAndDelOption(arguments, "--errorOnTimingCacheMiss", errorOnTimingCacheMiss); getAndDelOption(arguments, "--builderOptimizationLevel", builderOptimizationLevel); getAndDelOption(arguments, "--maxTactics", maxTactics); std::string runtimePlatformArgs; getAndDelOption(arguments, "--runtimePlatform", runtimePlatformArgs); if (runtimePlatformArgs == "SameAsBuild" || runtimePlatformArgs.empty()) { runtimePlatform = RuntimePlatform::kSAME_AS_BUILD; } else if (runtimePlatformArgs == "WindowsAMD64") { runtimePlatform = RuntimePlatform::kWINDOWS_AMD64; } else { std::string validOptions = "SameAsBuild, WindowsAMD64"; throw std::invalid_argument( std::string("Unknown runtime platform: ") + runtimePlatformArgs + ". Valid options: " + validOptions); } std::string hardwareCompatibleArgs; getAndDelOption(arguments, "--hardwareCompatibilityLevel", hardwareCompatibleArgs); if (hardwareCompatibleArgs == "none" || hardwareCompatibleArgs.empty()) { hardwareCompatibilityLevel = HardwareCompatibilityLevel::kNONE; } else if (samplesCommon::toLower(hardwareCompatibleArgs) == "ampere+") { hardwareCompatibilityLevel = HardwareCompatibilityLevel::kAMPERE_PLUS; } else if (samplesCommon::toLower(hardwareCompatibleArgs) == "samecomputecapability") { hardwareCompatibilityLevel = HardwareCompatibilityLevel::kSAME_COMPUTE_CAPABILITY; } else { throw std::invalid_argument(std::string("Unknown hardwareCompatibilityLevel: ") + hardwareCompatibleArgs + ". Valid options: none, ampere+, sameComputeCapability."); } if (pluginInstanceNorm && (versionCompatible || hardwareCompatibilityLevel == HardwareCompatibilityLevel::kAMPERE_PLUS)) { throw std::invalid_argument( "Plugin InstanceNorm cannot be used with version compatible or hardware compatible engines!"); } getAndDelOption(arguments, "--maxAuxStreams", maxAuxStreams); std::string previewFeaturesBuf; getAndDelOption(arguments, "--preview", previewFeaturesBuf); std::vector previewFeaturesVec{splitToStringVec(previewFeaturesBuf, ',')}; for (auto featureName : previewFeaturesVec) { bool enable{false}; if (featureName.front() == '+') { enable = true; } else if (featureName.front() != '-') { throw std::invalid_argument( "Preview features must be prefixed with + or -, indicating whether it should be enabled or disabled " "respectively."); } featureName.erase(0, 1); PreviewFeature feat{}; if (featureName == "aliasedPluginIO1003") { feat = PreviewFeature::kALIASED_PLUGIN_IO_10_03; } else if (featureName == "runtimeActivationResize") { feat = PreviewFeature::kRUNTIME_ACTIVATION_RESIZE_10_10; } else { throw std::invalid_argument(std::string("Unknown preview feature: ") + featureName); } previewFeatures[static_cast(feat)] = enable; } getAndDelOption(arguments, "--tempdir", tempdir); getTempfileControls(arguments, "--tempfileControls", tempfileControls); std::string runtimeMode; getAndDelOption(arguments, "--useRuntime", runtimeMode); if (runtimeMode == "full") { useRuntime = RuntimeMode::kFULL; } else if (runtimeMode == "dispatch") { useRuntime = RuntimeMode::kDISPATCH; } else if (runtimeMode == "lean") { useRuntime = RuntimeMode::kLEAN; } else if (!runtimeMode.empty()) { throw std::invalid_argument(std::string("Unknown useRuntime: ") + runtimeMode); } if ((useRuntime == RuntimeMode::kDISPATCH || useRuntime == RuntimeMode::kLEAN) && !versionCompatible) { versionCompatible = true; sample::gLogWarning << "Implicitly enabling --versionCompatible since --useRuntime=" << runtimeMode << " is set." << std::endl; } if (useRuntime != RuntimeMode::kFULL && !load) { throw std::invalid_argument(std::string("Building a TensorRT engine requires --useRuntime=full.")); } getAndDelOption(arguments, "--leanDLLPath", leanDLLPath); getAndDelOption(arguments, "--setBuildRoute", buildRoute); // Don't delete the option because the inference option parser requires it getOption(arguments, "--allowWeightStreaming", allowWeightStreaming); getAndDelOption(arguments, "--tilingOptimizationLevel", tilingOptimizationLevel); getAndDelOption(arguments, "--l2LimitForTiling", l2LimitForTiling); getAndDelOption(arguments, "--remoteAutoTuningConfig", remoteAutoTuningConfig); if (!remoteAutoTuningConfig.empty() && !safe) { throw std::invalid_argument( "Remote auto tuning is not supported in standard build. Use --safe flag to enable it."); } if (cpuOnly) { if (!safe) { throw std::invalid_argument("CPU-only mode (--cpuOnly) requires --safe flag to be enabled."); } if (remoteAutoTuningConfig.empty()) { throw std::invalid_argument("CPU-only mode (--cpuOnly) requires --remoteAutoTuningConfig to be specified."); } } } void SystemOptions::parse(Arguments& arguments) { getAndDelOption(arguments, "--device", device); getAndDelOption(arguments, "--useDLACore", DLACore); std::string pluginName; while (getAndDelOption(arguments, "--plugins", pluginName)) { sample::gLogWarning << "--plugins flag has been deprecated, use --staticPlugins flag instead." << std::endl; plugins.emplace_back(pluginName); } while (getAndDelOption(arguments, "--setPluginsToSerialize", pluginName)) { setPluginsToSerialize.emplace_back(pluginName); } while (getAndDelOption(arguments, "--dynamicPlugins", pluginName)) { dynamicPlugins.emplace_back(pluginName); } #if ENABLE_UNIFIED_BUILDER samplesSafeCommon::SafetyPluginLibraryArgument safetyPluginOption; while (getAndDelOption(arguments, "--safetyPlugins", safetyPluginOption)) { safetyPlugins.emplace_back(std::move(safetyPluginOption)); } #endif // ENABLE_UNIFIED_BUILDER getAndDelOption(arguments, "--ignoreParsedPluginLibs", ignoreParsedPluginLibs); if (this->enableStaticPlugins) { std::string staticPluginName; while (getAndDelOption(arguments, "--staticPlugins", staticPluginName)) { plugins.emplace_back(staticPluginName); } } } namespace { //! Parse the --tuningSearch= value into the enum. //! Throws std::invalid_argument on unknown non-empty strings; leaves the //! algorithm unchanged on empty input. TuningSearchAlgorithm parseTuningSearchAlgorithm(std::string const& spec, TuningSearchAlgorithm defaultValue) { if (spec.empty()) { return defaultValue; } if (spec == "fast") { return TuningSearchAlgorithm::kFAST; } if (spec == "full") { return TuningSearchAlgorithm::kEXHAUSTIVE; } if (spec == "mixed") { return TuningSearchAlgorithm::kMIXED; } throw std::invalid_argument(std::string("Unknown tuning search algorithm: ") + spec); } //! Validate the exclusivity rules for --continue. The flag recovers everything //! from the cache header, so any other tuning flag is ambiguous. void validateContinueExclusivity(TuningOptions const& opts) { if (opts.tuningCacheFile.empty()) { throw std::invalid_argument("--continue requires --tuningCacheFile to be specified."); } if (!opts.tuningExpr.empty() || !opts.tuningExprFile.empty()) { throw std::invalid_argument( "--continue cannot be used with --tuneBuildRoutes or --tuneBuildRouteFile. " "All options are recovered from the cache file header."); } if (opts.dryRun) { throw std::invalid_argument("--continue cannot be used with --dryRun."); } if (opts.helpBuildRoute) { throw std::invalid_argument("--continue cannot be used with --helpBuildRoute."); } } //! Read --tuneBuildRouteFile contents and append to tuningExpr. Newlines and //! spaces are both treated as delimiters, so the file content is equivalent //! to a single --tuneBuildRoutes argument. void appendTuningExprFromFile(std::string const& path, std::string& tuningExpr) { std::ifstream file(path); if (!file.is_open()) { throw std::invalid_argument("Cannot open --tuneBuildRouteFile: " + path); } std::string line; while (std::getline(file, line)) { if (!tuningExpr.empty()) { tuningExpr += " "; } tuningExpr += line; } } } // namespace void TuningOptions::parse(Arguments& arguments) { // --helpBuildRoute is a short-circuit; the option's value (if any) is the // optional knob filter (e.g. --helpBuildRoute=conv_use_long_w). if (getAndDelOption(arguments, "--helpBuildRoute", helpBuildRouteKnob)) { helpBuildRoute = true; } getAndDelOption(arguments, "--tuneBuildRoutes", tuningExpr); getAndDelOption(arguments, "--tuneBuildRouteFile", tuningExprFile); std::string searchAlgorithmString; getAndDelOption(arguments, "--tuningSearch", searchAlgorithmString); tuningSearchAlgorithm = parseTuningSearchAlgorithm(searchAlgorithmString, tuningSearchAlgorithm); getAndDelOption(arguments, "--tuningTimeOut", timeout); getAndDelOption(arguments, "--tuningCacheFile", tuningCacheFile); getAndDelOption(arguments, "--continue", continueFromCache); getAndDelOption(arguments, "--dryRun", dryRun); // Hidden parent->child IPC flag (not in TuningOptions::help()). getAndDelOption(arguments, "--tuningResultFile", tuningResultFile); // Validate if (!tuningExpr.empty() && !tuningExprFile.empty()) { throw std::invalid_argument("Cannot specify both --tuneBuildRoutes and --tuneBuildRouteFile."); } if (continueFromCache) { validateContinueExclusivity(*this); } if (tuningSearchAlgorithm == TuningSearchAlgorithm::kMIXED && dryRun) { throw std::invalid_argument("--dryRun is incompatible with --tuningSearch=mixed."); } if (!tuningExprFile.empty()) { appendTuningExprFromFile(tuningExprFile, tuningExpr); } } constexpr int64_t WeightStreamingBudget::kDISABLE; constexpr int64_t WeightStreamingBudget::kAUTOMATIC; // NOLINTNEXTLINE(readability-function-cognitive-complexity) void InferenceOptions::parse(Arguments& arguments) { if (getAndDelOption(arguments, "--streams", infStreams)) { sample::gLogWarning << "--streams flag has been deprecated, use --infStreams flag instead." << std::endl; } getAndDelOption(arguments, "--infStreams", infStreams); getAndDelOption(arguments, "--iterations", iterations); getAndDelOption(arguments, "--duration", duration); getAndDelOption(arguments, "--warmUp", warmup); getAndDelOption(arguments, "--sleepTime", sleep); getAndDelOption(arguments, "--idleTime", idle); bool exposeDMA{false}; if (getAndDelOption(arguments, "--exposeDMA", exposeDMA)) { overlap = !exposeDMA; } // Data transfers are now disabled by default (--noDataTransfers behavior). // Spin wait is now enabled by default (--useSpinWait behavior). // CUDA graph is now enabled by default (--useCudaGraph behavior). // The old flags are kept for backward compatibility but are no-ops (the behavior is already the default). // Use --includeDataTransfers, --noSpinWait, --noCudaGraph to override these defaults. bool dummyBool{false}; if (getAndDelOption(arguments, "--noDataTransfers", dummyBool)) { sample::gLogWarning << "--noDataTransfers is deprecated. Data transfers are now disabled by default. " "Use --includeDataTransfers to re-enable data transfers." << std::endl; } getAndDelOption(arguments, "--includeDataTransfers", includeTransfers); getAndDelOption(arguments, "--useManagedMemory", useManaged); if (getAndDelOption(arguments, "--useSpinWait", dummyBool)) { sample::gLogWarning << "--useSpinWait is deprecated. Spin wait is now enabled by default. " "Use --noSpinWait to disable spin wait." << std::endl; } bool noSpinWait{false}; if (getAndDelOption(arguments, "--noSpinWait", noSpinWait)) { spin = !noSpinWait; } getAndDelOption(arguments, "--threads", threads); if (getAndDelOption(arguments, "--useCudaGraph", dummyBool)) { sample::gLogWarning << "--useCudaGraph is deprecated. CUDA graph is now enabled by default. " "Use --noCudaGraph to disable CUDA graph." << std::endl; } bool noCudaGraph{false}; bool const noCudaGraphOption = getAndDelOption(arguments, "--noCudaGraph", noCudaGraph); if (noCudaGraphOption) { graph = !noCudaGraph; } if (getAndDelOption(arguments, "--separateProfileRun", dummyBool)) { sample::gLogWarning << "--separateProfileRun is deprecated. Separate profile run is now always enabled. " "This flag will be removed in a future release." << std::endl; } getAndDelOption(arguments, "--timeDeserialize", timeDeserialize); getAndDelOption(arguments, "--timeRefit", timeRefit); getAndDelOption(arguments, "--persistentCacheRatio", persistentCacheRatio); // Parse reference pairs: either single pair (--loadInputs/--loadRefOutputs) or multiple pairs (--refPair) // This is similar to how --profile works with --minShapes/--optShapes/--maxShapes if (!getRefPairs(arguments, refPairs)) { // No --refPair was used, parse single --loadInputs/--loadRefOutputs pair into refPairs[0] ASSERT(refPairs.size() > 0 && "refPairs must have at least one element"); auto& inferenceInputs = refPairs[0].first; auto& inferenceRefOutputs = refPairs[0].second; std::string ilist; getAndDelOption(arguments, "--loadInputs", ilist); std::vector inputsList{splitToStringVec(ilist, ',')}; splitInsertKeyValue(inputsList, inferenceInputs); std::string olist; getAndDelOption(arguments, "--loadRefOutputs", olist); std::vector refOutputsList{splitToStringVec(olist, ',')}; splitInsertKeyValue(refOutputsList, inferenceRefOutputs); // Rule: --loadRefOutputs without --loadInputs should fail if (!inferenceRefOutputs.empty() && inferenceInputs.empty()) { throw std::invalid_argument("--loadRefOutputs requires --loadInputs to be specified."); } // Output parsed inputs and refOutputs for verification if (!inferenceInputs.empty() || !inferenceRefOutputs.empty()) { sample::gLogVerbose << "Parsed inputs/refOutputs (no --refPair):" << std::endl; sample::gLogVerbose << " loadInputs: {" << mapToString(inferenceInputs) << "}" << std::endl; sample::gLogVerbose << " loadRefOutputs: {" << mapToString(inferenceRefOutputs) << "}" << std::endl; } } // Parse accuracy validation options std::string accuracyAlgorithmString; bool const algoExplicitlySet = getAndDelOption(arguments, "--accuracyAlgorithm", accuracyAlgorithmString); std::unordered_map fromString{ {"l0", AccuracyValidationAlgorithm::kL0}, {"l1", AccuracyValidationAlgorithm::kL1}, {"l2", AccuracyValidationAlgorithm::kL2}, {"lInf", AccuracyValidationAlgorithm::kLInf}, {"cos", AccuracyValidationAlgorithm::kCosineSimilarity}, }; if (!accuracyAlgorithmString.empty() && fromString.find(accuracyAlgorithmString) == fromString.end()) { throw std::invalid_argument(std::string("Unknown accuracyAlgorithm: ") + accuracyAlgorithmString); } accuracyValidationAlgorithm = algoExplicitlySet ? fromString[accuracyAlgorithmString] : AccuracyValidationAlgorithm::kL0; bool const atolSet = getAndDelOption(arguments, "--atol", atol); if (atol < 0) { throw std::invalid_argument("--atol must be non-negative."); } bool const rtolSet = getAndDelOption(arguments, "--rtol", rtol); if (rtol < 0) { throw std::invalid_argument("--rtol must be non-negative."); } if (accuracyValidationAlgorithm != AccuracyValidationAlgorithm::kL0) { if (atolSet) { throw std::invalid_argument("--atol is only valid for L0 accuracy algorithm."); } if (rtolSet) { throw std::invalid_argument("--rtol is only valid for L0 accuracy algorithm."); } } getAndDelOption(arguments, "--accuracyThreshold", accuracyThresholdEndToEnd); if (accuracyThresholdEndToEnd < 0) { throw std::invalid_argument("--accuracyThreshold must be non-negative."); } getShapesInference(arguments, shapes, "--shapes"); setOptProfile = getAndDelOption(arguments, "--useProfile", optProfileIndex); std::string allocationStrategyString; getAndDelOption(arguments, "--allocationStrategy", allocationStrategyString); if (allocationStrategyString == "static") { memoryAllocationStrategy = MemoryAllocationStrategy::kSTATIC; } else if (allocationStrategyString == "profile") { memoryAllocationStrategy = MemoryAllocationStrategy::kPROFILE; } else if (allocationStrategyString == "runtime") { memoryAllocationStrategy = MemoryAllocationStrategy::kRUNTIME; } else if (!allocationStrategyString.empty()) { throw std::invalid_argument(std::string("Unknown allocationStrategy: ") + allocationStrategyString); } bool allowWs{false}; getAndDelOption(arguments, "--allowWeightStreaming", allowWs); bool wsBudgetFound = getAndDelOption(arguments, "--weightStreamingBudget", weightStreamingBudget); if (wsBudgetFound && !allowWs) { throw std::invalid_argument( "The weight streaming budget can only be set with --allowWeightStreaming specified."); } if (allowWs && weightStreamingBudget.isDisabled()) { sample::gLogWarning << "The engine can stream its weights but it will not at runtime because " "--weightStreamingBudget unset or set to " << WeightStreamingBudget::kDISABLE << "." << std::endl; } std::string debugTensorList; getAndDelOption(arguments, "--saveDebugTensors", debugTensorList); std::vector fileNames{splitToStringVec(debugTensorList, ',')}; splitInsertKeyValue(fileNames, debugTensorFileNames); std::string debugFormats; getAndDelOption(arguments, "--saveAllDebugTensors", debugFormats); dumpAlldebugTensorFormats = splitToStringVec(debugFormats, ','); getAndDelOption(arguments, "--refitFromOnnx", refitOnnxModel); } void ReportingOptions::parse(Arguments& arguments) { getAndDelOption(arguments, "--avgRuns", avgs); getAndDelOption(arguments, "--verbose", verbose); getAndDelOption(arguments, "--dumpRefit", refit); getAndDelOption(arguments, "--dumpOutput", output); getAndDelOption(arguments, "--dumpRawBindingsToFile", dumpRawBindings); getAndDelOption(arguments, "--dumpProfile", profile); getAndDelOption(arguments, "--dumpLayerInfo", layerInfo); getAndDelOption(arguments, "--dumpOptimizationProfile", optProfileInfo); getAndDelOption(arguments, "--exportTimes", exportTimes); getAndDelOption(arguments, "--exportOutput", exportOutput); getAndDelOption(arguments, "--exportProfile", exportProfile); getAndDelOption(arguments, "--exportLayerInfo", exportLayerInfo); std::string percentileString; getAndDelOption(arguments, "--percentile", percentileString); std::vector percentileStrings = splitToStringVec(percentileString, ','); if (!percentileStrings.empty()) { percentiles.clear(); } for (auto const& p : percentileStrings) { percentiles.push_back(stringToValue(p)); } for (auto percentile : percentiles) { if (percentile < 0.F || percentile > 100.F) { throw std::invalid_argument(std::string("Percentile ") + std::to_string(percentile) + "is not in [0,100]"); } } } bool parseHelp(Arguments& arguments) { bool helpLong{false}; bool helpShort{false}; getAndDelOption(arguments, "--help", helpLong); getAndDelOption(arguments, "-h", helpShort); return helpLong || helpShort; } // NOLINTNEXTLINE(readability-function-cognitive-complexity) void AllOptions::parse(Arguments& arguments) { model.parse(arguments); build.parse(arguments); system.parse(arguments); inference.parse(arguments); tuning.parse(arguments); if (build.useRuntime != RuntimeMode::kFULL && inference.timeRefit) { throw std::invalid_argument("--timeRefit requires --useRuntime=full."); } if (inference.optProfileIndex < static_cast(build.optProfiles.size())) { // Propagate shape profile between builder and inference for (auto const& s : build.optProfiles[inference.optProfileIndex]) { if (inference.shapes.find(s.first) == inference.shapes.end()) { insertShapesInference( inference.shapes, s.first, s.second[static_cast(nvinfer1::OptProfileSelector::kOPT)]); } } for (auto const& s : inference.shapes) { if (build.optProfiles[inference.optProfileIndex].find(s.first) == build.optProfiles[inference.optProfileIndex].end()) { // assume min/opt/max all the same insertShapesBuild(build.optProfiles[inference.optProfileIndex], nvinfer1::OptProfileSelector::kMIN, s.first, s.second); insertShapesBuild(build.optProfiles[inference.optProfileIndex], nvinfer1::OptProfileSelector::kOPT, s.first, s.second); insertShapesBuild(build.optProfiles[inference.optProfileIndex], nvinfer1::OptProfileSelector::kMAX, s.first, s.second); } } } // Set nvtxVerbosity to be the same as build-time profilingVerbosity. inference.nvtxVerbosity = build.profilingVerbosity; reporting.parse(arguments); helps = parseHelp(arguments); // Skip validation if --help or --helpBuildRoute is specified (both short-circuit // trtexec before doing real work, so model presence is not required). if (!helps && !tuning.helpBuildRoute) { if (!build.load && model.baseModel.format == ModelFormat::kANY) { throw std::invalid_argument("Model missing or format not recognized"); } if (system.DLACore >= 0 && inference.graph) { sample::gLogWarning << "CUDA graphs and DLA offloading are not simultaneously supported. " << "The CUDA graph option has been disabled (alternatively, you may run without the " "`--useDLACore` option)." << std::endl; inference.graph = false; } if (build.safe && system.DLACore >= 0) { build.buildDLAStandalone = true; } if (build.runtimePlatform != nvinfer1::RuntimePlatform::kSAME_AS_BUILD) { build.skipInference = true; } if (build.buildDLAStandalone) { build.skipInference = true; auto checkSafeDLAFormats = [](std::vector const& fmt, bool isInput) { return !fmt.empty() && std::all_of(fmt.begin(), fmt.end(), [&](IOFormat const& ioFmt) { using TF = nvinfer1::TensorFormat; auto const f = ioFmt.formats; bool const isDLA_LINEAR{f == 1U << static_cast(TF::kDLA_LINEAR)}; bool const isHWC4{ f == 1U << static_cast(TF::kCHW4) || f == 1U << static_cast(TF::kDLA_HWC4)}; bool const isCHW32{f == 1U << static_cast(TF::kCHW32)}; bool const isCHW16{f == 1U << static_cast(TF::kCHW16)}; return isDLA_LINEAR || (isInput && isHWC4) || isCHW32 || isCHW16; }); }; if (!checkSafeDLAFormats(build.inputFormats, true) || !checkSafeDLAFormats(build.outputFormats, false)) { throw std::invalid_argument( "I/O formats for safe DLA capability are restricted to dla_linear, hwc4, chw16, or chw32"); } if (build.allowGPUFallback) { throw std::invalid_argument("GPU fallback (--allowGPUFallback) not allowed for DLA standalone mode"); } } if (system.DLACore < 0 && build.enableUInt8AsymmetricQuantizationDLA) { throw std::invalid_argument("--uint8AsymmetricQuantizationDLA is not supported without DLA cores."); } if (system.DLACore < 0 && build.reportCapabilityDLA) { throw std::invalid_argument("--reportCapabilityDLA is not supported without DLA cores."); } if (system.DLACore < 0 && build.adjustForDLA) { sample::gLogWarning << "--adjustForDLA was set, but no DLA cores are available. " << "The parser's behavior will be modified, but the network will run on GPU." << std::endl; } bool const hasRefOutputs = !inference.refPairs[0].second.empty() || inference.refPairs.size() > 1; if (hasRefOutputs && inference.accuracyThresholdEndToEnd <= 0) { throw std::invalid_argument( "--accuracyThreshold (with a positive value) is required when --loadRefOutputs or --refPair is set."); } if (hasRefOutputs && build.skipInference) { throw std::invalid_argument( "--loadRefOutputs/--refPair cannot be used with --skipInference: accuracy " "validation needs the inference phase to run. Note --skipInference is implicitly " "enabled by --buildDLAStandalone and by a cross-platform --runtimePlatform."); } // Warn when using --onnx with accuracy validation, // because engine builds are nondeterministic and may produce unreliable comparisons. if (hasRefOutputs && !build.load) { sample::gLogWarning << "Accuracy validation (--loadRefOutputs/--refPair) with --onnx may produce " << "unreliable results because engine builds are nondeterministic. " << "Use --loadEngine for deterministic comparison." << std::endl; } } } void TaskInferenceOptions::parse(Arguments& arguments) { getAndDelOption(arguments, "engine", engine); getAndDelOption(arguments, "device", device); getAndDelOption(arguments, "batch", batch); getAndDelOption(arguments, "DLACore", DLACore); getAndDelOption(arguments, "graph", graph); getAndDelOption(arguments, "persistentCacheRatio", persistentCacheRatio); } void SafeBuilderOptions::parse(Arguments& arguments) { auto getFormats = [&arguments](std::vector& formatsVector, char const* argument) { std::string list; getAndDelOption(arguments, argument, list); std::vector formats{splitToStringVec(list, ',')}; for (const auto& f : formats) { formatsVector.push_back(stringToValue(f)); } }; getAndDelOption(arguments, "--serialized", serialized); getAndDelOption(arguments, "--onnx", onnxModelFile); getAndDelOption(arguments, "--help", help); getAndDelOption(arguments, "-h", help); getAndDelOption(arguments, "--verbose", verbose); getAndDelOption(arguments, "-v", verbose); getFormats(inputFormats, "--inputIOFormats"); getFormats(outputFormats, "--outputIOFormats"); getAndDelOption(arguments, "--int8", int8); getAndDelOption(arguments, "--std", standard); std::string pluginName; while (getAndDelOption(arguments, "--plugins", pluginName)) { sample::gLogWarning << "--plugins flag has been deprecated, use --staticPlugins flag instead." << std::endl; plugins.emplace_back(pluginName); } while (getAndDelOption(arguments, "--staticPlugins", pluginName)) { plugins.emplace_back(pluginName); } bool noBuilderCache{false}; getAndDelOption(arguments, "--noBuilderCache", noBuilderCache); getAndDelOption(arguments, "--timingCacheFile", timingCacheFile); getAndDelOption(arguments, "--avgTiming", avgTiming); if (noBuilderCache) { timingCacheMode = TimingCacheMode::kDISABLE; } else if (!timingCacheFile.empty()) { timingCacheMode = TimingCacheMode::kGLOBAL; } else { timingCacheMode = TimingCacheMode::kLOCAL; } getAndDelOption(arguments, "--sparsity", sparsity); } std::ostream& operator<<(std::ostream& os, BaseModelOptions const& options) { os << "=== Model Options ===" << std::endl; os << "Format: "; switch (options.format) { case ModelFormat::kONNX: { os << "ONNX"; break; } case ModelFormat::kANY: os << "*"; break; } os << std::endl << "Model: " << options.model << std::endl; return os; } std::ostream& operator<<(std::ostream& os, ModelOptions const& options) { os << options.baseModel; switch (options.baseModel.format) { case ModelFormat::kONNX: // Fallthrough: No options to report for ONNX or the generic case case ModelFormat::kANY: break; } os << "Output:"; for (auto const& o : options.outputs) { os << " " << o; } os << std::endl; return os; } std::ostream& operator<<(std::ostream& os, nvinfer1::DataType dtype) { switch (dtype) { case nvinfer1::DataType::kFLOAT: { os << "fp32"; break; } case nvinfer1::DataType::kHALF: { os << "fp16"; break; } case nvinfer1::DataType::kBF16: { os << "bf16"; break; } case nvinfer1::DataType::kINT8: { os << "int8"; break; } case nvinfer1::DataType::kINT32: { os << "int32"; break; } case nvinfer1::DataType::kBOOL: { os << "bool"; break; } case nvinfer1::DataType::kUINT8: { os << "uint8"; break; } case nvinfer1::DataType::kFP8: { os << "fp8"; break; } case nvinfer1::DataType::kINT64: { os << "int64"; break; } case nvinfer1::DataType::kINT4: { os << "int4"; break; } case nvinfer1::DataType::kFP4: { os << "fp4"; break; } case nvinfer1::DataType::kE8M0: { os << "e8m0"; break; } } return os; } std::ostream& operator<<(std::ostream& os, IOFormat const& format) { for (int32_t f = 0; f < nvinfer1::EnumMax(); ++f) { if ((1U << f) & format.formats) { if (f) { os << "+"; } switch (nvinfer1::TensorFormat(f)) { case nvinfer1::TensorFormat::kLINEAR: { os << "chw"; break; } case nvinfer1::TensorFormat::kCHW2: { os << "chw2"; break; } case nvinfer1::TensorFormat::kHWC8: { os << "hwc8"; break; } case nvinfer1::TensorFormat::kHWC16: { os << "hwc16"; break; } case nvinfer1::TensorFormat::kCHW4: { os << "chw4"; break; } case nvinfer1::TensorFormat::kCHW16: { os << "chw16"; break; } case nvinfer1::TensorFormat::kCHW32: { os << "chw32"; break; } case nvinfer1::TensorFormat::kDHWC8: { os << "dhwc8"; break; } case nvinfer1::TensorFormat::kCDHW32: { os << "cdhw32"; break; } case nvinfer1::TensorFormat::kHWC: { os << "hwc"; break; } case nvinfer1::TensorFormat::kDHWC: { os << "dhwc"; break; } case nvinfer1::TensorFormat::kDLA_LINEAR: { os << "dla_linear"; break; } case nvinfer1::TensorFormat::kDLA_HWC4: { os << "dla_hwc4"; break; } } } } return os; } std::ostream& operator<<(std::ostream& os, nvinfer1::DeviceType devType) { switch (devType) { case nvinfer1::DeviceType::kGPU: { os << "GPU"; break; } case nvinfer1::DeviceType::kDLA: { os << "DLA"; break; } } return os; } std::ostream& operator<<(std::ostream& os, nvinfer1::RuntimePlatform platform) { switch (platform) { case nvinfer1::RuntimePlatform::kSAME_AS_BUILD: { os << "Same As Build"; break; } case nvinfer1::RuntimePlatform::kWINDOWS_AMD64: { os << "Windows AMD64"; break; } } return os; } std::ostream& operator<<(std::ostream& os, ShapeRange const& dims) { int32_t i = 0; for (auto const& d : dims) { if (!d.size()) { break; } os << (i ? "+" : "") << d; ++i; } return os; } std::ostream& operator<<(std::ostream& os, LayerDeviceTypes const& layerDeviceTypes) { int32_t i = 0; for (auto const& layerDevicePair : layerDeviceTypes) { os << (i++ ? ", " : "") << layerDevicePair.first << ":" << layerDevicePair.second; } return os; } std::ostream& operator<<(std::ostream& os, DecomposableAttentions const& decomposableAttentions) { char const* sep = ""; for (auto const& attentionDecomposablePair : decomposableAttentions) { os << sep << attentionDecomposablePair.first << ":" << attentionDecomposablePair.second; sep = ", "; } return os; } std::ostream& operator<<(std::ostream& os, StringSet const& stringSet) { int64_t i = 0; for (auto const& s : stringSet) { os << (i ? "," : "") << s; ++i; } return os; } std::ostream& operator<<(std::ostream& os, BuildOptions const& options) { // if loadEngine is specified, BuildOptions are N/A if (options.load) { os << std::endl; return os; } // clang-format off os << "=== Build Options ===" << std::endl << "Memory Pools: "; printMemoryPools(os, options) << std::endl << "avgTiming: " << options.avgTiming << std::endl << "Precision: "; printPrecision(os, options) << std::endl << "Layer Device Types: " << options.layerDeviceTypes << std::endl << "Decomposable Attentions: " << options.decomposableAttentions << std::endl << "Refit: " << boolToEnabled(options.refittable) << std::endl << "Strip weights: " << boolToEnabled(options.stripWeights) << std::endl << "Version Compatible: " << boolToEnabled(options.versionCompatible) << std::endl << "ONNX Plugin InstanceNorm: " << boolToEnabled(options.pluginInstanceNorm) << std::endl << "ONNX kENABLE_UINT8_AND_ASYMMETRIC_QUANTIZATION_DLA flag: " << boolToEnabled(options.enableUInt8AsymmetricQuantizationDLA) << std::endl << "ONNX kREPORT_CAPABILITY_DLA flag: " << boolToEnabled(options.reportCapabilityDLA) << std::endl << "ONNX kADJUST_FOR_DLA flag: " << boolToEnabled(options.adjustForDLA) << std::endl << "ONNX kENABLE_PLUGIN_OVERRIDE flag: " << boolToEnabled(options.enablePluginOverride) << std::endl << "TensorRT runtime: " << options.useRuntime << std::endl << "Lean DLL Path: " << options.leanDLLPath << std::endl << "Tempfile Controls: "; printTempfileControls(os, options.tempfileControls) << std::endl << "Exclude Lean Runtime: " << boolToEnabled(options.excludeLeanRuntime) << std::endl << "Sparsity: "; printSparsity(os, options) << std::endl << "Safe mode: " << boolToEnabled(options.safe) << std::endl << "Build DLA standalone loadable: " << boolToEnabled(options.buildDLAStandalone) << std::endl << "Allow GPU fallback for DLA: " << boolToEnabled(options.allowGPUFallback) << std::endl << "DirectIO mode: " << boolToEnabled(options.directIO) << std::endl << "Skip inference: " << boolToEnabled(options.skipInference) << std::endl << "Save engine: " << (options.save ? options.engine : "") << std::endl << "Load engine: " << (options.load ? options.engine : "") << std::endl << "Profiling verbosity: " << static_cast(options.profilingVerbosity) << std::endl << "Tactic sources: "; printTacticSources(os, options.enabledTactics, options.disabledTactics) << std::endl << "timingCacheMode: "; printTimingCache(os, options.timingCacheMode) << std::endl << "timingCacheFile: " << options.timingCacheFile << std::endl << "Enable Compilation Cache: "<< boolToEnabled(!options.disableCompilationCache) << std::endl << "Enable Monitor Memory: "<< boolToEnabled(options.enableMonitorMemory) << std::endl << "CPU Only Mode: "<< boolToEnabled(options.cpuOnly) << std::endl << "errorOnTimingCacheMiss: " << boolToEnabled(options.errorOnTimingCacheMiss) << std::endl << "Preview Features: "; printPreviewFlags(os, options) << std::endl << "MaxAuxStreams: " << options.maxAuxStreams << std::endl << "BuilderOptimizationLevel: " << options.builderOptimizationLevel << std::endl << "MaxTactics: " << options.maxTactics << std::endl << "Weight Streaming: " << boolToEnabled(options.allowWeightStreaming) << std::endl << "Runtime Platform: " << options.runtimePlatform << std::endl << "Debug Tensors: " << options.debugTensors << std::endl << "Distributive Independence: " << boolToEnabled(options.distributiveIndependence) << std::endl << "Mark Unfused Tensors As Debug Tensors: " << boolToEnabled(options.markUnfusedTensorsAsDebugTensors) << std::endl; // clang-format on auto printIOFormats = [](std::ostream& os, char const* direction, std::vector const& formats) { if (formats.empty()) { os << direction << "s format: CHW" << std::endl; } else { for (auto const& f : formats) { os << direction << ": " << f << std::endl; } } }; printIOFormats(os, "Input(s)", options.inputFormats); printIOFormats(os, "Output(s)", options.outputFormats); for (size_t i = 0; i < options.optProfiles.size(); i++) { printShapes(os, "build", options.optProfiles[i], i); } return os; } std::ostream& operator<<(std::ostream& os, SystemOptions const& options) { // clang-format off os << "=== System Options ===" << std::endl << "Device: " << options.device << std::endl << "DLACore: " << (options.DLACore != -1 ? std::to_string(options.DLACore) : "") << std::endl; if (options.enableStaticPlugins) { os << "Loaded static plugins:"; for (const auto& p : options.plugins) { os << " " << p; } os << std::endl; } os << "setPluginsToSerialize:"; for (const auto& p : options.setPluginsToSerialize) { os << " " << p; } os << std::endl; os << "dynamicPlugins:"; for (const auto& p : options.dynamicPlugins) { os << " " << p; } os << std::endl; os << "ignoreParsedPluginLibs: " << options.ignoreParsedPluginLibs << std::endl; os << std::endl; return os; // clang-format on } std::ostream& operator<<(std::ostream& os, InferenceOptions const& options) { // clang-format off os << "=== Inference Options ===" << std::endl << "Batch: "; if (options.batch && options.shapes.empty()) { os << options.batch << std::endl; } else { os << "Explicit" << std::endl; } printShapes(os, "inference", options.shapes, options.optProfileIndex); std::string wsBudget{"Disabled"}; if (options.weightStreamingBudget.bytes == WeightStreamingBudget::kAUTOMATIC) { wsBudget = "Automatic"; } else if (options.weightStreamingBudget.bytes != WeightStreamingBudget::kDISABLE) { wsBudget = std::to_string(options.weightStreamingBudget.bytes) + " bytes"; } else if (options.weightStreamingBudget.percent != WeightStreamingBudget::kDISABLE) { wsBudget = std::to_string(options.weightStreamingBudget.percent) + "%"; } os << "Iterations: " << options.iterations << std::endl << "Duration: " << options.duration << "s (+ " << options.warmup << "ms warm up)" << std::endl << "Sleep time: " << options.sleep << "ms" << std::endl << "Idle time: " << options.idle << "ms" << std::endl << "Inference Streams: " << options.infStreams << std::endl << "ExposeDMA: " << boolToEnabled(!options.overlap) << std::endl << "Data transfers: " << boolToEnabled(options.includeTransfers) << std::endl << "Spin-wait: " << boolToEnabled(options.spin) << std::endl << "Multithreading: " << boolToEnabled(options.threads) << std::endl << "CUDA Graph: " << boolToEnabled(options.graph) << std::endl << "Time Deserialize: " << boolToEnabled(options.timeDeserialize) << std::endl << "Time Refit: " << boolToEnabled(options.timeRefit) << std::endl << "NVTX verbosity: " << static_cast(options.nvtxVerbosity) << std::endl << "Persistent Cache Ratio: " << static_cast(options.persistentCacheRatio) << std::endl << "Optimization Profile Index: "<< options.optProfileIndex << std::endl << "Weight Streaming Budget: " << wsBudget << std::endl; // clang-format on // Accuracy validation settings os << "Accuracy Algorithm: "; switch (options.accuracyValidationAlgorithm) { case AccuracyValidationAlgorithm::kL0: os << "L0"; break; case AccuracyValidationAlgorithm::kL1: os << "L1"; break; case AccuracyValidationAlgorithm::kL2: os << "L2"; break; case AccuracyValidationAlgorithm::kLInf: os << "LInf"; break; case AccuracyValidationAlgorithm::kCosineSimilarity: os << "CosineSimilarity"; break; } os << std::endl; if (options.accuracyValidationAlgorithm == AccuracyValidationAlgorithm::kL0) { os << "Absolute Tolerance (atol): " << options.atol << std::endl; os << "Relative Tolerance (rtol): " << options.rtol << std::endl; } if (options.accuracyThresholdEndToEnd > 0) { os << "Accuracy Threshold: " << options.accuracyThresholdEndToEnd << std::endl; } os << "Inputs:" << std::endl; ASSERT(options.refPairs.size() > 0 && "refPairs must have at least one element"); auto const& inferenceInputs = options.refPairs[0].first; for (auto const& input : inferenceInputs) { os << input.first << "<-" << input.second << std::endl; } auto const& inferenceRefOutputs = options.refPairs[0].second; if (!inferenceRefOutputs.empty()) { os << "RefOutputs:" << std::endl; for (auto const& refOutput : inferenceRefOutputs) { os << refOutput.first << "<-" << refOutput.second << std::endl; } } os << "Debug Tensor Save Destinations:" << std::endl; for (auto const& fileName : options.debugTensorFileNames) { os << fileName.first << ": " << fileName.second << std::endl; } os << "Dump All Debug Tensor in Formats: " << std::endl; for (auto const& format : options.dumpAlldebugTensorFormats) { os << format << std::endl; } return os; } std::ostream& operator<<(std::ostream& os, ReportingOptions const& options) { // clang-format off os << "=== Reporting Options ===" << std::endl << "Verbose: " << boolToEnabled(options.verbose) << std::endl << "Averages: " << options.avgs << " inferences" << std::endl << "Percentiles: " << joinValuesToString(options.percentiles, ",") << std::endl << "Dump refittable layers:" << boolToEnabled(options.refit) << std::endl << "Dump output: " << boolToEnabled(options.output) << std::endl << "Profile: " << boolToEnabled(options.profile) << std::endl << "Export timing to JSON file: " << options.exportTimes << std::endl << "Export output to JSON file: " << options.exportOutput << std::endl << "Export profile to JSON file: " << options.exportProfile << std::endl; // clang-format on return os; } std::ostream& operator<<(std::ostream& os, AllOptions const& options) { os << options.model << options.build << options.system << options.inference << options.reporting << std::endl; return os; } std::ostream& operator<<(std::ostream& os, SafeBuilderOptions const& options) { auto printIOFormats = [](std::ostream& os, char const* direction, std::vector const& formats) { if (formats.empty()) { os << direction << "s format: CHW" << std::endl; } else { for (auto const& f : formats) { os << direction << ": " << f << std::endl; } } }; os << "=== Build Options ===" << std::endl; os << "Model ONNX: " << options.onnxModelFile << std::endl; os << "Precision: FP16"; if (options.int8) { os << " + INT8"; } if (options.fp8) { os << " + FP8"; } if (options.int4) { os << " + INT4"; } os << std::endl; os << "Serialized Network: " << options.serialized << std::endl; printIOFormats(os, "Input(s)", options.inputFormats); printIOFormats(os, "Output(s)", options.outputFormats); os << "Loaded static plugins:"; for (auto const& p : options.plugins) { os << " " << p; } os << "timingCacheMode: "; printTimingCache(os, options.timingCacheMode) << std::endl; os << "timingCacheFile: " << options.timingCacheFile << std::endl; os << std::endl; return os; } void BaseModelOptions::help(std::ostream& os) { // clang-format off os << " --onnx= ONNX model" << std::endl; // clang-format on } void ModelOptions::help(std::ostream& os) { // clang-format off os << "=== Model Options ===" << std::endl; BaseModelOptions::help(os); // clang-format on } void BuildOptions::help(std::ostream& os) { // clang-format off os << "=== Build Options ===" "\n" " --minShapes=spec Build with dynamic shapes using a profile with the min shapes provided" "\n" " --optShapes=spec Build with dynamic shapes using a profile with the opt shapes provided" "\n" " --maxShapes=spec Build with dynamic shapes using a profile with the max shapes provided" "\n" " --inputIOFormats=spec Memory layout of each of the input tensors (default = chw)" "\n" " See --outputIOFormats help for the grammar of format list." "\n" " Note: If this option is specified, please set comma-separated formats for all" "\n" " inputs following the same order as network inputs ID (even if only one input" "\n" " needs specifying IO format) or set the format once for broadcasting." "\n" " --outputIOFormats=spec Memory layout of each of the output tensors (default = chw)" "\n" " Note: If this option is specified, please set comma-separated formats for all" "\n" " outputs following the same order as network outputs ID (even if only one output" "\n" " needs specifying IO format) or set the format once for broadcasting." "\n" R"( IO Formats: spec ::= IOfmt[","spec])" "\n" R"( IOfmt ::= ("chw"|"chw2"|"hwc8"|"chw4"|"chw16"|"chw32"|"dhwc8"|)" "\n" R"( "cdhw32"|"hwc"|"dla_linear"|"dla_hwc4"|"hwc16"|"dhwc")["+"IOfmt])" "\n" " --memPoolSize=poolspec Specify the size constraints of the designated memory pool(s)" "\n" " Supports the following base-2 suffixes: " << getAvailableUnitSuffixes() << "." "\n" " If none of suffixes is appended, the defualt unit is in MiB." "\n" " Note: Also accepts decimal sizes, e.g. 0.25M. Will be rounded down to the nearest integer bytes." "\n" " In particular, for dlaSRAM the bytes will be rounded down to the nearest power of 2." "\n" R"( Pool constraint: poolspec ::= poolfmt[","poolspec])" "\n" " poolfmt ::= pool:size\n" R"( pool ::= "workspace"|"dlaSRAM"|"dlaLocalDRAM"|"dlaGlobalDRAM"|"tacticSharedMem")" "\n" " --profilingVerbosity=mode Specify profiling verbosity. mode ::= layer_names_only|detailed|none (default = layer_names_only)." "\n" " Please only assign once." "\n" " --avgTiming=M Set the number of times averaged in each iteration for kernel selection (default = " << defaultAvgTiming << ")" "\n" " --refit Mark the engine as refittable. This will allow the inspection of refittable layers " "\n" " and weights within the engine." "\n" " --stripWeights Strip weights from plan. This flag works with either refit or refit with identical weights. Default""\n" " to latter, but you can switch to the former by enabling both --stripWeights and --refit at the same""\n" " time." "\n" " --stripAllWeights Alias for combining the --refit and --stripWeights options. It marks all weights as refittable," "\n" " disregarding any performance impact. Additionally, it strips all refittable weights after the " "\n" " engine is built." "\n" " --versionCompatible, --vc Mark the engine as version compatible. This allows the engine to be used with newer versions" "\n" " of TensorRT on the same host OS, as well as TensorRT's dispatch and lean runtimes." "\n" " --pluginInstanceNorm, --pi Set `kNATIVE_INSTANCENORM` to false in the ONNX parser. This will cause the ONNX parser to use" "\n" " a plugin InstanceNorm implementation over the native implementation when parsing." "\n" " --uint8AsymmetricQuantizationDLA Set `kENABLE_UINT8_AND_ASYMMETRIC_QUANTIZATION_DLA` to true in the ONNX parser. This directs the" "\n" " ONNX parser to allow UINT8 as a quantization data type and import zero point values directly" "\n" " without converting to float type or all-zero values. Should only be set with DLA software version" "\n" " >= 3.16." "\n" " --reportCapabilityDLA Set `kREPORT_CAPABILITY_DLA` to true in the ONNX parser. This signals the ONNX parser to validate" "\n" " that all nodes in the model can run on DLA. This flag is set to be OFF by default." "\n" " --adjustForDLA Set `kADJUST_FOR_DLA` to true in the ONNX parser. This signals the ONNX parser to opportunistically""\n" " rewrite or modify layers to make them more amenable to running on DLA. This flag is set to be OFF" "\n" " by default." "\n" " --enablePluginOverride Set `kENABLE_PLUGIN_OVERRIDE` to true in the ONNX parser. This allows the ONNX parser to use" "\n" " a plugin implementation over the standard ONNX operator implementation when parsing." "\n" R"( --useRuntime=runtime TensorRT runtime to execute engine. "lean" and "dispatch" require loading VC engine and do)" "\n" " not support building an engine." "\n" R"( runtime::= "full"|"lean"|"dispatch")" "\n" " --leanDLLPath= External lean runtime DLL to use in version compatible mode." "\n" " --excludeLeanRuntime When --versionCompatible is enabled, this flag indicates that the generated engine should" "\n" " not include an embedded lean runtime. If this is set, the user must explicitly specify a" "\n" " valid lean runtime to use when loading the engine." "\n" " --monitorMemory Enable memory monitor report for debugging usage. (default = disabled)" "\n" " Disables CUDA timing cache and profile streams. Only allowed when building" "\n" " a safe engine (--safe) with remote auto-tuning (--remoteAutoTuningConfig)." "\n" " (default = disabled)" "\n" " --sparsity=spec Control sparsity (default = disabled). " "\n" R"( Sparsity: spec ::= "disable", "enable", "force")" "\n" " Note: Description about each of these options is as below" "\n" " disable = do not enable sparse tactics in the builder (this is the default)" "\n" " enable = enable sparse tactics in the builder (but these tactics will only be" "\n" " considered if the weights have the right sparsity pattern)" "\n" " force = enable sparse tactics in the builder and force-overwrite the weights to have" "\n" " a sparsity pattern (even if you loaded a model yourself)" "\n" " [Deprecated] this knob has been deprecated." "\n" " Please use to rewrite the weights." "\n" " --noTF32 Disable tf32 precision (default is to enable tf32, in addition to fp32)" "\n" " --stronglyTyped [Deprecated] Strongly typed network is now enabled by default. This flag is a no-op." "\n" " --directIO [Deprecated] Avoid reformatting at network boundaries. (default = disabled)" "\n" " --layerDeviceTypes=spec Specify layer-specific device type." "\n" " The specs are read left-to-right, and later ones override earlier ones. If a layer does not have" "\n" " a device type specified, the layer will opt for the default device type." "\n" R"( Per-layer device type spec ::= layerDeviceTypePair[","spec])" "\n" R"( layerDeviceTypePair ::= layerName":"deviceType)" "\n" R"( deviceType ::= "GPU"|"DLA")" "\n" " --decomposableAttentions=spec Specify decomposable attentions by comma-separated names." "\n" R"( The specs are read left-to-right, and later ones override earlier ones. Each layer name can)" "\n" " contain at most one wildcard ('*') character." "\n" " --safe Enable build safety certified engine." "\n" " If DLA is enabled, --buildDLAStandalone will be specified" "\n" " --dumpKernelText Dump the kernel text to a file, only available when --safe is enabled" "\n" " --buildDLAStandalone Enable build DLA standalone loadable which can be loaded by cuDLA, when this option is enabled, " "\n" " --allowGPUFallback is disallowed and --skipInference is enabled by default. Additionally, " "\n" " specifying --inputIOFormats and --outputIOFormats restricts memory layout" "\n" " (default = disabled)" "\n" " --allowGPUFallback When DLA is enabled, allow GPU fallback for unsupported layers (default = disabled)" "\n" " --consistency Perform consistency checking on safety certified engine" "\n" " --saveEngine= Save the serialized engine" "\n" " --loadEngine= Load a serialized engine" "\n" " --asyncFileReader Load a serialized engine using async stream reader. Should be combined with --loadEngine." "\n" " --getPlanVersionOnly Print TensorRT version when loaded plan was created. Works without deserialization of the plan." "\n" " Use together with --loadEngine. Supported only for engines created with 8.6 and forward." "\n" " --tacticSources=tactics Specify the tactics to be used by adding (+) or removing (-) tactics from the default " "\n" " tactic sources (default = all available tactics)." "\n" " Note: Currently only edge mask convolutions and JIT convolutions are listed as optional" "\n" " tactics." "\n" R"( Tactic Sources: tactics ::= tactic[","tactics])" "\n" " tactic ::= (+|-)lib" "\n" R"( lib ::= "EDGE_MASK_CONVOLUTIONS"|"JIT_CONVOLUTIONS")" "\n" " For example, to disable edge mask convolutions: --tacticSources=-EDGE_MASK_CONVOLUTIONS" "\n" " --noBuilderCache Disable timing cache in builder (default is to enable timing cache)" "\n" " --noCompilationCache Disable Compilation cache in builder, and the cache is part of timing cache (default is to enable compilation cache)" "\n" " --errorOnTimingCacheMiss Emit error when a tactic being timed is not present in the timing cache (default = false)" "\n" " --timingCacheFile= Save/load the serialized global timing cache" "\n" " --preview=features Specify preview feature to be used by adding (+) or removing (-) preview features from the default" "\n" R"( Preview Features: features ::= feature[","features])" "\n" " feature ::= (+|-)flag" "\n" R"( flag ::= "aliasedPluginIO1003")" "\n" R"( |"runtimeActivationResize")" "\n" " --builderOptimizationLevel Set the builder optimization level. (default is 3)" "\n" " A Higher level allows TensorRT to spend more time searching for better optimization strategy." "\n" " Valid values include integers from 0 to the maximum optimization level, which is currently 5." "\n" " --maxTactics Set the maximum number of tactics to time when there is a choice of tactics. (default is -1)" "\n" " Larger number of tactics allow TensorRT to spend more building time on evaluating tactics." "\n" " Default value -1 means TensorRT can decide the number of tactics based on its own heuristic." "\n" " --hardwareCompatibilityLevel=mode Make the engine file compatible with other GPU architectures. (default = none)" "\n" R"( Hardware Compatibility Level: mode ::= "none" | "ampere+" | "sameComputeCapability")" "\n" " none = no compatibility" "\n" " ampere+ = compatible with Ampere and newer GPUs" "\n" " sameComputeCapability = compatible with GPUs that have the same Compute Capability version" "\n" " --runtimePlatform=platform Set the target platform for runtime execution. (default = SameAsBuild)" "\n" " When this option is enabled, --skipInference is enabled by default." "\n" R"( RuntimePlatfrom: platform ::= "SameAsBuild" | "WindowsAMD64")" "\n" " SameAsBuild = no requirement for cross-platform compatibility." "\n" " WindowsAMD64 = set the target platform for engine execution as Windows AMD64 system" "\n" " --tempdir= Overrides the default temporary directory TensorRT will use when creating temporary files." "\n" " See IRuntime::setTemporaryDirectory API documentation for more information." "\n" " --tempfileControls=controls Controls what TensorRT is allowed to use when creating temporary executable files." "\n" " Should be a comma-separated list with entries in the format (in_memory|temporary):(allow|deny)." "\n" " in_memory: Controls whether TensorRT is allowed to create temporary in-memory executable files." "\n" " temporary: Controls whether TensorRT is allowed to create temporary executable files in the" "\n" " filesystem (in the directory given by --tempdir)." "\n" " For example, to allow in-memory files and disallow temporary files:" "\n" " --tempfileControls=in_memory:allow,temporary:deny" "\n" R"( If a flag is unspecified, the default behavior is "allow".)" "\n" " --maxAuxStreams=N Set maximum number of auxiliary streams per inference stream that TRT is allowed to use to run " "\n" " kernels in parallel if the network contains ops that can run in parallel, with the cost of more " "\n" " memory usage. Set this to 0 for optimal memory usage. (default = using heuristics)" "\n" " --profile Build with dynamic shapes using a profile with the min/max/opt shapes provided. Can be specified" "\n" " multiple times to create multiple profiles with contiguous index." "\n" " (ex: --profile=0 --minShapes= --optShapes= --maxShapes= --profile=1 ...)" "\n" " --allowWeightStreaming Enable a weight streaming engine. TensorRT will disable" "\n" " weight streaming at runtime unless --weightStreamingBudget is specified." "\n" " --markDebug Specify list of names of tensors to be marked as debug tensors. Separate names with a comma" "\n" " --markUnfusedTensorsAsDebugTensors Mark unfused tensors as debug tensors" "\n" " --tilingOptimizationLevel Set the tiling optimization level. (default is " << defaultTilingOptimizationLevel << ")" "\n" " A Higher level allows TensorRT to spend more time searching for better optimization strategy." "\n" " Valid values include integers from " << static_cast(nvinfer1::TilingOptimizationLevel::kNONE) << " to the maximum tiling optimization level(" << static_cast(nvinfer1::TilingOptimizationLevel::kFULL) << ")." "\n" " --l2LimitForTiling Set the L2 cache usage limit for tiling optimization(default is -1)" "\n" " --remoteAutoTuningConfig Set the remote auto tuning config. Must be specified with --safe." "\n" " Format: protocol://username[:password]@hostname[:port]?param1=value1¶m2=value2" "\n" " Example: ssh://user:pass@192.0.2.100:22?remote_exec_path=/opt/tensorrt/bin&remote_lib_path=/opt/tensorrt/lib" "\n" " --refitFromOnnx Refit the loaded engine with the weights from the provided ONNX model." "\n" " The model should be identical to the one used to generate the engine." "\n" " --cpuOnly Build the engine with CPU-only mode. No local GPU is required on the build machine." "\n" " Must be specified with --remoteAutoTuningConfig and --safe flags." "\n" ; // clang-format on os << std::flush; } void SystemOptions::help(std::ostream& os, bool const enableStaticPlugins) { // clang-format off os << "=== System Options ===" << std::endl << " --device=N Select cuda device N (default = " << defaultDevice << ")" << std::endl; if (enableStaticPlugins) { os << " --staticPlugins Plugin library (.so) to load statically (can be specified multiple times)" << std::endl << std::endl; } os << " --useDLACore=N Select DLA core N for layers that support DLA (default = none)" << std::endl << " --staticPlugins Plugin library (.so) to load statically (can be specified multiple times)" << std::endl << " --dynamicPlugins Plugin library (.so) to load dynamically and may be serialized with the engine if they are included in --setPluginsToSerialize (can be specified multiple times)" << std::endl << " --setPluginsToSerialize Plugin library (.so) to be serialized with the engine (can be specified multiple times)" << std::endl << " --ignoreParsedPluginLibs By default, when building a version-compatible engine, plugin libraries specified by the ONNX parser " << std::endl << " are implicitly serialized with the engine (unless --excludeLeanRuntime is specified) and loaded dynamically. " << std::endl << " Enable this flag to ignore these plugin libraries instead." << std::endl << " --safetyPlugins Plugin library (.so) for TensorRT auto safety to manually load safety plugins specified by the command line arguments." << std::endl << " Example: --safetyPlugins=/path/to/plugin_lib.so[pluginNamespace1::plugin1,pluginNamespace2::plugin2]." << std::endl << " The option can be specified multiple times with different plugin libraries." << std::endl; // clang-format on } void InferenceOptions::help(std::ostream& os) { // clang-format off os << "=== Inference Options ===" << std::endl << " --shapes=spec Set input shapes for dynamic shapes inference inputs." << std::endl << R"( Note: Input names can be wrapped with escaped single quotes (ex: 'Input:0').)" << std::endl << " Example input shapes spec: input0:1x3x256x256, input1:1x3x128x128" << std::endl << " For scalars (0-D shapes), use input0:scalar or simply input0: with nothing after the colon."<< std::endl << " Each input shape is supplied as a key-value pair where key is the input name and" << std::endl << " value is the dimensions (including the batch dimension) to be used for that input." << std::endl << " Each key-value pair has the key and value separated using a colon (:)." << std::endl << " Multiple input shapes can be provided via comma-separated key-value pairs, and each input " << std::endl << " name can contain at most one wildcard ('*') character." << std::endl << " --loadInputs=spec Load input values from files (default = generate random inputs). Input names can be " "wrapped with single quotes (ex: 'Input:0')" << std::endl << R"( Input values spec ::= Ival[","spec])" << std::endl << R"( Ival ::= name":"file)" << std::endl << " Consult the README for more information on generating files for custom inputs." << std::endl << " --loadRefOutputs=spec Load reference output values from files for accuracy validation. Output names can be " << std::endl << " wrapped with single quotes (ex: 'Output:0')." << std::endl << R"( Output values spec ::= Oval[","spec])" << std::endl << R"( Oval ::= name":"file)" << std::endl << " If the calculated outputs is not within the accuracy threshold, the inference result is " << std::endl << " considered to be inaccurate." << std::endl << " --iterations=N Run at least N inference iterations (default = " << defaultIterations << ")" << std::endl << " --warmUp=N Run for N milliseconds to warmup before measuring performance (default = " << defaultWarmUp << ")" << std::endl << " --duration=N Run performance measurements for at least N seconds wallclock time (default = " << defaultDuration << ")" << std::endl << " If -1 is specified, inference will keep running unless stopped manually" << std::endl << " --sleepTime=N Delay inference start with a gap of N milliseconds between launch and compute " "(default = " << defaultSleep << ")" << std::endl << " --idleTime=N Sleep N milliseconds between two continuous iterations" "(default = " << defaultIdle << ")" << std::endl << " --infStreams=N Instantiate N execution contexts to run inference concurrently " "(default = " << defaultStreams << ")" << std::endl << " --exposeDMA Serialize DMA transfers to and from device (default = disabled)." << std::endl << " --includeDataTransfers Enable DMA transfers to and from device (default = disabled). Note some device-to-host" << std::endl << " data transfers will remain if output dumping is enabled via the --dumpOutput or" << std::endl << " --exportOutput flags." << std::endl << " --noDataTransfers [Deprecated] DMA transfers are now disabled by default. This flag is a no-op." << std::endl << " --useManagedMemory Use managed memory instead of separate host and device allocations (default = disabled)." << std::endl << " --noSpinWait Disable spin wait and use blocking synchronization instead. This may reduce CPU usage " "but increase synchronization time (default = spin wait enabled)" << std::endl << " --useSpinWait [Deprecated] Spin wait is now enabled by default. This flag is a no-op." << std::endl << " --threads Enable multithreading to drive engines with independent threads" " or speed up refitting (default = disabled) " << std::endl << " --noCudaGraph Disable CUDA graph capture and launch (default = CUDA graph enabled)." << std::endl << " --useCudaGraph [Deprecated] CUDA graph is now enabled by default. This flag is a no-op." << std::endl << " --timeDeserialize Time the amount of time it takes to deserialize the network and exit." << std::endl << " --timeRefit Time the amount of time it takes to refit the engine before inference." << std::endl << " --separateProfileRun [Deprecated] Separate profile run is now always enabled. This flag is a no-op." << std::endl << " --skipInference Exit after the engine has been built and skip inference perf measurement " "(default = disabled)" << std::endl << " --persistentCacheRatio Set the persistentCacheLimit in ratio, 0.5 represent half of max persistent L2 size " "(default = 0)" << std::endl << " --useProfile Set the optimization profile for the inference context " "(default = " << defaultOptProfileIndex << " )." << std::endl << " --allocationStrategy=spec Specify how the internal device memory for inference is allocated." << std::endl << R"( Strategy: spec ::= "static"|"profile"|"runtime")" << std::endl << " static = Allocate device memory based on max size across all profiles." << std::endl << " profile = Allocate device memory based on max size of the current profile." << std::endl << " runtime = Allocate device memory based on the actual input shapes." << std::endl << " --accuracyAlgorithm=spec Specify the algorithm for computing the accuracy loss between actual" << std::endl << " and reference outputs. Lower accuracy loss is better; 0.0 = perfect match." << std::endl << R"( Algorithm: spec ::= "l0"|"l1"|"l2"|"lInf"|"cos")" << std::endl << " l0 = L0 algorithm. Fraction of elements outside tolerance:" << std::endl << " accuracy loss = Sum( Bool(" << std::endl << " |f(input[i]) - refOutput[i]| > atol + rtol * |refOutput[i]| ) ) / N" << std::endl << " where atol, rtol are the absolute and relative tolerances." << std::endl << " l1 = L1 algorithm. Mean absolute error:" << std::endl << " accuracy loss = Sum( |f(input[i]) - refOutput[i]| ) / N" << std::endl << " l2 = L2 algorithm. Mean squared error:" << std::endl << " accuracy loss = Sum( |f(input[i]) - refOutput[i]| ^2 ) / N" << std::endl << " lInf = LInf algorithm. Maximum absolute error:" << std::endl << " accuracy loss = Max( |f(input[i]) - refOutput[i]| )" << std::endl << " cos = Cosine similarity algorithm. 1 - cosine similarity:" << std::endl << " accuracy loss = 1 - Sum( f(input[i]) * refOutput[i] ) /" << std::endl << " ( sqrt(Sum( f(input[i]) ^2 )) * sqrt(Sum( refOutput[i] ^2 )) )" << std::endl << " --atol=number Absolute tolerance for element-wise accuracy comparison (only valid for L0" << std::endl << " algorithm). (Default = 1e-5)" << std::endl << " --rtol=number Relative tolerance for element-wise accuracy comparison (only valid for L0" << std::endl << " algorithm). (Default = 1e-5)" << std::endl << " --accuracyThreshold=number Threshold for accepting the inference result. If the computed accuracy loss" << std::endl << " exceeds this threshold, the result is considered inaccurate." << std::endl << " --refPair=N Specify a reference pair index for grouping --loadInputs and --loadRefOutputs." << std::endl << " Can be specified multiple times to validate accuracy across different input/output pairs." << std::endl << R"( Example: --refPair=0 --loadInputs="x:x1.dat" --loadRefOutputs="y:y1.dat")" << std::endl << R"( --refPair=1 --loadInputs="x:x2.dat" --loadRefOutputs="y:y2.dat")" << std::endl << " --saveDebugTensors Specify list of names of tensors to turn on the debug state" << std::endl << " and filename to save raw outputs to." << std::endl << " These tensors must be specified as debug tensors during build time." << std::endl << R"( Input values spec ::= Ival[","spec])" << std::endl << R"( Ival ::= name":"file)" << std::endl << " --saveAllDebugTensors Save all debug tensors to files. " << std::endl << " Including debug tensors marked by --markDebug and --markUnfusedTensorsAsDebugTensors" << std::endl << " Multiple file formats can be saved simultaneously." << std::endl << R"( Input values spec ::= format[","format])" << std::endl << R"( format ::= "summary"|"numpy"|"string"|"raw")" << std::endl << " --weightStreamingBudget Set the maximum amount of GPU memory TensorRT is allowed to use for weights." << std::endl << " It can take on the following values:" << std::endl << " -2: (default) Disable weight streaming at runtime." << std::endl << " -1: TensorRT will automatically decide the budget." << std::endl << " 0-100%: Percentage of streamable weights that reside on the GPU." << std::endl << " 0% saves the most memory but will have the worst performance." << std::endl << " Requires the '%' character." << std::endl << " >=0B: The exact amount of streamable weights that reside on the GPU. Supports the " << std::endl << " following base-2 suffixes: " << getAvailableUnitSuffixes() << "." << std::endl; // clang-format on } void TuningOptions::help(std::ostream& os) { // clang-format off os << "=== Tuning Options ===" << std::endl << " --tuneBuildRoutes= Run an autotuning loop over a build-route expression. The expression" << std::endl << " uses '-knob=[a|b|c]' for variable knobs and '-knob=fixed' for fixed" << std::endl << " values; multiple knobs are space-separated. Each iteration forks a" << std::endl << " child trtexec with --setBuildRoute= for full reproducibility." << std::endl << " --tuneBuildRouteFile= Read the same expression from a file (newline-delimited tokens)." << std::endl << " --tuningSearch= Search algorithm:" << std::endl << " fast = baseline + one-off variations per knob (default)" << std::endl << " full = enumerate every combination (Cartesian product)" << std::endl << " mixed = phase 1 fast scan, then exhaustive over positive knobs" << std::endl << " --tuningCacheFile= JSON file to which per-iteration results are appended (best-config cache)." << std::endl << " --tuningTimeOut= Stop the loop after N elapsed seconds. -1 = no timeout (default)." << std::endl << " --saveAllEngines Save the engine of every iteration as .iter. Requires --saveEngine." << std::endl << " --dryRun Enumerate the route list and exit without building any engine." << std::endl << " --continue Resume an interrupted tuning loop from --tuningCacheFile." << std::endl << " --helpBuildRoute[=] Print the knob database as JSON and exit. Optionally filter by knob name." << std::endl << " --setBuildRoute= Single-shot: build with a specific route. Equivalent to a single tuning" << std::endl << " iteration; used by the parent tuning loop when forking child workers." << std::endl; // clang-format on } void ReportingOptions::help(std::ostream& os) { // clang-format off os << "=== Reporting Options ===" << std::endl << " --verbose Use verbose logging (default = false)" << std::endl << " --avgRuns=N Report performance measurements averaged over N consecutive " "iterations (default = " << defaultAvgRuns << ")" << std::endl << " --percentile=P1,P2,P3,... Report performance for the P1,P2,P3,... percentages (0<=P_i<=100, 0 " "representing max perf, and 100 representing min perf; (default" " = " << joinValuesToString(defaultPercentiles, ",") << "%)" << std::endl << " --dumpRefit Print the refittable layers and weights from a refittable " "engine" << std::endl << " --dumpOutput Print the output tensor(s) of the last inference iteration " "(default = disabled)" << std::endl << " --dumpRawBindingsToFile Print the input/output tensor(s) of the last inference iteration to file" "(default = disabled)" << std::endl << " --dumpProfile Print profile information per layer (default = disabled)" << std::endl << " --dumpLayerInfo Print layer information of the engine to console " "(default = disabled)" << std::endl << " --dumpOptimizationProfile Print the optimization profile(s) information " "(default = disabled)" << std::endl << " --exportTimes= Write the timing results in a json file (default = disabled)" << std::endl << " --exportOutput= Write the output tensors to a json file (default = disabled)" << std::endl << " --exportProfile= Write the profile information per layer in a json file " "(default = disabled)" << std::endl << " --exportLayerInfo= Write the layer information of the engine in a json file " "(default = disabled)" << std::endl; // clang-format on } void TaskInferenceOptions::help(std::ostream& os) { // clang-format off os << "=== Task Inference Options ===" << std::endl << " engine= Specify a serialized engine for this task" << std::endl << " device=N Specify a GPU device for this task" << std::endl << " DLACore=N Specify a DLACore for this task" << std::endl << " batch=N Set batch size for implicit batch engines (default = " << defaultBatch << ")" << std::endl << " This option should not be used for explicit batch engines" << std::endl << " graph=1 Use cuda graph for this task" << std::endl << " persistentCacheRatio=[0-1] Set the persistentCacheLimit ratio for this task (default = 0)" << std::endl; // clang-format on } void helpHelp(std::ostream& os) { // clang-format off os << "=== Help ===" << std::endl << " --help, -h Print this message" << std::endl; // clang-format on } void AllOptions::help(std::ostream& os, bool const enableStaticPlugins) { ModelOptions::help(os); os << std::endl; BuildOptions::help(os); os << std::endl; InferenceOptions::help(os); os << std::endl; TuningOptions::help(os); os << std::endl; ReportingOptions::help(os); os << std::endl; SystemOptions::help(os, enableStaticPlugins); os << std::endl; helpHelp(os); } void SafeBuilderOptions::printHelp(std::ostream& os) { // clang-format off os << "=== Mandatory ===" << std::endl << " --onnx= ONNX model" << std::endl << " " << std::endl << "=== Optional ===" << std::endl << " --inputIOFormats=spec Memory layout of each of the input tensors (default = chw)" << std::endl << " See --outputIOFormats help for the grammar of format list." << std::endl << " Note: If this option is specified, please set comma-separated formats for all" << std::endl << " inputs following the same order as network inputs ID (even if only one input" << std::endl << " needs specifying IO format) or set the format once for broadcasting." << std::endl << " --outputIOFormats=spec Memory layout of each of the output tensors (default = chw)" << std::endl << " Note: If this option is specified, please set comma-separated formats for all" << std::endl << " outputs following the same order as network outputs ID (even if only one output" << std::endl << " needs specifying IO format) or set the format once for broadcasting." << std::endl << R"( IO Formats: spec ::= IOfmt[","spec])" << std::endl << R"( IOfmt ::= ("chw"|"chw2"|"hwc8"|"chw4"|"chw16"|"chw32"|"dhwc8"|)" << std::endl << R"( "cdhw32"|"hwc"|"dla_linear"|"dla_hwc4"|"hwc16"|"dhwc")["+"IOfmt])" << std::endl << " --int8 Enable int8 precision, in addition to fp16 (default = disabled)" << std::endl << " --std Build standard serialized engine, (default = disabled)" << std::endl << " --serialized= Save the serialized network" << std::endl << " --staticPlugins Plugin library (.so) to load statically (can be specified multiple times)" << std::endl << " --verbose or -v Use verbose logging (default = false)" << std::endl << " --help or -h Print this message" << std::endl << " --noBuilderCache Disable timing cache in builder (default is to enable timing cache)" << std::endl << " --timingCacheFile= Save/load the serialized global timing cache" << std::endl << " --sparsity=spec Control sparsity (default = disabled). " << std::endl << R"( Sparsity: spec ::= "disable", "enable", "force")" << std::endl << " Note: Description about each of these options is as below" << std::endl << " disable = do not enable sparse tactics in the builder (this is the default)" << std::endl << " enable = enable sparse tactics in the builder (but these tactics will only be" << std::endl << " considered if the weights have the right sparsity pattern)" << std::endl << " force = enable sparse tactics in the builder and force-overwrite the weights to have" << std::endl << " a sparsity pattern" << std::endl << " --avgTiming=M Set the number of times averaged in each iteration for kernel selection (default = " << std::endl << "" << defaultAvgTiming << ")" << std::endl << "" << std::endl; // clang-format on } } // namespace sample