Skip to content

Commit 1fc2b80

Browse files
cyyevermeta-codesync[bot]
authored andcommitted
Fix int32 overflow in segment_sum_csr and harden grid-size / num_valid narrowings (#5877)
Summary: X-link: https://github.com/facebookresearch/FBGEMM/pull/2806 Pull Request resolved: #5877 Reviewed By: henrylhtsang Differential Revision: D108339702 Pulled By: q10 fbshipit-source-id: 4c1080322bcc2175b785c551edf3e9ee7893f79f
1 parent 1864530 commit 1fc2b80

1 file changed

Lines changed: 17 additions & 9 deletions

File tree

fbgemm_gpu/src/sparse_ops/sparse_segment_sum_csr.cu

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9+
#include <limits>
10+
911
#include "common.cuh"
1012

1113
using Tensor = at::Tensor;
@@ -16,26 +18,27 @@ namespace fbgemm_gpu {
1618
// See https://moderngpu.github.io/segreduce.html
1719
template <typename values_t, typename index_t>
1820
__global__ __launch_bounds__(kMaxThreads) void _segment_sum_csr_cuda_kernel(
19-
int num_segments,
20-
int batch_size,
21+
int64_t batch_size,
2122
const index_t* csr_seg_data,
2223
const values_t* values_data,
2324
values_t* output_data) {
2425
typedef FBGEMM_GPU_CUB_NS_PREFIX cub::BlockReduce<values_t, 256> BlockReduce;
2526

2627
__shared__ typename BlockReduce::TempStorage temp_storage;
27-
index_t seg_start = csr_seg_data[blockIdx.x] * batch_size;
28-
index_t seg_end = csr_seg_data[blockIdx.x + 1] * batch_size;
28+
int64_t seg_start = csr_seg_data[blockIdx.x] * batch_size;
29+
int64_t seg_end = csr_seg_data[blockIdx.x + 1] * batch_size;
2930
values_t sum = 0;
3031

31-
for (index_t i = seg_start; i < seg_end; i += blockDim.x) {
32+
for (int64_t i = seg_start; i < seg_end; i += blockDim.x) {
3233
values_t thread_data;
3334
if (threadIdx.x < seg_end - i) {
3435
thread_data = values_data[i + threadIdx.x];
3536
}
3637

37-
values_t aggregate =
38-
BlockReduce(temp_storage).Sum(thread_data, seg_end - i);
38+
// cap at blockDim.x to fit cub's int num_valid without truncation
39+
const int num_valid =
40+
static_cast<int>(seg_end - i < blockDim.x ? seg_end - i : blockDim.x);
41+
values_t aggregate = BlockReduce(temp_storage).Sum(thread_data, num_valid);
3942

4043
__syncthreads();
4144

@@ -66,7 +69,13 @@ DLL_PUBLIC Tensor segment_sum_csr_cuda(
6669
}
6770

6871
constexpr uint32_t threads_per_block = 256;
69-
const uint32_t num_blocks = csr_seg.numel() - 1;
72+
const int64_t num_segments = csr_seg.numel() - 1;
73+
TORCH_CHECK(
74+
num_segments <= std::numeric_limits<int32_t>::max(),
75+
"segment_sum_csr: number of segments (",
76+
num_segments,
77+
") exceeds the maximum CUDA grid dimension");
78+
const uint32_t num_blocks = static_cast<uint32_t>(num_segments);
7079

7180
FBGEMM_DISPATCH_ALL_TYPES(
7281
values.scalar_type(), "_segment_sum_csr_cuda_1", [&] {
@@ -79,7 +88,6 @@ DLL_PUBLIC Tensor segment_sum_csr_cuda(
7988
threads_per_block,
8089
0,
8190
at::cuda::getCurrentCUDAStream(),
82-
csr_seg.numel() - 1,
8391
batch_size,
8492
csr_seg.data_ptr<index_t>(),
8593
values.data_ptr<values_t>(),

0 commit comments

Comments
 (0)