-
Notifications
You must be signed in to change notification settings - Fork 62
pyg::subgraph CUDA implementation
#42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
07f6a85
058c0bc
f85ff1e
4aa86b9
4bb8087
ef68b2b
377e261
9b5d9f7
9b4e6e6
bf23274
9113818
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,8 @@ namespace sampler { | |
|
|
||
| namespace { | ||
|
|
||
| #define FULL_MASK 0xffffffff | ||
|
|
||
| template <typename scalar_t> | ||
| __global__ void subgraph_deg_kernel_impl( | ||
| const scalar_t* __restrict__ rowptr_data, | ||
|
|
@@ -16,7 +18,24 @@ __global__ void subgraph_deg_kernel_impl( | |
| const scalar_t* __restrict__ to_local_node_data, | ||
| scalar_t* __restrict__ out_data, | ||
| int64_t num_nodes) { | ||
| CUDA_1D_KERNEL_LOOP(scalar_t, i, 32 * num_nodes) {} | ||
| CUDA_1D_KERNEL_LOOP(scalar_t, thread_idx, 32 * num_nodes) { | ||
| scalar_t i = thread_idx >> 5; // thread_idx / 32 | ||
| scalar_t lane = thread_idx & (32 - 1); // thread_idx % 32 | ||
|
|
||
| auto v = nodes_data[i]; | ||
|
|
||
| scalar_t deg = 0; | ||
| for (scalar_t j = rowptr_data[v] + lane; j < rowptr_data[v + 1]; j += 32) { | ||
| if (to_local_node_data[col_data[j]] >= 0) // contiguous access | ||
| deg++; | ||
| } | ||
|
|
||
| for (scalar_t offset = 16; offset > 0; offset /= 2) // warp-level reduction | ||
| deg += __shfl_down_sync(FULL_MASK, deg, offset); | ||
|
|
||
| if (lane == 0) | ||
| out_data[i] = deg; | ||
| } | ||
| } | ||
|
|
||
| std::tuple<at::Tensor, at::Tensor, c10::optional<at::Tensor>> subgraph_kernel( | ||
|
|
@@ -32,7 +51,7 @@ std::tuple<at::Tensor, at::Tensor, c10::optional<at::Tensor>> subgraph_kernel( | |
|
|
||
| // We maintain a O(N) vector to map global node indices to local ones. | ||
| // TODO Can we do this without O(N) storage requirement? | ||
| const auto to_local_node = nodes.new_empty({rowptr.size(0) - 1}); | ||
| const auto to_local_node = nodes.new_full({rowptr.size(0) - 1}, -1); | ||
| const auto arange = at::arange(nodes.size(0), nodes.options()); | ||
| to_local_node.index_copy_(/*dim=*/0, nodes, arange); | ||
|
|
||
|
|
@@ -48,6 +67,7 @@ std::tuple<at::Tensor, at::Tensor, c10::optional<at::Tensor>> subgraph_kernel( | |
| const auto to_local_node_data = to_local_node.data_ptr<scalar_t>(); | ||
| auto deg_data = deg.data_ptr<scalar_t>(); | ||
|
|
||
| // Compute induced subgraph degree, parallelize with 32 threads per node: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm actually not sure if it is necessary to parallelize with 32 threads per nodes. Most of the time we are dealing with sparse data and a lot of threads will not go into for loop. If you are looking for extreme performance, you can bundle
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you have an example of bundling I am okay with dropping the warp-level parallelism for now, but we will lose the contiguous access to
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On a second look, this doesn't seem possible since |
||
| subgraph_deg_kernel_impl<<<pyg::utils::blocks(32 * nodes.size(0)), | ||
| pyg::utils::threads(), 0, stream>>>( | ||
| rowptr_data, col_data, nodes_data, to_local_node_data, deg_data, | ||
|
|
@@ -57,7 +77,7 @@ std::tuple<at::Tensor, at::Tensor, c10::optional<at::Tensor>> subgraph_kernel( | |
| at::cumsum_out(tmp, deg, /*dim=*/0); | ||
| }); | ||
|
|
||
| return std::make_tuple(to_local_node, deg, rowptr); | ||
| return std::make_tuple(out_rowptr, deg, deg); | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.