| import os |
| from contextlib import ContextDecorator |
|
|
| import torch |
|
|
| ENABLE_LOGGING = int(os.getenv("TIME_BENCH", "0")) >= 1 |
| CLEAR_LOG_DATA = int(os.getenv("TIME_BENCH", "0")) == 2 |
|
|
|
|
| operator_log_data = {} |
|
|
|
|
| def clear_operator_log_data(): |
| operator_log_data.clear() |
|
|
|
|
| class TimeLoggingContext(ContextDecorator): |
| def __init__(self, operation_type): |
| self.operation_type = operation_type |
| self.start_event = None |
| self.end_event = None |
|
|
| def __enter__(self): |
| if ENABLE_LOGGING: |
| self.start_event = torch.cuda.Event(enable_timing=True) |
| self.end_event = torch.cuda.Event(enable_timing=True) |
| self.start_event.record() |
| return self |
|
|
| def __exit__(self, exc_type, exc_val, exc_tb): |
| if ENABLE_LOGGING: |
| self.end_event.record() |
| torch.cuda.synchronize() |
| duration = self.start_event.elapsed_time(self.end_event) |
| if self.operation_type not in operator_log_data: |
| operator_log_data[self.operation_type] = 0 |
| operator_log_data[self.operation_type] += duration |
|
|
|
|
| time_logging_decorator = TimeLoggingContext |
|
|
|
|
| def print_operator_log_data(module, input, output): |
| if not ENABLE_LOGGING: |
| return |
|
|
| from svg.timer import operator_log_data |
|
|
| max_key_length = max(len(str(key)) for key in operator_log_data.keys()) |
|
|
| |
| sorted_operator_log_data = dict(sorted(operator_log_data.items())) |
| operator_log_data.clear() |
| operator_log_data.update(sorted_operator_log_data) |
|
|
| |
| formatted_lines = [] |
| for key, value in operator_log_data.items(): |
| if CLEAR_LOG_DATA: |
| |
| formatted_value = format_aligned_decimal(value) |
| line = f"{key:<{max_key_length}} : {formatted_value:>4} ms" |
| else: |
| |
| formatted_value = format_aligned_decimal(value / 1000) |
| line = f"{key:<{max_key_length}} : {formatted_value:>4} s" |
| formatted_lines.append(line) |
| print("\n\n") |
|
|
| if CLEAR_LOG_DATA: |
| clear_operator_log_data() |
|
|
| |
| print("\n".join(formatted_lines)) |
|
|
|
|
| if __name__ == "__main__": |
| x = torch.randn(10000, 10000, device="cuda") |
|
|
| @time_logging_decorator("example_addition") |
| def example_function(x): |
| y = x + 1 |
| return y.cuda() |
|
|
| @time_logging_decorator("example_multiplication") |
| def another_function(x): |
| y = x @ x.T |
| return y.cuda() |
|
|
| for i in range(200): |
| result = example_function(x) |
| result = another_function(x) |
|
|
| print(operator_log_data) |
|
|
|
|
| def format_aligned_decimal(value, max_integer_digits=8, decimal_places=2): |
| """Format value, align decimal point""" |
| total_width = max_integer_digits + 1 + decimal_places |
| return f"{value:>{total_width}.{decimal_places}f}" |
|
|