/* * Copyright (c) Advanced Micro Devices, Inc., or its affiliates. * * SPDX-License-Identifier: MIT */ #include #include #include #include const int size = 32; template __global__ void shflDownSum(T* a, int size) { T val = a[threadIdx.x]; for (int i = size / 2; i > 0; i /= 2) { val += __shfl_down(val, i, size); } a[threadIdx.x] = val; } template __global__ void shflUpSum(T* a, int size) { T val = a[threadIdx.x]; for (int i = size / 2; i > 0; i /= 2) { val += __shfl_up(val, i, size); } a[threadIdx.x] = val; } template __global__ void shflXorSum(T* a, int size) { T val = a[threadIdx.x]; for (int i = size / 2; i > 0; i /= 2) { val += __shfl_xor(val, i, size); } a[threadIdx.x] = val; } static void getFactor(int* fact) { *fact = 101; } static void getFactor(unsigned int* fact) { *fact = static_cast(INT32_MAX) + 1; } static void getFactor(float* fact) { *fact = 2.5; } static void getFactor(double* fact) { *fact = 2.5; } static void getFactor(__half* fact) { *fact = 2.5; } static void getFactor(int64_t* fact) { *fact = 303; } static void getFactor(uint64_t* fact) { *fact = static_cast(__LONG_LONG_MAX__) + 1; } template T sum(T* a) { T cpuSum = 0; T factor; getFactor(&factor); for (int i = 0; i < size; i++) { a[i] = i + factor; cpuSum += a[i]; } return cpuSum; } template <> __half sum(__half* a) { __half cpuSum = 0; __half factor; getFactor(&factor); for (int i = 0; i < size; i++) { a[i] = i + __half2float(factor); cpuSum = __half2float(cpuSum) + __half2float(a[i]); } return cpuSum; } template bool compare(T gpuSum, T cpuSum) { if (gpuSum != cpuSum) { return true; } return false; } template <> bool compare(__half gpuSum, __half cpuSum) { if (__half2float(gpuSum) != __half2float(cpuSum)) { return true; } return false; } template static void runTestShflUp() { const int size = 32; T a[size]; T cpuSum = sum(a); T* d_a; HIP_CHECK(hipMalloc(&d_a, sizeof(T) * size)); HIP_CHECK(hipMemcpy(d_a, &a, sizeof(T) * size, hipMemcpyDefault)); hipLaunchKernelGGL(shflUpSum, 1, size, 0, 0, d_a, size); HIP_CHECK(hipMemcpy(&a, d_a, sizeof(T) * size, hipMemcpyDefault)); REQUIRE((compare(a[size - 1], cpuSum)) == 0); HIP_CHECK(hipFree(d_a)); } template static void runTestShflDown() { T a[size]; T cpuSum = sum(a); T* d_a; HIP_CHECK(hipMalloc(&d_a, sizeof(T) * size)); HIP_CHECK(hipMemcpy(d_a, &a, sizeof(T) * size, hipMemcpyDefault)); hipLaunchKernelGGL(shflDownSum, 1, size, 0, 0, d_a, size); HIP_CHECK(hipMemcpy(&a, d_a, sizeof(T) * size, hipMemcpyDefault)); REQUIRE((compare(a[0], cpuSum)) == 0); HIP_CHECK(hipFree(d_a)); } template static void runTestShflXor() { T a[size]; T cpuSum = sum(a); T* d_a; HIP_CHECK(hipMalloc(&d_a, sizeof(T) * size)); HIP_CHECK(hipMemcpy(d_a, &a, sizeof(T) * size, hipMemcpyDefault)); hipLaunchKernelGGL(shflXorSum, 1, size, 0, 0, d_a, size); HIP_CHECK(hipMemcpy(&a, d_a, sizeof(T) * size, hipMemcpyDefault)); REQUIRE((compare(a[0], cpuSum)) == 0); HIP_CHECK(hipFree(d_a)); } /** * @addtogroup __shfl __shfl * @{ * @ingroup ShflTest * `T __shfl_up(T var, unsigned int lane_delta, int width = warpSize)` - * Contains warp __shfl_up function */ /** * Test Description * ------------------------ * - Test case to verify __shfl_up warp functions for different datatypes. * Test source * ------------------------ * - catch/unit/kernel/hipShflUpDownTest.cc * Test requirements * ------------------------ * - HIP_VERSION >= 5.6 * - Gaurding this test against cuda with refernce to mentioned * ticket SWDEV-379177 */ HIP_TEST_CASE(Unit_runTestShfl_up) { SECTION("runTestShflUp for int") { runTestShflUp(); } SECTION("runTestShflUp for float") { runTestShflUp(); } SECTION("runTestShflUp for double") { runTestShflUp(); } SECTION("runTestShflUp for __half") { runTestShflUp<__half>(); } SECTION("runTestShflUp for int64_t") { runTestShflUp(); } SECTION("runTestShflUp for unsigned int") { runTestShflUp(); } SECTION("runTestShflUp for uint64_t") { runTestShflUp(); } } /** * End doxygen group __shfl. * @} */ /** * @addtogroup __shfl __shfl * @{ * @ingroup ShflTest * `T __shfl_down(T var, unsigned int lane_delta, int width = warpSize)` - * Contains warp __shfl_down function */ /** * Test Description * ------------------------ * - Test case to verify __shfl_down warp functions for different datatypes. * Test source * ------------------------ * - catch/unit/kernel/hipShflUpDownTest.cc * Test requirements * ------------------------ * - HIP_VERSION >= 5.6 * - Gaurding this test against cuda with refernce to mentioned * ticket SWDEV-379177 */ HIP_TEST_CASE(Unit_runTestShfl_Down) { SECTION("runTestShflDown for int") { runTestShflDown(); } SECTION("runTestShflDown for float") { runTestShflDown(); } SECTION("runTestShflDown for double") { runTestShflDown(); } SECTION("runTestShflDown for __half") { runTestShflDown<__half>(); } SECTION("runTestShflDown for int64_t") { runTestShflDown(); } SECTION("runTestShflDown for unsigned int") { runTestShflDown(); } SECTION("runTestShflDown for uint64_t") { runTestShflDown(); } } /** * End doxygen group __shfl. * @} */ /** * @addtogroup __shfl __shfl * @{ * @ingroup ShflTest * `T __shfl_xor(T var, int laneMask, int width=warpSize)` - * Contains warp __shfl_xor function */ /** * Test Description * ------------------------ * - Test case to verify __shfl_xor warp functions for different datatypes. * Test source * ------------------------ * - catch/unit/kernel/hipShflUpDownTest.cc * Test requirements * ------------------------ * - HIP_VERSION >= 5.6 * - Gaurding this test against cuda with refernce to mentioned * ticket SWDEV-379177 */ HIP_TEST_CASE(Unit_runTestShfl_Xor) { SECTION("runTestShflXor for int") { runTestShflXor(); } SECTION("runTestShflXor for float") { runTestShflXor(); } SECTION("runTestShflXor for double") { runTestShflXor(); } SECTION("runTestShflXor for __half") { runTestShflXor<__half>(); } SECTION("runTestShflXor for int64_t") { runTestShflXor(); } SECTION("runTestShflXor for unsigned int") { runTestShflXor(); } SECTION("runTestShflXor for uint64_t") { runTestShflXor(); } } /** * End doxygen group __shfl. * @} */