/* * Copyright (c) Advanced Micro Devices, Inc., or its affiliates. * * SPDX-License-Identifier: MIT */ #include "warp_common.hh" #include template __global__ void shfl_1(T* Input, T* Output) { int tid = threadIdx.x; // Creates groups consisting of every fourth thread. auto mask = __match_any_sync(AllThreads, tid % 4); int srcLane = tid % 4; // Each group reads from the first active thread within that group. Output[tid] = __shfl_sync(mask, Input[tid], srcLane); } template static void runTestShfl_1() { const int size = 64; T Input[size]; T Output[size]; T Expected[size]; int Values[size] = {0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3, 0, -1, 2, 3}; initializeInput(Input, size); initializeExpected(Expected, Values, size); int warpSize = getWarpSize(); T* d_Input; T* d_Output; HIP_CHECK(hipMalloc(&d_Input, sizeof(T) * size)); HIP_CHECK(hipMalloc(&d_Output, sizeof(T) * size)); HIP_CHECK(hipMemcpy(d_Input, &Input, sizeof(T) * size, hipMemcpyDefault)); hipLaunchKernelGGL(shfl_1, 1, warpSize, 0, 0, d_Input, d_Output); HIP_CHECK(hipMemcpy(&Output, d_Output, sizeof(T) * size, hipMemcpyDefault)); for (int i = 0; i != warpSize; ++i) { REQUIRE(compareEqual(Output[i], Expected[i])); } HIP_CHECK(hipFree(d_Input)); HIP_CHECK(hipFree(d_Output)); } template __global__ void shfl_2(T* Input, T* Output) { int tid = threadIdx.x; auto mask = __match_any_sync(AllThreads, tid % 4); int srcLane = tid % 4; // Each subgroup of eight reads from the first active thread within that // subgroup. Output[tid] = __shfl_sync(mask, Input[tid], srcLane, 8); } template static void runTestShfl_2() { const int size = 64; T Input[size]; T Output[size]; T Expected[size]; int Values[size] = {0, -1, 2, 3, 0, -1, 2, 3, 8, -9, 10, 11, 8, -9, 10, 11, 16, 17, -18, 19, 16, 17, -18, 19, 24, 25, 26, -27, 24, 25, 26, -27, -32, 33, 34, 35, -32, 33, 34, 35, 40, 41, 42, 43, 40, 41, 42, 43, 48, 49, 50, -51, 48, 49, 50, -51, 56, 57, -58, 59, 56, 57, -58, 59}; initializeInput(Input, size); initializeExpected(Expected, Values, size); int warpSize = getWarpSize(); T* d_Input; T* d_Output; HIP_CHECK(hipMalloc(&d_Input, sizeof(T) * size)); HIP_CHECK(hipMalloc(&d_Output, sizeof(T) * size)); HIP_CHECK(hipMemcpy(d_Input, &Input, sizeof(T) * size, hipMemcpyDefault)); hipLaunchKernelGGL(shfl_2, 1, warpSize, 0, 0, d_Input, d_Output); HIP_CHECK(hipMemcpy(&Output, d_Output, sizeof(T) * size, hipMemcpyDefault)); for (int i = 0; i != warpSize; ++i) { REQUIRE(compareEqual(Output[i], Expected[i])); } HIP_CHECK(hipFree(d_Input)); HIP_CHECK(hipFree(d_Output)); } __global__ void shfl_3(int* Input, int* Output) { auto tid = threadIdx.x; unsigned long long masks[2] = {Every5thBut9th, Every9thBit}; Output[tid] = -1; if (tid % 5 == 0 || tid % 9 == 0) Output[tid] = __shfl_sync(masks[tid % 9 == 0], Input[tid], tid); } static void runTestShfl_3() { size_t warpSize = getWarpSize(); auto Input = std::vector(warpSize); for (size_t i = 0; i < Input.size(); i++) { Input[i] = i; } auto Output = std::vector(warpSize); auto Expected = std::vector(warpSize); for (size_t i = 0; i < Expected.size(); i++) { if (i % 9 == 0 || i % 5 == 0) { Expected[i] = i; } else { Expected[i] = -1; } } int* d_Input; int* d_Output; HIP_CHECK(hipMalloc(&d_Input, Input.size() * sizeof(Input[0]))); HIP_CHECK(hipMalloc(&d_Output, Output.size() * sizeof(Output[0]))); HIP_CHECK(hipMemcpy(d_Input, Input.data(), Input.size() * sizeof(Input[0]), hipMemcpyDefault)); hipLaunchKernelGGL(shfl_3, 1, warpSize, 0, 0, d_Input, d_Output); HIP_CHECK( hipMemcpy(Output.data(), d_Output, Output.size() * sizeof(Output[0]), hipMemcpyDefault)); for (size_t i = 0; i < Output.size(); i++) { REQUIRE(Output[i] == Expected[i]); } HIP_CHECK(hipFree(d_Input)); HIP_CHECK(hipFree(d_Output)); } /** * @addtogroup __shfl_sync * @{ * @ingroup ShflSyncTest * `T __shfl_sync(unsigned long long mask, T var, int srcLane, int width=warpSize)` - * Contains warp __shfl sync functions. * @} */ /** * Test Description * ------------------------ * - Test case to verify __shfl_sync warp functions for different datatypes. * Test source * ------------------------ * - catch/unit/kernel/hipShflSyncTests.cc * Test requirements * ------------------------ * - HIP_VERSION >= 5.6 */ HIP_TEST_CASE(Unit_hipShflSync) { CHECK_WARP_MATCH_FUNCTIONS_SUPPORT SECTION("run test for short") { runTestShfl_1(); runTestShfl_2(); } SECTION("run test for unsigned short") { runTestShfl_1(); runTestShfl_2(); } SECTION("run test for int") { runTestShfl_1(); runTestShfl_2(); } SECTION("run test for unsigned int") { runTestShfl_1(); runTestShfl_2(); } SECTION("run test for long") { runTestShfl_1(); runTestShfl_2(); } SECTION("run test for unsigned long") { runTestShfl_1(); runTestShfl_2(); } SECTION("run test for long long") { runTestShfl_1(); runTestShfl_2(); } SECTION("run test for unsigned long long") { runTestShfl_1(); runTestShfl_2(); } SECTION("run test for float") { runTestShfl_1(); runTestShfl_2(); } SECTION("run test for double") { runTestShfl_1(); runTestShfl_2(); } SECTION("divergent execution test") { runTestShfl_3(); } }