#pragma once #include #include #include #include #include "ctranslate2/types.h" namespace ctranslate2 { bool string_to_bool(const std::string& str); void log_system_config(); int get_gpu_count(); void set_num_threads(size_t num_threads); bool ends_with(const std::string& str, const std::string& suffix); bool starts_with(const std::string& str, const std::string& prefix); // Wrapper around std::getline to remove the carriage return, if present. std::istream& getline(std::istream& input, std::string& str, bool remove_carriage_return = true); std::vector split_string(const std::string& str, char delimiter); std::vector split_string(const std::string& str, const std::string& delimiter); std::string join_string(const std::vector& tokens, const std::string& separator = ""); std::vector split_tokens(const std::string& text); std::string join_tokens(const std::vector& tokens); std::vector>> extract_features(std::vector> batch, size_t num_features, const std::string& features_separator = "\uFFE8"); template static std::vector index_vector(const std::vector& v, const std::vector& index) { std::vector new_v; new_v.resize(index.size()); for (size_t i = 0; i < index.size(); ++i) new_v[i] = v[index[i]]; return new_v; } template std::vector repeat_vector(const std::vector& v, size_t repeats) { std::vector new_v; new_v.reserve(v.size() * repeats); for (const T& e : v) { for (size_t i = 0; i < repeats; ++i) new_v.emplace_back(e); } return new_v; } // Helper function to only run the model on inputs without an immediate result. template std::vector get_batch_results_helper(size_t batch_size, const SkipRun& skip_run, const GetBatchResults& get_batch_results) { if (batch_size == 0) return {}; std::vector final_results(batch_size); std::vector index_to_run; index_to_run.reserve(batch_size); for (size_t i = 0; i < batch_size; ++i) { if (!skip_run(i, final_results[i])) index_to_run.emplace_back(i); } if (!index_to_run.empty()) { std::vector results = get_batch_results(index_to_run); for (size_t i = 0; i < results.size(); ++i) final_results[index_to_run[i]] = std::move(results[i]); } return final_results; } template inline T ceil_divide(const T& x, const T& y) { return (x + y - 1) / y; } #ifdef NDEBUG # define THROW_EXCEPTION(EXCEPTION, MESSAGE) throw EXCEPTION(MESSAGE) #else # define THROW_EXCEPTION(EXCEPTION, MESSAGE) \ throw EXCEPTION(std::string(__FILE__) + ":" + std::to_string(__LINE__) + ": " + MESSAGE) #endif #define THROW_RUNTIME_ERROR(MESSAGE) THROW_EXCEPTION(std::runtime_error, MESSAGE) #define THROW_INVALID_ARGUMENT(MESSAGE) THROW_EXCEPTION(std::invalid_argument, MESSAGE) #define SAFE_DIVIDE(x, y) ((y != 0 && (x % y == 0)) ? (x / y) : (throw std::runtime_error("Division has a remainder," \ "Model can't be ran with the tensor parallel mode in " + std::to_string(y) + " nodes"))) #define ERROR_CHECK(ans, message) \ { \ if (!ans) \ THROW_RUNTIME_ERROR(message); \ } }