已合并
feat: 校验 deterministic 与 level 一致性 #4247
feat: 校验 deterministic 与 level 一致性 #4247
已合并
ClarkXie创建于 8月3日
8 个文件变更+208-4
@@ -196,6 +196,7 @@ const char *const kRawCompileOptionsGraph = "graph";
196const char *const kCliOptionPrefix = "--";196const char *const kCliOptionPrefix = "--";
197const char *const kMultiStreamParallelModeFlag = "multi_stream_parallel_mode";197const char *const kMultiStreamParallelModeFlag = "multi_stream_parallel_mode";
198const char *const kMultiStreamParallelModeOption = "--multi_stream_parallel_mode";198const char *const kMultiStreamParallelModeOption = "--multi_stream_parallel_mode";
199+const char *const kDeterministicLevelFlag = "deterministic_level";
199const std::set<std::string> kRawNonReplaceableCliOptions = {"model", "output", "framework", "soc_version"};200const std::set<std::string> kRawNonReplaceableCliOptions = {"model", "output", "framework", "soc_version"};
200 201 
201std::set<std::string> &GetRawAppliedFlagNames() {202std::set<std::string> &GetRawAppliedFlagNames() {
@@ -208,11 +209,13 @@ std::map<std::string, std::string> &GetRawAppliedFlagOptions() {
208 return raw_applied_flag_options;209 return raw_applied_flag_options;
209}210}
210 211 
212+bool IsDeterministicLevelExplicitlySet() {
213+ return (flgs::GetUserOptions().count(kDeterministicLevelFlag) > 0U) ||
214+ (GetRawAppliedFlagNames().count(kDeterministicLevelFlag) > 0U);
215+}
216+ 
211void AppendDeterministicLevelOption(std::map<std::string, std::string> &options) {217void AppendDeterministicLevelOption(std::map<std::string, std::string> &options) {
212- constexpr const char *kDeterministicLevelFlag = "deterministic_level";218+ if (IsDeterministicLevelExplicitlySet()) {
213- const bool is_explicitly_set = (flgs::GetUserOptions().count(kDeterministicLevelFlag) > 0U) ||
214- (GetRawAppliedFlagNames().count(kDeterministicLevelFlag) > 0U);
215- if (is_explicitly_set) {
216 options.emplace("ge.deterministicLevel", FLAGS_deterministic_level);219 options.emplace("ge.deterministicLevel", FLAGS_deterministic_level);
217 }220 }
218}221}
@@ -2292,8 +2295,23 @@ Status CheckDeprecatedAutoTuneMode() {
2292 return FAILED;2295 return FAILED;
2293}2296}
2294 2297 
2298+static Status CheckDeterministicLevelOption() {
2299+ if (!IsDeterministicLevelExplicitlySet()) {
2300+ return SUCCESS;
2301+ }
2302+ int32_t deterministic = 0;
2303+ GE_ASSERT_SUCCESS(ConvertDeterministicOptionToInt32("--deterministic", FLAGS_deterministic, deterministic),
2304+ "[Convert][Param:deterministic] failed.");
2305+ int32_t deterministic_level = 0;
2306+ GE_ASSERT_SUCCESS(
2307+ ConvertDeterministicOptionToInt32("--deterministic_level", FLAGS_deterministic_level, deterministic_level),
2308+ "[Convert][Param:deterministic_level] failed.");
2309+ return CheckDeterministicConfig(deterministic, deterministic_level);
2310+}
2311+ 
2295Status CheckGlobalOptionsBeforeRun() {2312Status CheckGlobalOptionsBeforeRun() {
2296 GE_ASSERT_SUCCESS(CheckDeprecatedAutoTuneMode(), "[Check][AutoTuneMode]failed.");2313 GE_ASSERT_SUCCESS(CheckDeprecatedAutoTuneMode(), "[Check][AutoTuneMode]failed.");
2314+ GE_ASSERT_SUCCESS(CheckDeterministicLevelOption(), "[Check][Deterministic]failed.");
2297 return SUCCESS;2315 return SUCCESS;
2298}2316}
2299 2317 
@@ -373,6 +373,10 @@ static graphStatus CheckGlobalOptions(std::map<std::string, std::string> &global
373 }373 }
374 GE_ASSERT_SUCCESS(CheckScreenPrinterOption(global_options), "[Check][ge.screen_print_mode]failed!");374 GE_ASSERT_SUCCESS(CheckScreenPrinterOption(global_options), "[Check][ge.screen_print_mode]failed!");
375 GE_ASSERT_GRAPH_SUCCESS(CheckOptimizationOptionValid(global_options));375 GE_ASSERT_GRAPH_SUCCESS(CheckOptimizationOptionValid(global_options));
376+ 
377+ // check deterministic and deterministic_level consistency
378+ GE_ASSERT_SUCCESS(CheckDeterministicOptionsValid(global_options), "[Check][DeterministicConfig] failed!");
379+ 
376 return GRAPH_SUCCESS;380 return GRAPH_SUCCESS;
377}381}
378 382 
@@ -28,6 +28,7 @@
28#include "graph/ge_context.h"28#include "graph/ge_context.h"
29#include "common/checker.h"29#include "common/checker.h"
30#include "graph/compute_graph.h"30#include "graph/compute_graph.h"
31+#include "register/op_tiling/op_tiling_constants.h"
31#include "graph/utils/type_utils.h"32#include "graph/utils/type_utils.h"
32#include "graph/utils/type_utils_inner.h"33#include "graph/utils/type_utils_inner.h"
33#include "graph/utils/tensor_utils.h"34#include "graph/utils/tensor_utils.h"
@@ -953,6 +954,68 @@ Status CheckAttrCompressionParamValid(const std::string &enable_attr_compression
953 return SUCCESS;954 return SUCCESS;
954}955}
955 956 
957+Status CheckDeterministicConfig(int32_t deterministic, int32_t deterministic_level) {
958+ if ((deterministic == 0) != (deterministic_level == 0)) {
959+ std::string val_str = std::to_string(deterministic) + " / " + std::to_string(deterministic_level);
960+ const char *reason = "must both be 0 or both non-zero.";
961+ REPORT_PREDEFINED_ERR_MSG(
962+ "E10001", std::vector<const char *>({"parameter", "value", "reason"}),
963+ std::vector<const char *>({"ge.deterministic / ge.deterministicLevel", val_str.c_str(), reason}));
964+ GELOGE(PARAM_INVALID, "[Check][Param:ge.deterministic/ge.deterministicLevel] value:%s is invalid. %s",
965+ val_str.c_str(), reason);
966+ return PARAM_INVALID;
967+ }
968+ return SUCCESS;
969+}
970+ 
971+Status ConvertDeterministicOptionToInt32(const std::string &parameter, const std::string &option_value,
972+ int32_t &result) {
973+ if (ge::ConvertToInt32(option_value, result) != SUCCESS) {
974+ const char *reason = "must be an integer.";
975+ REPORT_PREDEFINED_ERR_MSG("E10001", std::vector<const char *>({"parameter", "value", "reason"}),
976+ std::vector<const char *>({parameter.c_str(), option_value.c_str(), reason}));
977+ GELOGE(PARAM_INVALID, "[Check][Param:%s] value:%s is invalid. %s", parameter.c_str(), option_value.c_str(), reason);
978+ return PARAM_INVALID;
979+ }
980+ return SUCCESS;
981+}
982+ 
983+Status CheckDeterministicOptionsValid(const std::map<std::string, std::string> &options) {
984+ int32_t deterministic = 0;
985+ auto it_det = options.find(ge::DETERMINISTIC);
986+ if (it_det != options.end()) {
987+ GE_ASSERT_SUCCESS(ConvertDeterministicOptionToInt32(ge::DETERMINISTIC, it_det->second, deterministic),
988+ "[Convert][Param:%s] failed.", ge::DETERMINISTIC.c_str());
989+ if (deterministic < 0 || deterministic > optiling::kMaxDeterministic) {
990+ const char *reason = "must be in {0,1}.";
991+ REPORT_PREDEFINED_ERR_MSG("E10001", std::vector<const char *>({"parameter", "value", "reason"}),
992+ std::vector<const char *>({ge::DETERMINISTIC.c_str(), it_det->second.c_str(), reason}));
993+ GELOGE(PARAM_INVALID, "[Check][Param:%s] value:%s is invalid. %s", ge::DETERMINISTIC.c_str(),
994+ it_det->second.c_str(), reason);
995+ return PARAM_INVALID;
996+ }
997+ }
998+ 
999+ auto it_det_level = options.find(ge::DETERMINISTIC_LEVEL);
1000+ if (it_det_level == options.end()) {
1001+ return SUCCESS;
1002+ }
1003+ int32_t deterministic_level = 0;
1004+ GE_ASSERT_SUCCESS(
1005+ ConvertDeterministicOptionToInt32(ge::DETERMINISTIC_LEVEL, it_det_level->second, deterministic_level),
1006+ "[Convert][Param:%s] failed.", ge::DETERMINISTIC_LEVEL.c_str());
1007+ if (deterministic_level < 0 || deterministic_level > optiling::kMaxDeterministicLevel) {
1008+ const char *reason = "must be in {0,1,2,3}.";
1009+ REPORT_PREDEFINED_ERR_MSG(
1010+ "E10001", std::vector<const char *>({"parameter", "value", "reason"}),
1011+ std::vector<const char *>({ge::DETERMINISTIC_LEVEL.c_str(), it_det_level->second.c_str(), reason}));
1012+ GELOGE(PARAM_INVALID, "[Check][Param:%s] value:%s is invalid. %s", ge::DETERMINISTIC_LEVEL.c_str(),
1013+ it_det_level->second.c_str(), reason);
atomgit-bot
atomgit-botatomgit-bot8月3日

🟡 Medium Priority

changed line → affected behavior/contract → failure mode → suggested fix

option_utils.cc:992:996 处,ge::ConvertToInt32(it_det->second, deterministic)ge::ConvertToInt32(it_det_level->second, deterministic_level) 的返回值被 (void) 丢弃。

当 options map 中 ge.deterministicge.deterministicLevel 的值为非数值字符串时(如用户误配 "true"、空字符串以外的非法串),转换失败但 deterministic / deterministic_level 保持 0,校验逻辑用错误值继续执行。

失败模式与 main_impl.cc 中的问题相同:

  1. 两个值均为非法 → 被当作 (0,0) → SUCCESS,无效配置静默通过;
  2. 一个非法被当作 0,另一个合法 → 一致性检查基于错误值报错。

此函数被 aclgrphBuildInitialize(IR 构图路径)和 GELib::Initialize 调用,影响面较广。

修复方向:检查两次 ConvertToInt32 的返回值,转换失败时记录具体参数名和原始值,返回 PARAM_INVALID

建议:在两次 ConvertToInt32 后检查返回值,转换失败时记录错误并返回 PARAM_INVALID,与同一代码库中 op_tiling_rt2.cc 的防御模式保持一致。

改动建议
1013
+ int32_t deterministic = 0;
1014
+ auto it_det = options.find(ge::DETERMINISTIC);
1015
+ if (it_det != options.end() && !it_det->second.empty()) {
1016
+ if (ge::ConvertToInt32(it_det->second, deterministic) != ge::SUCCESS) {
1017
+ GELOGE(PARAM_INVALID, "[Check][Param:ge.deterministic] value:%s is not a valid int32.",
1018
+ it_det->second.c_str());
1019
+ return PARAM_INVALID;
1020
+ }
1021
+ }
1022
+ int32_t deterministic_level = 0;
1023
+ if (!it_det_level->second.empty()) {
1024
+ if (ge::ConvertToInt32(it_det_level->second, deterministic_level) != ge::SUCCESS) {
1025
+ GELOGE(PARAM_INVALID, "[Check][Param:ge.deterministicLevel] value:%s is not a valid int32.",
1013
- it_det_level->second.c_str(), reason);
1026
+ it_det_level->second.c_str());
1027
+ return PARAM_INVALID;
1028
+ }
1029
+ }
1030
+ return CheckDeterministicConfigValid(deterministic, deterministic_level);
应用建议
likedislike
1014+ return PARAM_INVALID;
1015+ }
1016+ return CheckDeterministicConfig(deterministic, deterministic_level);
1017+}
1018+ 
956Status CheckKeepTypeParamValid(const std::string &keep_dtype) {1019Status CheckKeepTypeParamValid(const std::string &keep_dtype) {
957 if ((!keep_dtype.empty()) && (!CheckInputPathValid(keep_dtype, "--keep_dtype"))) {1020 if ((!keep_dtype.empty()) && (!CheckInputPathValid(keep_dtype, "--keep_dtype"))) {
958 REPORT_PREDEFINED_ERR_MSG("E10001", std::vector<const char *>({"parameter", "value", "reason"}),1021 REPORT_PREDEFINED_ERR_MSG("E10001", std::vector<const char *>({"parameter", "value", "reason"}),
@@ -119,6 +119,10 @@ Status CheckModifyMixlistParamValid(const std::map<std::string, std::string> &op
119Status CheckModifyMixlistParamValid(const std::string &precision_mode, const std::string &precision_mode_v2,119Status CheckModifyMixlistParamValid(const std::string &precision_mode, const std::string &precision_mode_v2,
120 const std::string &modify_mixlist);120 const std::string &modify_mixlist);
121Status CheckAllowHF32ParamValid(const std::string &allow_hf32);121Status CheckAllowHF32ParamValid(const std::string &allow_hf32);
122+Status ConvertDeterministicOptionToInt32(const std::string &parameter, const std::string &option_value,
123+ int32_t &result);
124+Status CheckDeterministicConfig(int32_t deterministic, int32_t deterministic_level);
125+Status CheckDeterministicOptionsValid(const std::map<std::string, std::string> &options);
122Status CheckInputFormat(const std::string &input_format);126Status CheckInputFormat(const std::string &input_format);
123Status CheckKeepTypeParamValid(const std::string &keep_dtype);127Status CheckKeepTypeParamValid(const std::string &keep_dtype);
124void PrintOptionMap(const std::map<std::string, std::string> &options, std::string tips,128void PrintOptionMap(const std::map<std::string, std::string> &options, std::string tips,
@@ -28,6 +28,7 @@
28#include "graph/manager/graph_var_manager.h"28#include "graph/manager/graph_var_manager.h"
29#include "graph/manager/graph_external_weight_manager.h"29#include "graph/manager/graph_external_weight_manager.h"
30#include "host_cpu_engine/host_cpu_engine.h"30#include "host_cpu_engine/host_cpu_engine.h"
31+#include "api/aclgrph/option_utils.h"
31#include "engines/manager/opskernel_manager/ops_kernel_builder_manager.h"32#include "engines/manager/opskernel_manager/ops_kernel_builder_manager.h"
32#include "register/core_num_utils.h"33#include "register/core_num_utils.h"
33#include "acl/acl_rt.h"34#include "acl/acl_rt.h"
@@ -155,6 +156,7 @@ Status GELib::Initialize(const std::map<std::string, std::string> &options) {
155 156 
156 GE_INIT_TRACE_TIMESTAMP_END(GELibInitializePrepare, "GELib::InitializePrepare");157 GE_INIT_TRACE_TIMESTAMP_END(GELibInitializePrepare, "GELib::InitializePrepare");
157 GE_TRACE_START(Init);158 GE_TRACE_START(Init);
159+ GE_ASSERT_SUCCESS(CheckDeterministicOptionsValid(new_options), "[Check][DeterministicConfig]failed.");
158 ret = instancePtr_->InnerInitialize(new_options);160 ret = instancePtr_->InnerInitialize(new_options);
159 if (ret != SUCCESS) {161 if (ret != SUCCESS) {
160 GELOGE(ret, "[Init][GeLib]GeLib initial failed.");162 GELOGE(ret, "[Init][GeLib]GeLib initial failed.");
@@ -449,6 +449,25 @@ TEST_F(GeIrBuildTest, TestBuildOptions) {
449 aclgrphBuildInitialize(init_options);449 aclgrphBuildInitialize(init_options);
450}450}
451 451 
452+TEST_F(GeIrBuildTest, TestDeterministicOptionsInvalid) {
453+ std::map<std::string, std::string> init_options = {{ge::DETERMINISTIC, "abc"}};
454+ EXPECT_EQ(aclgrphBuildInitialize(init_options), GRAPH_PARAM_INVALID);
455+ 
456+ init_options[ge::DETERMINISTIC] = "2";
457+ EXPECT_EQ(aclgrphBuildInitialize(init_options), GRAPH_PARAM_INVALID);
458+ 
459+ init_options[ge::DETERMINISTIC] = "1";
460+ init_options[ge::DETERMINISTIC_LEVEL] = "abc";
461+ EXPECT_EQ(aclgrphBuildInitialize(init_options), GRAPH_PARAM_INVALID);
462+ 
463+ init_options[ge::DETERMINISTIC_LEVEL] = "4";
464+ EXPECT_EQ(aclgrphBuildInitialize(init_options), GRAPH_PARAM_INVALID);
465+ 
466+ init_options[ge::DETERMINISTIC] = "0";
467+ init_options[ge::DETERMINISTIC_LEVEL] = "2";
468+ EXPECT_EQ(aclgrphBuildInitialize(init_options), GRAPH_PARAM_INVALID);
469+}
470+ 
452TEST_F(GeIrBuildTest, TestBuildModelOm2UnsupportedGlobalOption) {471TEST_F(GeIrBuildTest, TestBuildModelOm2UnsupportedGlobalOption) {
453 aclgrphBuildFinalize();472 aclgrphBuildFinalize();
454 std::map<std::string, std::string> init_options = {473 std::map<std::string, std::string> init_options = {
@@ -709,6 +709,59 @@ TEST(UtestIrCommon, check_external_weight_param_succ) {
709 EXPECT_EQ(ret, SUCCESS);709 EXPECT_EQ(ret, SUCCESS);
710}710}
711 711 
712+TEST(UtestIrCommon, check_deterministic_config) {
713+ // Both zero → valid
714+ Status ret = CheckDeterministicConfig(0, 0);
715+ EXPECT_EQ(ret, SUCCESS);
716+ 
717+ // Both non-zero → valid
718+ ret = CheckDeterministicConfig(1, 1);
719+ EXPECT_EQ(ret, SUCCESS);
720+ ret = CheckDeterministicConfig(1, 2);
721+ EXPECT_EQ(ret, SUCCESS);
722+ ret = CheckDeterministicConfig(1, 3);
723+ EXPECT_EQ(ret, SUCCESS);
724+ 
725+ // Inconsistent (one zero, one non-zero) → invalid
726+ ret = CheckDeterministicConfig(0, 1);
727+ EXPECT_EQ(ret, PARAM_INVALID);
728+ ret = CheckDeterministicConfig(1, 0);
729+ EXPECT_EQ(ret, PARAM_INVALID);
730+ ret = CheckDeterministicConfig(0, 2);
731+ EXPECT_EQ(ret, PARAM_INVALID);
732+}
733+ 
734+TEST(UtestIrCommon, convert_deterministic_option_to_int32) {
735+ int32_t option_value = 0;
736+ EXPECT_EQ(ConvertDeterministicOptionToInt32(ge::DETERMINISTIC, "1", option_value), SUCCESS);
737+ EXPECT_EQ(option_value, 1);
738+ EXPECT_EQ(ConvertDeterministicOptionToInt32(ge::DETERMINISTIC, "abc", option_value), PARAM_INVALID);
739+}
740+ 
741+TEST(UtestIrCommon, check_deterministic_options_invalid) {
742+ std::map<std::string, std::string> options = {{ge::DETERMINISTIC, "abc"}};
743+ EXPECT_EQ(CheckDeterministicOptionsValid(options), PARAM_INVALID);
744+ 
745+ options[ge::DETERMINISTIC] = "1abc";
746+ EXPECT_EQ(CheckDeterministicOptionsValid(options), PARAM_INVALID);
747+ 
748+ options[ge::DETERMINISTIC] = "";
749+ EXPECT_EQ(CheckDeterministicOptionsValid(options), PARAM_INVALID);
750+ 
751+ options[ge::DETERMINISTIC] = "2";
752+ EXPECT_EQ(CheckDeterministicOptionsValid(options), PARAM_INVALID);
753+ 
754+ options[ge::DETERMINISTIC] = "1";
755+ options[ge::DETERMINISTIC_LEVEL] = "";
756+ EXPECT_EQ(CheckDeterministicOptionsValid(options), PARAM_INVALID);
757+ 
758+ options[ge::DETERMINISTIC_LEVEL] = "3abc";
759+ EXPECT_EQ(CheckDeterministicOptionsValid(options), PARAM_INVALID);
760+ 
761+ options[ge::DETERMINISTIC_LEVEL] = "4";
762+ EXPECT_EQ(CheckDeterministicOptionsValid(options), PARAM_INVALID);
763+}
764+ 
712TEST(UtestIrBuild, test_subgraph) {765TEST(UtestIrBuild, test_subgraph) {
713 auto graph = BuildSubGraph();766 auto graph = BuildSubGraph();
714 WeightRefreshableGraphs split_graphs;767 WeightRefreshableGraphs split_graphs;
@@ -1374,6 +1427,46 @@ TEST(UtestIrBuild, aclgrphBuildInitialize_test_fail) {
1374 ge::aclgrphBuildFinalize();1427 ge::aclgrphBuildFinalize();
1375}1428}
1376 1429 
1430+TEST(UtestIrBuild, aclgrphBuildInitialize_without_deterministic_level_succ) {
1431+ std::map<std::string, std::string> global_options;
1432+ global_options[ge::DETERMINISTIC] = "1";
1433+ global_options[ge::OPTION_HOST_ENV_OS] = "linux";
1434+ global_options[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1435+ EXPECT_EQ(ge::aclgrphBuildInitialize(global_options), ge::GRAPH_SUCCESS);
1436+ ge::aclgrphBuildFinalize();
1437+}
1438+ 
1439+TEST(UtestIrBuild, aclgrphBuildInitialize_deterministic_inconsistent) {
1440+ // deterministic=0, level=2 → must fail (both must be 0 or both non-zero)
1441+ std::map<std::string, std::string> global_options;
1442+ global_options[ge::DETERMINISTIC] = "0";
1443+ global_options["ge.deterministicLevel"] = "2";
1444+ global_options[ge::OPTION_HOST_ENV_OS] = "linux";
1445+ global_options[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1446+ EXPECT_EQ(ge::aclgrphBuildInitialize(global_options), ge::GRAPH_PARAM_INVALID);
1447+ ge::aclgrphBuildFinalize();
1448+}
1449+ 
1450+TEST(UtestIrBuild, aclgrphBuildInitialize_deterministic_level_nonzero_det_zero) {
1451+ // deterministic=1, level=0 → must fail
1452+ std::map<std::string, std::string> global_options;
1453+ global_options[ge::DETERMINISTIC] = "1";
1454+ global_options["ge.deterministicLevel"] = "0";
1455+ global_options[ge::OPTION_HOST_ENV_OS] = "linux";
1456+ global_options[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1457+ EXPECT_EQ(ge::aclgrphBuildInitialize(global_options), ge::GRAPH_PARAM_INVALID);
1458+ ge::aclgrphBuildFinalize();
1459+}
1460+ 
1461+TEST(UtestIrBuild, aclgrphBuildInitialize_invalid_deterministic_value) {
1462+ std::map<std::string, std::string> global_options;
1463+ global_options[ge::DETERMINISTIC] = "abc";
1464+ global_options[ge::OPTION_HOST_ENV_OS] = "linux";
1465+ global_options[ge::OPTION_HOST_ENV_CPU] = "x86_64";
1466+ EXPECT_EQ(ge::aclgrphBuildInitialize(global_options), ge::GRAPH_PARAM_INVALID);
1467+ ge::aclgrphBuildFinalize();
1468+}
1469+ 
1377TEST(UtestIrBuild, check_compression_optimize_conf_test) {1470TEST(UtestIrBuild, check_compression_optimize_conf_test) {
1378 std::map<std::string, std::string> global_options2;1471 std::map<std::string, std::string> global_options2;
1379 global_options2[ge::COMPRESSION_OPTIMIZE_CONF] = "0";1472 global_options2[ge::COMPRESSION_OPTIMIZE_CONF] = "0";
@@ -369,6 +369,7 @@ TEST_F(UtestMain, MainImplTest_global_options) {
369 const_cast<char *>(output_arg.c_str()),369 const_cast<char *>(output_arg.c_str()),
370 "--soc_version=\"Ascend310\"",370 "--soc_version=\"Ascend310\"",
371 "--deterministic=1",371 "--deterministic=1",
372+ "--deterministic_level=2",
372 const_cast<char *>(op_arg.c_str()),373 const_cast<char *>(op_arg.c_str()),
373 "--input_format=NCHW",374 "--input_format=NCHW",
374 "--host_env_os=linux",375 "--host_env_os=linux",