CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
184 lines
6.0 KiB
C++
184 lines
6.0 KiB
C++
/*
|
|
* Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
/**
|
|
Testcase Scenarios :
|
|
(TestCase 1)::
|
|
1) Execute atomicAdd in multi threaded scenario by diverging the data across
|
|
multiple threads and validate the output at the end of all operations.
|
|
2) Execute atomicAddNoRet in multi threaded scenario by diverging the data
|
|
across multiple threads and validate the output at the end of all operations.
|
|
(TestCase 2)::
|
|
3) Execute atomicAdd API and validate the result.
|
|
4) Execute atomicAddNoRet API and validate the result.
|
|
(TestCase 3)::
|
|
5) atomicadd/NoRet negative scenarios (TBD).
|
|
*/
|
|
|
|
#include <hip_test_kernels.hh>
|
|
#include <hip_test_common.hh>
|
|
#include <hip_test_checkers.hh>
|
|
/*
|
|
* Defines initial and increment values
|
|
*/
|
|
#define INCREMENT_VALUE 10
|
|
#define INT_INITIAL_VALUE 10
|
|
#define FLOAT_INITIAL_VALUE 10.50
|
|
#define DOUBLE_INITIAL_VALUE 200.12
|
|
#define LONG_INITIAL_VALUE 10000
|
|
#define UNSIGNED_INITIAL_VALUE 20
|
|
|
|
#if HT_NVIDIA
|
|
// atomicAddNoRet is unavailable in cuda
|
|
template <typename T> __device__ void atomicAddNoRet(T* x, int y) {
|
|
atomicAdd(x, static_cast<T>(y));
|
|
}
|
|
#endif
|
|
|
|
bool p_atomicNoRet = false;
|
|
|
|
template <typename T> __global__ void atomicnoret_manywaves(T* C_d) {
|
|
atomicAddNoRet(C_d, INCREMENT_VALUE);
|
|
}
|
|
|
|
template <typename T> __global__ void atomic_manywaves(T* C_d) { atomicAdd(C_d, INCREMENT_VALUE); }
|
|
|
|
template <typename T> __global__ void atomicnoret_simple(T* C_d) {
|
|
atomicAddNoRet(C_d, INCREMENT_VALUE);
|
|
}
|
|
|
|
template <typename T> __global__ void atomic_simple(T* C_d) { atomicAdd(C_d, INCREMENT_VALUE); }
|
|
|
|
template <typename T> bool atomictest_manywaves(const T& initial_val) {
|
|
unsigned int ThreadsperBlock = 10;
|
|
unsigned int numBlocks = 1;
|
|
T memSize = sizeof(T);
|
|
T* hOData = reinterpret_cast<T*>(malloc(memSize));
|
|
*hOData = initial_val;
|
|
T* dOData;
|
|
HIP_CHECK(hipMalloc(&dOData, memSize));
|
|
// copy host memory to device to initialize to zero
|
|
HIP_CHECK(hipMemcpy(dOData, hOData, memSize, hipMemcpyHostToDevice));
|
|
|
|
// execute the kernel
|
|
hipLaunchKernelGGL(atomic_manywaves, dim3(numBlocks), dim3(ThreadsperBlock), 0, 0, dOData);
|
|
|
|
// Copy result from device to host
|
|
HIP_CHECK(hipMemcpy(hOData, dOData, memSize, hipMemcpyDeviceToHost));
|
|
REQUIRE(hOData[0] ==
|
|
initial_val + static_cast<T>(INCREMENT_VALUE * (ThreadsperBlock * numBlocks)));
|
|
|
|
// Cleanup memory
|
|
free(hOData);
|
|
HIP_CHECK(hipFree(dOData));
|
|
|
|
return true;
|
|
}
|
|
|
|
template <typename T> bool atomictestnoret_manywaves(const T& initial_val) {
|
|
unsigned int ThreadsperBlock = 10;
|
|
unsigned int numBlocks = 1;
|
|
T memSize = sizeof(T);
|
|
T* hOData = reinterpret_cast<T*>(malloc(memSize));
|
|
*hOData = initial_val;
|
|
T* dOData;
|
|
HIP_CHECK(hipMalloc(&dOData, memSize));
|
|
// copy host memory to device to initialize to zero
|
|
HIP_CHECK(hipMemcpy(dOData, hOData, memSize, hipMemcpyHostToDevice));
|
|
|
|
// execute the kernel
|
|
hipLaunchKernelGGL(atomicnoret_manywaves, dim3(numBlocks), dim3(ThreadsperBlock), 0, 0, dOData);
|
|
|
|
// Copy result from device to host
|
|
HIP_CHECK(hipMemcpy(hOData, dOData, memSize, hipMemcpyDeviceToHost));
|
|
REQUIRE(hOData[0] == initial_val + (INCREMENT_VALUE * (ThreadsperBlock * numBlocks)));
|
|
|
|
// Cleanup memory
|
|
free(hOData);
|
|
HIP_CHECK(hipFree(dOData));
|
|
|
|
return true;
|
|
}
|
|
|
|
template <typename T> bool atomictest_simple(const T& initial_val) {
|
|
unsigned int ThreadsperBlock = 1;
|
|
unsigned int numBlocks = 1;
|
|
T memSize = sizeof(T);
|
|
T* hOData = reinterpret_cast<T*>(malloc(memSize));
|
|
*hOData = initial_val;
|
|
T* dOData;
|
|
HIP_CHECK(hipMalloc(&dOData, memSize));
|
|
// copy host memory to device to initialize to zero
|
|
HIP_CHECK(hipMemcpy(dOData, hOData, memSize, hipMemcpyHostToDevice));
|
|
|
|
// execute the kernel
|
|
hipLaunchKernelGGL(atomic_simple, dim3(numBlocks), dim3(ThreadsperBlock), 0, 0, dOData);
|
|
|
|
// Copy result from device to host
|
|
HIP_CHECK(hipMemcpy(hOData, dOData, memSize, hipMemcpyDeviceToHost));
|
|
REQUIRE(hOData[0] == initial_val + INCREMENT_VALUE);
|
|
|
|
// Cleanup memory
|
|
free(hOData);
|
|
HIP_CHECK(hipFree(dOData));
|
|
|
|
return true;
|
|
}
|
|
|
|
template <typename T> bool atomictestnoret_simple(const T& initial_val) {
|
|
unsigned int ThreadsperBlock = 1;
|
|
unsigned int numBlocks = 1;
|
|
T memSize = sizeof(T);
|
|
T* hOData = reinterpret_cast<T*>(malloc(memSize));
|
|
*hOData = initial_val;
|
|
T* dOData;
|
|
HIP_CHECK(hipMalloc(&dOData, memSize));
|
|
// copy host memory to device to initialize to zero
|
|
HIP_CHECK(hipMemcpy(dOData, hOData, memSize, hipMemcpyHostToDevice));
|
|
|
|
// execute the kernel
|
|
hipLaunchKernelGGL(atomicnoret_simple, dim3(numBlocks), dim3(ThreadsperBlock), 0, 0, dOData);
|
|
|
|
// Copy result from device to host
|
|
HIP_CHECK(hipMemcpy(hOData, dOData, memSize, hipMemcpyDeviceToHost));
|
|
REQUIRE(hOData[0] == initial_val + INCREMENT_VALUE);
|
|
|
|
// Cleanup memory
|
|
free(hOData);
|
|
HIP_CHECK(hipFree(dOData));
|
|
|
|
return true;
|
|
}
|
|
|
|
HIP_TEST_CASE(Unit_hipTestAtomicAdd) {
|
|
bool TestPassed = true;
|
|
|
|
SECTION("atomic tests with many waves") {
|
|
REQUIRE(TestPassed == atomictest_manywaves<int>(INT_INITIAL_VALUE));
|
|
REQUIRE(TestPassed == atomictest_manywaves<unsigned int>(UNSIGNED_INITIAL_VALUE));
|
|
REQUIRE(TestPassed == atomictest_manywaves<float>(FLOAT_INITIAL_VALUE));
|
|
#if HT_AMD
|
|
REQUIRE(TestPassed == atomictest_manywaves<uint64_t>(LONG_INITIAL_VALUE));
|
|
REQUIRE(TestPassed == atomictest_manywaves<double>(DOUBLE_INITIAL_VALUE));
|
|
#endif
|
|
}
|
|
SECTION("atomic tests with many waves and no return") {
|
|
REQUIRE(TestPassed == atomictestnoret_manywaves<float>(FLOAT_INITIAL_VALUE));
|
|
}
|
|
SECTION("simple atomic tests") {
|
|
REQUIRE(TestPassed == atomictest_simple<int>(INT_INITIAL_VALUE));
|
|
REQUIRE(TestPassed == atomictest_simple<unsigned int>(UNSIGNED_INITIAL_VALUE));
|
|
REQUIRE(TestPassed == atomictest_simple<float>(FLOAT_INITIAL_VALUE));
|
|
#if HT_AMD
|
|
REQUIRE(TestPassed == atomictest_simple<uint64_t>(LONG_INITIAL_VALUE));
|
|
REQUIRE(TestPassed == atomictest_simple<double>(DOUBLE_INITIAL_VALUE));
|
|
#endif
|
|
}
|
|
SECTION("Simple atomic test with no return") {
|
|
REQUIRE(TestPassed == atomictestnoret_simple<float>(FLOAT_INITIAL_VALUE));
|
|
}
|
|
}
|