// Copyright 2020-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of NVIDIA CORPORATION nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "common.h" namespace triton { namespace client { //============================================================================== const Error Error::Success(""); Error::Error(const std::string& msg) : msg_(msg) {} std::ostream& operator<<(std::ostream& out, const Error& err) { if (!err.msg_.empty()) { out << err.msg_; } return out; } //============================================================================== Error InferenceServerClient::ClientInferStat(InferStat* infer_stat) const { *infer_stat = infer_stat_; return Error::Success; } Error InferenceServerClient::UpdateInferStat(const RequestTimers& timer) { const uint64_t request_time_ns = timer.Duration( RequestTimers::Kind::REQUEST_START, RequestTimers::Kind::REQUEST_END); const uint64_t send_time_ns = timer.Duration( RequestTimers::Kind::SEND_START, RequestTimers::Kind::SEND_END); const uint64_t recv_time_ns = timer.Duration( RequestTimers::Kind::RECV_START, RequestTimers::Kind::RECV_END); if ((request_time_ns == std::numeric_limits::max()) || (send_time_ns == std::numeric_limits::max()) || (recv_time_ns == std::numeric_limits::max())) { return Error( "Timer not set correctly." + ((timer.Timestamp(RequestTimers::Kind::REQUEST_START) > timer.Timestamp(RequestTimers::Kind::REQUEST_END)) ? (" Request time from " + std::to_string( timer.Timestamp(RequestTimers::Kind::REQUEST_START)) + " to " + std::to_string( timer.Timestamp(RequestTimers::Kind::REQUEST_END)) + ".") : "") + ((timer.Timestamp(RequestTimers::Kind::SEND_START) > timer.Timestamp(RequestTimers::Kind::SEND_END)) ? (" Send time from " + std::to_string( timer.Timestamp(RequestTimers::Kind::SEND_START)) + " to " + std::to_string(timer.Timestamp(RequestTimers::Kind::SEND_END)) + ".") : "") + ((timer.Timestamp(RequestTimers::Kind::RECV_START) > timer.Timestamp(RequestTimers::Kind::RECV_END)) ? (" Receive time from " + std::to_string( timer.Timestamp(RequestTimers::Kind::RECV_START)) + " to " + std::to_string(timer.Timestamp(RequestTimers::Kind::RECV_END)) + ".") : "")); } infer_stat_.completed_request_count++; infer_stat_.cumulative_total_request_time_ns += request_time_ns; infer_stat_.cumulative_send_time_ns += send_time_ns; infer_stat_.cumulative_receive_time_ns += recv_time_ns; return Error::Success; } //============================================================================== Error InferInput::Create( InferInput** infer_input, const std::string& name, const std::vector& dims, const std::string& datatype) { *infer_input = new InferInput(name, dims, datatype); return Error::Success; } Error InferInput::SetShape(const std::vector& shape) { shape_ = shape; return Error::Success; } Error InferInput::Reset() { bufs_.clear(); buf_byte_sizes_.clear(); str_bufs_.clear(); bufs_idx_ = 0; byte_size_ = 0; io_type_ = NONE; return Error::Success; } Error InferInput::AppendRaw(const std::vector& input) { return AppendRaw(&input[0], input.size()); } Error InferInput::AppendRaw(const uint8_t* input, size_t input_byte_size) { byte_size_ += input_byte_size; bufs_.push_back(input); buf_byte_sizes_.push_back(input_byte_size); io_type_ = RAW; return Error::Success; } Error InferInput::SetSharedMemory( const std::string& name, size_t byte_size, size_t offset) { shm_name_ = name; shm_offset_ = offset; byte_size_ = byte_size; io_type_ = SHARED_MEMORY; return Error::Success; } Error InferInput::AppendFromString(const std::vector& input) { // Serialize the strings into a "raw" buffer. The first 4-bytes are // the length of the string length. Next are the actual string // characters. There is *not* a null-terminator on the string. str_bufs_.emplace_back(); std::string& sbuf = str_bufs_.back(); for (const auto& str : input) { uint32_t len = str.size(); sbuf.append(reinterpret_cast(&len), sizeof(uint32_t)); sbuf.append(str); } return AppendRaw(reinterpret_cast(&sbuf[0]), sbuf.size()); } Error InferInput::ByteSize(size_t* byte_size) const { *byte_size = byte_size_; return Error::Success; } InferInput::InferInput( const std::string& name, const std::vector& shape, const std::string& datatype) : name_(name), shape_(shape), datatype_(datatype), byte_size_(0), bufs_idx_(0), buf_pos_(0), io_type_(NONE), shm_name_(""), shm_offset_(0) { } Error InferInput::SharedMemoryInfo( std::string* name, size_t* byte_size, size_t* offset) const { if (io_type_ != SHARED_MEMORY) { return Error("The input has not been set with the shared memory."); } *name = shm_name_; *offset = shm_offset_; *byte_size = byte_size_; return Error::Success; } Error InferInput::SetBinaryData(const bool binary_data) { binary_data_ = binary_data; return Error::Success; } Error InferInput::PrepareForRequest() { // Reset position so request sends entire input. bufs_idx_ = 0; buf_pos_ = 0; return Error::Success; } Error InferInput::GetNext( uint8_t* buf, size_t size, size_t* input_bytes, bool* end_of_input) { size_t total_size = 0; while ((bufs_idx_ < bufs_.size()) && (size > 0)) { const size_t buf_byte_size = buf_byte_sizes_[bufs_idx_]; const size_t csz = (std::min)(buf_byte_size - buf_pos_, size); if (csz > 0) { const uint8_t* input_ptr = bufs_[bufs_idx_] + buf_pos_; std::copy(input_ptr, input_ptr + csz, buf); buf_pos_ += csz; buf += csz; size -= csz; total_size += csz; } if (buf_pos_ == buf_byte_size) { bufs_idx_++; buf_pos_ = 0; } } *input_bytes = total_size; *end_of_input = (bufs_idx_ >= bufs_.size()); return Error::Success; } Error InferInput::GetNext( const uint8_t** buf, size_t* input_bytes, bool* end_of_input) { if (bufs_idx_ < bufs_.size()) { *buf = bufs_[bufs_idx_]; *input_bytes = buf_byte_sizes_[bufs_idx_]; bufs_idx_++; } else { *buf = nullptr; *input_bytes = 0; } *end_of_input = (bufs_idx_ >= bufs_.size()); return Error::Success; } //============================================================================== Error InferRequestedOutput::Create( InferRequestedOutput** infer_output, const std::string& name, const size_t class_count) { *infer_output = new InferRequestedOutput(name, class_count); return Error::Success; } Error InferRequestedOutput::SetSharedMemory( const std::string& region_name, const size_t byte_size, const size_t offset) { shm_name_ = region_name; shm_byte_size_ = byte_size; shm_offset_ = offset; io_type_ = SHARED_MEMORY; return Error::Success; } Error InferRequestedOutput::UnsetSharedMemory() { shm_name_ = ""; shm_byte_size_ = 0; shm_offset_ = 0; io_type_ = NONE; return Error::Success; } InferRequestedOutput::InferRequestedOutput( const std::string& name, const size_t class_count) : name_(name), class_count_(class_count), io_type_(NONE) { } Error InferRequestedOutput::SharedMemoryInfo( std::string* name, size_t* byte_size, size_t* offset) const { if (io_type_ != SHARED_MEMORY) { return Error("The input has not been set with the shared memory."); } *name = shm_name_; *byte_size = shm_byte_size_; *offset = shm_offset_; return Error::Success; } Error InferRequestedOutput::SetBinaryData(const bool binary_data) { binary_data_ = binary_data; return Error::Success; } //============================================================================== }} // namespace triton::client