@@ -1457,6 +1457,107 @@ void cat_reorder_batched_ad_indices_cpu_(
14571457 });
14581458}
14591459
1460+ template <typename index_t , typename scalar_t >
1461+ void reorder_batched_sequence_embeddings_cpu_ (
1462+ const Tensor& cat_sequence_embeddings_offsets,
1463+ const Tensor& cat_sequence_embeddings,
1464+ const Tensor& reordered_cat_sequence_embeddings_offsets,
1465+ const Tensor& batch_offsets,
1466+ const int64_t num_items_in_batch,
1467+ const int32_t dim,
1468+ Tensor& output) {
1469+ const int64_t nB = batch_offsets.numel () - 1 ;
1470+ const int64_t nT = (reordered_cat_sequence_embeddings_offsets.numel () - 1 ) /
1471+ num_items_in_batch;
1472+
1473+ const auto * batch_offsets_data = batch_offsets.data_ptr <index_t >();
1474+ const auto * cat_sequence_embeddings_offsets_data =
1475+ cat_sequence_embeddings_offsets.data_ptr <index_t >();
1476+ const auto * reordered_cat_sequence_embeddings_offsets_data =
1477+ reordered_cat_sequence_embeddings_offsets.data_ptr <index_t >();
1478+ const auto * cat_sequence_embeddings_data =
1479+ cat_sequence_embeddings.data_ptr <scalar_t >();
1480+ auto * output_data = output.data_ptr <scalar_t >();
1481+ at::parallel_for (
1482+ 0 , nB * nT, FALSE_SHARING_PAD , [&](int64_t tb_begin, int64_t tb_end) {
1483+ auto b_begin = tb_begin / nT;
1484+ auto b_end = (tb_end + nT - 1 ) / nT;
1485+
1486+ for (const auto b : c10::irange (b_begin, b_end)) {
1487+ const auto num_ads_b =
1488+ batch_offsets_data[b + 1 ] - batch_offsets_data[b];
1489+ int64_t t_begin = (b == b_begin) ? tb_begin % nT : 0 ;
1490+ int64_t t_end =
1491+ (b == b_end - 1 && tb_end % nT != 0 ) ? tb_end % nT : nT;
1492+ for (const auto t : c10::irange (t_begin, t_end)) {
1493+ const auto output_segment_offset_start =
1494+ t * num_items_in_batch + batch_offsets_data[b];
1495+ const auto output_segment_start =
1496+ reordered_cat_sequence_embeddings_offsets_data
1497+ [output_segment_offset_start] *
1498+ dim;
1499+ const int32_t input_segment_offset_start =
1500+ nT * batch_offsets_data[b] + t * num_ads_b;
1501+ const int32_t input_segment_offset_end =
1502+ input_segment_offset_start + num_ads_b;
1503+ const auto input_segment_start =
1504+ cat_sequence_embeddings_offsets_data
1505+ [input_segment_offset_start] *
1506+ dim;
1507+ const auto input_segment_end =
1508+ cat_sequence_embeddings_offsets_data[input_segment_offset_end] *
1509+ dim;
1510+ const auto num_elements = (input_segment_end - input_segment_start);
1511+
1512+ for (auto i : c10::irange (num_elements)) {
1513+ // TODO memcpy once this path is heavily used?
1514+ output_data[output_segment_start + i] =
1515+ cat_sequence_embeddings_data[input_segment_start + i];
1516+ }
1517+ }
1518+ }
1519+ });
1520+ }
1521+
1522+ Tensor reorder_batched_sequence_embeddings_cpu (
1523+ const Tensor& cat_sequence_embeddings_offsets,
1524+ const Tensor& cat_sequence_embeddings,
1525+ const Tensor& reordered_cat_sequence_embeddings_offsets,
1526+ const Tensor& batch_offsets,
1527+ const int64_t num_items_in_batch) {
1528+ TENSOR_ON_CPU (cat_sequence_embeddings_offsets);
1529+ TENSOR_ON_CPU (cat_sequence_embeddings);
1530+ TENSOR_ON_CPU (reordered_cat_sequence_embeddings_offsets);
1531+ TENSOR_ON_CPU (batch_offsets);
1532+ TORCH_CHECK (cat_sequence_embeddings.dim () == 2 );
1533+ // reorder embeddings from (ragged) [B x T x #num_ads_B_{i} x length_{B_{i},
1534+ // t, a})x D] to [T][B][#num_ads_b][length_{b, t, a}][D], i.e.
1535+ // [sum(length_{B_{i}, t, a}), D]
1536+ Tensor reordered_cat_ad_indices = at::empty_like (
1537+ cat_sequence_embeddings, cat_sequence_embeddings.options ());
1538+
1539+ AT_DISPATCH_INDEX_TYPES (
1540+ cat_sequence_embeddings_offsets.scalar_type (),
1541+ " reorder_batched_sequence_embeddings_cpu_kernel_1" ,
1542+ [&] {
1543+ AT_DISPATCH_ALL_TYPES (
1544+ cat_sequence_embeddings.scalar_type (),
1545+ " reorder_eorder_batched_sequence_embeddings_cpu_kernel_2" ,
1546+ [&] {
1547+ reorder_batched_sequence_embeddings_cpu_<index_t , scalar_t >(
1548+ cat_sequence_embeddings_offsets,
1549+ cat_sequence_embeddings,
1550+ reordered_cat_sequence_embeddings_offsets,
1551+ batch_offsets,
1552+ num_items_in_batch,
1553+ cat_sequence_embeddings.size (1 ),
1554+ reordered_cat_ad_indices);
1555+ });
1556+ });
1557+
1558+ return reordered_cat_ad_indices;
1559+ }
1560+
14601561Tensor reorder_batched_ad_indices_cpu (
14611562 const Tensor& cat_ad_offsets,
14621563 const Tensor& cat_ad_indices,
@@ -2752,6 +2853,8 @@ TORCH_LIBRARY_FRAGMENT(fbgemm, m) {
27522853 m.def (
27532854 " asynchronous_complete_cumsum(Tensor t_in) -> Tensor" ,
27542855 {PT2_COMPLIANT_TAG });
2856+ m.def (
2857+ " reorder_batched_sequence_embeddings(Tensor cat_sequence_embeddings_offsets, Tensor cat_sequence_embeddings, Tensor reordered_cat_sequence_embeddings_offsets, Tensor batch_offsets, SymInt num_items_in_batch) -> Tensor" );
27552858 m.def (
27562859 " reorder_batched_ad_lengths(Tensor cat_ad_lengths, Tensor batch_offsets, SymInt num_ads_in_batch, bool broadcast_lengths=False) -> Tensor" );
27572860 m.def (
@@ -2856,6 +2959,9 @@ TORCH_LIBRARY_IMPL(fbgemm, CPU, m) {
28562959 DISPATCH_TO_CPU (
28572960 " cat_reorder_batched_ad_indices" ,
28582961 fbgemm_gpu::cat_reorder_batched_ad_indices_cpu);
2962+ DISPATCH_TO_CPU (
2963+ " reorder_batched_sequence_embeddings" ,
2964+ fbgemm_gpu::reorder_batched_sequence_embeddings_cpu);
28592965 DISPATCH_TO_CPU (" offsets_range" , fbgemm_gpu::offsets_range_cpu);
28602966 DISPATCH_TO_CPU (
28612967 " batched_unary_embeddings" ,
0 commit comments