-
Notifications
You must be signed in to change notification settings - Fork 11.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libc] Add utility functions for warp-level scan and reduction (#84866)
Summary: The GPU uses a SIMT execution model. That means that each value actually belongs to a group of 32 or 64 other lanes executing next to it. These platforms offer some intrinsic fuctions to actually take elements from neighboring lanes. With these we can do parallel scans or reductions. These functions do not have an immediate user, but will be used in the allocator interface that is in-progress and are generally good to have. This patch is a precommit for these new utilitly functions.
- Loading branch information
Showing
7 changed files
with
111 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
add_subdirectory(threads) | ||
if(LIBC_TARGET_OS_IS_GPU) | ||
add_subdirectory(GPU) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
add_custom_target(libc-support-gpu-tests) | ||
add_dependencies(libc-integration-tests libc-support-gpu-tests) | ||
|
||
add_integration_test( | ||
scan_reduce_test | ||
SUITE libc-support-gpu-tests | ||
SRCS | ||
scan_reduce.cpp | ||
LOADER_ARGS | ||
--threads 64 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
//===-- Test for the parallel scan and reduction operations on the GPU ----===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "src/__support/CPP/bit.h" | ||
#include "src/__support/GPU/utils.h" | ||
#include "test/IntegrationTest/test.h" | ||
|
||
using namespace LIBC_NAMESPACE; | ||
|
||
static uint32_t sum(uint32_t n) { return n * (n + 1) / 2; } | ||
|
||
// Tests a reduction within a convergant warp or wavefront using some known | ||
// values. For example, if every element in the lane is one, then the sum should | ||
// be the size of the warp or wavefront, i.e. 1 + 1 + 1 ... + 1. | ||
static void test_reduce() { | ||
uint64_t mask = gpu::get_lane_mask(); | ||
uint32_t x = gpu::reduce(mask, 1); | ||
EXPECT_EQ(x, gpu::get_lane_size()); | ||
|
||
uint32_t y = gpu::reduce(mask, gpu::get_lane_id()); | ||
EXPECT_EQ(y, sum(gpu::get_lane_size() - 1)); | ||
|
||
uint32_t z = 0; | ||
if (gpu::get_lane_id() % 2) | ||
z = gpu::reduce(gpu::get_lane_mask(), 1); | ||
gpu::sync_lane(mask); | ||
|
||
EXPECT_EQ(z, gpu::get_lane_id() % 2 ? gpu::get_lane_size() / 2 : 0); | ||
} | ||
|
||
// Tests an accumulation scan within a convergent warp or wavefront using some | ||
// known values. For example, if every element in the lane is one, then the scan | ||
// should have each element be equivalent to its ID, i.e. 1, 1 + 1, ... | ||
static void test_scan() { | ||
uint64_t mask = gpu::get_lane_mask(); | ||
|
||
uint32_t x = gpu::scan(mask, 1); | ||
EXPECT_EQ(x, gpu::get_lane_id() + 1); | ||
|
||
uint32_t y = gpu::scan(mask, gpu::get_lane_id()); | ||
EXPECT_EQ(y, sum(gpu::get_lane_id())); | ||
|
||
uint32_t z = 0; | ||
if (gpu::get_lane_id() % 2) | ||
z = gpu::scan(gpu::get_lane_mask(), 1); | ||
gpu::sync_lane(mask); | ||
|
||
EXPECT_EQ(z, gpu::get_lane_id() % 2 ? gpu::get_lane_id() / 2 + 1 : 0); | ||
} | ||
|
||
TEST_MAIN(int argc, char **argv, char **envp) { | ||
test_reduce(); | ||
|
||
test_scan(); | ||
|
||
return 0; | ||
} |