Skip to content

Commit 999e405

Browse files
levythufacebook-github-bot
authored andcommitted
GPU timing and basic reporting framework (rebase of D52716004) (#2314)
Summary: Implements the reporting framework for internal state per TBE for better visibility. Pull Request resolved: #2314 Reviewed By: sryap Differential Revision: D53028585 fbshipit-source-id: fa8564068aef533b03aac93abf82c95969b2f9c2
1 parent 79e2329 commit 999e405

4 files changed

Lines changed: 105 additions & 1 deletion

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
8+
import abc
9+
10+
from dataclasses import dataclass
11+
from typing import Optional
12+
13+
14+
class TBEStatsReporter(abc.ABC):
15+
"""
16+
Interface for TBE runtime stats reporting. Actual implementation may do
17+
custome aggregation (on intended group-key) and reporting destination.
18+
19+
All the report_XXX functions should be light weighted and fail-safe.
20+
"""
21+
22+
@abc.abstractmethod
23+
def should_report(self, iteration_step: int) -> bool:
24+
"""
25+
Return whether we should report metrics during this step.
26+
This function should be cheap, side-effect free and return immediately.
27+
"""
28+
...
29+
30+
@abc.abstractmethod
31+
def report_duration(
32+
self,
33+
iteration_step: int,
34+
event_name: str,
35+
duration_ms: float,
36+
embedding_id: str = "",
37+
tbe_id: str = "",
38+
) -> None:
39+
"""
40+
Report the duration of a timed event.
41+
"""
42+
...
43+
44+
45+
@dataclass
46+
class TBEStatsReporterConfig:
47+
"""
48+
Configuration for TBEStatsReporter. It eventually instantiates the actual
49+
reporter, so it can be deep-copied without incurring the actual reporter
50+
getting copied.
51+
"""
52+
53+
# Collect required batches every given batches. Non-positive stands for
54+
# no collection or reporting
55+
interval: int = -1
56+
57+
def create_reporter(self) -> Optional[TBEStatsReporter]:
58+
assert (
59+
self.interval <= 0
60+
), "Cannot specify interval without an actual implementation of reporter"
61+
return None

fbgemm_gpu/fbgemm_gpu/split_table_batched_embeddings_ops_training.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from torch import nn, Tensor # usort:skip
2121

2222
import fbgemm_gpu.split_embedding_codegen_lookup_invokers as invokers
23+
from fbgemm_gpu.runtime_monitor import TBEStatsReporter, TBEStatsReporterConfig
2324
from fbgemm_gpu.split_embedding_configs import EmbOptimType as OptimType, SparseType
2425
from fbgemm_gpu.split_table_batched_embeddings_ops_common import (
2526
BoundsCheckMode,
@@ -349,6 +350,7 @@ def __init__( # noqa C901
349350
# If a separate stream is used for prefetch, the optional forward_stream arg of prefetch function
350351
# should be set.
351352
prefetch_pipeline: bool = False,
353+
stats_reporter_config: Optional[TBEStatsReporterConfig] = None,
352354
) -> None:
353355
super(SplitTableBatchedEmbeddingBagsCodegen, self).__init__()
354356

@@ -442,6 +444,13 @@ def __init__( # noqa C901
442444
# 0: N_calls, 1: N_requested_indices, 2: N_unique_indices, 3: N_unique_misses,
443445
# 4: N_conflict_unique_misses, 5: N_conflict_misses
444446

447+
# Reporter to collect runtime performance stats bottom-up. Reporter may
448+
# do aggregation across TBEs and publish results per training batch.
449+
# Example of stats include UVM cache hit rate, table I/O size, etc.
450+
self.stats_reporter: Optional[TBEStatsReporter] = (
451+
stats_reporter_config.create_reporter() if stats_reporter_config else None
452+
)
453+
445454
self.int8_emb_row_dim_offset: int = INT8_EMB_ROW_DIM_OFFSET
446455

447456
self.feature_table_map: List[int] = (

fbgemm_gpu/test/tbe/cache/cache_common.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77

88
# pyre-ignore-all-errors[56]
99

10-
from typing import Tuple
10+
from dataclasses import dataclass
11+
from typing import List, Optional, Tuple, Union
1112

1213
import numpy as np
1314
import torch
15+
from fbgemm_gpu.runtime_monitor import TBEStatsReporter, TBEStatsReporterConfig
1416
from fbgemm_gpu.split_embedding_configs import SparseType
1517

1618
from fbgemm_gpu.split_embedding_utils import round_up
@@ -37,6 +39,33 @@
3739
VERBOSITY: Verbosity = Verbosity.verbose
3840

3941

42+
class TestingStatsReporter(TBEStatsReporter):
43+
def __init__(self, reporting_interval: int = 1) -> None:
44+
self.reported_data: List[List[Union[int, str, float]]] = []
45+
self.reporting_interval = reporting_interval
46+
47+
def should_report(self, iteration_step: int) -> bool:
48+
return (iteration_step - 1) % self.reporting_interval == 0
49+
50+
def report_duration(
51+
self,
52+
iteration_step: int,
53+
event_name: str,
54+
duration_ms: float,
55+
embedding_id: str = "",
56+
tbe_id: str = "",
57+
) -> None:
58+
self.reported_data.append(
59+
[iteration_step, event_name, duration_ms, embedding_id, tbe_id]
60+
)
61+
62+
63+
@dataclass
64+
class TestingStatsReporterConfig(TBEStatsReporterConfig):
65+
def create_reporter(self) -> Optional[TBEStatsReporter]:
66+
return TestingStatsReporter(reporting_interval=self.interval)
67+
68+
4069
def generate_cache_tbes(
4170
T: int,
4271
D: int,
@@ -49,6 +78,7 @@ def generate_cache_tbes(
4978
weights_cache_precision: SparseType = SparseType.FP32,
5079
stochastic_rounding: bool = False,
5180
gather_uvm_cache_stats: bool = False,
81+
reporter_config: Optional[TestingStatsReporterConfig] = None,
5282
) -> Tuple[
5383
SplitTableBatchedEmbeddingBagsCodegen,
5484
SplitTableBatchedEmbeddingBagsCodegen,
@@ -105,6 +135,7 @@ def generate_cache_tbes(
105135
weights_precision=weights_cache_precision,
106136
cache_precision=weights_cache_precision,
107137
gather_uvm_cache_stats=gather_uvm_cache_stats,
138+
stats_reporter_config=reporter_config,
108139
)
109140

110141
if use_int_weight:

fbgemm_gpu/test/tbe/cache/cache_test.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
generate_cache_tbes,
3939
gpu_unavailable,
4040
optests,
41+
TestingStatsReporterConfig,
4142
VERBOSITY,
4243
)
4344

@@ -126,6 +127,7 @@ def _test_cache_prefetch_pipeline( # noqa C901
126127
"""
127128

128129
assert prefetch_location in ["before_fwd", "between_fwd_bwd"]
130+
reporter = TestingStatsReporterConfig(interval=2)
129131
cc, cc_ref, min_Es, sum_Ds = generate_cache_tbes(
130132
T,
131133
D,
@@ -137,6 +139,7 @@ def _test_cache_prefetch_pipeline( # noqa C901
137139
weights_cache_precision=weights_cache_precision,
138140
stochastic_rounding=stochastic_rounding,
139141
gather_uvm_cache_stats=gather_uvm_cache_stats,
142+
reporter_config=reporter,
140143
)
141144
iters = 5
142145
requests = generate_requests(iters, B, T, L, min_Es, reuse=0.1)

0 commit comments

Comments
 (0)