parse_aio_stats.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. """
  2. Copyright 2020 The Microsoft DeepSpeed Team
  3. Licensed under the MIT license.
  4. Functionality of swapping optimizer tensors to/from (NVMe) storage devices.
  5. """
  6. import os
  7. import argparse
  8. READ_SPEED = 'read_speed'
  9. WRITE_SPEED = 'write_speed'
  10. PERF_METRICS = [READ_SPEED, WRITE_SPEED]
  11. METRIC_SEARCH = {READ_SPEED: 'E2E Read Speed', WRITE_SPEED: 'E2E Write Speed'}
  12. def parse_arguments():
  13. parser = argparse.ArgumentParser()
  14. parser.add_argument('--log_dir',
  15. type=str,
  16. required=True,
  17. help='Folder of statistics logs')
  18. parser.add_argument('--metric',
  19. type=str,
  20. required=True,
  21. help='Performance metric to report: [read_speed|write_speed]')
  22. args = parser.parse_args()
  23. print(f'args = {args}')
  24. return args
  25. def extract_value(key, file):
  26. INVALID_PREFIXES = ["ds"]
  27. for p in INVALID_PREFIXES:
  28. if key.startswith(p):
  29. return key
  30. try:
  31. if key[0] in ['t', 'd', 'p']:
  32. return int(key[1:])
  33. if key.startswith("bs"):
  34. if key.endswith('K'):
  35. v = key[2:].split('K')
  36. return int(v[0]) * 1024
  37. elif key.endswith('M'):
  38. v = key[2:].split('M')
  39. return int(v[0]) * 1024 * 1024
  40. else:
  41. return int(key[2:])
  42. except:
  43. print(f"{file}: extract_value fails on {key}")
  44. return None
  45. return key
  46. def get_file_key(file):
  47. f, _ = os.path.splitext(os.path.basename(file))
  48. fields = f.split('_')
  49. values = [extract_value(k, file) for k in fields]
  50. return tuple(values)
  51. def get_thread_count(file):
  52. f, _ = os.path.splitext(os.path.basename(file))
  53. fields = f.split('_')
  54. for key in fields:
  55. if key[0] == 't':
  56. return int(key[1:])
  57. return 1
  58. """
  59. Extract performance metric from log file.
  60. Sample file lines are:
  61. Task Read Latency = 0.031647682189941406 sec
  62. Task Read Speed = 12.342926020792527 GB/sec
  63. E2E Read Latency = 0.031697988510131836 sec
  64. E2E Read Speed = 12.323337169333062 GB/sec
  65. For the above sample, -metric = "read_speed" corresponds to "E2E Read Speed", and 12.32 will be returned
  66. """
  67. def get_metric(file, metric):
  68. thread_count = get_thread_count(file)
  69. with open(file) as f:
  70. for line in f.readlines():
  71. if line.startswith(METRIC_SEARCH[metric]):
  72. if metric in [READ_SPEED, WRITE_SPEED]:
  73. fields = line.split()
  74. return float(fields[-2])
  75. else:
  76. fields = line.split('=')
  77. return float(fields[-1])
  78. return None
  79. def validate_args(args):
  80. if not args.metric in PERF_METRICS:
  81. print(f'{args.metric} is not a valid performance metrics')
  82. return False
  83. if not os.path.isdir(args.log_dir):
  84. print(f'{args.log_dir} folder is not existent')
  85. return False
  86. return True
  87. def get_results(log_files, metric):
  88. results = {}
  89. for f in log_files:
  90. file_key = get_file_key(f)
  91. value = get_metric(f, metric)
  92. results[file_key] = value
  93. return results
  94. def get_sorted_results(log_dir, metric):
  95. log_files = [
  96. f for f in os.listdir(log_dir) if os.path.isfile(os.path.join(log_dir,
  97. f))
  98. ]
  99. log_files_path = [os.path.join(log_dir, f) for f in log_files]
  100. results = get_results(log_files_path, metric)
  101. result_keys = list(results.keys())
  102. sorted_keys = sorted(result_keys)
  103. return sorted_keys, results
  104. def main():
  105. print("Parsing aio statistics")
  106. args = parse_arguments()
  107. if not validate_args(args):
  108. quit()
  109. sorted_keys, results = get_sorted_results(args.log_dir, args.metric)
  110. for k in sorted_keys:
  111. print(f'{k} = {results[k]}')
  112. if __name__ == "__main__":
  113. main()