run_regression_tests.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #!/usr/bin/env python
  2. # Runs one or more regression tests. Retries tests up to 3 times.
  3. #
  4. # Example usage:
  5. # $ python run_regression_tests.py regression-tests/cartpole-es-[tf|torch].yaml
  6. #
  7. # When using in BAZEL (with py_test), e.g. see in ray/rllib/BUILD:
  8. # py_test(
  9. # name = "run_regression_tests",
  10. # main = "tests/run_regression_tests.py",
  11. # tags = ["learning_tests"],
  12. # size = "medium", # 5min timeout
  13. # srcs = ["tests/run_regression_tests.py"],
  14. # data = glob(["tuned_examples/regression_tests/*.yaml"]),
  15. # # Pass `BAZEL` option and the path to look for yaml regression files.
  16. # args = ["BAZEL", "tuned_examples/regression_tests"]
  17. # )
  18. import argparse
  19. import os
  20. from pathlib import Path
  21. import sys
  22. import yaml
  23. import ray
  24. from ray.tune import run_experiments
  25. from ray.rllib import _register_all
  26. from ray.rllib.utils.deprecation import deprecation_warning
  27. parser = argparse.ArgumentParser()
  28. parser.add_argument(
  29. "--framework",
  30. choices=["jax", "tf2", "tf", "tfe", "torch"],
  31. default="tf",
  32. help="The deep learning framework to use.")
  33. parser.add_argument(
  34. "--yaml-dir",
  35. type=str,
  36. required=True,
  37. help="The directory in which to find all yamls to test.")
  38. parser.add_argument("--num-cpus", type=int, default=6)
  39. parser.add_argument(
  40. "--local-mode",
  41. action="store_true",
  42. help="Run ray in local mode for easier debugging.")
  43. # Obsoleted arg, use --framework=torch instead.
  44. parser.add_argument(
  45. "--torch",
  46. action="store_true",
  47. help="Runs all tests with PyTorch enabled.")
  48. if __name__ == "__main__":
  49. args = parser.parse_args()
  50. # Bazel regression test mode: Get path to look for yaml files.
  51. # Get the path or single file to use.
  52. rllib_dir = Path(__file__).parent.parent
  53. print("rllib dir={}".format(rllib_dir))
  54. abs_yaml_path = os.path.join(rllib_dir, args.yaml_dir)
  55. # Single file given.
  56. if os.path.isfile(abs_yaml_path):
  57. yaml_files = [abs_yaml_path]
  58. # Given path/file does not exist.
  59. elif not os.path.isdir(abs_yaml_path):
  60. raise ValueError("yaml-dir ({}) not found!".format(args.yaml_dir))
  61. # Path given -> Get all yaml files in there via rglob.
  62. else:
  63. yaml_files = rllib_dir.rglob(args.yaml_dir + "/*.yaml")
  64. yaml_files = sorted(
  65. map(lambda path: str(path.absolute()), yaml_files), reverse=True)
  66. print("Will run the following regression tests:")
  67. for yaml_file in yaml_files:
  68. print("->", yaml_file)
  69. # Loop through all collected files.
  70. for yaml_file in yaml_files:
  71. experiments = yaml.safe_load(open(yaml_file).read())
  72. assert len(experiments) == 1,\
  73. "Error, can only run a single experiment per yaml file!"
  74. # Add torch option to exp config.
  75. exp = list(experiments.values())[0]
  76. exp["config"]["framework"] = args.framework
  77. if args.torch:
  78. deprecation_warning(old="--torch", new="--framework=torch")
  79. exp["config"]["framework"] = "torch"
  80. args.framework = "torch"
  81. # Always run with eager-tracing when framework=tf2.
  82. if args.framework in ["tf2", "tfe"]:
  83. exp["config"]["eager_tracing"] = True
  84. # Print out the actual config.
  85. print("== Test config ==")
  86. print(yaml.dump(experiments))
  87. # Try running each test 3 times and make sure it reaches the given
  88. # reward.
  89. passed = False
  90. for i in range(3):
  91. # Try starting a new ray cluster.
  92. try:
  93. ray.init(num_cpus=args.num_cpus, local_mode=args.local_mode)
  94. # Allow running this script on existing cluster as well.
  95. except ConnectionError:
  96. ray.init()
  97. else:
  98. try:
  99. trials = run_experiments(
  100. experiments, resume=False, verbose=2)
  101. finally:
  102. ray.shutdown()
  103. _register_all()
  104. for t in trials:
  105. # If we have evaluation workers, use their rewards.
  106. # This is useful for offline learning tests, where
  107. # we evaluate against an actual environment.
  108. check_eval = \
  109. exp["config"].get("evaluation_interval", None) is not None
  110. reward_mean = \
  111. t.last_result["evaluation"]["episode_reward_mean"] if \
  112. check_eval else t.last_result["episode_reward_mean"]
  113. # If we are using evaluation workers, we may have
  114. # a stopping criterion under the "evaluation/" scope. If
  115. # not, use `episode_reward_mean`.
  116. if check_eval:
  117. min_reward = t.stopping_criterion.get(
  118. "evaluation/episode_reward_mean",
  119. t.stopping_criterion.get("episode_reward_mean"))
  120. # Otherwise, expect `episode_reward_mean` to be set.
  121. else:
  122. min_reward = t.stopping_criterion.get(
  123. "episode_reward_mean")
  124. # If min reward not defined, always pass.
  125. if min_reward is None or reward_mean >= min_reward:
  126. passed = True
  127. break
  128. if passed:
  129. print("Regression test PASSED")
  130. break
  131. else:
  132. print("Regression test FAILED on attempt {}".format(i + 1))
  133. if not passed:
  134. print("Overall regression FAILED: Exiting with Error.")
  135. sys.exit(1)