From 89c7161655a17cff5cf8c1b7aa678e36611a5f3b Mon Sep 17 00:00:00 2001 From: "G.O.D" <32255912+gameofdimension@users.noreply.github.com> Date: Thu, 19 Mar 2026 20:05:51 +0800 Subject: [PATCH 1/5] error handling for empty kv list --- corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py b/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py index 282f6165d..f3a7ab7e6 100644 --- a/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py +++ b/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py @@ -1207,6 +1207,10 @@ def export_keys_values( f"Rank {dist.get_rank()} has accumulated count {accumulated_counts} which is different from expected {local_max_rows}, " f"difference: {accumulated_counts - local_max_rows}" ) + + if len(keys_list) == 0: + assert len(values_list) == 0 + return torch.empty(0, device=device), torch.empty(0, device=device) return torch.cat(keys_list), torch.cat(values_list, dim=0) def incremental_dump( From a6c8e152844bffc1b0807554a96825ff3eaff209 Mon Sep 17 00:00:00 2001 From: "G.O.D" <32255912+gameofdimension@users.noreply.github.com> Date: Thu, 19 Mar 2026 20:15:24 +0800 Subject: [PATCH 2/5] Update corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py b/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py index f3a7ab7e6..1a773d2c9 100644 --- a/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py +++ b/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py @@ -1209,7 +1209,7 @@ def export_keys_values( ) if len(keys_list) == 0: - assert len(values_list) == 0 + return torch.empty(0, dtype=torch.int64, device=device), torch.empty(0, device=device) return torch.empty(0, device=device), torch.empty(0, device=device) return torch.cat(keys_list), torch.cat(values_list, dim=0) From 0955d388bfd3e4f11f13cd1ab6fbf3b6bfda5a16 Mon Sep 17 00:00:00 2001 From: "G.O.D" <32255912+gameofdimension@users.noreply.github.com> Date: Thu, 19 Mar 2026 20:18:06 +0800 Subject: [PATCH 3/5] Update batched_dynamicemb_tables.py --- corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py b/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py index 1a773d2c9..9c1c274a1 100644 --- a/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py +++ b/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py @@ -1209,8 +1209,7 @@ def export_keys_values( ) if len(keys_list) == 0: - return torch.empty(0, dtype=torch.int64, device=device), torch.empty(0, device=device) - return torch.empty(0, device=device), torch.empty(0, device=device) + return torch.empty(0, dtype=torch.int64, device=device), torch.empty(0, 0, device=device) return torch.cat(keys_list), torch.cat(values_list, dim=0) def incremental_dump( From f092a69b19be46ad2e370e3028e2af01e86d2e60 Mon Sep 17 00:00:00 2001 From: "felix01.yu" Date: Fri, 20 Mar 2026 15:40:18 +0800 Subject: [PATCH 4/5] fortmat code Signed-off-by: felix01.yu --- corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py b/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py index 9c1c274a1..9770bff77 100644 --- a/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py +++ b/corelib/dynamicemb/dynamicemb/batched_dynamicemb_tables.py @@ -1209,7 +1209,9 @@ def export_keys_values( ) if len(keys_list) == 0: - return torch.empty(0, dtype=torch.int64, device=device), torch.empty(0, 0, device=device) + return torch.empty(0, dtype=torch.int64, device=device), torch.empty( + 0, 0, device=device + ) return torch.cat(keys_list), torch.cat(values_list, dim=0) def incremental_dump( From b82c47fd99150490f57530026c0bca617660afe9 Mon Sep 17 00:00:00 2001 From: gameofdimension Date: Mon, 23 Mar 2026 04:43:20 +0000 Subject: [PATCH 5/5] test: add unit test for export_keys_values empty table guard Covers the empty keys_list early-return fix in export_keys_values, ensuring it returns empty tensors instead of crashing on torch.cat([]). --- ...est_batched_dynamic_embedding_tables_v2.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/corelib/dynamicemb/test/test_batched_dynamic_embedding_tables_v2.py b/corelib/dynamicemb/test/test_batched_dynamic_embedding_tables_v2.py index 22eae8737..6aaaa57ef 100644 --- a/corelib/dynamicemb/test/test_batched_dynamic_embedding_tables_v2.py +++ b/corelib/dynamicemb/test/test_batched_dynamic_embedding_tables_v2.py @@ -1143,3 +1143,36 @@ def test_empty_batch(opt_type, opt_params, dim, caching, deterministic, PS): del os.environ["DEMB_DETERMINISM_MODE"] print("all check passed") + + +def test_export_keys_values_empty_table(): + """export_keys_values() on a never-used table must return empty tensors + (not crash on torch.cat([])) -- covers the empty keys_list guard.""" + assert torch.cuda.is_available() + device = torch.device("cuda:0") + + opt = DynamicEmbTableOptions( + dim=8, + init_capacity=1024, + max_capacity=1024, + index_type=torch.int64, + embedding_dtype=torch.float32, + device_id=0, + score_strategy=DynamicEmbScoreStrategy.TIMESTAMP, + caching=False, + local_hbm_for_values=1024**3, + ) + bdebt = BatchedDynamicEmbeddingTablesV2( + table_names=["t0"], + table_options=[opt], + feature_table_map=[0], + pooling_mode=DynamicEmbPoolingMode.SUM, + optimizer=EmbOptimType.SGD, + learning_rate=0.1, + ) + + keys, values = bdebt.export_keys_values("t0", device) + + assert keys.shape == (0,) + assert keys.dtype == torch.int64 + assert values.shape[0] == 0