parse_aio_stats.py 4.0 KB

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