Files
paddlepaddle--paddle/paddle/common/flags.h
T
2026-07-13 12:40:42 +08:00

411 lines
17 KiB
C++

// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
//
// 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.
#pragma once
#include <array>
#include <cstdint>
#include <map>
#include <string>
#include <type_traits>
#include <vector>
#ifdef PADDLE_WITH_GFLAGS
#include "gflags/gflags.h"
#else
#endif
#include "paddle/common/macros.h"
#include "paddle/utils/test_macros.h"
#include "paddle/utils/variant.h"
#if defined(_WIN32)
#define COMMON_IMPORT_FLAG __declspec(dllimport)
#else
#define COMMON_IMPORT_FLAG
#endif
#ifdef PADDLE_WITH_GFLAGS
#define PD_DEFINE_bool(name, val, txt) DEFINE_bool(name, val, txt)
#define PD_DEFINE_int32(name, val, txt) DEFINE_int32(name, val, txt)
#define PD_DEFINE_uint32(name, val, txt) DEFINE_uint32(name, val, txt)
#define PD_DEFINE_int64(name, val, txt) DEFINE_int64(name, val, txt)
#define PD_DEFINE_uint64(name, val, txt) DEFINE_uint64(name, val, txt)
#define PD_DEFINE_double(name, val, txt) DEFINE_double(name, val, txt)
#define PD_DEFINE_string(name, val, txt) DEFINE_string(name, val, txt)
#define PD_DECLARE_bool(name) DECLARE_bool(name)
#define PD_DECLARE_int32(name) DECLARE_int32(name)
#define PD_DECLARE_uint32(name) DECLARE_uint32(name)
#define PD_DECLARE_int64(name) DECLARE_int64(name)
#define PD_DECLARE_uint64(name) DECLARE_uint64(name)
#define PD_DECLARE_double(name) DECLARE_double(name)
#define PD_DECLARE_string(name) DECLARE_string(name)
#endif
#define PD_DECLARE_VARIABLE(type, name) \
namespace paddle_flags { \
extern COMMON_IMPORT_FLAG type FLAGS_##name; \
} \
using paddle_flags::FLAGS_##name
#define COMMON_DECLARE_VARIABLE(type, name) \
namespace paddle_flags { \
extern COMMON_IMPORT_FLAG type FLAGS_##name; \
} \
using paddle_flags::FLAGS_##name
#define PD_DECLARE_bool(name) PD_DECLARE_VARIABLE(bool, name)
#define PD_DECLARE_int32(name) PD_DECLARE_VARIABLE(int32_t, name)
#define PD_DECLARE_uint32(name) PD_DECLARE_VARIABLE(uint32_t, name)
#define PD_DECLARE_int64(name) PD_DECLARE_VARIABLE(int64_t, name)
#define PD_DECLARE_uint64(name) PD_DECLARE_VARIABLE(uint64_t, name)
#define PD_DECLARE_double(name) PD_DECLARE_VARIABLE(double, name)
#define PD_DECLARE_string(name) PD_DECLARE_VARIABLE(std::string, name)
#define COMMON_DECLARE_bool(name) COMMON_DECLARE_VARIABLE(bool, name)
#define COMMON_DECLARE_int32(name) COMMON_DECLARE_VARIABLE(int32_t, name)
#define COMMON_DECLARE_uint32(name) COMMON_DECLARE_VARIABLE(uint32_t, name)
#define COMMON_DECLARE_int64(name) COMMON_DECLARE_VARIABLE(int64_t, name)
#define COMMON_DECLARE_uint64(name) COMMON_DECLARE_VARIABLE(uint64_t, name)
#define COMMON_DECLARE_double(name) COMMON_DECLARE_VARIABLE(double, name)
#define COMMON_DECLARE_string(name) COMMON_DECLARE_VARIABLE(std::string, name)
// ----------------------------DEFINE FLAGS----------------------------
#define PD_DEFINE_VARIABLE(type, name, default_value, description) \
namespace paddle_flags { \
static const type FLAGS_##name##_default = default_value; \
type FLAGS_##name = default_value; \
/* Register FLAG */ \
static ::paddle::flags::FlagRegisterer flag_##name##_registerer( \
#name, description, __FILE__, &FLAGS_##name##_default, &FLAGS_##name); \
} \
using paddle_flags::FLAGS_##name
#define PD_DEFINE_bool(name, val, txt) PD_DEFINE_VARIABLE(bool, name, val, txt)
#define PD_DEFINE_int32(name, val, txt) \
PD_DEFINE_VARIABLE(int32_t, name, val, txt)
#define PD_DEFINE_uint32(name, val, txt) \
PD_DEFINE_VARIABLE(uint32_t, name, val, txt)
#define PD_DEFINE_int64(name, val, txt) \
PD_DEFINE_VARIABLE(int64_t, name, val, txt)
#define PD_DEFINE_uint64(name, val, txt) \
PD_DEFINE_VARIABLE(uint64_t, name, val, txt)
#define PD_DEFINE_double(name, val, txt) \
PD_DEFINE_VARIABLE(double, name, val, txt)
#define PD_DEFINE_string(name, val, txt) \
PD_DEFINE_VARIABLE(std::string, name, val, txt)
namespace paddle {
namespace flags {
PADDLE_API void SetFlagsFromEnv(const std::vector<std::string>& flags,
bool error_fatal);
/**
* @brief Parse commandline flags.
*
* It receives commandline arguments passed in argc and argv from main function,
* argv[0] is the program name, and argv[1:] are the commandline arguments
* which matching the format "--name=value" or "--name value". After parsing,
* the corresponding flag value will be reset.
*/
PADDLE_API void ParseCommandLineFlags(int* argc, char*** argv);
/**
* @brief Allow undefined flags in ParseCommandLineFlags()
*/
PADDLE_API void AllowUndefinedFlags();
/**
* @brief Set Single flag value, return true if success.
*/
bool SetFlagValue(const std::string& name, const std::string& value);
PADDLE_API bool UpdateLinkedFlags(const std::string& name,
const std::string& value);
/**
* @brief Find flag by name, return true if found.
*/
bool FindFlag(const std::string& name);
/**
* @brief Print all registered flags' help message. If to_file is true,
* write help message to file.
*/
void PrintAllFlagHelp(bool to_file = false,
const std::string& file_name = "all_flags.txt");
/**
* @brief Get environment variable. If not found, return default value.
*/
template <typename T>
T GetFromEnv(const std::string& name, const T& default_val);
class PADDLE_API FlagRegisterer {
public:
template <typename T>
FlagRegisterer(std::string name,
std::string description,
std::string file,
const T* default_value,
T* value);
};
#ifdef PADDLE_WITH_GFLAGS
inline void ParseCommandLineFlags(int* argc, char*** argv) {
gflags::ParseCommandLineFlags(argc, argv, true);
}
#else
using paddle::flags::ParseCommandLineFlags;
#endif
#ifdef PADDLE_WITH_GFLAGS
inline bool SetFlagValue(const char* name, const char* value) {
std::string ret = gflags::SetCommandLineOption(name, value);
return ret.empty() ? false : true;
}
#else
using paddle::flags::SetFlagValue;
#endif
#ifdef PADDLE_WITH_GFLAGS
inline bool UpdateLinkedFlags(const std::string& name,
const std::string& value) {
// Gflags does not support this feature.
return false;
}
#else
using paddle::flags::UpdateLinkedFlags;
#endif
#ifdef PADDLE_WITH_GFLAGS
inline bool FindFlag(const char* name) {
std::string value;
return gflags::GetCommandLineOption(name, &value);
}
#else
using paddle::flags::FindFlag;
#endif
#ifdef PADDLE_WITH_GFLAGS
inline void AllowUndefinedFlags() { gflags::AllowCommandLineReparsing(); }
#else
using paddle::flags::AllowUndefinedFlags;
#endif
#ifdef PADDLE_WITH_GFLAGS
using gflags::BoolFromEnv;
using gflags::DoubleFromEnv;
using gflags::Int32FromEnv;
using gflags::Int64FromEnv;
using gflags::StringFromEnv;
using gflags::Uint32FromEnv;
using gflags::Uint64FromEnv;
#else
#define DEFINE_FROM_ENV_FUNC(type, name) \
inline type name##FromEnv(const std::string& env_var_name, \
type default_val) { \
return GetFromEnv(env_var_name, default_val); \
}
DEFINE_FROM_ENV_FUNC(bool, Bool);
DEFINE_FROM_ENV_FUNC(int32_t, Int32);
DEFINE_FROM_ENV_FUNC(uint32_t, Uint32);
DEFINE_FROM_ENV_FUNC(int64_t, Int64);
DEFINE_FROM_ENV_FUNC(uint64_t, Uint64);
DEFINE_FROM_ENV_FUNC(double, Double);
DEFINE_FROM_ENV_FUNC(std::string, String);
#undef DEFINE_FROM_ENV_FUNC
#endif
} // namespace flags
} // namespace paddle
#if defined(_WIN32)
#define PHI_EXPORT_FLAG __declspec(dllexport)
#if defined(PHI_INNER)
#define PHI_IMPORT_FLAG __declspec(dllexport)
#else
#define PHI_IMPORT_FLAG __declspec(dllimport)
#endif // PHI_INNER
#else
#define PHI_EXPORT_FLAG
#define PHI_IMPORT_FLAG
#endif // _WIN32
// We redefine the flags macro for exporting flags defined in phi
#ifdef PADDLE_WITH_GFLAGS
// clang-format off
#define PHI_DECLARE_VARIABLE(type, shorttype, name) \
namespace fL##shorttype { \
extern PHI_IMPORT_FLAG type FLAGS_##name; \
} \
using fL##shorttype::FLAGS_##name
// clang-format on
#define PHI_DEFINE_VARIABLE(type, shorttype, name, value, help) \
namespace fL##shorttype { \
PHI_EXPORT_FLAG type FLAGS_##name = value; \
static type FLAGS_no##name = value; \
static GFLAGS_NAMESPACE::FlagRegisterer o_##name( \
#name, \
MAYBE_STRIPPED_HELP(help), \
__FILE__, \
&FLAGS_##name, \
&FLAGS_no##name); \
} /* NOLINT */ \
using fL##shorttype::FLAGS_##name
#else // PADDLE_WITH_GFLAGS
#define PHI_DECLARE_VARIABLE(type, shorttype, name) \
namespace paddle_flags { \
extern PHI_IMPORT_FLAG type FLAGS_##name; \
} \
using paddle_flags::FLAGS_##name
#define PHI_DEFINE_VARIABLE(type, shorttype, name, default_value, description) \
namespace paddle_flags { \
static const type FLAGS_##name##_default = default_value; \
PHI_EXPORT_FLAG type FLAGS_##name = default_value; \
/* Register FLAG */ \
static ::paddle::flags::FlagRegisterer flag_##name##_registerer( \
#name, description, __FILE__, &FLAGS_##name##_default, &FLAGS_##name); \
} \
using paddle_flags::FLAGS_##name
#endif
// ----------------------------DECLARE FLAGS----------------------------
#define PHI_DECLARE_bool(name) PHI_DECLARE_VARIABLE(bool, B, name)
#define PHI_DECLARE_int32(name) PHI_DECLARE_VARIABLE(int32_t, I, name)
#define PHI_DECLARE_uint32(name) PHI_DECLARE_VARIABLE(uint32_t, U, name)
#define PHI_DECLARE_int64(name) PHI_DECLARE_VARIABLE(int64_t, I64, name)
#define PHI_DECLARE_uint64(name) PHI_DECLARE_VARIABLE(uint64_t, U64, name)
#define PHI_DECLARE_double(name) PHI_DECLARE_VARIABLE(double, D, name)
// ----------------------------DEFINE FLAGS-----------------------------
#define PHI_DEFINE_bool(name, val, txt) \
PHI_DEFINE_VARIABLE(bool, B, name, val, txt)
#define PHI_DEFINE_int32(name, val, txt) \
PHI_DEFINE_VARIABLE(int32_t, I, name, val, txt)
#define PHI_DEFINE_uint32(name, val, txt) \
PHI_DEFINE_VARIABLE(uint32_t, U, name, val, txt)
#define PHI_DEFINE_int64(name, val, txt) \
PHI_DEFINE_VARIABLE(int64_t, I64, name, val, txt)
#define PHI_DEFINE_uint64(name, val, txt) \
PHI_DEFINE_VARIABLE(uint64_t, U64, name, val, txt)
#define PHI_DEFINE_double(name, val, txt) \
PHI_DEFINE_VARIABLE(double, D, name, val, txt)
#ifdef PADDLE_WITH_GFLAGS
#define PHI_DECLARE_string(name) \
namespace fLS { \
extern PHI_IMPORT_FLAG ::fLS::clstring& FLAGS_##name; \
} \
using fLS::FLAGS_##name
#define PHI_DEFINE_string(name, val, txt) \
namespace fLS { \
using ::fLS::clstring; \
clstring FLAGS_##name##_default = val; \
clstring FLAGS_##name##_current = val; \
static GFLAGS_NAMESPACE::FlagRegisterer o_##name(#name, \
MAYBE_STRIPPED_HELP(txt), \
__FILE__, \
&FLAGS_##name##_current, \
&FLAGS_##name##_default); \
PHI_EXPORT_FLAG clstring& FLAGS_##name = FLAGS_##name##_current; \
} /* NOLINT */ \
using ::fLS::FLAGS_##name
#else
#define PHI_DECLARE_string(name) PHI_DECLARE_VARIABLE(std::string, S, name)
#define PHI_DEFINE_string(name, val, txt) \
PHI_DEFINE_VARIABLE(std::string, S, name, val, txt)
#endif
namespace phi {
struct FlagInfo {
using ValueType =
paddle::variant<bool, int32_t, int64_t, uint64_t, double, std::string>;
std::string name;
mutable void* value_ptr;
ValueType default_value;
std::string doc;
bool is_writable;
};
using ExportedFlagInfoMap = std::map<std::string, FlagInfo>;
PADDLE_API const ExportedFlagInfoMap& GetExportedFlagInfoMap();
PADDLE_API ExportedFlagInfoMap* GetMutableExportedFlagInfoMap();
#define __PHI_DEFINE_EXPORTED_FLAG( \
__name, __is_writable, __cpp_type, __gflag_type, __default_value, __doc) \
PHI_DEFINE_##__gflag_type(__name, __default_value, __doc); \
struct __PaddleRegisterFlag_##__name { \
__PaddleRegisterFlag_##__name() { \
using FlagDeclaredType = \
typename std::remove_reference<decltype(FLAGS_##__name)>::type; \
static_assert(std::is_same<FlagDeclaredType, ::std::string>::value || \
std::is_arithmetic<FlagDeclaredType>::value, \
"FLAGS should be std::string or arithmetic type"); \
auto* instance = ::phi::GetMutableExportedFlagInfoMap(); \
auto& info = (*instance)[#__name]; \
info.name = #__name; \
info.value_ptr = &(FLAGS_##__name); \
info.default_value = static_cast<__cpp_type>(__default_value); \
info.doc = __doc; \
info.is_writable = __is_writable; \
} \
int Touch() const { return 0; } \
}; \
static __PaddleRegisterFlag_##__name __PaddleRegisterFlag_instance##__name; \
PADDLE_API int TouchPaddleFlagRegister_##__name() { \
return __PaddleRegisterFlag_instance##__name.Touch(); \
} \
static_assert(std::is_same<__PaddleRegisterFlag_##__name, \
::__PaddleRegisterFlag_##__name>::value, \
"FLAGS should define in global namespace")
#define PADDLE_FORCE_LINK_FLAG(__name) \
PADDLE_API extern int TouchPaddleFlagRegister_##__name(); \
UNUSED static int __paddle_use_flag_##__name = \
TouchPaddleFlagRegister_##__name()
#define PHI_DEFINE_EXPORTED_bool(name, default_value, doc) \
__PHI_DEFINE_EXPORTED_FLAG(name, true, bool, bool, default_value, doc)
#define PHI_DEFINE_EXPORTED_READONLY_bool(name, default_value, doc) \
__PHI_DEFINE_EXPORTED_FLAG(name, false, bool, bool, default_value, doc)
#define PHI_DEFINE_EXPORTED_int32(name, default_value, doc) \
__PHI_DEFINE_EXPORTED_FLAG(name, true, int32_t, int32, default_value, doc)
#define PHI_DEFINE_EXPORTED_int64(name, default_value, doc) \
__PHI_DEFINE_EXPORTED_FLAG(name, true, int64_t, int64, default_value, doc)
#define PHI_DEFINE_EXPORTED_uint64(name, default_value, doc) \
__PHI_DEFINE_EXPORTED_FLAG(name, true, uint64_t, uint64, default_value, doc)
#define PHI_DEFINE_EXPORTED_double(name, default_value, doc) \
__PHI_DEFINE_EXPORTED_FLAG(name, true, double, double, default_value, doc)
#define PHI_DEFINE_EXPORTED_string(name, default_value, doc) \
__PHI_DEFINE_EXPORTED_FLAG( \
name, true, ::std::string, string, default_value, doc)
} // namespace phi