Rakesh Roy
2024-02-19 15:14:45 +05:30
101 arquivos alterados com 11970 adições e 257 exclusões
+6 -33
Ver Arquivo
@@ -251,6 +251,12 @@
"Unit_hipGraphicsUnregisterResource_Negative_Parameters",
"SWDEV-443760: This test fails when device memory is used for kernel args",
"Unit_hipGraphExecMemcpyNodeSetParams1D_Negative",
"=== Below tests fail in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/356 ===",
"Unit_Device_Complex_Unary_Negative_Parameters_RTC",
"Unit_Device_Complex_Binary_Negative_Parameters_RTC",
"Unit_Device_Complex_hipCfma_Negative_Parameters_RTC",
"Unit_Device_make_Complex_Negative_Parameters_RTC",
"Unit_Device_Complex_Cast_Negative_Parameters_RTC",
#endif
#if defined VEGA20
"=== SWDEV-419112 Below tests fail in stress test on 29/08/23 ===",
@@ -303,7 +309,6 @@
"Unit_hipFreeMipmappedArray_Negative_DoubleFree",
"Unit_hipFreeMipmappedArrayMultiTArray - char",
"Unit_hipFreeMipmappedArrayMultiTArray - int",
"Unit_Printf_Negative",
"Unit_Multi_Grid_Group_Getters_Positive_Basic",
"Unit_Multi_Grid_Group_Getters_Positive_Base_Type",
"Unit_Multi_Grid_Group_Getters_Positive_Non_Member_Functions",
@@ -340,16 +345,6 @@
"Unit_Warp_Ballot_Positive_Basic",
"Unit_Warp_Vote_Any_Positive_Basic",
"Unit_Warp_Vote_All_Positive_Basic",
"Unit_Device_memcpy_Negative",
"Unit_Device_memset_Negative",
"Unit_Device_Complex_make_Negative",
"Unit_Device_Complex_Cast_Negative",
"Unit_Device_Complex_Unary_float_Negative",
"Unit_Device_Complex_Unary_double_Negative",
"Unit_Device_Complex_Binary_float_Negative",
"Unit_Device_Complex_Binary_double_Negative",
"Unit_Device_Complex_hipCfma_Negative",
"Unit_Device__hip_hc_8pk_Negative",
#endif
#if defined MI2XX
"Unit_hipStreamPerThread_DeviceReset_1",
@@ -437,7 +432,6 @@
"Unit_hipFreeMipmappedArray_Negative_DoubleFree",
"Unit_hipFreeMipmappedArrayMultiTArray - char",
"Unit_hipFreeMipmappedArrayMultiTArray - int",
"Unit_Printf_Negative",
"Unit_Multi_Grid_Group_Getters_Positive_Basic",
"Unit_Multi_Grid_Group_Getters_Positive_Base_Type",
"Unit_Multi_Grid_Group_Getters_Positive_Non_Member_Functions",
@@ -474,16 +468,6 @@
"Unit_Warp_Ballot_Positive_Basic",
"Unit_Warp_Vote_Any_Positive_Basic",
"Unit_Warp_Vote_All_Positive_Basic",
"Unit_Device_memcpy_Negative",
"Unit_Device_memset_Negative",
"Unit_Device_Complex_make_Negative",
"Unit_Device_Complex_Cast_Negative",
"Unit_Device_Complex_Unary_float_Negative",
"Unit_Device_Complex_Unary_double_Negative",
"Unit_Device_Complex_Binary_float_Negative",
"Unit_Device_Complex_Binary_double_Negative",
"Unit_Device_Complex_hipCfma_Negative",
"Unit_Device__hip_hc_8pk_Negative",
"=== SWDEV-439298: Below test failing in CQE staging ===",
"Unit_hipCGMultiGridGroupType_Barrier",
#endif
@@ -520,7 +504,6 @@
"Unit_hipFreeMipmappedArray_Negative_DoubleFree",
"Unit_hipFreeMipmappedArrayMultiTArray - char",
"Unit_hipFreeMipmappedArrayMultiTArray - int",
"Unit_Printf_Negative",
"Unit_Multi_Grid_Group_Getters_Positive_Basic",
"Unit_Multi_Grid_Group_Getters_Positive_Base_Type",
"Unit_Multi_Grid_Group_Getters_Positive_Non_Member_Functions",
@@ -533,16 +516,6 @@
"Unit_Coalesced_Group_Shfl_Positive_Basic - unsigned long long",
"Unit_Coalesced_Group_Shfl_Positive_Basic - float",
"Unit_Coalesced_Group_Shfl_Positive_Basic - double",
"Unit_Device_memcpy_Negative",
"Unit_Device_memset_Negative",
"Unit_Device_Complex_make_Negative",
"Unit_Device_Complex_Cast_Negative",
"Unit_Device_Complex_Unary_float_Negative",
"Unit_Device_Complex_Unary_double_Negative",
"Unit_Device_Complex_Binary_float_Negative",
"Unit_Device_Complex_Binary_double_Negative",
"Unit_Device_Complex_hipCfma_Negative",
"Unit_Device__hip_hc_8pk_Negative",
#endif
#if defined NAVI3X
"=== Below tests soft hang in stress test on 13/09/23 ===",
+27 -11
Ver Arquivo
@@ -286,6 +286,14 @@
"Unit_atomicExch_system_Positive_Host_And_Peer_GPUs - unsigned long long",
"Unit_atomicExch_system_Positive_Host_And_Peer_GPUs - float",
"Unit_atomicExch_system_Positive_Host_And_Peer_GPUs - double",
"=== SWDEV-435667: Below tests failing randomly in stress test on 08/12/23 ===",
"Unit_hipMemPoolSetAccess_Negative_Parameters",
"Unit_hipMallocMipmappedArray_Negative_Parameters",
"Unit_hipFreeMipmappedArray_Negative_Parameters",
"Unit_hipGetMipmappedArrayLevel_Negative_Parameters",
"Unit_hipMipmappedArrayCreate_Negative_Parameters",
"Unit_hipMipmappedArrayDestroy_Negative_Parameters",
"Unit_hipMipmappedArrayGetLevel_Negative_Parameters",
"SWDEV-438524: Below tests taking long time to run in stress test on 15/12/23 ===",
"Unit_Coalesced_Group_Shfl_Up_Positive_Basic - int",
"Unit_Coalesced_Group_Shfl_Up_Positive_Basic - unsigned int",
@@ -314,17 +322,6 @@
"SWDEV-438524: Below tests causing TDR & machine down in stress test on 15/12/23 ===",
"Unit_hipExtModuleLaunchKernel_Functional",
"Unit_hipExtLaunchKernelGGL_Functional",
"SWDEV-438524:Below tests failed in stress test on 15/12/23 ===",
"Unit_Device_memcpy_Negative",
"Unit_Device_memset_Negative",
"Unit_Device_Complex_make_Negative",
"Unit_Device_Complex_Cast_Negative",
"Unit_Device_Complex_Unary_float_Negative",
"Unit_Device_Complex_Unary_double_Negative",
"Unit_Device_Complex_Binary_float_Negative",
"Unit_Device_Complex_Binary_double_Negative",
"Unit_Device_Complex_hipCfma_Negative",
"Unit_Device__hip_hc_8pk_Negative",
"SWDEV-413997: VMM test still failing in windows",
"Unit_hipMemSetAccess_ChangeAccessProp",
"SWDEV-444265: This test fails in Phoenix",
@@ -340,6 +337,25 @@
"Unit_hipMemSetAccess_Vmm2VMMMemCpy",
"SWDEV-444031: This test fails in Navi32 MGPU",
"Unit_hipMemSetAccess_Multithreaded",
"=== Below test fails in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/274 ===",
"Unit_Printf_flags_Sanity_Positive",
"Unit_Printf_length_Sanity_Positive",
"=== Below tests fail in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/356 ===",
"Unit_Device_Complex_Unary_Negative_Parameters_RTC",
"Unit_Device_Complex_Binary_Negative_Parameters_RTC",
"Unit_Device_Complex_hipCfma_Negative_Parameters_RTC",
"Unit_Device_make_Complex_Negative_Parameters_RTC",
"Unit_Device_Complex_Cast_Negative_Parameters_RTC",
"=== Below tests are failing PSDB ===",
"Unit_hipGraphMem_Alloc_Free_NodeGetParams_Functional_3",
"Unit_hipGraphAddMemAllocNode_Positive_FreeInGraph",
"Unit_hipFreeAsync_Negative_Parameters",
"Unit_hipMallocMipmappedArray_DiffSizes",
"Unit_hipMallocMipmappedArray_MultiThread",
"Unit_hipMallocMipmappedArray_Negative_InvalidFlags",
"Unit_hipGetMipmappedArrayLevel_Negative",
"Unit_hipFreeMipmappedArray_Negative_DoubleFree",
"Unit_hipFreeMipmappedArrayMultiTArray - int",
#endif
"End of json"
]
@@ -19,7 +19,7 @@
"Unit_ChannelDescriptor_Positive_Basic_4D - ulong4",
"Unit_ChannelDescriptor_Positive_Basic_4D - long4",
"=== Below test fails in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/38 ===",
"Unit_hipFreeAsync_negative",
"Unit_hipFreeAsync_Negative_Parameters",
"=== Below test fails in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/92 ===",
"Unit_hipGetTexObjectResourceDesc_positive",
"Unit_hipGetTexObjectResourceDesc_Negative_Parameters",
@@ -52,6 +52,24 @@
"Unit_atomicExch_system_Positive_Host_And_GPU - int",
"Unit_atomicExch_system_Positive_Host_And_GPU - unsigned int",
"Unit_atomicExch_system_Positive_Host_And_GPU - unsigned long long",
"Unit_atomicExch_system_Positive_Host_And_GPU - float"
"Unit_atomicExch_system_Positive_Host_And_GPU - float",
"=== Below tests fail in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/356 ===",
"Unit_Device_Complex_Unary_Negative_Parameters_RTC",
"Unit_Device_Complex_Binary_Negative_Parameters_RTC",
"Unit_Device_Complex_hipCfma_Negative_Parameters_RTC",
"Unit_Device_make_Complex_Negative_Parameters_RTC",
"Unit_Device_Complex_Cast_Negative_Parameters_RTC",
"=== Below 2 tests are disabled due to defect EXSWHTEC-342 ===",
"Unit_hipDeviceSetLimit_Negative_Parameters",
"Unit_hipDeviceGetLimit_Negative_Parameters",
"=== Below tests are failing PSDB ===",
"Unit_hipGraphMem_Alloc_Free_NodeGetParams_Functional_3",
"Unit_hipMemPoolSetAccess_Negative_Parameters",
"Unit_hipMallocMipmappedArray_Negative_NumLevels",
"Unit_hipFreeMipmappedArray_Negative_Nullptr",
"Unit_hipFreeMipmappedArrayMultiTArray - int",
"Unit_hipFreeMipmappedArray_Negative_Parameters",
"Unit_hipCreateSurfaceObject_Negative_Parameters",
"Unit_hipDestroySurfaceObject_Negative_Parameters"
]
}
@@ -15,6 +15,15 @@
"Unit_ChannelDescriptor_Positive_Basic_3D - ulong3",
"Unit_ChannelDescriptor_Positive_Basic_3D - long3",
"Unit_ChannelDescriptor_Positive_Basic_4D - ulong4",
"Unit_ChannelDescriptor_Positive_Basic_4D - long4"
"Unit_ChannelDescriptor_Positive_Basic_4D - long4",
"=== Below tests fail in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/356 ===",
"Unit_Device_Complex_Unary_Negative_Parameters_RTC",
"Unit_Device_Complex_Binary_Negative_Parameters_RTC",
"Unit_Device_Complex_hipCfma_Negative_Parameters_RTC",
"Unit_Device_make_Complex_Negative_Parameters_RTC",
"Unit_Device_Complex_Cast_Negative_Parameters_RTC",
"=== Below 2 tests are disabled due to defect EXSWHTEC-342 ===",
"Unit_hipDeviceSetLimit_Negative_Parameters",
"Unit_hipDeviceGetLimit_Negative_Parameters"
]
}
+4 -1
Ver Arquivo
@@ -17,7 +17,7 @@ int main(int argc, char** argv) {
using namespace Catch::clara;
// clang-format off
auto cli = session.cli()
auto cli = session.cli()
| Opt(cmd_options.iterations, "iterations")
["-I"]["--iterations"]
("Number of iterations used for performance tests (default: 1000)")
@@ -32,6 +32,9 @@ int main(int argc, char** argv) {
("Show progress bar when running performance tests")
| Opt(cmd_options.cg_extended_run, "cg_extened_run")
["-E"]["--cg-extended-run"]
("TODO: Description goes here")
| Opt(cmd_options.cg_iterations, "cg_iterations")
["-C"]["--cg-iterations"]
("Number of iterations used for cooperative groups sync tests (default: 5)")
;
// clang-format on
+2 -1
Ver Arquivo
@@ -26,8 +26,9 @@ struct CmdOptions {
int iterations = 10;
int warmups = 100;
int cg_extended_run = 5;
int cg_iterations = 5;
bool no_display = false;
bool progress = false;
};
extern CmdOptions cmd_options;
extern CmdOptions cmd_options;
+26
Ver Arquivo
@@ -78,6 +78,32 @@ struct CPUGrid {
unsigned int thread_count_;
};
struct CPUMultiGrid {
CPUMultiGrid(const unsigned int num_grids, const dim3 grid_dims[], const dim3 block_dims[]) {
thread_count_ = 0;
grid_count_ = num_grids;
grids_.reserve(grid_count_);
for (int i = 0; i < grid_count_; i++) {
grids_.emplace_back(grid_dims[i], block_dims[i]);
thread_count_ += grids_[i].thread_count_;
}
}
inline unsigned int thread0_rank_in_multi_grid(const unsigned int grid_rank) const {
unsigned int multi_grid_thread_rank_0 = 0;
unsigned int multi_grid_thread_count = 0;
for (int i = 0; i <= grid_rank; i++) {
multi_grid_thread_rank_0 = multi_grid_thread_count;
multi_grid_thread_count += grids_[i].thread_count_;
}
return multi_grid_thread_rank_0;
}
std::vector<CPUGrid> grids_;
unsigned int grid_count_;
unsigned int thread_count_;
};
/* Generate dimensions for 1D, 2D and 3D blocks of threads */
inline dim3 GenerateThreadDimensions() {
hipDeviceProp_t props;
+36
Ver Arquivo
@@ -144,6 +144,28 @@ THE SOFTWARE.
* @}
*/
/**
* @defgroup StreamOTest Ordered Memory Allocator
* @{
* This section describes the tests for Stream Ordered Memory Allocator functions of HIP runtime
* API.
* @}
*/
/**
* @defgroup StreamOTest Ordered Memory Allocator
* @{
* This section describes the tests for Stream Ordered Memory Allocator functions of HIP runtime
* API.
*/
/**
* @defgroup StreamOTest Ordered Memory Allocator
* @{
* This section describes the tests for Stream Ordered Memory Allocator functions of HIP runtime
* API.
*/
/**
* @defgroup StreamTest Stream Management
* @{
@@ -171,3 +193,17 @@ THE SOFTWARE.
* This section describes the various Printf use case Scenarios.
* @}
*/
/**
* @defgroup SurfaceTest Surface Management
* @{
* This section describes tests for the surface management functions of HIP runtime API.
* @}
*/
/**
* @defgroup ComplexTest Complex type
* @{
* This section describes tests for the Complex type functions.
* @}
*/
+62 -18
Ver Arquivo
@@ -102,23 +102,25 @@ template <typename T> class LinearAllocGuard {
~LinearAllocGuard() {
// No Catch macros, don't want to possibly throw in the destructor
switch (allocation_type_) {
case LinearAllocs::noAlloc:
break;
case LinearAllocs::malloc:
free(ptr_);
break;
case LinearAllocs::mallocAndRegister:
// Cast to void to suppress nodiscard warnings
static_cast<void>(hipHostUnregister(host_ptr_));
free(host_ptr_);
break;
case LinearAllocs::hipHostMalloc:
static_cast<void>(hipHostFree(ptr_));
break;
case LinearAllocs::hipMalloc:
case LinearAllocs::hipMallocManaged:
static_cast<void>(hipFree(ptr_));
if (ptr_ != nullptr) {
switch (allocation_type_) {
case LinearAllocs::noAlloc:
break;
case LinearAllocs::malloc:
free(ptr_);
break;
case LinearAllocs::mallocAndRegister:
// Cast to void to suppress nodiscard warnings
static_cast<void>(hipHostUnregister(host_ptr_));
free(host_ptr_);
break;
case LinearAllocs::hipHostMalloc:
static_cast<void>(hipHostFree(ptr_));
break;
case LinearAllocs::hipMalloc:
case LinearAllocs::hipMallocManaged:
static_cast<void>(hipFree(ptr_));
}
}
}
@@ -287,7 +289,7 @@ class StreamGuard {
}
~StreamGuard() {
if (stream_type_ == Streams::created) {
if (stream_type_ == Streams::created && stream_ != nullptr) {
static_cast<void>(hipStreamDestroy(stream_));
}
}
@@ -346,3 +348,45 @@ class StreamsGuard {
private:
std::vector<hipStream_t> streams_;
};
enum class MemPools { dev_default, created };
class MemPoolGuard {
public:
MemPoolGuard(const MemPools mempool_type, int device,
hipMemAllocationHandleType handle_type = hipMemHandleTypeNone)
: mempool_type_{mempool_type}, device_{device}, handle_type_{handle_type} {
switch (mempool_type_) {
case MemPools::dev_default:
HIP_CHECK(hipDeviceGetDefaultMemPool(&mempool_, device_));
break;
case MemPools::created:
hipMemPoolProps pool_props;
pool_props.allocType = hipMemAllocationTypePinned;
pool_props.handleTypes = handle_type_;
pool_props.location.type = hipMemLocationTypeDevice;
pool_props.location.id = device_;
pool_props.win32SecurityAttributes = nullptr;
memset(pool_props.reserved, 0, sizeof(pool_props.reserved));
HIP_CHECK(hipMemPoolCreate(&mempool_, &pool_props));
}
}
MemPoolGuard(const MemPoolGuard&) = delete;
MemPoolGuard(MemPoolGuard&&) = delete;
~MemPoolGuard() {
if (mempool_type_ == MemPools::created) {
static_cast<void>(hipMemPoolDestroy(mempool_));
}
}
hipMemPool_t mempool() const { return mempool_; }
private:
const MemPools mempool_type_;
int device_;
hipMemAllocationHandleType handle_type_;
hipMemPool_t mempool_;
};
+5 -2
Ver Arquivo
@@ -35,8 +35,9 @@ add_subdirectory(multiThread)
add_subdirectory(compiler)
add_subdirectory(errorHandling)
add_subdirectory(cooperativeGrps)
add_subdirectory(context)
add_subdirectory(warp)
add_subdirectory(context)
add_subdirectory(device_memory)
add_subdirectory(dynamicLoading)
add_subdirectory(g++)
add_subdirectory(module)
@@ -44,12 +45,14 @@ add_subdirectory(channelDescriptor)
add_subdirectory(executionControl)
add_subdirectory(vector_types)
add_subdirectory(atomics)
add_subdirectory(complex)
add_subdirectory(p2p)
add_subdirectory(gcc)
if(HIP_PLATFORM STREQUAL "amd")
add_subdirectory(callback)
add_subdirectory(clock)
#add_subdirectory(clock)
add_subdirectory(hip_specific)
# Vulkan interop APIs currently undefined for Nvidia
add_subdirectory(vulkan_interop)
add_subdirectory(gl_interop) # Disabled on NVIDIA due to defect - EXSWHTEC-246
+2 -2
Ver Arquivo
@@ -80,7 +80,7 @@ if __name__ == '__main__':
CompileAndCapture.platform = sys.argv[2]
except IndexError:
CompileAndCapture.platform = None
try:
CompileAndCapture.hip_path = sys.argv[3]
except IndexError:
@@ -95,7 +95,7 @@ if __name__ == '__main__':
CompileAndCapture.expected_error_count = int(sys.argv[5])
except IndexError:
CompileAndCapture.expected_error_count = 0
try:
CompileAndCapture.expected_warning_count = int(sys.argv[6])
except IndexError:
+73
Ver Arquivo
@@ -0,0 +1,73 @@
# Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Common Tests - Test independent of all platforms
set(TEST_SRC
complex.cc
)
if(HIP_PLATFORM MATCHES "nvidia")
set(LINKER_LIBS nvrtc)
elseif(HIP_PLATFORM MATCHES "amd")
set(LINKER_LIBS hiprtc)
endif()
hip_add_exe_to_target(NAME ComplexTest
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests
LINKER_LIBS ${LINKER_LIBS})
# These tests fail in PSDB
#add_test(NAME Unit_Device_Complex_make_Negative
# COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/../compileAndCaptureOutput.py
# ${CMAKE_CURRENT_SOURCE_DIR} ${HIP_PLATFORM} ${HIP_PATH}
# complex_make_negative_kernels.cc 54)
#
#add_test(NAME Unit_Device_Complex_Cast_Negative
# COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/../compileAndCaptureOutput.py
# ${CMAKE_CURRENT_SOURCE_DIR} ${HIP_PLATFORM} ${HIP_PATH}
# complex_cast_negative_kernels.cc 28)
#
#add_test(NAME Unit_Device_Complex_Unary_float_Negative
# COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/../compileAndCaptureOutput.py
# ${CMAKE_CURRENT_SOURCE_DIR} ${HIP_PLATFORM} ${HIP_PATH}
# complex_negative_kernels_1Arg_float.cc 62)
#
#add_test(NAME Unit_Device_Complex_Unary_double_Negative
# COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/../compileAndCaptureOutput.py
# ${CMAKE_CURRENT_SOURCE_DIR} ${HIP_PLATFORM} ${HIP_PATH}
# complex_negative_kernels_1Arg_double.cc 62)
#
#add_test(NAME Unit_Device_Complex_Binary_float_Negative
# COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/../compileAndCaptureOutput.py
# ${CMAKE_CURRENT_SOURCE_DIR} ${HIP_PLATFORM} ${HIP_PATH}
# complex_negative_kernels_2Arg_float.cc 88)
#
#add_test(NAME Unit_Device_Complex_Binary_double_Negative
# COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/../compileAndCaptureOutput.py
# ${CMAKE_CURRENT_SOURCE_DIR} ${HIP_PLATFORM} ${HIP_PATH}
# complex_negative_kernels_2Arg_double.cc 88)
#
#add_test(NAME Unit_Device_Complex_hipCfma_Negative
# COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/../compileAndCaptureOutput.py
# ${CMAKE_CURRENT_SOURCE_DIR} ${HIP_PLATFORM} ${HIP_PATH}
# complex_negative_kernels_3Arg.cc 60)
+479
Ver Arquivo
@@ -0,0 +1,479 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "complex_function_common.hh"
#include "complex_cast_negative_kernels_rtc.hh"
#include "complex_make_negative_kernels_rtc.hh"
#include "complex_negative_kernels_1Arg_rtc.hh"
#include "complex_negative_kernels_2Arg_rtc.hh"
#include "complex_negative_kernels_3Arg_rtc.hh"
/**
* @addtogroup complex complex
* @{
* @ingroup ComplexTest
* Contains unit tests for complex type functions
*/
/**
* Test Description
* ------------------------
* - Test that checks unary complex functions on device for reduced set of input values. The
* results are compared against manually calculated ones:
* -# hipConj, hipConjf
* -# hipCreal, hipCrealf
* -# hipCimag, hipCimagf
* -# hipCabs, hipCabsf
* -# hipCsqabs, hipCsqabsf
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Device_Complex_Unary_Device_Sanity_Positive", "", hipFloatComplex,
hipDoubleComplex) {
decltype(TestType().x) input_r = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input_i = GENERATE(-4.75, 0, 1.75);
TestType input_val = MakeComplexType<TestType>(input_r, input_i);
for (const auto function :
{ComplexFunction::kConj, ComplexFunction::kReal, ComplexFunction::kImag,
ComplexFunction::kAbs, ComplexFunction::kSqabs}) {
DYNAMIC_SECTION("function: " << to_string(function)) {
ComplexFunctionUnaryDeviceTest(function, input_val);
}
}
}
/**
* Test Description
* ------------------------
* - Test that checks unary complex functions on host for reduced set of input values. The
* results are compared against manually calculated ones:
* -# hipConj, hipConjf
* -# hipCreal, hipCrealf
* -# hipCimag, hipCimagf
* -# hipCabs, hipCabsf
* -# hipCsqabs, hipCsqabsf
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Device_Complex_Unary_Host_Sanity_Positive", "", hipFloatComplex,
hipDoubleComplex) {
decltype(TestType().x) input_r = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input_i = GENERATE(-4.75, 0, 1.75);
TestType input_val = MakeComplexType<TestType>(input_r, input_i);
for (const auto function :
{ComplexFunction::kConj, ComplexFunction::kReal, ComplexFunction::kImag,
ComplexFunction::kAbs, ComplexFunction::kSqabs}) {
DYNAMIC_SECTION("function: " << to_string(function)) {
ComplexFunctionUnaryHostTest(function, input_val);
}
}
}
/**
* Test Description
* ------------------------
* - RTCs kernels that pass argument of invalid type for unary complex functions.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device_Complex_Unary_Negative_Parameters_RTC") {
ComplexTypeRTCWrapper<28>(kComplexConj);
ComplexTypeRTCWrapper<24>(kComplexReal);
ComplexTypeRTCWrapper<24>(kComplexImag);
ComplexTypeRTCWrapper<24>(kComplexAbs);
ComplexTypeRTCWrapper<24>(kComplexSqabs);
}
/**
* Test Description
* ------------------------
* - Test that checks binary complex functions on device for reduced set of input values. The
* results are compared against manually calculated ones:
* -# hipCadd, hipCaddf
* -# hipCsub, hipCsubf
* -# hipCmul, hipCmulf
* -# hipCdiv, hipCdivf
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Device_Complex_Binary_Device_Sanity_Positive", "", hipFloatComplex,
hipDoubleComplex) {
decltype(TestType().x) input1_r = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input1_i = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input2_r = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input2_i = GENERATE(-4.75, 0, 1.75);
TestType input_val1 = MakeComplexType<TestType>(input1_r, input1_i);
TestType input_val2 = MakeComplexType<TestType>(input2_r, input2_i);
for (const auto function : {ComplexFunction::kAdd, ComplexFunction::kSub, ComplexFunction::kMul,
ComplexFunction::kDiv}) {
DYNAMIC_SECTION("function: " << to_string(function)) {
ComplexFunctionBinaryDeviceTest(function, input_val1, input_val2);
}
}
}
/**
* Test Description
* ------------------------
* - Test that checks binary complex functions on host for reduced set of input values. The
* results are compared against manually calculated ones:
* -# hipCadd, hipCaddf
* -# hipCsub, hipCsubf
* -# hipCmul, hipCmulf
* -# hipCdiv, hipCdivf
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Device_Complex_Binary_Host_Sanity_Positive", "", hipFloatComplex,
hipDoubleComplex) {
decltype(TestType().x) input1_r = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input1_i = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input2_r = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input2_i = GENERATE(-4.75, 0, 1.75);
TestType input_val1 = MakeComplexType<TestType>(input1_r, input1_i);
TestType input_val2 = MakeComplexType<TestType>(input2_r, input2_i);
for (const auto function : {ComplexFunction::kAdd, ComplexFunction::kSub, ComplexFunction::kMul,
ComplexFunction::kDiv}) {
DYNAMIC_SECTION("function: " << to_string(function)) {
ComplexFunctionBinaryHostTest(function, input_val1, input_val2);
}
}
}
/**
* Test Description
* ------------------------
* - RTCs kernels that pass argument of invalid type for binary complex functions.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device_Complex_Binary_Negative_Parameters_RTC") {
ComplexTypeRTCWrapper<44>(kComplexAdd);
ComplexTypeRTCWrapper<44>(kComplexSub);
ComplexTypeRTCWrapper<44>(kComplexMul);
ComplexTypeRTCWrapper<44>(kComplexDiv);
}
/**
* Test Description
* ------------------------
* - Test that checks hipCfma/hipCfmaf complex functions on device for reduced set of input
* values. The results are compared against manually calculated ones.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Device_Complex_hipCfma_Device_Sanity_Positive", "", hipFloatComplex,
hipDoubleComplex) {
decltype(TestType().x) input1_r = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input1_i = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input2_r = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input2_i = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input3_r = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input3_i = GENERATE(-4.75, 0, 1.75);
TestType input_val1 = MakeComplexType<TestType>(input1_r, input1_i);
TestType input_val2 = MakeComplexType<TestType>(input2_r, input2_i);
TestType input_val3 = MakeComplexType<TestType>(input3_r, input3_i);
ComplexFunctionTernaryDeviceTest(ComplexFunction::kFma, input_val1, input_val2, input_val3);
}
/**
* Test Description
* ------------------------
* - Test that checks hipCfma/hipCfmaf complex functions on host for reduced set of input
* values. The results are compared against manually calculated ones.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Device_Complex_hipCfma_Host_Sanity_Positive", "", hipFloatComplex,
hipDoubleComplex) {
decltype(TestType().x) input1_r = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input1_i = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input2_r = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input2_i = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input3_r = GENERATE(-4.75, 0, 1.75);
decltype(TestType().x) input3_i = GENERATE(-4.75, 0, 1.75);
TestType input_val1 = MakeComplexType<TestType>(input1_r, input1_i);
TestType input_val2 = MakeComplexType<TestType>(input2_r, input2_i);
TestType input_val3 = MakeComplexType<TestType>(input3_r, input3_i);
ComplexFunctionTernaryHostTest(ComplexFunction::kFma, input_val1, input_val2, input_val3);
}
/**
* Test Description
* ------------------------
* - RTCs kernels that pass argument of invalid type for hipCfma/hipCfmaf complex function.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device_Complex_hipCfma_Negative_Parameters_RTC") {
ComplexTypeRTCWrapper<60>(kComplexFma);
}
/**
* Test Description
* ------------------------
* - Test that checks make_hipFloatComplex/make_hipDoubleComplex functions on device for reduced
* set of input values. The results are compared against manually calculated ones.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Device_make_Complex_Device_Positive", "", hipFloatComplex,
hipDoubleComplex) {
decltype(TestType().x) input_r = GENERATE(-0.25, 0, 0.25);
decltype(TestType().x) input_i = GENERATE(-1.75, 0, 1.75);
LinearAllocGuard<TestType> result_d(LinearAllocs::hipMalloc, sizeof(TestType));
LinearAllocGuard<TestType> result_h(LinearAllocs::hipHostMalloc, sizeof(TestType));
MakeComplexTypeKernel<TestType><<<1, 1>>>(result_d.ptr(), input_r, input_i);
HIP_CHECK(hipMemcpy(result_h.ptr(), result_d.ptr(), sizeof(TestType), hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
REQUIRE(result_h.ptr()[0].x == input_r);
REQUIRE(result_h.ptr()[0].y == input_i);
}
/**
* Test Description
* ------------------------
* - Test that checks make_hipFloatComplex/make_hipDoubleComplex functions on device for reduced
* set of input values. The results are compared against manually calculated ones.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Device_make_Complex_Host_Positive", "", hipFloatComplex,
hipDoubleComplex) {
decltype(TestType().x) input_r = GENERATE(-0.25, 0, 0.25);
decltype(TestType().x) input_i = GENERATE(-1.75, 0, 1.75);
TestType result = MakeComplexType<TestType>(input_r, input_i);
REQUIRE(result.x == input_r);
REQUIRE(result.y == input_i);
}
#if HT_AMD // EXSWHTEC-321
/**
* Test Description
* ------------------------
* - Test that checks make_hipComplex functions on device for reduced set of input values. The
* results are compared against manually calculated ones.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device_make_hipComplex_Device_Positive") {
float input_r = GENERATE(-0.25, 0, 0.25);
float input_i = GENERATE(-1.75, 0, 1.75);
LinearAllocGuard<hipComplex> result_d(LinearAllocs::hipMalloc, sizeof(hipComplex));
LinearAllocGuard<hipComplex> result_h(LinearAllocs::hipHostMalloc, sizeof(hipComplex));
MakeHipComplexTypeKernel<<<1, 1>>>(result_d.ptr(), input_r, input_i);
HIP_CHECK(hipMemcpy(result_h.ptr(), result_d.ptr(), sizeof(hipComplex), hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
REQUIRE(result_h.ptr()[0].x == input_r);
REQUIRE(result_h.ptr()[0].y == input_i);
}
/**
* Test Description
* ------------------------
* - Test that checks make_hipComplex functions on host for reduced set of input values. The
* results are compared against manually calculated ones.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device_make_hipComplex_Host_Positive") {
float input_r = GENERATE(-0.25, 0, 0.25);
float input_i = GENERATE(-1.75, 0, 1.75);
hipComplex result = make_hipComplex(input_r, input_i);
REQUIRE(result.x == input_r);
REQUIRE(result.y == input_i);
}
#endif
/**
* Test Description
* ------------------------
* - RTCs kernels that pass argument of invalid type for make complex functions.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device_make_Complex_Negative_Parameters_RTC") {
ComplexTypeRTCWrapper<18>(kMakeHipComplex);
ComplexTypeRTCWrapper<18>(kMakeHipFloatComplex);
ComplexTypeRTCWrapper<18>(kMakeHipDoubleComplex);
}
/**
* Test Description
* ------------------------
* - Test that checks hipComplexDoubleToFloat/hipComplexFloatToDouble functions on device for
* reduced set of input values. The results are compared against manually calculated ones.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Device_Complex_Cast_Device_Sanity_Positive", "", hipFloatComplex,
hipDoubleComplex) {
decltype(TestType().x) input_r = GENERATE(-0.25, 0, 0.25);
decltype(TestType().x) input_i = GENERATE(-1.75, 0, 1.75);
TestType input = MakeComplexType<TestType>(input_r, input_i);
LinearAllocGuard<CastType_t<TestType>> result_d{LinearAllocs::hipMalloc,
sizeof(CastType_t<TestType>)};
LinearAllocGuard<CastType_t<TestType>> result_h{LinearAllocs::hipHostMalloc,
sizeof(CastType_t<TestType>)};
CastComplexTypeKernel<<<1, 1>>>(result_d.ptr(), input);
HIP_CHECK(hipMemcpy(result_h.ptr(), result_d.ptr(), sizeof(CastType_t<TestType>),
hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
REQUIRE(result_h.ptr()[0].x == static_cast<decltype(CastType_t<TestType>().x)>(input_r));
REQUIRE(result_h.ptr()[0].y == static_cast<decltype(CastType_t<TestType>().x)>(input_i));
}
/**
* Test Description
* ------------------------
* - Test that checks hipComplexDoubleToFloat/hipComplexFloatToDouble functions on host for
* reduced set of input values. The results are compared against manually calculated ones.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Device_Complex_Cast_Host_Sanity_Positive", "", hipFloatComplex,
hipDoubleComplex) {
decltype(TestType().x) input_r = GENERATE(-0.25, 0, 0.25);
decltype(TestType().x) input_i = GENERATE(-1.75, 0, 1.75);
TestType input = MakeComplexType<TestType>(input_r, input_i);
CastType_t<TestType> result = CastComplexType<CastType_t<TestType>>(input);
REQUIRE(result.x == static_cast<decltype(CastType_t<TestType>().x)>(input_r));
REQUIRE(result.y == static_cast<decltype(CastType_t<TestType>().x)>(input_i));
}
/**
* Test Description
* ------------------------
* - RTCs kernels that pass argument of invalid type for complex cast functions.
*
* Test source
* ------------------------
* - unit/complex/complex.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device_Complex_Cast_Negative_Parameters_RTC") {
ComplexTypeRTCWrapper<14>(kComplexDoubleToFloat);
ComplexTypeRTCWrapper<14>(kComplexFloatToDouble);
}
+106
Ver Arquivo
@@ -0,0 +1,106 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
#include <hip_test_common.hh>
#include <resource_guards.hh>
#include <hip/hip_complex.h>
template <typename T>
__host__ __device__ T MakeComplexType(decltype(T().x) input_val1, decltype(T().x) input_val2) {
if constexpr (std::is_same_v<T, hipFloatComplex>) {
return make_hipFloatComplex(input_val1, input_val2);
} else {
return make_hipDoubleComplex(input_val1, input_val2);
}
}
template <typename T>
__global__ void MakeComplexTypeKernel(T* const output_val, decltype(T().x) const input_val1,
decltype(T().x) const input_val2) {
*output_val = MakeComplexType<T>(input_val1, input_val2);
}
#if HT_AMD // EXSWHTEC-321
__global__ void MakeHipComplexTypeKernel(hipComplex* const output_val, float const input_val1,
float const input_val2) {
*output_val = make_hipComplex(input_val1, input_val2);
}
#endif
template <typename T> struct CastType {};
template <> struct CastType<hipFloatComplex> {
using type = hipDoubleComplex;
};
template <> struct CastType<hipDoubleComplex> {
using type = hipFloatComplex;
};
template <typename T> using CastType_t = typename CastType<T>::type;
template <typename T1, typename T2> __device__ __host__ T1 CastComplexType(T2 const input_val) {
if constexpr (std::is_same_v<hipDoubleComplex, T2>) {
return hipComplexDoubleToFloat(input_val);
} else if constexpr (std::is_same_v<hipFloatComplex, T2>) {
return hipComplexFloatToDouble(input_val);
}
}
template <typename T1, typename T2>
__global__ void CastComplexTypeKernel(T1* const output_val, T2 const input_val) {
*output_val = CastComplexType<T1, T2>(input_val);
}
template <typename T> void CompareValues(T actual_val, T ref_val, double margin) {
if (!std::isnan(ref_val)) {
REQUIRE_THAT(actual_val, Catch::WithinAbs(ref_val, margin));
}
}
template <int expected_errors_num> void ComplexTypeRTCWrapper(const char* program_source) {
hiprtcProgram program{};
HIPRTC_CHECK(hiprtcCreateProgram(&program, program_source, "complex_type_kernels.cc", 0, nullptr,
nullptr));
#if HT_AMD
std::string args = std::string("-ferror-limit=100");
const char* options[] = {args.c_str()};
hiprtcResult result{hiprtcCompileProgram(program, 1, options)};
#else
hiprtcResult result{hiprtcCompileProgram(program, 0, nullptr)};
#endif
size_t log_size{};
HIPRTC_CHECK(hiprtcGetProgramLogSize(program, &log_size));
std::string log(log_size, ' ');
HIPRTC_CHECK(hiprtcGetProgramLog(program, log.data()));
int error_count{0};
std::string error_message{"error:"};
size_t npos_e = log.find(error_message, 0);
while (npos_e != std::string::npos) {
++error_count;
npos_e = log.find(error_message, npos_e + 1);
}
HIPRTC_CHECK(hiprtcDestroyProgram(&program));
HIPRTC_CHECK_ERROR(result, HIPRTC_ERROR_COMPILATION);
REQUIRE(error_count == expected_errors_num);
}
@@ -0,0 +1,113 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <hip/hip_complex.h>
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipComplexDoubleToFloat_kernel_v1(hipFloatComplex* result, hipDoubleComplex* x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexDoubleToFloat_kernel_v2(hipFloatComplex* result, hipFloatComplex x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexDoubleToFloat_kernel_v3(hipFloatComplex* result, double x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexDoubleToFloat_kernel_v4(hipFloatComplex* result, Dummy x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexDoubleToFloat_kernel_v5(float* result, hipDoubleComplex x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexDoubleToFloat_kernel_v6(hipDoubleComplex* result, hipDoubleComplex x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexDoubleToFloat_kernel_v7(Dummy* result, hipDoubleComplex x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v1(hipFloatComplex* result, hipDoubleComplex* x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v2(hipFloatComplex* result, hipFloatComplex x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v3(hipFloatComplex* result, double x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v4(hipFloatComplex* result, Dummy x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v5(float* result, hipDoubleComplex x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v6(hipDoubleComplex* result, hipDoubleComplex x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v7(Dummy* result, hipDoubleComplex x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexFloatToDouble_kernel_v1(hipDoubleComplex* result, hipFloatComplex* x) {
*result = hipComplexFloatToDouble(x);
}
__global__ void hipComplexFloatToDouble_kernel_v2(hipDoubleComplex* result, hipDoubleComplex x) {
*result = hipComplexFloatToDouble(x);
}
__global__ void hipComplexFloatToDouble_kernel_v3(hipDoubleComplex* result, float x) {
*result = hipComplexFloatToDouble(x);
}
__global__ void hipComplexFloatToDouble_kernel_v4(hipDoubleComplex* result, Dummy x) {
*result = hipComplexFloatToDouble(x);
}
__global__ void hipComplexFloatToDouble_kernel_v5(double* result, hipFloatComplex x) {
*result = hipComplexFloatToDouble(x);
}
__global__ void hipComplexFloatToDouble_kernel_v6(hipFloatComplex* result, hipFloatComplex x) {
*result = hipComplexFloatToDouble(x);
}
__global__ void hipComplexFloatToDouble_kernel_v7(Dummy* result, hipFloatComplex x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v1(hipDoubleComplex* result, hipFloatComplex* x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v2(hipDoubleComplex* result, hipDoubleComplex x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v3(hipDoubleComplex* result, float x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v4(hipDoubleComplex* result, Dummy x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v5(double* result, hipFloatComplex x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v6(hipFloatComplex* result, hipFloatComplex x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v7(Dummy* result, hipFloatComplex x) {
*result = hipComplexFloatToDouble(x);
}
@@ -0,0 +1,121 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
static constexpr auto kComplexDoubleToFloat{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipComplexDoubleToFloat_kernel_v1(hipFloatComplex* result, hipDoubleComplex* x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexDoubleToFloat_kernel_v2(hipFloatComplex* result, hipFloatComplex x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexDoubleToFloat_kernel_v3(hipFloatComplex* result, double x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexDoubleToFloat_kernel_v4(hipFloatComplex* result, Dummy x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexDoubleToFloat_kernel_v5(float* result, hipDoubleComplex x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexDoubleToFloat_kernel_v6(hipDoubleComplex* result, hipDoubleComplex x) {
*result = hipComplexDoubleToFloat(x);
}
__global__ void hipComplexDoubleToFloat_kernel_v7(Dummy* result, hipDoubleComplex x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v1(hipFloatComplex* result, hipDoubleComplex* x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v2(hipFloatComplex* result, hipFloatComplex x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v3(hipFloatComplex* result, double x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v4(hipFloatComplex* result, Dummy x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v5(float* result, hipDoubleComplex x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v6(hipDoubleComplex* result, hipDoubleComplex x) {
*result = hipComplexDoubleToFloat(x);
}
void hipComplexDoubleToFloat_v7(Dummy* result, hipDoubleComplex x) {
*result = hipComplexDoubleToFloat(x);
}
)"};
static constexpr auto kComplexFloatToDouble{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipComplexFloatToDouble_kernel_v1(hipDoubleComplex* result, hipFloatComplex* x) {
*result = hipComplexFloatToDouble(x);
}
__global__ void hipComplexFloatToDouble_kernel_v2(hipDoubleComplex* result, hipDoubleComplex x) {
*result = hipComplexFloatToDouble(x);
}
__global__ void hipComplexFloatToDouble_kernel_v3(hipDoubleComplex* result, float x) {
*result = hipComplexFloatToDouble(x);
}
__global__ void hipComplexFloatToDouble_kernel_v4(hipDoubleComplex* result, Dummy x) {
*result = hipComplexFloatToDouble(x);
}
__global__ void hipComplexFloatToDouble_kernel_v5(double* result, hipFloatComplex x) {
*result = hipComplexFloatToDouble(x);
}
__global__ void hipComplexFloatToDouble_kernel_v6(hipFloatComplex* result, hipFloatComplex x) {
*result = hipComplexFloatToDouble(x);
}
__global__ void hipComplexFloatToDouble_kernel_v7(Dummy* result, hipFloatComplex x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v1(hipDoubleComplex* result, hipFloatComplex* x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v2(hipDoubleComplex* result, hipDoubleComplex x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v3(hipDoubleComplex* result, float x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v4(hipDoubleComplex* result, Dummy x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v5(double* result, hipFloatComplex x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v6(hipFloatComplex* result, hipFloatComplex x) {
*result = hipComplexFloatToDouble(x);
}
void hipComplexFloatToDouble_v7(Dummy* result, hipFloatComplex x) {
*result = hipComplexFloatToDouble(x);
}
)"};
+311
Ver Arquivo
@@ -0,0 +1,311 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
#include "complex_basic_common.hh"
enum class ComplexFunction { kReal, kImag, kConj, kAdd, kSub, kMul, kDiv, kAbs, kSqabs, kFma };
inline std::string to_string(ComplexFunction function) {
switch (function) {
case ComplexFunction::kReal:
return "real";
case ComplexFunction::kImag:
return "imaginary";
case ComplexFunction::kConj:
return "conjugate ";
case ComplexFunction::kAdd:
return "addition";
case ComplexFunction::kSub:
return "subtract";
case ComplexFunction::kMul:
return "multiply";
case ComplexFunction::kDiv:
return "divide";
case ComplexFunction::kAbs:
return "absolute";
case ComplexFunction::kSqabs:
return "square absolute";
case ComplexFunction::kFma:
return "fused multiply";
default:
return "Unknown";
}
}
// Function that validates complex functions with complex type result
template <typename T>
void ValidateComplexResultFunction(ComplexFunction function, T input_val1, T input_val2,
T input_val3, T actual_val) {
decltype(T().x) ref_val_r;
decltype(T().x) ref_val_i;
double margin = 0;
switch (function) {
case ComplexFunction::kAdd: {
ref_val_r = input_val1.x + input_val2.x;
ref_val_i = input_val1.y + input_val2.y;
break;
}
case ComplexFunction::kSub: {
ref_val_r = input_val1.x - input_val2.x;
ref_val_i = input_val1.y - input_val2.y;
break;
}
case ComplexFunction::kMul: {
ref_val_r = input_val1.x * input_val2.x - input_val1.y * input_val2.y;
ref_val_i = input_val1.y * input_val2.x + input_val1.x * input_val2.y;
break;
}
case ComplexFunction::kDiv: {
decltype(T().x) sqabs = input_val2.x * input_val2.x + input_val2.y * input_val2.y;
ref_val_r = (input_val1.x * input_val2.x + input_val1.y * input_val2.y) / sqabs;
ref_val_i = (input_val1.y * input_val2.x - input_val1.x * input_val2.y) / sqabs;
#if HT_NVIDIA
// Nvidia implementation uses scaling to guard against intermediate underflow and overflow
margin = 0.000001;
#endif
break;
}
case ComplexFunction::kConj: {
ref_val_r = input_val1.x;
ref_val_i = -input_val1.y;
break;
}
case ComplexFunction::kFma: {
ref_val_r = (input_val1.x * input_val2.x) + input_val3.x;
ref_val_i = (input_val2.x * input_val1.y) + input_val3.y;
ref_val_r = -(input_val1.y * input_val2.y) + ref_val_r;
ref_val_i = (input_val1.x * input_val2.y) + ref_val_i;
break;
}
default: {
ref_val_r = input_val1.x;
ref_val_i = input_val1.y;
break;
}
}
CompareValues(actual_val.x, ref_val_r, margin);
CompareValues(actual_val.y, ref_val_i, margin);
}
// Function that validates complex functions with scalar type result
template <typename T>
void ValidateScalarResultFunction(ComplexFunction function, T input_val,
decltype(T().x) actual_val) {
decltype(T().x) ref_val;
switch (function) {
case ComplexFunction::kReal: {
ref_val = input_val.x;
break;
}
case ComplexFunction::kImag: {
ref_val = input_val.y;
break;
}
case ComplexFunction::kAbs: {
decltype(T().x) sqabs = input_val.x * input_val.x + input_val.y * input_val.y;
ref_val = std::sqrt(sqabs);
break;
}
case ComplexFunction::kSqabs: {
ref_val = input_val.x * input_val.x + input_val.y * input_val.y;
break;
}
default: {
ref_val = input_val.x;
break;
}
}
CompareValues(actual_val, ref_val, 0);
}
// Function that performs complex functions with complex type result on host/device
template <typename T>
__device__ __host__ void PerformComplexResultFunction(ComplexFunction function, T* output_val,
T input_val1, T input_val2, T input_val3) {
if (function == ComplexFunction::kAdd) {
if constexpr (std::is_same_v<hipFloatComplex, T>) {
*output_val = hipCaddf(input_val1, input_val2);
} else if constexpr (std::is_same_v<hipDoubleComplex, T>) {
*output_val = hipCadd(input_val1, input_val2);
}
} else if (function == ComplexFunction::kSub) {
if constexpr (std::is_same_v<hipFloatComplex, T>) {
*output_val = hipCsubf(input_val1, input_val2);
} else if constexpr (std::is_same_v<hipDoubleComplex, T>) {
*output_val = hipCsub(input_val1, input_val2);
}
} else if (function == ComplexFunction::kMul) {
if constexpr (std::is_same_v<hipFloatComplex, T>) {
*output_val = hipCmulf(input_val1, input_val2);
} else if constexpr (std::is_same_v<hipDoubleComplex, T>) {
*output_val = hipCmul(input_val1, input_val2);
}
} else if (function == ComplexFunction::kDiv) {
if constexpr (std::is_same_v<hipFloatComplex, T>) {
*output_val = hipCdivf(input_val1, input_val2);
} else if constexpr (std::is_same_v<hipDoubleComplex, T>) {
*output_val = hipCdiv(input_val1, input_val2);
}
} else if (function == ComplexFunction::kConj) {
if constexpr (std::is_same_v<hipFloatComplex, T>) {
*output_val = hipConjf(input_val1);
} else if constexpr (std::is_same_v<hipDoubleComplex, T>) {
*output_val = hipConj(input_val1);
}
} else if (function == ComplexFunction::kFma) {
if constexpr (std::is_same_v<hipFloatComplex, T>) {
*output_val = hipCfmaf(input_val1, input_val2, input_val3);
} else if constexpr (std::is_same_v<hipDoubleComplex, T>) {
*output_val = hipCfma(input_val1, input_val2, input_val3);
}
} else {
*output_val = input_val1;
}
}
// Function that performs complex functions with scalar type result on host/device
template <typename T>
__device__ __host__ void PerformScalarResultFunction(ComplexFunction function,
decltype(T().x)* output_val, T input_val) {
if (function == ComplexFunction::kReal) {
if constexpr (std::is_same_v<hipFloatComplex, T>) {
*output_val = hipCrealf(input_val);
} else if constexpr (std::is_same_v<hipDoubleComplex, T>) {
*output_val = hipCreal(input_val);
}
} else if (function == ComplexFunction::kImag) {
if constexpr (std::is_same_v<hipFloatComplex, T>) {
*output_val = hipCimagf(input_val);
} else if constexpr (std::is_same_v<hipDoubleComplex, T>) {
*output_val = hipCimag(input_val);
}
} else if (function == ComplexFunction::kAbs) {
if constexpr (std::is_same_v<hipFloatComplex, T>) {
*output_val = hipCabsf(input_val);
} else if constexpr (std::is_same_v<hipDoubleComplex, T>) {
*output_val = hipCabs(input_val);
}
} else if (function == ComplexFunction::kSqabs) {
if constexpr (std::is_same_v<hipFloatComplex, T>) {
*output_val = hipCsqabsf(input_val);
} else if constexpr (std::is_same_v<hipDoubleComplex, T>) {
*output_val = hipCsqabs(input_val);
}
} else {
*output_val = input_val.x;
}
}
// Kernel that calls device function which performs complex functions with complex type result
template <typename T>
__global__ void ComplexResultKernel(ComplexFunction function, T* output_val, T input_val1,
T input_val2, T input_val3) {
PerformComplexResultFunction(function, output_val, input_val1, input_val2, input_val3);
}
// Kernel that calls device function which performs complex functions with scalar type result
template <typename T>
__global__ void ScalarResultKernel(ComplexFunction function, decltype(T().x)* output_val,
T input_val) {
PerformScalarResultFunction(function, output_val, input_val);
}
// Wrapper function for testing complex functions with one input parameter on device
template <typename T> void ComplexFunctionUnaryDeviceTest(ComplexFunction function, T input_val) {
if (function == ComplexFunction::kConj) {
LinearAllocGuard<T> result_d{LinearAllocs::hipMalloc, sizeof(T)};
LinearAllocGuard<T> result_h{LinearAllocs::hipHostMalloc, sizeof(T)};
ComplexResultKernel<<<1, 1>>>(function, result_d.ptr(), input_val, input_val, input_val);
HIP_CHECK(hipMemcpy(result_h.ptr(), result_d.ptr(), sizeof(T), hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
ValidateComplexResultFunction(function, input_val, input_val, input_val, result_h.ptr()[0]);
} else {
LinearAllocGuard<decltype(T().x)> result_d{LinearAllocs::hipMalloc, sizeof(decltype(T().x))};
LinearAllocGuard<decltype(T().x)> result_h{LinearAllocs::hipHostMalloc,
sizeof(decltype(T().x))};
ScalarResultKernel<<<1, 1>>>(function, result_d.ptr(), input_val);
HIP_CHECK(
hipMemcpy(result_h.ptr(), result_d.ptr(), sizeof(decltype(T().x)), hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
ValidateScalarResultFunction(function, input_val, result_h.ptr()[0]);
}
}
// Wrapper function for testing complex functions with one input parameter on host
template <typename T> void ComplexFunctionUnaryHostTest(ComplexFunction function, T input_val) {
if (function == ComplexFunction::kConj) {
T result;
PerformComplexResultFunction(function, &result, input_val, input_val, input_val);
ValidateComplexResultFunction(function, input_val, input_val, input_val, result);
} else {
decltype(T().x) result;
PerformScalarResultFunction(function, &result, input_val);
ValidateScalarResultFunction(function, input_val, result);
}
}
// Wrapper function for testing complex functions with two input parameters on device
template <typename T>
void ComplexFunctionBinaryDeviceTest(ComplexFunction function, T input_val1, T input_val2) {
LinearAllocGuard<T> result_d{LinearAllocs::hipMalloc, sizeof(T)};
LinearAllocGuard<T> result_h{LinearAllocs::hipHostMalloc, sizeof(T)};
ComplexResultKernel<<<1, 1>>>(function, result_d.ptr(), input_val1, input_val2, input_val2);
HIP_CHECK(hipMemcpy(result_h.ptr(), result_d.ptr(), sizeof(T), hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
ValidateComplexResultFunction(function, input_val1, input_val2, input_val2, result_h.ptr()[0]);
}
// Wrapper function for testing complex functions with two input parameters on host
template <typename T>
void ComplexFunctionBinaryHostTest(ComplexFunction function, T input_val1, T input_val2) {
T result;
PerformComplexResultFunction(function, &result, input_val1, input_val2, input_val2);
ValidateComplexResultFunction(function, input_val1, input_val2, input_val2, result);
}
// Wrapper function for testing complex functions with three input parameters on device
template <typename T>
void ComplexFunctionTernaryDeviceTest(ComplexFunction function, T input_val1, T input_val2,
T input_val3) {
LinearAllocGuard<T> result_d{LinearAllocs::hipMalloc, sizeof(T)};
LinearAllocGuard<T> result_h{LinearAllocs::hipHostMalloc, sizeof(T)};
ComplexResultKernel<<<1, 1>>>(function, result_d.ptr(), input_val1, input_val2, input_val3);
HIP_CHECK(hipMemcpy(result_h.ptr(), result_d.ptr(), sizeof(T), hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
ValidateComplexResultFunction(function, input_val1, input_val2, input_val3, result_h.ptr()[0]);
}
// Wrapper function for testing complex functions with three input parameters on host
template <typename T>
void ComplexFunctionTernaryHostTest(ComplexFunction function, T input_val1, T input_val2,
T input_val3) {
T result;
PerformComplexResultFunction(function, &result, input_val1, input_val2, input_val3);
ValidateComplexResultFunction(function, input_val1, input_val2, input_val3, result);
}
@@ -0,0 +1,121 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <hip/hip_complex.h>
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
#define NEGATIVE_SHELL_MAKE_FLOAT(T, func_name) \
__global__ void func_name##_kernel_v1(T* result, float* x, float y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v2(T* result, float x, float* y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v3(T* result, T x, float y) { *result = func_name(x, y); } \
__global__ void func_name##_kernel_v4(T* result, float x, T y) { *result = func_name(x, y); } \
__global__ void func_name##_kernel_v5(T* result, Dummy x, float y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v6(T* result, float x, Dummy y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v7(float* result, float x, float y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v8(hipDoubleComplex* result, float x, float y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v9(Dummy* result, float x, float y) { \
*result = func_name(x, y); \
} \
void func_name##_v1(T* result, float* x, float y) { *result = func_name(x, y); } \
void func_name##_v2(T* result, float x, float* y) { *result = func_name(x, y); } \
void func_name##_v3(T* result, T x, float y) { *result = func_name(x, y); } \
void func_name##_v4(T* result, float x, T y) { *result = func_name(x, y); } \
void func_name##_v5(T* result, Dummy x, float y) { *result = func_name(x, y); } \
void func_name##_v6(T* result, float x, Dummy y) { *result = func_name(x, y); } \
void func_name##_v7(float* result, float x, float y) { *result = func_name(x, y); } \
void func_name##_v8(hipDoubleComplex* result, float x, float y) { *result = func_name(x, y); } \
void func_name##_v9(Dummy* result, float x, float y) { *result = func_name(x, y); }
__global__ void make_hipDoubleComplex_kernel_v1(hipDoubleComplex* result, double* x, double y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v2(hipDoubleComplex* result, double x, double* y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v3(hipDoubleComplex* result, hipDoubleComplex x,
double y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v4(hipDoubleComplex* result, double x,
hipDoubleComplex y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v5(hipDoubleComplex* result, Dummy x, double y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v6(hipDoubleComplex* result, double x, Dummy y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v7(double* result, double x, double y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v8(hipFloatComplex* result, double x, double y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v9(Dummy* result, double x, double y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v1(hipDoubleComplex* result, double* x, double y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v2(hipDoubleComplex* result, double x, double* y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v3(hipDoubleComplex* result, hipDoubleComplex x, double y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v4(hipDoubleComplex* result, double x, hipDoubleComplex y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v5(hipDoubleComplex* result, Dummy x, double y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v6(hipDoubleComplex* result, double x, Dummy y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v7(float* result, double x, double y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v8(hipFloatComplex* result, double x, double y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v9(Dummy* result, double x, double y) {
*result = make_hipDoubleComplex(x, y);
}
NEGATIVE_SHELL_MAKE_FLOAT(hipFloatComplex, make_hipFloatComplex)
NEGATIVE_SHELL_MAKE_FLOAT(hipComplex, make_hipComplex)
@@ -0,0 +1,198 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
static constexpr auto kMakeHipComplex{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void make_hipComplex_kernel_v1(hipComplex* result, float* x, float y) {
*result = make_hipComplex(x, y);
}
__global__ void make_hipComplex_kernel_v2(hipComplex* result, float x, float* y) {
*result = make_hipComplex(x, y);
}
__global__ void make_hipComplex_kernel_v3(hipComplex* result, hipComplex x, float y) {
*result = make_hipComplex(x, y);
}
__global__ void make_hipComplex_kernel_v4(hipComplex* result, float x, hipComplex y) {
*result = make_hipComplex(x, y);
}
__global__ void make_hipComplex_kernel_v5(hipComplex* result, Dummy x, float y) {
*result = make_hipComplex(x, y);
}
__global__ void make_hipComplex_kernel_v6(hipComplex* result, float x, Dummy y) {
*result = make_hipComplex(x, y);
}
__global__ void make_hipComplex_kernel_v7(float* result, float x, float y) {
*result = make_hipComplex(x, y);
}
__global__ void make_hipComplex_kernel_v8(hipDoubleComplex* result, float x, float y) {
*result = make_hipComplex(x, y);
}
__global__ void make_hipComplex_kernel_v9(Dummy* result, float x, float y) {
*result = make_hipComplex(x, y);
}
void make_hipComplex_v1(hipComplex* result, float* x, float y) { *result = make_hipComplex(x, y); }
void make_hipComplex_v2(hipComplex* result, float x, float* y) { *result = make_hipComplex(x, y); }
void make_hipComplex_v3(hipComplex* result, hipComplex x, float y) {
*result = make_hipComplex(x, y);
}
void make_hipComplex_v4(hipComplex* result, float x, hipComplex y) {
*result = make_hipComplex(x, y);
}
void make_hipComplex_v5(hipComplex* result, Dummy x, float y) { *result = make_hipComplex(x, y); }
void make_hipComplex_v6(hipComplex* result, float x, Dummy y) { *result = make_hipComplex(x, y); }
void make_hipComplex_v7(float* result, float x, float y) { *result = make_hipComplex(x, y); }
void make_hipComplex_v8(hipDoubleComplex* result, float x, float y) {
*result = make_hipComplex(x, y);
}
void make_hipComplex_v9(Dummy* result, float x, float y) { *result = make_hipComplex(x, y); }
)"};
static constexpr auto kMakeHipFloatComplex{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void make_hipFloatComplex_kernel_v1(hipFloatComplex* result, float* x, float y) {
*result = make_hipFloatComplex(x, y);
}
__global__ void make_hipFloatComplex_kernel_v2(hipFloatComplex* result, float x, float* y) {
*result = make_hipFloatComplex(x, y);
}
__global__ void make_hipFloatComplex_kernel_v3(hipFloatComplex* result, hipFloatComplex x,
float y) {
*result = make_hipFloatComplex(x, y);
}
__global__ void make_hipFloatComplex_kernel_v4(hipFloatComplex* result, float x,
hipFloatComplex y) {
*result = make_hipFloatComplex(x, y);
}
__global__ void make_hipFloatComplex_kernel_v5(hipFloatComplex* result, Dummy x, float y) {
*result = make_hipFloatComplex(x, y);
}
__global__ void make_hipFloatComplex_kernel_v6(hipFloatComplex* result, float x, Dummy y) {
*result = make_hipFloatComplex(x, y);
}
__global__ void make_hipFloatComplex_kernel_v7(float* result, float x, float y) {
*result = make_hipFloatComplex(x, y);
}
__global__ void make_hipFloatComplex_kernel_v8(hipDoubleComplex* result, float x, float y) {
*result = make_hipFloatComplex(x, y);
}
__global__ void make_hipFloatComplex_kernel_v9(Dummy* result, float x, float y) {
*result = make_hipFloatComplex(x, y);
}
void make_hipFloatComplex_v1(hipFloatComplex* result, float* x, float y) {
*result = make_hipFloatComplex(x, y);
}
void make_hipFloatComplex_v2(hipFloatComplex* result, float x, float* y) {
*result = make_hipFloatComplex(x, y);
}
void make_hipFloatComplex_v3(hipFloatComplex* result, hipFloatComplex x, float y) {
*result = make_hipFloatComplex(x, y);
}
void make_hipFloatComplex_v4(hipFloatComplex* result, float x, hipFloatComplex y) {
*result = make_hipFloatComplex(x, y);
}
void make_hipFloatComplex_v5(hipFloatComplex* result, Dummy x, float y) {
*result = make_hipFloatComplex(x, y);
}
void make_hipFloatComplex_v6(hipFloatComplex* result, float x, Dummy y) {
*result = make_hipFloatComplex(x, y);
}
void make_hipFloatComplex_v7(float* result, float x, float y) {
*result = make_hipFloatComplex(x, y);
}
void make_hipFloatComplex_v8(hipDoubleComplex* result, float x, float y) {
*result = make_hipFloatComplex(x, y);
}
void make_hipFloatComplex_v9(Dummy* result, float x, float y) {
*result = make_hipFloatComplex(x, y);
}
)"};
static constexpr auto kMakeHipDoubleComplex{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void make_hipDoubleComplex_kernel_v1(hipDoubleComplex* result, double* x, double y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v2(hipDoubleComplex* result, double x, double* y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v3(hipDoubleComplex* result, hipDoubleComplex x,
double y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v4(hipDoubleComplex* result, double x,
hipDoubleComplex y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v5(hipDoubleComplex* result, Dummy x, double y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v6(hipDoubleComplex* result, double x, Dummy y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v7(double* result, double x, double y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v8(hipFloatComplex* result, double x, double y) {
*result = make_hipDoubleComplex(x, y);
}
__global__ void make_hipDoubleComplex_kernel_v9(Dummy* result, double x, double y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v1(hipDoubleComplex* result, double* x, double y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v2(hipDoubleComplex* result, double x, double* y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v3(hipDoubleComplex* result, hipDoubleComplex x, double y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v4(hipDoubleComplex* result, double x, hipDoubleComplex y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v5(hipDoubleComplex* result, Dummy x, double y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v6(hipDoubleComplex* result, double x, Dummy y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v7(float* result, double x, double y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v8(hipFloatComplex* result, double x, double y) {
*result = make_hipDoubleComplex(x, y);
}
void make_hipDoubleComplex_v9(Dummy* result, double x, double y) {
*result = make_hipDoubleComplex(x, y);
}
)"};
@@ -0,0 +1,75 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <hip/hip_complex.h>
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
#define NEGATIVE_SHELL_ONE_ARG_DOUBLE(func_name) \
__global__ void func_name##_kernel_v1(double* result, hipDoubleComplex* x) { \
*result = func_name(x); \
} \
__global__ void func_name##_kernel_v2(double* result, hipFloatComplex x) { \
*result = func_name(x); \
} \
__global__ void func_name##_kernel_v3(double* result, double x) { *result = func_name(x); } \
__global__ void func_name##_kernel_v4(double* result, Dummy x) { *result = func_name(x); } \
__global__ void func_name##_kernel_v5(hipDoubleComplex* result, hipDoubleComplex x) { \
*result = func_name(x); \
} \
__global__ void func_name##_kernel_v6(Dummy* result, hipDoubleComplex x) { \
*result = func_name(x); \
} \
void func_name##_v1(double* result, hipDoubleComplex* x) { *result = func_name(x); } \
void func_name##_v2(double* result, hipFloatComplex x) { *result = func_name(x); } \
void func_name##_v3(double* result, double x) { *result = func_name(x); } \
void func_name##_v4(double* result, Dummy x) { *result = func_name(x); } \
void func_name##_v5(hipDoubleComplex* result, hipDoubleComplex x) { *result = func_name(x); } \
void func_name##_v6(Dummy* result, hipDoubleComplex x) { *result = func_name(x); }
__global__ void hipConj_kernel_v1(hipDoubleComplex* result, hipDoubleComplex* x) {
*result = hipConj(x);
}
__global__ void hipConj_kernel_v2(hipDoubleComplex* result, hipFloatComplex x) {
*result = hipConj(x);
}
__global__ void hipConj_kernel_v3(hipDoubleComplex* result, double x) { *result = hipConj(x); }
__global__ void hipConj_kernel_v4(hipDoubleComplex* result, Dummy x) { *result = hipConj(x); }
__global__ void hipConj_kernel_v5(double* result, hipDoubleComplex x) { *result = hipConj(x); }
__global__ void hipConj_kernel_v6(hipFloatComplex* result, hipDoubleComplex x) {
*result = hipConj(x);
}
__global__ void hipConj_kernel_v7(Dummy* result, hipDoubleComplex x) { *result = hipConj(x); }
void hipConj_v1(hipDoubleComplex* result, hipDoubleComplex* x) { *result = hipConj(x); }
void hipConj_v2(hipDoubleComplex* result, hipFloatComplex x) { *result = hipConj(x); }
void hipConj_v3(hipDoubleComplex* result, double x) { *result = hipConj(x); }
void hipConj_v4(hipDoubleComplex* result, Dummy x) { *result = hipConj(x); }
void hipConj_v5(double* result, hipDoubleComplex x) { *result = hipConj(x); }
void hipConj_v6(hipFloatComplex* result, hipDoubleComplex x) { *result = hipConj(x); }
void hipConj_v7(Dummy* result, hipDoubleComplex x) { *result = hipConj(x); }
NEGATIVE_SHELL_ONE_ARG_DOUBLE(hipCreal)
NEGATIVE_SHELL_ONE_ARG_DOUBLE(hipCimag)
NEGATIVE_SHELL_ONE_ARG_DOUBLE(hipCabs)
NEGATIVE_SHELL_ONE_ARG_DOUBLE(hipCsqabs)
@@ -0,0 +1,75 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <hip/hip_complex.h>
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
#define NEGATIVE_SHELL_ONE_ARG_FLOAT(func_name) \
__global__ void func_name##_kernel_v1(float* result, hipFloatComplex* x) { \
*result = func_name(x); \
} \
__global__ void func_name##_kernel_v2(float* result, hipDoubleComplex x) { \
*result = func_name(x); \
} \
__global__ void func_name##_kernel_v3(float* result, float x) { *result = func_name(x); } \
__global__ void func_name##_kernel_v4(float* result, Dummy x) { *result = func_name(x); } \
__global__ void func_name##_kernel_v5(hipFloatComplex* result, hipFloatComplex x) { \
*result = func_name(x); \
} \
__global__ void func_name##_kernel_v6(Dummy* result, hipFloatComplex x) { \
*result = func_name(x); \
} \
void func_name##_v1(float* result, hipFloatComplex* x) { *result = func_name(x); } \
void func_name##_v2(float* result, hipDoubleComplex x) { *result = func_name(x); } \
void func_name##_v3(float* result, float x) { *result = func_name(x); } \
void func_name##_v4(float* result, Dummy x) { *result = func_name(x); } \
void func_name##_v5(hipFloatComplex* result, hipFloatComplex x) { *result = func_name(x); } \
void func_name##_v6(Dummy* result, hipFloatComplex x) { *result = func_name(x); }
__global__ void hipConjf_kernel_v1(hipFloatComplex* result, hipFloatComplex* x) {
*result = hipConjf(x);
}
__global__ void hipConjf_kernel_v2(hipFloatComplex* result, hipDoubleComplex x) {
*result = hipConjf(x);
}
__global__ void hipConjf_kernel_v3(hipFloatComplex* result, float x) { *result = hipConjf(x); }
__global__ void hipConjf_kernel_v4(hipFloatComplex* result, Dummy x) { *result = hipConjf(x); }
__global__ void hipConjf_kernel_v5(float* result, hipFloatComplex x) { *result = hipConjf(x); }
__global__ void hipConjf_kernel_v6(hipDoubleComplex* result, hipFloatComplex x) {
*result = hipConjf(x);
}
__global__ void hipConjf_kernel_v7(Dummy* result, hipFloatComplex x) { *result = hipConjf(x); }
void hipConjf_v1(hipFloatComplex* result, hipFloatComplex* x) { *result = hipConjf(x); }
void hipConjf_v2(hipFloatComplex* result, hipDoubleComplex x) { *result = hipConjf(x); }
void hipConjf_v3(hipFloatComplex* result, float x) { *result = hipConjf(x); }
void hipConjf_v4(hipFloatComplex* result, Dummy x) { *result = hipConjf(x); }
void hipConjf_v5(float* result, hipFloatComplex x) { *result = hipConjf(x); }
void hipConjf_v6(hipDoubleComplex* result, hipFloatComplex x) { *result = hipConjf(x); }
void hipConjf_v7(Dummy* result, hipFloatComplex x) { *result = hipConjf(x); }
NEGATIVE_SHELL_ONE_ARG_FLOAT(hipCrealf)
NEGATIVE_SHELL_ONE_ARG_FLOAT(hipCimagf)
NEGATIVE_SHELL_ONE_ARG_FLOAT(hipCabsf)
NEGATIVE_SHELL_ONE_ARG_FLOAT(hipCsqabsf)
@@ -0,0 +1,207 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
static constexpr auto kComplexConj{R"(
__global__ void hipConjf_kernel_v1(hipFloatComplex* result, hipFloatComplex* x) {
*result = hipConjf(x);
}
__global__ void hipConjf_kernel_v2(hipFloatComplex* result, hipDoubleComplex x) {
*result = hipConjf(x);
}
__global__ void hipConjf_kernel_v3(hipFloatComplex* result, float x) { *result = hipConjf(x); }
__global__ void hipConjf_kernel_v4(hipFloatComplex* result, Dummy x) { *result = hipConjf(x); }
__global__ void hipConjf_kernel_v5(float* result, hipFloatComplex x) { *result = hipConjf(x); }
__global__ void hipConjf_kernel_v6(hipDoubleComplex* result, hipFloatComplex x) {
*result = hipConjf(x);
}
__global__ void hipConjf_kernel_v7(Dummy* result, hipFloatComplex x) { *result = hipConjf(x); }
__global__ void hipConj_kernel_v1(hipDoubleComplex* result, hipDoubleComplex* x) {
*result = hipConj(x);
}
__global__ void hipConj_kernel_v2(hipDoubleComplex* result, hipFloatComplex x) {
*result = hipConj(x);
}
__global__ void hipConj_kernel_v3(hipDoubleComplex* result, double x) { *result = hipConj(x); }
__global__ void hipConj_kernel_v4(hipDoubleComplex* result, Dummy x) { *result = hipConj(x); }
__global__ void hipConj_kernel_v5(double* result, hipDoubleComplex x) { *result = hipConj(x); }
__global__ void hipConj_kernel_v6(hipFloatComplex* result, hipDoubleComplex x) {
*result = hipConj(x);
}
__global__ void hipConj_kernel_v7(Dummy* result, hipDoubleComplex x) { *result = hipConj(x); }
void hipConjf_v1(hipFloatComplex* result, hipFloatComplex* x) { *result = hipConjf(x); }
void hipConjf_v2(hipFloatComplex* result, hipDoubleComplex x) { *result = hipConjf(x); }
void hipConjf_v3(hipFloatComplex* result, float x) { *result = hipConjf(x); }
void hipConjf_v4(hipFloatComplex* result, Dummy x) { *result = hipConjf(x); }
void hipConjf_v5(float* result, hipFloatComplex x) { *result = hipConjf(x); }
void hipConjf_v6(hipDoubleComplex* result, hipFloatComplex x) { *result = hipConjf(x); }
void hipConjf_v7(Dummy* result, hipFloatComplex x) { *result = hipConjf(x); }
void hipConj_v1(hipDoubleComplex* result, hipDoubleComplex* x) { *result = hipConj(x); }
void hipConj_v2(hipDoubleComplex* result, hipFloatComplex x) { *result = hipConj(x); }
void hipConj_v3(hipDoubleComplex* result, double x) { *result = hipConj(x); }
void hipConj_v4(hipDoubleComplex* result, Dummy x) { *result = hipConj(x); }
void hipConj_v5(double* result, hipDoubleComplex x) { *result = hipConj(x); }
void hipConj_v6(hipFloatComplex* result, hipDoubleComplex x) { *result = hipConj(x); }
void hipConj_v7(Dummy* result, hipDoubleComplex x) { *result = hipConj(x); }
)"};
static constexpr auto kComplexReal{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipCrealf_kernel_v1(float* result, hipFloatComplex* x) { *result = hipCrealf(x); }
__global__ void hipCrealf_kernel_v2(float* result, hipDoubleComplex x) { *result = hipCrealf(x); }
__global__ void hipCrealf_kernel_v3(float* result, float x) { *result = hipCrealf(x); }
__global__ void hipCrealf_kernel_v4(float* result, Dummy x) { *result = hipCrealf(x); }
__global__ void hipCrealf_kernel_v5(hipFloatComplex* result, hipFloatComplex x) {
*result = hipCrealf(x);
}
__global__ void hipCrealf_kernel_v6(Dummy* result, hipFloatComplex x) { *result = hipCrealf(x); }
__global__ void hipCreal_kernel_v1(double* result, hipDoubleComplex* x) { *result = hipCreal(x); }
__global__ void hipCreal_kernel_v2(double* result, hipFloatComplex x) { *result = hipCreal(x); }
__global__ void hipCreal_kernel_v3(double* result, double x) { *result = hipCreal(x); }
__global__ void hipCreal_kernel_v4(double* result, Dummy x) { *result = hipCreal(x); }
__global__ void hipCreal_kernel_v5(hipDoubleComplex* result, hipDoubleComplex x) {
*result = hipCreal(x);
}
__global__ void hipCreal_kernel_v6(Dummy* result, hipDoubleComplex x) { *result = hipCreal(x); }
void hipCrealf_v1(float* result, hipFloatComplex* x) { *result = hipCrealf(x); }
void hipCrealf_v2(float* result, hipDoubleComplex x) { *result = hipCrealf(x); }
void hipCrealf_v3(float* result, float x) { *result = hipCrealf(x); }
void hipCrealf_v4(float* result, Dummy x) { *result = hipCrealf(x); }
void hipCrealf_v5(hipFloatComplex* result, hipFloatComplex x) { *result = hipCrealf(x); }
void hipCrealf_v6(Dummy* result, hipFloatComplex x) { *result = hipCrealf(x); }
void hipCreal_v1(double* result, hipDoubleComplex* x) { *result = hipCreal(x); }
void hipCreal_v2(double* result, hipFloatComplex x) { *result = hipCreal(x); }
void hipCreal_v3(double* result, double x) { *result = hipCreal(x); }
void hipCreal_v4(double* result, Dummy x) { *result = hipCreal(x); }
void hipCreal_v5(hipDoubleComplex* result, hipDoubleComplex x) { *result = hipCreal(x); }
void hipCreal_v6(Dummy* result, hipDoubleComplex x) { *result = hipCreal(x); }
)"};
static constexpr auto kComplexImag{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipCimagf_kernel_v1(float* result, hipFloatComplex* x) { *result = hipCimagf(x); }
__global__ void hipCimagf_kernel_v2(float* result, hipDoubleComplex x) { *result = hipCimagf(x); }
__global__ void hipCimagf_kernel_v3(float* result, float x) { *result = hipCimagf(x); }
__global__ void hipCimagf_kernel_v4(float* result, Dummy x) { *result = hipCimagf(x); }
__global__ void hipCimagf_kernel_v5(hipFloatComplex* result, hipFloatComplex x) {
*result = hipCimagf(x);
}
__global__ void hipCimagf_kernel_v6(Dummy* result, hipFloatComplex x) { *result = hipCimagf(x); }
__global__ void hipCimag_kernel_v1(double* result, hipDoubleComplex* x) { *result = hipCimag(x); }
__global__ void hipCimag_kernel_v2(double* result, hipFloatComplex x) { *result = hipCimag(x); }
__global__ void hipCimag_kernel_v3(double* result, double x) { *result = hipCimag(x); }
__global__ void hipCimag_kernel_v4(double* result, Dummy x) { *result = hipCimag(x); }
__global__ void hipCimag_kernel_v5(hipDoubleComplex* result, hipDoubleComplex x) {
*result = hipCimag(x);
}
__global__ void hipCimag_kernel_v6(Dummy* result, hipDoubleComplex x) { *result = hipCimag(x); }
void hipCimagf_v1(float* result, hipFloatComplex* x) { *result = hipCimagf(x); }
void hipCimagf_v2(float* result, hipDoubleComplex x) { *result = hipCimagf(x); }
void hipCimagf_v3(float* result, float x) { *result = hipCimagf(x); }
void hipCimagf_v4(float* result, Dummy x) { *result = hipCimagf(x); }
void hipCimagf_v5(hipFloatComplex* result, hipFloatComplex x) { *result = hipCimagf(x); }
void hipCimagf_v6(Dummy* result, hipFloatComplex x) { *result = hipCimagf(x); }
void hipCimag_v1(double* result, hipDoubleComplex* x) { *result = hipCimag(x); }
void hipCimag_v2(double* result, hipFloatComplex x) { *result = hipCimag(x); }
void hipCimag_v3(double* result, double x) { *result = hipCimag(x); }
void hipCimag_v4(double* result, Dummy x) { *result = hipCimag(x); }
void hipCimag_v5(hipDoubleComplex* result, hipDoubleComplex x) { *result = hipCimag(x); }
void hipCimag_v6(Dummy* result, hipDoubleComplex x) { *result = hipCimag(x); }
)"};
static constexpr auto kComplexAbs{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipCabsf_kernel_v1(float* result, hipFloatComplex* x) { *result = hipCabsf(x); }
__global__ void hipCabsf_kernel_v2(float* result, hipDoubleComplex x) { *result = hipCabsf(x); }
__global__ void hipCabsf_kernel_v3(float* result, float x) { *result = hipCabsf(x); }
__global__ void hipCabsf_kernel_v4(float* result, Dummy x) { *result = hipCabsf(x); }
__global__ void hipCabsf_kernel_v5(hipFloatComplex* result, hipFloatComplex x) {
*result = hipCabsf(x);
}
__global__ void hipCabsf_kernel_v6(Dummy* result, hipFloatComplex x) { *result = hipCabsf(x); }
__global__ void hipCabs_kernel_v1(double* result, hipDoubleComplex* x) { *result = hipCabs(x); }
__global__ void hipCabs_kernel_v2(double* result, hipFloatComplex x) { *result = hipCabs(x); }
__global__ void hipCabs_kernel_v3(double* result, double x) { *result = v(x); }
__global__ void hipCabs_kernel_v4(double* result, Dummy x) { *result = hipCabs(x); }
__global__ void hipCabs_kernel_v5(hipDoubleComplex* result, hipDoubleComplex x) {
*result = hipCabs(x);
}
__global__ void hipCabs_kernel_v6(Dummy* result, hipDoubleComplex x) { *result = hipCabs(x); }
void hipCabsf_v1(float* result, hipFloatComplex* x) { *result = hipCabsf(x); }
void hipCabsf_v2(float* result, hipDoubleComplex x) { *result = hipCabsf(x); }
void hipCabsf_v3(float* result, float x) { *result = hipCabsf(x); }
void hipCabsf_v4(float* result, Dummy x) { *result = hipCabsf(x); }
void hipCabsf_v5(hipFloatComplex* result, hipFloatComplex x) { *result = hipCabsf(x); }
void hipCabsf_v6(Dummy* result, hipFloatComplex x) { *result = hipCabsf(x); }
void hipCabs_v1(double* result, hipDoubleComplex* x) { *result = hipCabs(x); }
void hipCabs_v2(double* result, hipFloatComplex x) { *result = hipCabs(x); }
void hipCabs_v3(double* result, double x) { *result = hipCabs(x); }
void hipCabs_v4(double* result, Dummy x) { *result = hipCabs(x); }
void hipCabs_v5(hipDoubleComplex* result, hipDoubleComplex x) { *result = hipCabs(x); }
void hipCabs_v6(Dummy* result, hipDoubleComplex x) { *result = hipCabs(x); }
)"};
static constexpr auto kComplexSqabs{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipCsqabsf_kernel_v1(float* result, hipFloatComplex* x) { *result = hipCsqabsf(x); }
__global__ void hipCsqabsf_kernel_v2(float* result, hipDoubleComplex x) { *result = hipCsqabsf(x); }
__global__ void hipCsqabsf_kernel_v3(float* result, float x) { *result = hipCsqabsf(x); }
__global__ void hipCsqabsf_kernel_v4(float* result, Dummy x) { *result = hipCsqabsf(x); }
__global__ void hipCsqabsf_kernel_v5(hipFloatComplex* result, hipFloatComplex x) {
*result = hipCsqabsf(x);
}
__global__ void hipCsqabsf_kernel_v6(Dummy* result, hipFloatComplex x) { *result = hipCsqabs(x); }
__global__ void hipCsqabs_kernel_v1(double* result, hipDoubleComplex* x) { *result = hipCsqabs(x); }
__global__ void hipCsqabs_kernel_v2(double* result, hipFloatComplex x) { *result = hipCsqabs(x); }
__global__ void hipCsqabs_kernel_v3(double* result, double x) { *result = hipCsqabs(x); }
__global__ void hipCsqabs_kernel_v4(double* result, Dummy x) { *result = hipCsqabs(x); }
__global__ void hipCsqabs_kernel_v5(hipDoubleComplex* result, hipDoubleComplex x) {
*result = hipCsqabs(x);
}
__global__ void hipCsqabs_kernel_v6(Dummy* result, hipDoubleComplex x) { *result = hipCsqabs(x); }
void hipCsqabsf_v1(float* result, hipFloatComplex* x) { *result = hipCsqabsf(x); }
void hipCsqabsf_v2(float* result, hipDoubleComplex x) { *result = hipCsqabsf(x); }
void hipCsqabsf_v3(float* result, float x) { *result = hipCsqabsf(x); }
void hipCsqabsf_v4(float* result, Dummy x) { *result = hipCsqabsf(x); }
void hipCsqabsf_v5(hipFloatComplex* result, hipFloatComplex x) { *result = hipCsqabsf(x); }
void hipCsqabsf_v6(Dummy* result, hipFloatComplex x) { *result = hipCsqabsf(x); }
void hipCsqabs_v1(double* result, hipDoubleComplex* x) { *result = hipCsqabs(x); }
void hipCsqabs_v2(double* result, hipFloatComplex x) { *result = hipCsqabs(x); }
void hipCsqabs_v3(double* result, double x) { *result = hipCsqabs(x); }
void hipCsqabs_v4(double* result, Dummy x) { *result = hipCsqabs(x); }
void hipCsqabs_v5(hipDoubleComplex* result, hipDoubleComplex x) { *result = hipCsqabs(x); }
void hipCsqabs_v6(Dummy* result, hipDoubleComplex x) { *result = hipCsqabs(x); }
)"};
@@ -0,0 +1,105 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <hip/hip_complex.h>
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
#define NEGATIVE_SHELL_TWO_ARG_DOUBLE(func_name) \
__global__ void func_name##_kernel_v1(hipDoubleComplex* result, hipDoubleComplex* x, \
hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v2(hipDoubleComplex* result, hipDoubleComplex x, \
hipDoubleComplex* y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v3(hipDoubleComplex* result, double x, hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v4(hipDoubleComplex* result, hipDoubleComplex x, double y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v5(hipDoubleComplex* result, hipFloatComplex x, \
hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v6(hipDoubleComplex* result, hipDoubleComplex x, \
hipFloatComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v7(hipDoubleComplex* result, Dummy x, hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v8(hipDoubleComplex* result, hipDoubleComplex x, Dummy y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v9(double* result, hipDoubleComplex x, hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v10(hipFloatComplex* result, hipDoubleComplex x, \
hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v11(Dummy* result, hipDoubleComplex x, hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v1(hipDoubleComplex* result, hipDoubleComplex* x, hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v2(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex* y) { \
*result = func_name(x, y); \
} \
void func_name##_v3(hipDoubleComplex* result, double x, hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v4(hipDoubleComplex* result, hipDoubleComplex x, double y) { \
*result = func_name(x, y); \
} \
void func_name##_v5(hipDoubleComplex* result, hipFloatComplex x, hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v6(hipDoubleComplex* result, hipDoubleComplex x, hipFloatComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v7(hipDoubleComplex* result, Dummy x, hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v8(hipDoubleComplex* result, hipDoubleComplex x, Dummy y) { \
*result = func_name(x, y); \
} \
void func_name##_v9(double* result, hipDoubleComplex x, hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v10(hipFloatComplex* result, hipDoubleComplex x, hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v11(Dummy* result, hipDoubleComplex x, hipDoubleComplex y) { \
*result = func_name(x, y); \
}
NEGATIVE_SHELL_TWO_ARG_DOUBLE(hipCadd)
NEGATIVE_SHELL_TWO_ARG_DOUBLE(hipCsub)
NEGATIVE_SHELL_TWO_ARG_DOUBLE(hipCmul)
NEGATIVE_SHELL_TWO_ARG_DOUBLE(hipCdiv)
@@ -0,0 +1,105 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <hip/hip_complex.h>
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
#define NEGATIVE_SHELL_TWO_ARG_FLOAT(func_name) \
__global__ void func_name##_kernel_v1(hipFloatComplex* result, hipFloatComplex* x, \
hipFloatComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v2(hipFloatComplex* result, hipFloatComplex x, \
hipFloatComplex* y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v3(hipFloatComplex* result, float x, hipFloatComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v4(hipFloatComplex* result, hipFloatComplex x, float y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v5(hipFloatComplex* result, hipDoubleComplex x, \
hipFloatComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v6(hipFloatComplex* result, hipFloatComplex x, \
hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v7(hipFloatComplex* result, Dummy x, hipFloatComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v8(hipFloatComplex* result, hipFloatComplex x, Dummy y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v9(float* result, hipFloatComplex x, hipFloatComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v10(hipDoubleComplex* result, hipFloatComplex x, \
hipFloatComplex y) { \
*result = func_name(x, y); \
} \
__global__ void func_name##_kernel_v11(Dummy* result, hipFloatComplex x, hipFloatComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v1(hipFloatComplex* result, hipFloatComplex* x, hipFloatComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v2(hipFloatComplex* result, hipFloatComplex x, hipFloatComplex* y) { \
*result = func_name(x, y); \
} \
void func_name##_v3(hipFloatComplex* result, float x, hipFloatComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v4(hipFloatComplex* result, hipFloatComplex x, float y) { \
*result = func_name(x, y); \
} \
void func_name##_v5(hipFloatComplex* result, hipDoubleComplex x, hipFloatComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v6(hipFloatComplex* result, hipFloatComplex x, hipDoubleComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v7(hipFloatComplex* result, Dummy x, hipFloatComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v8(hipFloatComplex* result, hipFloatComplex x, Dummy y) { \
*result = func_name(x, y); \
} \
void func_name##_v9(float* result, hipFloatComplex x, hipFloatComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v10(hipDoubleComplex* result, hipFloatComplex x, hipFloatComplex y) { \
*result = func_name(x, y); \
} \
void func_name##_v11(Dummy* result, hipFloatComplex x, hipFloatComplex y) { \
*result = func_name(x, y); \
}
NEGATIVE_SHELL_TWO_ARG_FLOAT(hipCaddf)
NEGATIVE_SHELL_TWO_ARG_FLOAT(hipCsubf)
NEGATIVE_SHELL_TWO_ARG_FLOAT(hipCmulf)
NEGATIVE_SHELL_TWO_ARG_FLOAT(hipCdivf)
@@ -0,0 +1,620 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
static constexpr auto kComplexAdd{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipCaddf_kernel_v1(hipFloatComplex* result, hipFloatComplex* x,
hipFloatComplex y) {
*result = hipCaddf(x, y);
}
__global__ void hipCaddf_kernel_v2(hipFloatComplex* result, hipFloatComplex x,
hipFloatComplex* y) {
*result = hipCaddf(x, y);
}
__global__ void hipCaddf_kernel_v3(hipFloatComplex* result, float x, hipFloatComplex y) {
*result = hipCaddf(x, y);
}
__global__ void hipCaddf_kernel_v4(hipFloatComplex* result, hipFloatComplex x, float y) {
*result = hipCaddf(x, y);
}
__global__ void hipCaddf_kernel_v5(hipFloatComplex* result, hipDoubleComplex x,
hipFloatComplex y) {
*result = hipCaddf(x, y);
}
__global__ void hipCaddf_kernel_v6(hipFloatComplex* result, hipFloatComplex x,
hipDoubleComplex y) {
*result = hipCaddf(x, y);
}
__global__ void hipCaddf_kernel_v7(hipFloatComplex* result, Dummy x, hipFloatComplex y) {
*result = hipCaddf(x, y);
}
__global__ void hipCaddf_kernel_v8(hipFloatComplex* result, hipFloatComplex x, Dummy y) {
*result = hipCaddf(x, y);
}
__global__ void hipCaddf_kernel_v9(float* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCaddf(x, y);
}
__global__ void hipCaddf_kernel_v10(hipDoubleComplex* result, hipFloatComplex x,
hipFloatComplex y) {
*result = hipCaddf(x, y);
}
__global__ void hipCaddf_kernel_v11(Dummy* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCaddf(x, y);
}
__global__ void hipCadd_kernel_v1(hipDoubleComplex* result, hipDoubleComplex* x,
hipDoubleComplex y) {
*result = hipCadd(x, y);
}
__global__ void hipCadd_kernel_v2(hipDoubleComplex* result, hipDoubleComplex x,
hipDoubleComplex* y) {
*result = hipCadd(x, y);
}
__global__ void hipCadd_kernel_v3(hipDoubleComplex* result, double x, hipDoubleComplex y) {
*result = hipCadd(x, y);
}
__global__ void hipCadd_kernel_v4(hipDoubleComplex* result, hipDoubleComplex x, double y) {
*result = hipCadd(x, y);
}
__global__ void hipCadd_kernel_v5(hipDoubleComplex* result, hipFloatComplex x,
hipDoubleComplex y) {
*result = hipCadd(x, y);
}
__global__ void hipCadd_kernel_v6(hipDoubleComplex* result, hipDoubleComplex x,
hipFloatComplex y) {
*result = hipCadd(x, y);
}
__global__ void hipCadd_kernel_v7(hipDoubleComplex* result, Dummy x, hipDoubleComplex y) {
*result = hipCadd(x, y);
}
__global__ void hipCadd_kernel_v8(hipDoubleComplex* result, hipDoubleComplex x, Dummy y) {
*result = hipCadd(x, y);
}
__global__ void hipCadd_kernel_v9(double* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCadd(x, y);
}
__global__ void hipCadd_kernel_v10(hipFloatComplex* result, hipDoubleComplex x,
hipDoubleComplex y) {
*result = hipCadd(x, y);
}
__global__ void hipCadd_kernel_v11(Dummy* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCadd(x, y);
}
void hipCaddf_v1(hipFloatComplex* result, hipFloatComplex* x, hipFloatComplex y) {
*result = hipCaddf(x, y);
}
void hipCaddf_v2(hipFloatComplex* result, hipFloatComplex x, hipFloatComplex* y) {
*result = hipCaddf(x, y);
}
void hipCaddf_v3(hipFloatComplex* result, float x, hipFloatComplex y) {
*result = hipCaddf(x, y);
}
void hipCaddf_v4(hipFloatComplex* result, hipFloatComplex x, float y) {
*result = hipCaddf(x, y);
}
void hipCaddf_v5(hipFloatComplex* result, hipDoubleComplex x, hipFloatComplex y) {
*result = hipCaddf(x, y);
}
void hipCaddf_v6(hipFloatComplex* result, hipFloatComplex x, hipDoubleComplex y) {
*result = hipCaddf(x, y);
}
void hipCaddf_v7(hipFloatComplex* result, Dummy x, hipFloatComplex y) {
*result = hipCaddf(x, y);
}
void hipCaddf_v8(hipFloatComplex* result, hipFloatComplex x, Dummy y) {
*result = hipCaddf(x, y);
}
void hipCaddf_v9(float* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCaddf(x, y);
}
void hipCaddf_v10(hipDoubleComplex* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCaddf(x, y);
}
void hipCaddf_v11(Dummy* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCaddf(x, y);
}
void hipCadd_v1(hipDoubleComplex* result, hipDoubleComplex* x, hipDoubleComplex y) {
*result = hipCadd(x, y);
}
void hipCadd_v2(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex* y) {
*result = hipCadd(x, y);
}
void hipCadd_v3(hipDoubleComplex* result, double x, hipDoubleComplex y) {
*result = hipCadd(x, y);
}
void hipCadd_v4(hipDoubleComplex* result, hipDoubleComplex x, double y) {
*result = hipCadd(x, y);
}
void hipCadd_v5(hipDoubleComplex* result, hipFloatComplex x, hipDoubleComplex y) {
*result = hipCadd(x, y);
}
void hipCadd_v6(hipDoubleComplex* result, hipDoubleComplex x, hipFloatComplex y) {
*result = hipCadd(x, y);
}
void hipCadd_v7(hipDoubleComplex* result, Dummy x, hipDoubleComplex y) {
*result = hipCadd(x, y);
}
void hipCadd_v8(hipDoubleComplex* result, hipDoubleComplex x, Dummy y) {
*result = hipCadd(x, y);
}
void hipCadd_v9(double* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCadd(x, y);
}
void hipCadd_v10(hipFloatComplex* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCadd(x, y);
}
void hipCadd_v11(Dummy* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCadd(x, y);
}
)"};
static constexpr auto kComplexSub{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipCsubf_kernel_v1(hipFloatComplex* result, hipFloatComplex* x,
hipFloatComplex y) {
*result = hipCsubf(x, y);
}
__global__ void hipCsubf_kernel_v2(hipFloatComplex* result, hipFloatComplex x,
hipFloatComplex* y) {
*result = hipCsubf(x, y);
}
__global__ void hipCsubf_kernel_v3(hipFloatComplex* result, float x, hipFloatComplex y) {
*result = hipCsubf(x, y);
}
__global__ void hipCsubf_kernel_v4(hipFloatComplex* result, hipFloatComplex x, float y) {
*result = hipCsubf(x, y);
}
__global__ void hipCsubf_kernel_v5(hipFloatComplex* result, hipDoubleComplex x,
hipFloatComplex y) {
*result = hipCsubf(x, y);
}
__global__ void hipCsubf_kernel_v6(hipFloatComplex* result, hipFloatComplex x,
hipDoubleComplex y) {
*result = hipCsubf(x, y);
}
__global__ void hipCsubf_kernel_v7(hipFloatComplex* result, Dummy x, hipFloatComplex y) {
*result = hipCsubf(x, y);
}
__global__ void hipCsubf_kernel_v8(hipFloatComplex* result, hipFloatComplex x, Dummy y) {
*result = hipCsubf(x, y);
}
__global__ void hipCsubf_kernel_v9(float* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCsubf(x, y);
}
__global__ void hipCsubf_kernel_v10(hipDoubleComplex* result, hipFloatComplex x,
hipFloatComplex y) {
*result = hipCsubf(x, y);
}
__global__ void hipCsubf_kernel_v11(Dummy* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCsubf(x, y);
}
__global__ void hipCsub_kernel_v1(hipDoubleComplex* result, hipDoubleComplex* x,
hipDoubleComplex y) {
*result = hipCsub(x, y);
}
__global__ void hipCsub_kernel_v2(hipDoubleComplex* result, hipDoubleComplex x,
hipDoubleComplex* y) {
*result = hipCsub(x, y);
}
__global__ void hipCsub_kernel_v3(hipDoubleComplex* result, double x, hipDoubleComplex y) {
*result = hipCsub(x, y);
}
__global__ void hipCsub_kernel_v4(hipDoubleComplex* result, hipDoubleComplex x, double y) {
*result = hipCsub(x, y);
}
__global__ void hipCsub_kernel_v5(hipDoubleComplex* result, hipFloatComplex x,
hipDoubleComplex y) {
*result = hipCsub(x, y);
}
__global__ void hipCsub_kernel_v6(hipDoubleComplex* result, hipDoubleComplex x,
hipFloatComplex y) {
*result = hipCsub(x, y);
}
__global__ void hipCsub_kernel_v7(hipDoubleComplex* result, Dummy x, hipDoubleComplex y) {
*result = hipCsub(x, y);
}
__global__ void hipCsub_kernel_v8(hipDoubleComplex* result, hipDoubleComplex x, Dummy y) {
*result = hipCsub(x, y);
}
__global__ void hipCsub_kernel_v9(double* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCsub(x, y);
}
__global__ void hipCsub_kernel_v10(hipFloatComplex* result, hipDoubleComplex x,
hipDoubleComplex y) {
*result = hipCsub(x, y);
}
__global__ void hipCsub_kernel_v11(Dummy* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCsub(x, y);
}
void hipCsubf_v1(hipFloatComplex* result, hipFloatComplex* x, hipFloatComplex y) {
*result = hipCsubf(x, y);
}
void hipCsubf_v2(hipFloatComplex* result, hipFloatComplex x, hipFloatComplex* y) {
*result = hipCsubf(x, y);
}
void hipCsubf_v3(hipFloatComplex* result, float x, hipFloatComplex y) {
*result = hipCsubf(x, y);
}
void hipCsubf_v4(hipFloatComplex* result, hipFloatComplex x, float y) {
*result = hipCsubf(x, y);
}
void hipCsubf_v5(hipFloatComplex* result, hipDoubleComplex x, hipFloatComplex y) {
*result = hipCsubf(x, y);
}
void hipCsubf_v6(hipFloatComplex* result, hipFloatComplex x, hipDoubleComplex y) {
*result = hipCsubf(x, y);
}
void hipCsubf_v7(hipFloatComplex* result, Dummy x, hipFloatComplex y) {
*result = hipCsubf(x, y);
}
void hipCsubf_v8(hipFloatComplex* result, hipFloatComplex x, Dummy y) {
*result = hipCsubf(x, y);
}
void hipCaddf_v9(float* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCaddf(x, y);
}
void hipCsubf_v10(hipDoubleComplex* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCsubf(x, y);
}
void hipCsubf_v11(Dummy* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCsubf(x, y);
}
void hipCsub_v1(hipDoubleComplex* result, hipDoubleComplex* x, hipDoubleComplex y) {
*result = hipCsub(x, y);
}
void hipCsub_v2(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex* y) {
*result = hipCsub(x, y);
}
void hipCsub_v3(hipDoubleComplex* result, double x, hipDoubleComplex y) {
*result = hipCsub(x, y);
}
void hipCsub_v4(hipDoubleComplex* result, hipDoubleComplex x, double y) {
*result = hipCsub(x, y);
}
void hipCsub_v5(hipDoubleComplex* result, hipFloatComplex x, hipDoubleComplex y) {
*result = hipCsub(x, y);
}
void hipCsub_v6(hipDoubleComplex* result, hipDoubleComplex x, hipFloatComplex y) {
*result = hipCsub(x, y);
}
void hipCsub_v7(hipDoubleComplex* result, Dummy x, hipDoubleComplex y) {
*result = hipCsub(x, y);
}
void hipCsub_v8(hipDoubleComplex* result, hipDoubleComplex x, Dummy y) {
*result = hipCsub(x, y);
}
void hipCsub_v9(double* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCsub(x, y);
}
void hipCsub_v10(hipFloatComplex* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCsub(x, y);
}
void hipCsub_v11(Dummy* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCsub(x, y);
}
)"};
static constexpr auto kComplexMul{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipCmulf_kernel_v1(hipFloatComplex* result, hipFloatComplex* x,
hipFloatComplex y) {
*result = hipCmulf(x, y);
}
__global__ void hipCmulf_kernel_v2(hipFloatComplex* result, hipFloatComplex x,
hipFloatComplex* y) {
*result = hipCmulf(x, y);
}
__global__ void hipCmulf_kernel_v3(hipFloatComplex* result, float x, hipFloatComplex y) {
*result = hipCmulf(x, y);
}
__global__ void hipCmulf_kernel_v4(hipFloatComplex* result, hipFloatComplex x, float y) {
*result = hipCmulf(x, y);
}
__global__ void hipCmulf_kernel_v5(hipFloatComplex* result, hipDoubleComplex x,
hipFloatComplex y) {
*result = hipCmulf(x, y);
}
__global__ void hipCmulf_kernel_v6(hipFloatComplex* result, hipFloatComplex x,
hipDoubleComplex y) {
*result = hipCmulf(x, y);
}
__global__ void hipCmulf_kernel_v7(hipFloatComplex* result, Dummy x, hipFloatComplex y) {
*result = hipCmulf(x, y);
}
__global__ void hipCmulf_kernel_v8(hipFloatComplex* result, hipFloatComplex x, Dummy y) {
*result = hipCmulf(x, y);
}
__global__ void hipCmulf_kernel_v9(float* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCmulf(x, y);
}
__global__ void hipCmulf_kernel_v10(hipDoubleComplex* result, hipFloatComplex x,
hipFloatComplex y) {
*result = hipCmulf(x, y);
}
__global__ void hipCmulf_kernel_v11(Dummy* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCmulf(x, y);
}
__global__ void hipCmul_kernel_v1(hipDoubleComplex* result, hipDoubleComplex* x,
hipDoubleComplex y) {
*result = hipCmul(x, y);
}
__global__ void hipCmul_kernel_v2(hipDoubleComplex* result, hipDoubleComplex x,
hipDoubleComplex* y) {
*result = hipCmul(x, y);
}
__global__ void hipCmul_kernel_v3(hipDoubleComplex* result, double x, hipDoubleComplex y) {
*result = hipCmul(x, y);
}
__global__ void hipCmul_kernel_v4(hipDoubleComplex* result, hipDoubleComplex x, double y) {
*result = hipCmul(x, y);
}
__global__ void hipCmul_kernel_v5(hipDoubleComplex* result, hipFloatComplex x,
hipDoubleComplex y) {
*result = hipCmul(x, y);
}
__global__ void hipCmul_kernel_v6(hipDoubleComplex* result, hipDoubleComplex x,
hipFloatComplex y) {
*result = hipCmul(x, y);
}
__global__ void hipCmul_kernel_v7(hipDoubleComplex* result, Dummy x, hipDoubleComplex y) {
*result = hipCmul(x, y);
}
__global__ void hipCmul_kernel_v8(hipDoubleComplex* result, hipDoubleComplex x, Dummy y) {
*result = hipCmul(x, y);
}
__global__ void hipCmul_kernel_v9(double* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCmul(x, y);
}
__global__ void hipCmul_kernel_v10(hipFloatComplex* result, hipDoubleComplex x,
hipDoubleComplex y) {
*result = hipCmul(x, y);
}
__global__ void hipCmul_kernel_v11(Dummy* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCmul(x, y);
}
void hipCmulf_v1(hipFloatComplex* result, hipFloatComplex* x, hipFloatComplex y) {
*result = hipCmulf(x, y);
}
void hipCmulf_v2(hipFloatComplex* result, hipFloatComplex x, hipFloatComplex* y) {
*result = hipCmulf(x, y);
}
void hipCmulf_v3(hipFloatComplex* result, float x, hipFloatComplex y) {
*result = hipCmulf(x, y);
}
void hipCmulf_v4(hipFloatComplex* result, hipFloatComplex x, float y) {
*result = hipCmulf(x, y);
}
void hipCmulf_v5(hipFloatComplex* result, hipDoubleComplex x, hipFloatComplex y) {
*result = hipCmulf(x, y);
}
void hipCmulf_v6(hipFloatComplex* result, hipFloatComplex x, hipDoubleComplex y) {
*result = hipCmulf(x, y);
}
void hipCmulf_v7(hipFloatComplex* result, Dummy x, hipFloatComplex y) {
*result = hipCmulf(x, y);
}
void hipCmulf_v8(hipFloatComplex* result, hipFloatComplex x, Dummy y) {
*result = hipCmulf(x, y);
}
void hipCmulf_v9(float* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCmulf(x, y);
}
void hipCmulf_v10(hipDoubleComplex* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCmulf(x, y);
}
void hipCmulf_v11(Dummy* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCmulf(x, y);
}
void hipCmul_v1(hipDoubleComplex* result, hipDoubleComplex* x, hipDoubleComplex y) {
*result = hipCmul(x, y);
}
void hipCmul_v2(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex* y) {
*result = hipCmul(x, y);
}
void hipCmul_v3(hipDoubleComplex* result, double x, hipDoubleComplex y) {
*result = hipCmul(x, y);
}
void hipCmul_v4(hipDoubleComplex* result, hipDoubleComplex x, double y) {
*result = hipCmul(x, y);
}
void hipCmul_v5(hipDoubleComplex* result, hipFloatComplex x, hipDoubleComplex y) {
*result = hipCmul(x, y);
}
void hipCmul_v6(hipDoubleComplex* result, hipDoubleComplex x, hipFloatComplex y) {
*result = hipCmul(x, y);
}
void hipCmul_v7(hipDoubleComplex* result, Dummy x, hipDoubleComplex y) {
*result = hipCmul(x, y);
}
void hipCmul_v8(hipDoubleComplex* result, hipDoubleComplex x, Dummy y) {
*result = hipCmul(x, y);
}
void hipCmul_v9(double* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCmul(x, y);
}
void hipCmul_v10(hipFloatComplex* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCmul(x, y);
}
void hipCmul_v11(Dummy* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCmul(x, y);
}
)"};
static constexpr auto kComplexDiv{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipCdivf_kernel_v1(hipFloatComplex* result, hipFloatComplex* x,
hipFloatComplex y) {
*result = hipCdivf(x, y);
}
__global__ void hipCdivf_kernel_v2(hipFloatComplex* result, hipFloatComplex x,
hipFloatComplex* y) {
*result = hipCdivf(x, y);
}
__global__ void hipCdivf_kernel_v3(hipFloatComplex* result, float x, hipFloatComplex y) {
*result = hipCdivf(x, y);
}
__global__ void hipCdivf_kernel_v4(hipFloatComplex* result, hipFloatComplex x, float y) {
*result = hipCdivf(x, y);
}
__global__ void hipCdivf_kernel_v5(hipFloatComplex* result, hipDoubleComplex x,
hipFloatComplex y) {
*result = hipCdivf(x, y);
}
__global__ void hipCdivf_kernel_v6(hipFloatComplex* result, hipFloatComplex x,
hipDoubleComplex y) {
*result = hipCdivf(x, y);
}
__global__ void hipCdivf_kernel_v7(hipFloatComplex* result, Dummy x, hipFloatComplex y) {
*result = hipCdivf(x, y);
}
__global__ void hipCdivf_kernel_v8(hipFloatComplex* result, hipFloatComplex x, Dummy y) {
*result = hipCdivf(x, y);
}
__global__ void hipCdivf_kernel_v9(float* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCdivf(x, y);
}
__global__ void hipCdivf_kernel_v10(hipDoubleComplex* result, hipFloatComplex x,
hipFloatComplex y) {
*result = hipCdivf(x, y);
}
__global__ void hipCdivf_kernel_v11(Dummy* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCdivf(x, y);
}
__global__ void hipCdiv_kernel_v1(hipDoubleComplex* result, hipDoubleComplex* x,
hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
__global__ void hipCdiv_kernel_v2(hipDoubleComplex* result, hipDoubleComplex x,
hipDoubleComplex* y) {
*result = hipCdiv(x, y);
}
__global__ void hipCdiv_kernel_v3(hipDoubleComplex* result, double x, hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
__global__ void hipCdiv_kernel_v4(hipDoubleComplex* result, hipDoubleComplex x, double y) {
*result = hipCdiv(x, y);
}
__global__ void hipCdiv_kernel_v5(hipDoubleComplex* result, hipFloatComplex x,
hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
__global__ void hipCdiv_kernel_v6(hipDoubleComplex* result, hipDoubleComplex x,
hipFloatComplex y) {
*result = hipCdiv(x, y);
}
__global__ void hipCdiv_kernel_v7(hipDoubleComplex* result, Dummy x, hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
__global__ void hipCdiv_kernel_v8(hipDoubleComplex* result, hipDoubleComplex x, Dummy y) {
*result = hipCdiv(x, y);
}
__global__ void hipCdiv_kernel_v9(double* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
__global__ void hipCdiv_kernel_v10(hipFloatComplex* result, hipDoubleComplex x,
hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
__global__ void hipCdiv_kernel_v11(Dummy* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
void hipCdivf_v1(hipFloatComplex* result, hipFloatComplex* x, hipFloatComplex y) {
*result = hipCdivf(x, y);
}
void hipCdivf_v2(hipFloatComplex* result, hipFloatComplex x, hipFloatComplex* y) {
*result = hipCdivf(x, y);
}
void hipCdivf_v3(hipFloatComplex* result, float x, hipFloatComplex y) {
*result = hipCdivf(x, y);
}
void hipCdivf_v4(hipFloatComplex* result, hipFloatComplex x, float y) {
*result = hipCdivf(x, y);
}
void hipCdivf_v5(hipFloatComplex* result, hipDoubleComplex x, hipFloatComplex y) {
*result = hipCdivf(x, y);
}
void hipCdivf_v6(hipFloatComplex* result, hipFloatComplex x, hipDoubleComplex y) {
*result = hipCdivf(x, y);
}
void hipCdivf_v7(hipFloatComplex* result, Dummy x, hipFloatComplex y) {
*result = hipCdivf(x, y);
}
void hipCdivf_v8(hipFloatComplex* result, hipFloatComplex x, Dummy y) {
*result = hipCdivf(x, y);
}
void hipCdivf_v9(float* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCdivf(x, y);
}
void hipCdivf_v10(hipDoubleComplex* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCdivf(x, y);
}
void hipCdivf_v11(Dummy* result, hipFloatComplex x, hipFloatComplex y) {
*result = hipCdivf(x, y);
}
void hipCdiv_v1(hipDoubleComplex* result, hipDoubleComplex* x, hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
void hipCdiv_v2(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex* y) {
*result = hipCdiv(x, y);
}
void hipCdiv_v3(hipDoubleComplex* result, double x, hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
void hipCdiv_v4(hipDoubleComplex* result, hipDoubleComplex x, double y) {
*result = hipCdiv(x, y);
}
void hipCdiv_v5(hipDoubleComplex* result, hipFloatComplex x, hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
void hipCdiv_v6(hipDoubleComplex* result, hipDoubleComplex x, hipFloatComplex y) {
*result = hipCdiv(x, y);
}
void hipCdiv_v7(hipDoubleComplex* result, Dummy x, hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
void hipCdiv_v8(hipDoubleComplex* result, hipDoubleComplex x, Dummy y) {
*result = hipCdiv(x, y);
}
void hipCdiv_v9(double* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
void hipCdiv_v10(hipFloatComplex* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
void hipCdiv_v11(Dummy* result, hipDoubleComplex x, hipDoubleComplex y) {
*result = hipCdiv(x, y);
}
)"};
@@ -0,0 +1,247 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <hip/hip_complex.h>
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipCfmaf_kernel_v1(hipComplex* result, hipFloatComplex* x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v2(hipComplex* result, hipFloatComplex x, hipFloatComplex* y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v3(hipComplex* result, hipFloatComplex x, hipFloatComplex y,
hipFloatComplex* z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v4(hipComplex* result, float x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v5(hipComplex* result, hipFloatComplex x, float y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v6(hipComplex* result, hipFloatComplex x, hipFloatComplex y,
float z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v7(hipComplex* result, hipDoubleComplex x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v8(hipComplex* result, hipFloatComplex x, hipDoubleComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v9(hipComplex* result, hipFloatComplex x, hipFloatComplex y,
hipDoubleComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v10(hipComplex* result, Dummy x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v11(hipComplex* result, hipFloatComplex x, Dummy y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v12(hipComplex* result, hipFloatComplex x, hipFloatComplex y,
Dummy z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v13(float* result, hipFloatComplex x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v14(hipDoubleComplex* result, hipFloatComplex x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v15(Dummy* result, hipFloatComplex x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v1(hipComplex* result, hipFloatComplex* x, hipFloatComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v2(hipComplex* result, hipFloatComplex x, hipFloatComplex* y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v3(hipComplex* result, hipFloatComplex x, hipFloatComplex y, hipFloatComplex* z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v4(hipComplex* result, float x, hipFloatComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v5(hipComplex* result, hipFloatComplex x, float y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v6(hipComplex* result, hipFloatComplex x, hipFloatComplex y, float z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v7(hipComplex* result, hipDoubleComplex x, hipFloatComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v8(hipComplex* result, hipFloatComplex x, hipDoubleComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v9(hipComplex* result, hipFloatComplex x, hipFloatComplex y, hipDoubleComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v10(hipComplex* result, Dummy x, hipFloatComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v11(hipComplex* result, hipFloatComplex x, Dummy y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v12(hipComplex* result, hipFloatComplex x, hipFloatComplex y, Dummy z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v13(float* result, hipFloatComplex x, hipFloatComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v14(hipDoubleComplex* result, hipFloatComplex x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v15(Dummy* result, hipFloatComplex x, hipFloatComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfma_kernel_v1(hipDoubleComplex* result, hipDoubleComplex* x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v2(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex* y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v3(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y,
hipDoubleComplex* z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v4(hipDoubleComplex* result, double x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v5(hipDoubleComplex* result, hipDoubleComplex x, double y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v6(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y,
double z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v7(hipDoubleComplex* result, hipFloatComplex x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v8(hipDoubleComplex* result, hipDoubleComplex x, hipFloatComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v9(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y,
hipFloatComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v10(hipDoubleComplex* result, Dummy x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v11(hipDoubleComplex* result, hipDoubleComplex x, Dummy y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v12(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y,
Dummy z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v13(double* result, hipDoubleComplex x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v14(hipFloatComplex* result, hipDoubleComplex x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v15(Dummy* result, hipDoubleComplex x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v1(hipDoubleComplex* result, hipDoubleComplex* x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v2(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex* y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v3(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y,
hipDoubleComplex* z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v4(hipDoubleComplex* result, double x, hipDoubleComplex y, hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v5(hipDoubleComplex* result, hipDoubleComplex x, double y, hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v6(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y, double z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v7(hipDoubleComplex* result, hipFloatComplex x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v8(hipDoubleComplex* result, hipDoubleComplex x, hipFloatComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v9(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y,
hipFloatComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v10(hipDoubleComplex* result, Dummy x, hipDoubleComplex y, hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v11(hipDoubleComplex* result, hipDoubleComplex x, Dummy y, hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v12(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y, Dummy z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v13(double* result, hipDoubleComplex x, hipDoubleComplex y, hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v14(hipFloatComplex* result, hipDoubleComplex x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v15(Dummy* result, hipDoubleComplex x, hipDoubleComplex y, hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
@@ -0,0 +1,246 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
static constexpr auto kComplexFma{R"(
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hipCfmaf_kernel_v1(hipComplex* result, hipFloatComplex* x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v2(hipComplex* result, hipFloatComplex x, hipFloatComplex* y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v3(hipComplex* result, hipFloatComplex x, hipFloatComplex y,
hipFloatComplex* z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v4(hipComplex* result, float x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v5(hipComplex* result, hipFloatComplex x, float y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v6(hipComplex* result, hipFloatComplex x, hipFloatComplex y,
float z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v7(hipComplex* result, hipDoubleComplex x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v8(hipComplex* result, hipFloatComplex x, hipDoubleComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v9(hipComplex* result, hipFloatComplex x, hipFloatComplex y,
hipDoubleComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v10(hipComplex* result, Dummy x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v11(hipComplex* result, hipFloatComplex x, Dummy y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v12(hipComplex* result, hipFloatComplex x, hipFloatComplex y,
Dummy z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v13(float* result, hipFloatComplex x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v14(hipDoubleComplex* result, hipFloatComplex x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfmaf_kernel_v15(Dummy* result, hipFloatComplex x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
__global__ void hipCfma_kernel_v1(hipDoubleComplex* result, hipDoubleComplex* x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v2(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex* y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v3(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y,
hipDoubleComplex* z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v4(hipDoubleComplex* result, double x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v5(hipDoubleComplex* result, hipDoubleComplex x, double y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v6(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y,
double z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v7(hipDoubleComplex* result, hipFloatComplex x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v8(hipDoubleComplex* result, hipDoubleComplex x, hipFloatComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v9(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y,
hipFloatComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v10(hipDoubleComplex* result, Dummy x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v11(hipDoubleComplex* result, hipDoubleComplex x, Dummy y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v12(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y,
Dummy z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v13(double* result, hipDoubleComplex x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v14(hipFloatComplex* result, hipDoubleComplex x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
__global__ void hipCfma_kernel_v15(Dummy* result, hipDoubleComplex x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfmaf_v1(hipComplex* result, hipFloatComplex* x, hipFloatComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v2(hipComplex* result, hipFloatComplex x, hipFloatComplex* y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v3(hipComplex* result, hipFloatComplex x, hipFloatComplex y, hipFloatComplex* z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v4(hipComplex* result, float x, hipFloatComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v5(hipComplex* result, hipFloatComplex x, float y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v6(hipComplex* result, hipFloatComplex x, hipFloatComplex y, float z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v7(hipComplex* result, hipDoubleComplex x, hipFloatComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v8(hipComplex* result, hipFloatComplex x, hipDoubleComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v9(hipComplex* result, hipFloatComplex x, hipFloatComplex y, hipDoubleComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v10(hipComplex* result, Dummy x, hipFloatComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v11(hipComplex* result, hipFloatComplex x, Dummy y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v12(hipComplex* result, hipFloatComplex x, hipFloatComplex y, Dummy z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v13(float* result, hipFloatComplex x, hipFloatComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v14(hipDoubleComplex* result, hipFloatComplex x, hipFloatComplex y,
hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfmaf_v15(Dummy* result, hipFloatComplex x, hipFloatComplex y, hipFloatComplex z) {
*result = hipCfmaf(x, y, z);
}
void hipCfma_v1(hipDoubleComplex* result, hipDoubleComplex* x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v2(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex* y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v3(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y,
hipDoubleComplex* z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v4(hipDoubleComplex* result, double x, hipDoubleComplex y, hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v5(hipDoubleComplex* result, hipDoubleComplex x, double y, hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v6(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y, double z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v7(hipDoubleComplex* result, hipFloatComplex x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v8(hipDoubleComplex* result, hipDoubleComplex x, hipFloatComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v9(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y,
hipFloatComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v10(hipDoubleComplex* result, Dummy x, hipDoubleComplex y, hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v11(hipDoubleComplex* result, hipDoubleComplex x, Dummy y, hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v12(hipDoubleComplex* result, hipDoubleComplex x, hipDoubleComplex y, Dummy z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v13(double* result, hipDoubleComplex x, hipDoubleComplex y, hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v14(hipFloatComplex* result, hipDoubleComplex x, hipDoubleComplex y,
hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
void hipCfma_v15(Dummy* result, hipDoubleComplex x, hipDoubleComplex y, hipDoubleComplex z) {
*result = hipCfma(x, y, z);
}
)"};
+6 -2
Ver Arquivo
@@ -8,14 +8,18 @@ set(TEST_SRC
hipCGCoalescedGroups_old.cc
hipLaunchCooperativeKernel_old.cc
hipLaunchCooperativeKernelMultiDevice_old.cc
multi_grid_group.cc
coalesced_groups_shfl_down_old.cc
coalesced_groups_shfl_up_old.cc
hipCGCoalescedGroups_old.cc
coalesced_group.cc
grid_group.cc
coalesced_groups_shfl_down.cc
coalesced_groups_shfl_up.cc
coalesced_tiled_groups_metagrp.cc
)
if(HIP_PLATFORM STREQUAL "nvidia")
set_source_files_properties(hipCGMultiGridGroupType_old.cc PROPERTIES COMPILE_FLAGS "-D_CG_ABI_EXPERIMENTAL -rdc=true -gencode arch=compute_60,code=sm_60 -gencode arch=compute_70,code=sm_70 -gencode arch=compute_80,code=sm_80")
set_source_files_properties(hipLaunchCooperativeKernelMultiDevice_old.cc PROPERTIES COMPILE_FLAGS "-D_CG_ABI_EXPERIMENTAL -rdc=true -gencode arch=compute_60,code=sm_60 -gencode arch=compute_70,code=sm_70 -gencode arch=compute_80,code=sm_80")
set_source_files_properties(multi_grid_group.cc PROPERTIES COMPILE_FLAGS "-D_CG_ABI_EXPERIMENTAL -rdc=true -gencode arch=compute_60,code=sm_60 -gencode arch=compute_70,code=sm_70 -gencode arch=compute_80,code=sm_80")
hip_add_exe_to_target(NAME coopGrpTest
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests
+760
Ver Arquivo
@@ -0,0 +1,760 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "cooperative_groups_common.hh"
#include <cmd_options.hh>
#include <cpu_grid.h>
#include <resource_guards.hh>
/**
* @addtogroup coalesced_group coalesced_group
* @{
* @ingroup DeviceLanguageTest
* Contains unit tests for all coalesced_group basic APIs
*/
namespace cg = cooperative_groups;
template <unsigned int warp_size, typename BaseType = cg::coalesced_group>
static __global__ void coalesced_group_size_getter(unsigned int* sizes, uint64_t active_mask) {
const cg::thread_block_tile<warp_size> tile =
cg::tiled_partition<warp_size>(cg::this_thread_block());
if (active_mask & (static_cast<uint64_t>(1) << tile.thread_rank())) {
BaseType active = cg::coalesced_threads();
sizes[thread_rank_in_grid()] = active.size();
}
}
template <unsigned int warp_size, typename BaseType = cg::coalesced_group>
static __global__ void coalesced_group_thread_rank_getter(unsigned int* thread_ranks,
uint64_t active_mask) {
const cg::thread_block_tile<warp_size> tile =
cg::tiled_partition<warp_size>(cg::this_thread_block());
if (active_mask & (static_cast<uint64_t>(1) << tile.thread_rank())) {
BaseType active = cg::coalesced_threads();
thread_ranks[thread_rank_in_grid()] = active.thread_rank();
}
}
template <unsigned int warp_size>
static __global__ void coalesced_group_non_member_size_getter(unsigned int* sizes,
uint64_t active_mask) {
const cg::thread_block_tile<warp_size> tile =
cg::tiled_partition<warp_size>(cg::this_thread_block());
if (active_mask & (static_cast<uint64_t>(1) << tile.thread_rank())) {
cg::coalesced_group active = cg::coalesced_threads();
sizes[thread_rank_in_grid()] = cg::group_size(active);
}
}
template <unsigned int warp_size>
static __global__ void coalesced_group_non_member_thread_rank_getter(unsigned int* thread_ranks,
uint64_t active_mask) {
const cg::thread_block_tile<warp_size> tile =
cg::tiled_partition<warp_size>(cg::this_thread_block());
if (active_mask & (static_cast<uint64_t>(1) << tile.thread_rank())) {
cg::coalesced_group active = cg::coalesced_threads();
thread_ranks[thread_rank_in_grid()] = cg::thread_rank(active);
}
}
static unsigned int get_active_thread_count(uint64_t active_mask, unsigned int partition_size) {
unsigned int active_thread_count = 0;
for (int i = 0; i < partition_size; i++) {
if (active_mask & (static_cast<uint64_t>(1) << i)) active_thread_count++;
}
return active_thread_count;
}
static uint64_t get_active_mask(unsigned int test_case) {
uint64_t active_mask = 0;
switch (test_case) {
case 0: // 1st thread
active_mask = 1;
break;
case 1: // last thread
active_mask = static_cast<uint64_t>(1) << (kWarpSize - 1);
break;
case 2: // all threads
active_mask = 0xFFFFFFFFFFFFFFFF;
break;
case 3: // every second thread
active_mask = 0xAAAAAAAAAAAAAAAA;
break;
default: // random
static std::mt19937_64 mt(test_case);
std::uniform_int_distribution<uint64_t> dist(0, std::numeric_limits<uint64_t>::max());
active_mask = dist(mt);
}
return active_mask;
}
/**
* Test Description
* ------------------------
* - Launches kernels that write the return values of size and thread_rank member
* functions of coalesced groups, created according to the generated mask, to an output array that
* is validated on the host side. The kernels are run sequentially, reusing the output array, to
* avoid running out of device memory for large kernel launches
* Test source
* ------------------------
* - unit/cooperativeGrps/coalesced_group.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Coalesced_Group_Getters_Positive_Basic") {
int device;
hipDeviceProp_t device_properties;
HIP_CHECK(hipGetDevice(&device));
HIP_CHECK(hipGetDeviceProperties(&device_properties, device));
if (!device_properties.cooperativeLaunch) {
HipTest::HIP_SKIP_TEST("Device doesn't support cooperative launch!");
return;
}
const auto blocks = GenerateBlockDimensionsForShuffle();
const auto threads = GenerateThreadDimensionsForShuffle();
auto test_case = GENERATE(range(0, 4));
uint64_t active_mask = get_active_mask(test_case);
INFO("Grid dimensions: x " << blocks.x << ", y " << blocks.y << ", z " << blocks.z);
INFO("Block dimensions: x " << threads.x << ", y " << threads.y << ", z " << threads.z);
INFO("Coalesced group mask: " << active_mask);
const CPUGrid grid(blocks, threads);
LinearAllocGuard<unsigned int> uint_arr_dev(LinearAllocs::hipMalloc,
grid.thread_count_ * sizeof(unsigned int));
LinearAllocGuard<unsigned int> uint_arr(LinearAllocs::hipHostMalloc,
grid.thread_count_ * sizeof(unsigned int));
HIP_CHECK(hipMemset(uint_arr_dev.ptr(), 0, grid.thread_count_ * sizeof(unsigned int)));
// Launch Kernel
coalesced_group_size_getter<kWarpSize><<<blocks, threads>>>(uint_arr_dev.ptr(), active_mask);
HIP_CHECK(hipMemcpy(uint_arr.ptr(), uint_arr_dev.ptr(),
grid.thread_count_ * sizeof(*uint_arr.ptr()), hipMemcpyDeviceToHost));
HIP_CHECK(hipMemset(uint_arr_dev.ptr(), 0, grid.thread_count_ * sizeof(unsigned int)));
HIP_CHECK(hipDeviceSynchronize());
coalesced_group_thread_rank_getter<kWarpSize>
<<<blocks, threads>>>(uint_arr_dev.ptr(), active_mask);
// Verify coalesced_group.size() values
unsigned int coalesced_size = 0;
const auto partitions_in_block = (grid.threads_in_block_count_ + kWarpSize - 1) / kWarpSize;
for (int i = 0; i < grid.thread_count_; i++) {
const auto rank_in_block = grid.thread_rank_in_block(i).value();
const int rank_in_partition = rank_in_block % kWarpSize;
// If the number of threads in a block is not a multiple of warp size, the
// last warp will have inactive threads and coalesced group size must be recalculated
if (rank_in_block == (partitions_in_block - 1) * kWarpSize) {
unsigned int partition_size =
grid.threads_in_block_count_ - (partitions_in_block - 1) * kWarpSize;
coalesced_size = get_active_thread_count(active_mask, partition_size);
} else if (rank_in_block == 0) {
coalesced_size = get_active_thread_count(active_mask, kWarpSize);
}
if (active_mask & (static_cast<uint64_t>(1) << rank_in_partition)) {
if (uint_arr.ptr()[i] != coalesced_size) {
REQUIRE(uint_arr.ptr()[i] == coalesced_size);
}
}
}
HIP_CHECK(hipMemcpy(uint_arr.ptr(), uint_arr_dev.ptr(),
grid.thread_count_ * sizeof(*uint_arr.ptr()), hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
// Verify coalesced_group.thread_rank() values
unsigned int coalesced_rank = 0;
for (int i = 0; i < grid.thread_count_; i++) {
const auto rank_in_block = grid.thread_rank_in_block(i).value();
const int rank_in_partition = rank_in_block % kWarpSize;
if (rank_in_partition == 0) coalesced_rank = 0;
if (active_mask & (static_cast<uint64_t>(1) << rank_in_partition)) {
if (uint_arr.ptr()[i] != coalesced_rank) {
REQUIRE(uint_arr.ptr()[i] == coalesced_rank);
}
coalesced_rank++;
}
}
}
/**
* Test Description
* ------------------------
* - Launches kernels that write the return values of size and thread_rank member functions to an
* output array that is validated on the host side, while treating the coalesced group, created
* according to the generated mask, as a thread group. The kernels are run sequentially, reusing the
* output array, to avoid running out of device memory for large kernel launches
* Test source
* ------------------------
* - unit/cooperativeGrps/coalesced_group.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Coalesced_Group_Getters_Via_Base_Type_Positive_Basic") {
int device;
hipDeviceProp_t device_properties;
HIP_CHECK(hipGetDevice(&device));
HIP_CHECK(hipGetDeviceProperties(&device_properties, device));
if (!device_properties.cooperativeLaunch) {
HipTest::HIP_SKIP_TEST("Device doesn't support cooperative launch!");
return;
}
const auto blocks = GenerateBlockDimensionsForShuffle();
const auto threads = GenerateThreadDimensionsForShuffle();
auto test_case = GENERATE(range(0, 4));
uint64_t active_mask = get_active_mask(test_case);
INFO("Grid dimensions: x " << blocks.x << ", y " << blocks.y << ", z " << blocks.z);
INFO("Block dimensions: x " << threads.x << ", y " << threads.y << ", z " << threads.z);
INFO("Coalesced group mask: " << active_mask);
const CPUGrid grid(blocks, threads);
LinearAllocGuard<unsigned int> uint_arr_dev(LinearAllocs::hipMalloc,
grid.thread_count_ * sizeof(unsigned int));
LinearAllocGuard<unsigned int> uint_arr(LinearAllocs::hipHostMalloc,
grid.thread_count_ * sizeof(unsigned int));
HIP_CHECK(hipMemset(uint_arr_dev.ptr(), 0, grid.thread_count_ * sizeof(unsigned int)));
// Launch Kernel
coalesced_group_size_getter<kWarpSize, cg::thread_group>
<<<blocks, threads>>>(uint_arr_dev.ptr(), active_mask);
HIP_CHECK(hipMemcpy(uint_arr.ptr(), uint_arr_dev.ptr(),
grid.thread_count_ * sizeof(*uint_arr.ptr()), hipMemcpyDeviceToHost));
HIP_CHECK(hipMemset(uint_arr_dev.ptr(), 0, grid.thread_count_ * sizeof(unsigned int)));
HIP_CHECK(hipDeviceSynchronize());
coalesced_group_thread_rank_getter<kWarpSize, cg::thread_group>
<<<blocks, threads>>>(uint_arr_dev.ptr(), active_mask);
// Verify coalesced_group.size() values
unsigned int coalesced_size = 0;
const auto partitions_in_block = (grid.threads_in_block_count_ + kWarpSize - 1) / kWarpSize;
for (int i = 0; i < grid.thread_count_; i++) {
const auto rank_in_block = grid.thread_rank_in_block(i).value();
const int rank_in_partition = rank_in_block % kWarpSize;
// If the number of threads in a block is not a multiple of warp size, the
// last warp will have inactive threads and coalesced group size must be recalculated
if (rank_in_block == (partitions_in_block - 1) * kWarpSize) {
unsigned int partition_size =
grid.threads_in_block_count_ - (partitions_in_block - 1) * kWarpSize;
coalesced_size = get_active_thread_count(active_mask, partition_size);
} else if (rank_in_block == 0) {
coalesced_size = get_active_thread_count(active_mask, kWarpSize);
}
if (active_mask & (static_cast<uint64_t>(1) << rank_in_partition)) {
if (uint_arr.ptr()[i] != coalesced_size) {
REQUIRE(uint_arr.ptr()[i] == coalesced_size);
}
}
}
HIP_CHECK(hipMemcpy(uint_arr.ptr(), uint_arr_dev.ptr(),
grid.thread_count_ * sizeof(*uint_arr.ptr()), hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
// Verify coalesced_group.thread_rank() values
unsigned int coalesced_rank = 0;
for (int i = 0; i < grid.thread_count_; i++) {
const auto rank_in_block = grid.thread_rank_in_block(i).value();
const int rank_in_partition = rank_in_block % kWarpSize;
if (rank_in_partition == 0) coalesced_rank = 0;
if (active_mask & (static_cast<uint64_t>(1) << rank_in_partition)) {
if (uint_arr.ptr()[i] != coalesced_rank) {
REQUIRE(uint_arr.ptr()[i] == coalesced_rank);
}
coalesced_rank++;
}
}
}
/**
* Test Description
* ------------------------
* - Launches kernels that write the return values of size and thread_rank non-member functions
* of coalesced groups, created according to the generated mask, to an output array that is
* validated on the host side. The kernels are run sequentially, reusing the output array, to avoid
* running out of device memory for large kernel launches.
* Test source
* ------------------------
* - unit/cooperativeGrps/coalesced_group.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Coalesced_Group_Getters_Via_Non_Member_Functions_Positive_Basic") {
int device;
hipDeviceProp_t device_properties;
HIP_CHECK(hipGetDevice(&device));
HIP_CHECK(hipGetDeviceProperties(&device_properties, device));
if (!device_properties.cooperativeLaunch) {
HipTest::HIP_SKIP_TEST("Device doesn't support cooperative launch!");
return;
}
const auto blocks = GenerateBlockDimensionsForShuffle();
const auto threads = GenerateThreadDimensionsForShuffle();
auto test_case = GENERATE(range(0, 4));
uint64_t active_mask = get_active_mask(test_case);
INFO("Grid dimensions: x " << blocks.x << ", y " << blocks.y << ", z " << blocks.z);
INFO("Block dimensions: x " << threads.x << ", y " << threads.y << ", z " << threads.z);
INFO("Coalesced group mask: " << active_mask);
const CPUGrid grid(blocks, threads);
LinearAllocGuard<unsigned int> uint_arr_dev(LinearAllocs::hipMalloc,
grid.thread_count_ * sizeof(unsigned int));
LinearAllocGuard<unsigned int> uint_arr(LinearAllocs::hipHostMalloc,
grid.thread_count_ * sizeof(unsigned int));
HIP_CHECK(hipMemset(uint_arr_dev.ptr(), 0, grid.thread_count_ * sizeof(unsigned int)));
// Launch Kernel
coalesced_group_non_member_size_getter<kWarpSize>
<<<blocks, threads>>>(uint_arr_dev.ptr(), active_mask);
HIP_CHECK(hipMemcpy(uint_arr.ptr(), uint_arr_dev.ptr(),
grid.thread_count_ * sizeof(*uint_arr.ptr()), hipMemcpyDeviceToHost));
HIP_CHECK(hipMemset(uint_arr_dev.ptr(), 0, grid.thread_count_ * sizeof(unsigned int)));
HIP_CHECK(hipDeviceSynchronize());
coalesced_group_non_member_thread_rank_getter<kWarpSize>
<<<blocks, threads>>>(uint_arr_dev.ptr(), active_mask);
// Verify coalesced_group.size() values
unsigned int coalesced_size = 0;
const auto partitions_in_block = (grid.threads_in_block_count_ + kWarpSize - 1) / kWarpSize;
for (int i = 0; i < grid.thread_count_; i++) {
const auto rank_in_block = grid.thread_rank_in_block(i).value();
const int rank_in_partition = rank_in_block % kWarpSize;
// If the number of threads in a block is not a multiple of warp size, the
// last warp will have inactive threads and coalesced group size must be recalculated
if (rank_in_block == (partitions_in_block - 1) * kWarpSize) {
unsigned int partition_size =
grid.threads_in_block_count_ - (partitions_in_block - 1) * kWarpSize;
coalesced_size = get_active_thread_count(active_mask, partition_size);
} else if (rank_in_block == 0) {
coalesced_size = get_active_thread_count(active_mask, kWarpSize);
}
if (active_mask & (static_cast<uint64_t>(1) << rank_in_partition)) {
if (uint_arr.ptr()[i] != coalesced_size) {
REQUIRE(uint_arr.ptr()[i] == coalesced_size);
}
}
}
HIP_CHECK(hipMemcpy(uint_arr.ptr(), uint_arr_dev.ptr(),
grid.thread_count_ * sizeof(*uint_arr.ptr()), hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
// Verify coalesced_group.thread_rank() values
unsigned int coalesced_rank = 0;
for (int i = 0; i < grid.thread_count_; i++) {
const auto rank_in_block = grid.thread_rank_in_block(i).value();
const int rank_in_partition = rank_in_block % kWarpSize;
if (rank_in_partition == 0) coalesced_rank = 0;
if (active_mask & (static_cast<uint64_t>(1) << rank_in_partition)) {
if (uint_arr.ptr()[i] != coalesced_rank) {
REQUIRE(uint_arr.ptr()[i] == coalesced_rank);
}
coalesced_rank++;
}
}
}
template <typename T, unsigned int warp_size>
__global__ void coalesced_group_shfl_up(T* const out, const unsigned int delta,
const uint64_t active_mask) {
const cg::thread_block_tile<warp_size> tile =
cg::tiled_partition<warp_size>(cg::this_thread_block());
if (active_mask & (static_cast<uint64_t>(1) << tile.thread_rank())) {
cg::coalesced_group active = cg::coalesced_threads();
T var = static_cast<T>(active.thread_rank());
out[thread_rank_in_grid()] = active.shfl_up(var, delta);
}
}
template <typename T> void CoalescedGroupShflUpTestImpl() {
const auto blocks = GenerateBlockDimensionsForShuffle();
const auto threads = GenerateThreadDimensionsForShuffle();
auto test_case = GENERATE(range(0, 4));
uint64_t active_mask = get_active_mask(test_case);
INFO("Grid dimensions: x " << blocks.x << ", y " << blocks.y << ", z " << blocks.z);
INFO("Block dimensions: x " << threads.x << ", y " << threads.y << ", z " << threads.z);
INFO("Coalesced group mask: " << active_mask);
unsigned int active_thread_count = get_active_thread_count(active_mask, kWarpSize);
auto delta = GENERATE(range(static_cast<size_t>(0), kWarpSize));
delta = delta % active_thread_count;
INFO("Delta: " << delta);
CPUGrid grid(blocks, threads);
const auto alloc_size = grid.thread_count_ * sizeof(T);
LinearAllocGuard<T> arr_dev(LinearAllocs::hipMalloc, alloc_size);
LinearAllocGuard<T> arr(LinearAllocs::hipHostMalloc, alloc_size);
coalesced_group_shfl_up<T, kWarpSize><<<blocks, threads>>>(arr_dev.ptr(), delta, active_mask);
HIP_CHECK(hipMemcpy(arr.ptr(), arr_dev.ptr(), alloc_size, hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
unsigned int coalesced_rank = 0;
for (int i = 0; i < grid.thread_count_; i++) {
const auto rank_in_block = grid.thread_rank_in_block(i).value();
const int rank_in_partition = rank_in_block % kWarpSize;
if (rank_in_partition == 0) coalesced_rank = 0;
if (active_mask & (static_cast<uint64_t>(1) << rank_in_partition)) {
int target = coalesced_rank - delta;
target = target < 0 ? coalesced_rank : target;
if (arr.ptr()[i] != target) {
REQUIRE(arr.ptr()[i] == target);
}
coalesced_rank++;
}
}
}
/**
* Test Description
* ------------------------
* - Validates the shuffle up behavior of coalesced group, created according to the generated
* mask, for various delta values
* Test source
* ------------------------
* - unit/cooperativeGrps/coalesced_group.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Coalesced_Group_Shfl_Up_Positive_Basic", "", int, unsigned int, long,
unsigned long, long long, unsigned long long, float, double) {
CoalescedGroupShflUpTestImpl<TestType>();
}
template <typename T, unsigned int warp_size>
__global__ void coalesced_group_shfl_down(T* const out, const unsigned int delta,
const uint64_t active_mask) {
const cg::thread_block_tile<warp_size> tile =
cg::tiled_partition<warp_size>(cg::this_thread_block());
if (active_mask & (static_cast<uint64_t>(1) << tile.thread_rank())) {
cg::coalesced_group active = cg::coalesced_threads();
T var = static_cast<T>(active.thread_rank());
out[thread_rank_in_grid()] = active.shfl_down(var, delta);
}
}
template <typename T> void CoalescedGroupShflDownTest() {
const auto blocks = GenerateBlockDimensionsForShuffle();
const auto threads = GenerateThreadDimensionsForShuffle();
auto test_case = GENERATE(range(0, 4));
uint64_t active_mask = get_active_mask(test_case);
INFO("Grid dimensions: x " << blocks.x << ", y " << blocks.y << ", z " << blocks.z);
INFO("Block dimensions: x " << threads.x << ", y " << threads.y << ", z " << threads.z);
INFO("Coalesced group mask: " << active_mask);
unsigned int active_thread_count = get_active_thread_count(active_mask, kWarpSize);
auto delta = GENERATE(range(static_cast<size_t>(0), kWarpSize));
delta = delta % active_thread_count;
INFO("Delta: " << delta);
CPUGrid grid(blocks, threads);
const auto alloc_size = grid.thread_count_ * sizeof(T);
LinearAllocGuard<T> arr_dev(LinearAllocs::hipMalloc, alloc_size);
LinearAllocGuard<T> arr(LinearAllocs::hipHostMalloc, alloc_size);
coalesced_group_shfl_down<T, kWarpSize><<<blocks, threads>>>(arr_dev.ptr(), delta, active_mask);
HIP_CHECK(hipMemcpy(arr.ptr(), arr_dev.ptr(), alloc_size, hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
unsigned int coalesced_rank = 0;
unsigned int coalesced_size = 0;
const auto partitions_in_block = (grid.threads_in_block_count_ + kWarpSize - 1) / kWarpSize;
for (int i = 0; i < grid.thread_count_; i++) {
const auto rank_in_block = grid.thread_rank_in_block(i).value();
const int rank_in_partition = rank_in_block % kWarpSize;
if (rank_in_partition == 0) coalesced_rank = 0;
// If the number of threads in a block is not a multiple of warp size, the
// last warp will have inactive threads and coalesced group size must be recalculated
if (rank_in_block == (partitions_in_block - 1) * kWarpSize) {
unsigned int partition_size =
grid.threads_in_block_count_ - (partitions_in_block - 1) * kWarpSize;
coalesced_size = get_active_thread_count(active_mask, partition_size);
} else if (rank_in_block == 0) {
coalesced_size = get_active_thread_count(active_mask, kWarpSize);
}
if (active_mask & (static_cast<uint64_t>(1) << rank_in_partition)) {
int target = coalesced_rank + delta;
target = target < coalesced_size ? target : coalesced_rank;
if (arr.ptr()[i] != target) {
REQUIRE(arr.ptr()[i] == target);
}
coalesced_rank++;
}
}
}
/**
* Test Description
* ------------------------
* - Validates the shuffle down behavior of coalesced group, created according to the generated
* mask, for various delta values
* Test source
* ------------------------
* - unit/cooperativeGrps/coalesced_group.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Coalesced_Group_Shfl_Down_Positive_Basic", "", int, unsigned int, long,
unsigned long, long long, unsigned long long, float, double) {
CoalescedGroupShflDownTest<TestType>();
}
template <typename T, unsigned int warp_size>
__global__ void coalesced_group_shfl(T* const out, uint8_t* target_lanes,
const uint64_t active_mask) {
const cg::thread_block_tile<warp_size> tile =
cg::tiled_partition<warp_size>(cg::this_thread_block());
if (active_mask & (static_cast<uint64_t>(1) << tile.thread_rank())) {
cg::coalesced_group active = cg::coalesced_threads();
T var = static_cast<T>(active.thread_rank());
out[thread_rank_in_grid()] = active.shfl(var, target_lanes[active.thread_rank()]);
;
}
}
template <typename T> void CoalescedGroupShflTest() {
const auto blocks = GenerateBlockDimensionsForShuffle();
const auto threads = GenerateThreadDimensionsForShuffle();
auto test_case = GENERATE(range(0, 4));
uint64_t active_mask = get_active_mask(test_case);
INFO("Grid dimensions: x " << blocks.x << ", y " << blocks.y << ", z " << blocks.z);
INFO("Block dimensions: x " << threads.x << ", y " << threads.y << ", z " << threads.z);
INFO("Coalesced group mask: " << active_mask);
unsigned int active_thread_count = get_active_thread_count(active_mask, kWarpSize);
CPUGrid grid(blocks, threads);
const auto alloc_size = grid.thread_count_ * sizeof(T);
LinearAllocGuard<T> arr_dev(LinearAllocs::hipMalloc, alloc_size);
LinearAllocGuard<T> arr(LinearAllocs::hipHostMalloc, alloc_size);
LinearAllocGuard<uint8_t> target_lanes_dev(LinearAllocs::hipMalloc,
active_thread_count * sizeof(uint8_t));
LinearAllocGuard<uint8_t> target_lanes(LinearAllocs::hipHostMalloc,
active_thread_count * sizeof(uint8_t));
// Generate a couple different combinations for target lanes
for (auto i = 0u; i < active_thread_count; ++i) {
target_lanes.ptr()[i] = active_thread_count - 1 - i;
}
HIP_CHECK(hipMemcpy(target_lanes_dev.ptr(), target_lanes.ptr(),
active_thread_count * sizeof(uint8_t), hipMemcpyHostToDevice));
coalesced_group_shfl<T, kWarpSize>
<<<blocks, threads>>>(arr_dev.ptr(), target_lanes_dev.ptr(), active_mask);
HIP_CHECK(hipMemcpy(arr.ptr(), arr_dev.ptr(), alloc_size, hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
unsigned int coalesced_rank = 0;
unsigned int coalesced_size = 0;
const auto partitions_in_block = (grid.threads_in_block_count_ + kWarpSize - 1) / kWarpSize;
for (int i = 0; i < grid.thread_count_; i++) {
const auto rank_in_block = grid.thread_rank_in_block(i).value();
const int rank_in_partition = rank_in_block % kWarpSize;
if (rank_in_partition == 0) coalesced_rank = 0;
// If the number of threads in a block is not a multiple of warp size, the
// last warp will have inactive threads and coalesced group size must be recalculated
if (rank_in_block == (partitions_in_block - 1) * kWarpSize) {
unsigned int partition_size =
grid.threads_in_block_count_ - (partitions_in_block - 1) * kWarpSize;
coalesced_size = get_active_thread_count(active_mask, partition_size);
} else if (rank_in_block == 0) {
coalesced_size = get_active_thread_count(active_mask, kWarpSize);
}
if (active_mask & (static_cast<uint64_t>(1) << rank_in_partition)) {
auto target = target_lanes.ptr()[coalesced_rank];
if (target >= coalesced_size) target = 0;
if (arr.ptr()[i] != target) {
REQUIRE(arr.ptr()[i] == target);
}
coalesced_rank++;
}
}
}
/**
* Test Description
* ------------------------
* - Validates the shuffle behavior of of coalesced group, created according to the generated
* mask, for generated shuffle target lanes
* Test source
* ------------------------
* - unit/cooperativeGrps/coalesced_group.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Coalesced_Group_Shfl_Positive_Basic", "", int, unsigned int, long,
unsigned long, long long, unsigned long long, float, double) {
CoalescedGroupShflTest<TestType>();
}
static inline std::mt19937& GetRandomGenerator() {
static std::mt19937 mt(11);
return mt;
}
template <typename T> static inline T GenerateRandomInteger(const T min, const T max) {
std::uniform_int_distribution<T> dist(min, max);
return dist(GetRandomGenerator());
}
template <bool use_global, size_t warp_size, typename T>
__global__ void coalesced_group_sync_check(T* global_data, unsigned int* wait_modifiers,
const uint64_t active_mask) {
extern __shared__ uint8_t shared_data[];
T* const data = use_global ? global_data : reinterpret_cast<T*>(shared_data);
const auto tid = cg::this_grid().thread_rank();
const auto block = cg::this_thread_block();
const cg::thread_block_tile<warp_size> partition = cg::tiled_partition<warp_size>(block);
const auto data_idx = [&block](unsigned int i) { return use_global ? i : (i % block.size()); };
const auto partition_rank = block.thread_rank() / partition.size();
const auto block_base_idx = tid / block.size() * block.size();
const auto tile_base_idx = block_base_idx + partition_rank * partition.size();
const auto wait_modifier = wait_modifiers[tid];
if (active_mask & (static_cast<uint64_t>(1) << partition.thread_rank())) {
cg::coalesced_group active = cg::coalesced_threads();
busy_wait(wait_modifier);
data[data_idx(tid)] = active.thread_rank();
active.sync();
bool valid = true;
for (auto i = 0; i < active.size(); ++i) {
const auto expected = (active.thread_rank() + i) % active.size();
unsigned int active_count = 0;
int offset = -1;
while (active_count <= expected) {
offset++;
if (active_mask & (static_cast<uint64_t>(1) << offset)) active_count++;
}
if (!(valid &= (data[data_idx(tile_base_idx + offset)] == expected))) {
break;
}
}
active.sync();
data[data_idx(tid)] = valid;
if constexpr (!use_global) {
global_data[tid] = data[data_idx(tid)];
}
}
}
template <bool global_memory, typename T> void CoalescedGroupSyncTest() {
const auto randomized_run_count = GENERATE(range(0, cmd_options.cg_iterations));
const auto blocks = GenerateBlockDimensionsForShuffle();
const auto threads = GenerateThreadDimensionsForShuffle();
auto test_case = GENERATE(range(0, 4));
uint64_t active_mask = get_active_mask(test_case);
INFO("Grid dimensions: x " << blocks.x << ", y " << blocks.y << ", z " << blocks.z);
INFO("Block dimensions: x " << threads.x << ", y " << threads.y << ", z " << threads.z);
INFO("Coalesced group mask: " << active_mask);
CPUGrid grid(blocks, threads);
const auto alloc_size = grid.thread_count_ * sizeof(T);
const auto alloc_size_per_block = alloc_size / grid.block_count_;
int max_shared_mem_per_block = 0;
HIP_CHECK(hipDeviceGetAttribute(&max_shared_mem_per_block,
hipDeviceAttributeMaxSharedMemoryPerBlock, 0));
if (!global_memory && (max_shared_mem_per_block < alloc_size_per_block)) {
return;
}
LinearAllocGuard<T> arr_dev(LinearAllocs::hipMalloc, alloc_size);
LinearAllocGuard<T> arr(LinearAllocs::hipHostMalloc, alloc_size);
LinearAllocGuard<unsigned int> wait_modifiers_dev(LinearAllocs::hipMalloc,
grid.thread_count_ * sizeof(unsigned int));
LinearAllocGuard<unsigned int> wait_modifiers(LinearAllocs::hipHostMalloc,
grid.thread_count_ * sizeof(unsigned int));
if (randomized_run_count != 0) {
std::generate(wait_modifiers.ptr(), wait_modifiers.ptr() + grid.thread_count_,
[] { return GenerateRandomInteger(0u, 1500u); });
} else {
std::fill_n(wait_modifiers.ptr(), grid.thread_count_, 0u);
}
const auto shared_memory_size = global_memory ? 0u : alloc_size_per_block;
HIP_CHECK(hipMemcpy(wait_modifiers_dev.ptr(), wait_modifiers.ptr(),
grid.thread_count_ * sizeof(unsigned int), hipMemcpyHostToDevice));
coalesced_group_sync_check<global_memory, kWarpSize><<<blocks, threads, shared_memory_size>>>(
arr_dev.ptr(), wait_modifiers_dev.ptr(), active_mask);
HIP_CHECK(hipGetLastError());
HIP_CHECK(hipMemcpy(arr.ptr(), arr_dev.ptr(), alloc_size, hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
for (int i = 0; i < grid.thread_count_; i++) {
const auto rank_in_block = grid.thread_rank_in_block(i).value();
const int rank_in_partition = rank_in_block % kWarpSize;
if (active_mask & (static_cast<uint64_t>(1) << rank_in_partition)) {
if (arr.ptr()[i] != 1) {
REQUIRE(arr.ptr()[i] == 1);
}
}
}
}
/**
* Test Description
* ------------------------
* - Launches a kernel where blocks are devided into coalesced groups and every thread writes its
* intra-tile rank into an array slot determined by its grid-wide linear index. The array is either
* in global or dynamic shared memory based on a compile time switch, and the test is run for arrays
* of 1, 2, and 4 byte elements. Before the write each thread executes a busy wait loop for a random
* amount of clock cycles, the amount being read from an input array. After the write a sync for
* active threads is performed and each thread validates that it can read the expected values that
* other active threads within the same coalesced group have written to their respective array
* slots. Each thread begins the validation from a given offset from its own index. For the first
* run of the test, all the offsets are zero, so memory reads should be coalesced as adjacent
* threads read from adjacent memory locations. On subsequent runs the offsets are randomized for
* each thread, leading to non-coalesced reads and cache thrashing.
* Test source
* ------------------------
* - unit/cooperativeGrps/coalesced_group.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Coalesced_Group_Sync_Positive_Basic", "", uint8_t, uint16_t, uint32_t) {
SECTION("Global memory") { CoalescedGroupSyncTest<true, TestType>(); }
SECTION("Shared memory") { CoalescedGroupSyncTest<false, TestType>(); }
}
@@ -28,10 +28,9 @@ constexpr size_t kWarpSize = 32;
#else
constexpr size_t kWarpSize = 64;
#endif
constexpr int kMaxGPUs = 8;
} // namespace
constexpr int MaxGPUs = 8;
__device__ inline unsigned int thread_rank_in_grid() {
const auto block_size = blockDim.x * blockDim.y * blockDim.z;
const auto block_rank_in_grid = (blockIdx.z * gridDim.y + blockIdx.y) * gridDim.x + blockIdx.x;
@@ -0,0 +1,652 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "cooperative_groups_common.hh"
#include <cpu_grid.h>
#include <resource_guards.hh>
#include <utils.hh>
/**
* @addtogroup multi_grid_group multi_grid_group
* @{
* @ingroup DeviceLanguageTest
* Contains unit tests for all multi_grid_group APIs
*/
namespace cg = cooperative_groups;
template <typename BaseType = cg::multi_grid_group>
static __global__ void multi_grid_group_size_getter(unsigned int* sizes) {
const BaseType group = cg::this_multi_grid();
sizes[thread_rank_in_grid()] = group.size();
}
template <typename BaseType = cg::multi_grid_group>
static __global__ void multi_grid_group_thread_rank_getter(unsigned int* thread_ranks) {
const BaseType group = cg::this_multi_grid();
thread_ranks[thread_rank_in_grid()] = group.thread_rank();
}
template <typename BaseType = cg::multi_grid_group>
static __global__ void multi_grid_group_is_valid_getter(unsigned int* is_valid_flags) {
const BaseType group = cg::this_multi_grid();
is_valid_flags[thread_rank_in_grid()] = static_cast<unsigned int>(group.is_valid());
}
static __global__ void multi_grid_group_num_grids_getter(unsigned int* num_grids) {
num_grids[thread_rank_in_grid()] = cg::this_multi_grid().num_grids();
}
static __global__ void multi_grid_group_grid_rank_getter(unsigned int* grid_ranks) {
grid_ranks[thread_rank_in_grid()] = cg::this_multi_grid().grid_rank();
}
static __global__ void multi_grid_group_non_member_size_getter(unsigned int* sizes) {
sizes[thread_rank_in_grid()] = cg::group_size(cg::this_multi_grid());
}
static __global__ void multi_grid_group_non_member_thread_rank_getter(unsigned int* thread_ranks) {
thread_ranks[thread_rank_in_grid()] = cg::thread_rank(cg::this_multi_grid());
}
static __global__ void sync_kernel(unsigned int* atomic_val, unsigned int* global_array,
unsigned int* array, uint32_t loops) {
cooperative_groups::grid_group grid = cooperative_groups::this_grid();
cooperative_groups::multi_grid_group mgrid = cooperative_groups::this_multi_grid();
unsigned rank = grid.thread_rank();
unsigned global_rank = mgrid.thread_rank();
int offset = (blockIdx.z * gridDim.y + blockIdx.y) * gridDim.x + blockIdx.x;
for (int i = 0; i < loops; i++) {
// Make the last thread run way behind everyone else.
// If the sync below fails, then the other threads may hit the
// atomicInc instruction many times before the last thread ever gets to it.
// If the sync works, then it will likely contain "total number of blocks"*i
if (rank == (grid.size() - 1)) {
busy_wait(100000);
}
if (threadIdx.x == blockDim.x - 1 && threadIdx.y == blockDim.y - 1 &&
threadIdx.z == blockDim.z - 1) {
array[offset] = atomicInc(atomic_val, UINT_MAX);
}
grid.sync();
// Make the last thread in the entire multi-grid run way behind
// everyone else.
if (global_rank == (mgrid.size() - 1)) {
busy_wait(100000);
}
// During even iterations, add into your own array entry
// During odd iterations, add into next array entry
unsigned grid_rank = mgrid.grid_rank();
unsigned inter_gpu_offset = (grid_rank + 1) % mgrid.num_grids();
if (rank == (grid.size() - 1)) {
if (i % 2 == 0) {
global_array[grid_rank] += 2;
} else {
global_array[inter_gpu_offset] *= 2;
}
}
mgrid.sync();
offset += gridDim.x * gridDim.y * gridDim.z;
}
}
static void get_multi_grid_dims(dim3& grid_dim, dim3& block_dim, unsigned int device,
unsigned int test_case) {
hipDeviceProp_t props;
HIP_CHECK(hipSetDevice(device))
HIP_CHECK(hipGetDeviceProperties(&props, 0));
int sm = props.multiProcessorCount;
std::vector<dim3> block_dim_values = {dim3(1, 1, 1),
dim3(props.maxThreadsDim[0], 1, 1),
dim3(1, props.maxThreadsDim[1], 1),
dim3(1, 1, props.maxThreadsDim[2]),
dim3(16, 8, 8),
dim3(32, 32, 1),
dim3(64, 8, 2),
dim3(16, 16, 3),
dim3(kWarpSize - 1, 3, 3),
dim3(kWarpSize + 1, 3, 3)};
std::vector<dim3> grid_dim_values = {dim3(1, 1, 1),
dim3(static_cast<int>(0.5 * sm), 1, 3),
dim3(4, static_cast<int>(0.5 * sm), 1),
dim3(1, 1, static_cast<int>(0.5 * sm)),
dim3(sm, 2, 1),
dim3(2, sm, 1),
dim3(1, sm, 2),
dim3(3, 3, 3)};
if (test_case < 10) {
grid_dim = grid_dim_values[test_case % grid_dim_values.size()];
block_dim = block_dim_values[test_case % block_dim_values.size()];
} else {
grid_dim = grid_dim_values[(test_case + device) % grid_dim_values.size()];
block_dim = block_dim_values[(test_case + device) % block_dim_values.size()];
}
}
/**
* Test Description
* ------------------------
* - Launches kernels that write the return values of size, thread_rank, grid_rank, num_grids and
* is_valid member functions to an output array that is validated on the host side. The kernels are
* run sequentially, reusing the output array, to avoid running out of device memory for large
* kernel launches.
* Test source
* ------------------------
* - unit/cooperativeGrps/multi_grid_group.c
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
* - Devices support cooperative multi device launch
*/
TEST_CASE("Unit_Multi_Grid_Group_Getters_Positive_Basic") {
int num_devices = 0;
HIP_CHECK(hipGetDeviceCount(&num_devices));
num_devices = min(num_devices, kMaxGPUs);
std::vector<hipDeviceProp_t> device_properties(num_devices);
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipGetDeviceProperties(&device_properties[i], i));
if (!device_properties[i].cooperativeMultiDeviceLaunch) {
HipTest::HIP_SKIP_TEST("Device doesn't support cooperative launch!");
return;
}
}
const auto test_case = GENERATE(range(0, 20));
std::vector<dim3> grid_dims(num_devices);
std::vector<dim3> block_dims(num_devices);
for (int i = 0; i < num_devices; i++) {
get_multi_grid_dims(grid_dims[i], block_dims[i], i, test_case);
if (!CheckDimensions(i, multi_grid_group_size_getter<cg::multi_grid_group>, grid_dims[i],
block_dims[i]))
return;
INFO("Grid dimensions dev " << i << " : x " << grid_dims[i].x << ", y " << grid_dims[i].y
<< ", z " << grid_dims[i].z);
INFO("Block dimensions dev " << i << " : x " << block_dims[i].x << ", y " << block_dims[i].y
<< ", z " << block_dims[i].z);
}
CPUMultiGrid multi_grid(num_devices, grid_dims.data(), block_dims.data());
std::vector<StreamGuard> streams;
std::vector<LinearAllocGuard<unsigned int>> uint_arr_dev;
std::vector<LinearAllocGuard<unsigned int>> uint_arr;
std::vector<unsigned int*> uint_arr_dev_ptr(num_devices);
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
HIP_CHECK(hipDeviceSynchronize());
streams.emplace_back(Streams::created);
uint_arr_dev.emplace_back(LinearAllocs::hipMalloc,
multi_grid.grids_[i].thread_count_ * sizeof(unsigned int));
uint_arr_dev_ptr[i] = uint_arr_dev[i].ptr();
uint_arr.emplace_back(LinearAllocs::hipHostMalloc,
multi_grid.grids_[i].thread_count_ * sizeof(unsigned int));
}
// Launch Kernel
std::vector<hipLaunchParams> launchParamsList(num_devices);
std::vector<void*> args(num_devices);
for (int i = 0; i < num_devices; i++) {
args[i] = &uint_arr_dev_ptr[i];
launchParamsList[i].func =
reinterpret_cast<void*>(multi_grid_group_size_getter<cg::multi_grid_group>);
launchParamsList[i].gridDim = grid_dims[i];
launchParamsList[i].blockDim = block_dims[i];
launchParamsList[i].sharedMem = 0;
launchParamsList[i].stream = streams[i].stream();
launchParamsList[i].args = &args[i];
}
HIP_CHECK(hipLaunchCooperativeKernelMultiDevice(launchParamsList.data(), num_devices, 0));
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
HIP_CHECK(hipMemcpy(uint_arr[i].ptr(), uint_arr_dev[i].ptr(),
multi_grid.grids_[i].thread_count_ * sizeof(*uint_arr[i].ptr()),
hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
launchParamsList[i].func =
reinterpret_cast<void*>(multi_grid_group_thread_rank_getter<cg::multi_grid_group>);
}
HIP_CHECK(hipLaunchCooperativeKernelMultiDevice(launchParamsList.data(), num_devices, 0));
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
// Verify multi_grid_group.size() values
ArrayAllOf(uint_arr[i].ptr(), multi_grid.grids_[i].thread_count_,
[size = multi_grid.thread_count_](uint32_t) { return size; });
HIP_CHECK(hipMemcpy(uint_arr[i].ptr(), uint_arr_dev[i].ptr(),
multi_grid.grids_[i].thread_count_ * sizeof(*uint_arr[i].ptr()),
hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
launchParamsList[i].func = reinterpret_cast<void*>(multi_grid_group_grid_rank_getter);
}
HIP_CHECK(hipLaunchCooperativeKernelMultiDevice(launchParamsList.data(), num_devices, 0));
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
// Verify multi_grid_group.thread_rank() values
const auto multi_grid_thread0_rank = multi_grid.thread0_rank_in_multi_grid(i);
ArrayAllOf(uint_arr[i].ptr(), multi_grid.grids_[i].thread_count_,
[rank_0 = multi_grid_thread0_rank](uint32_t j) { return rank_0 + j; });
HIP_CHECK(hipMemcpy(uint_arr[i].ptr(), uint_arr_dev[i].ptr(),
multi_grid.grids_[i].thread_count_ * sizeof(*uint_arr[i].ptr()),
hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
launchParamsList[i].func = reinterpret_cast<void*>(multi_grid_group_num_grids_getter);
}
HIP_CHECK(hipLaunchCooperativeKernelMultiDevice(launchParamsList.data(), num_devices, 0));
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
// Verify multi_grid_group.grid_rank() values
ArrayFindIfNot(uint_arr[i].ptr(), static_cast<unsigned int>(i),
multi_grid.grids_[i].thread_count_);
HIP_CHECK(hipMemcpy(uint_arr[i].ptr(), uint_arr_dev[i].ptr(),
multi_grid.grids_[i].thread_count_ * sizeof(*uint_arr[i].ptr()),
hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
launchParamsList[i].func =
reinterpret_cast<void*>(multi_grid_group_is_valid_getter<cg::multi_grid_group>);
}
HIP_CHECK(hipLaunchCooperativeKernelMultiDevice(launchParamsList.data(), num_devices, 0));
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
// Verify multi_grid_group.num_grids() values
ArrayFindIfNot(uint_arr[i].ptr(), static_cast<unsigned int>(num_devices),
multi_grid.grids_[i].thread_count_);
HIP_CHECK(hipMemcpy(uint_arr[i].ptr(), uint_arr_dev[i].ptr(),
multi_grid.grids_[i].thread_count_ * sizeof(*uint_arr[i].ptr()),
hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
// Verify multi_grid_group.is_valid() values
ArrayFindIfNot(uint_arr[i].ptr(), 1U, multi_grid.grids_[i].thread_count_);
}
}
/**
* Test Description
* ------------------------
* - Launches kernels that write the return values of size, thread_rank and is_valid member
* functions to an output array that is validated on the host side, while treating the
* multi_grid_group as a thread group. The kernels are run sequentially, reusing the output array,
* to avoid running out of device memory for large kernel launches.
* Test source
* ------------------------
* - unit/cooperativeGrps/multi_grid_group.c
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
* - Devices support cooperative multi device launch
*/
TEST_CASE("Unit_Multi_Grid_Group_Getters_Positive_Base_Type") {
int num_devices = 0;
HIP_CHECK(hipGetDeviceCount(&num_devices));
num_devices = min(num_devices, kMaxGPUs);
std::vector<hipDeviceProp_t> device_properties(num_devices);
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipGetDeviceProperties(&device_properties[i], i));
if (!device_properties[i].cooperativeMultiDeviceLaunch) {
HipTest::HIP_SKIP_TEST("Device doesn't support cooperative launch!");
return;
}
}
const auto test_case = GENERATE(range(0, 20));
std::vector<dim3> grid_dims(num_devices);
std::vector<dim3> block_dims(num_devices);
for (int i = 0; i < num_devices; i++) {
get_multi_grid_dims(grid_dims[i], block_dims[i], i, test_case);
if (!CheckDimensions(i, multi_grid_group_size_getter<cg::multi_grid_group>, grid_dims[i],
block_dims[i]))
return;
INFO("Grid dimensions dev " << i << " : x " << grid_dims[i].x << ", y " << grid_dims[i].y
<< ", z " << grid_dims[i].z);
INFO("Block dimensions dev " << i << " : x " << block_dims[i].x << ", y " << block_dims[i].y
<< ", z " << block_dims[i].z);
}
CPUMultiGrid multi_grid(num_devices, grid_dims.data(), block_dims.data());
std::vector<StreamGuard> streams;
std::vector<LinearAllocGuard<unsigned int>> uint_arr_dev;
std::vector<LinearAllocGuard<unsigned int>> uint_arr;
std::vector<unsigned int*> uint_arr_dev_ptr(num_devices);
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
HIP_CHECK(hipDeviceSynchronize());
streams.emplace_back(Streams::created);
uint_arr_dev.emplace_back(LinearAllocs::hipMalloc,
multi_grid.grids_[i].thread_count_ * sizeof(unsigned int));
uint_arr_dev_ptr[i] = uint_arr_dev[i].ptr();
uint_arr.emplace_back(LinearAllocs::hipHostMalloc,
multi_grid.grids_[i].thread_count_ * sizeof(unsigned int));
}
// Launch Kernel
std::vector<hipLaunchParams> launchParamsList(num_devices);
std::vector<void*> args(num_devices);
for (int i = 0; i < num_devices; i++) {
args[i] = &uint_arr_dev_ptr[i];
launchParamsList[i].func =
reinterpret_cast<void*>(multi_grid_group_size_getter<cg::thread_group>);
launchParamsList[i].gridDim = grid_dims[i];
launchParamsList[i].blockDim = block_dims[i];
launchParamsList[i].sharedMem = 0;
launchParamsList[i].stream = streams[i].stream();
launchParamsList[i].args = &args[i];
}
HIP_CHECK(hipLaunchCooperativeKernelMultiDevice(launchParamsList.data(), num_devices, 0));
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
HIP_CHECK(hipMemcpy(uint_arr[i].ptr(), uint_arr_dev[i].ptr(),
multi_grid.grids_[i].thread_count_ * sizeof(*uint_arr[i].ptr()),
hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
launchParamsList[i].func =
reinterpret_cast<void*>(multi_grid_group_thread_rank_getter<cg::thread_group>);
}
HIP_CHECK(hipLaunchCooperativeKernelMultiDevice(launchParamsList.data(), num_devices, 0));
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
// Verify multi_grid_group.size() values
ArrayFindIfNot(uint_arr[i].ptr(), multi_grid.thread_count_, multi_grid.grids_[i].thread_count_);
HIP_CHECK(hipMemcpy(uint_arr[i].ptr(), uint_arr_dev[i].ptr(),
multi_grid.grids_[i].thread_count_ * sizeof(*uint_arr[i].ptr()),
hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
#if HT_AMD
launchParamsList[i].func =
reinterpret_cast<void*>(multi_grid_group_is_valid_getter<cg::thread_group>);
#else
launchParamsList[i].func =
reinterpret_cast<void*>(multi_grid_group_is_valid_getter<cg::multi_grid_group>);
#endif
}
HIP_CHECK(hipLaunchCooperativeKernelMultiDevice(launchParamsList.data(), num_devices, 0));
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
// Verify multi_grid_group.thread_rank() values
const auto multi_grid_thread0_rank = multi_grid.thread0_rank_in_multi_grid(i);
ArrayAllOf(uint_arr[i].ptr(), multi_grid.grids_[i].thread_count_,
[rank_0 = multi_grid_thread0_rank](uint32_t j) { return rank_0 + j; });
HIP_CHECK(hipMemcpy(uint_arr[i].ptr(), uint_arr_dev[i].ptr(),
multi_grid.grids_[i].thread_count_ * sizeof(*uint_arr[i].ptr()),
hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
// Verify multi_grid_group.is_valid() values
ArrayFindIfNot(uint_arr[i].ptr(), 1U, multi_grid.grids_[i].thread_count_);
}
}
/**
* Test Description
* ------------------------
* - Launches kernels that write the return values of size and thread_rank non-member functions
* to an output array that is validated on the host side. The kernels are run sequentially, reusing
* the output array, to avoid running out of device memory for large kernel launches.
* Test source
* ------------------------
* - unit/cooperativeGrps/multi_grid_group.c
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
* - Devices support cooperative multi device launch
*/
TEST_CASE("Unit_Multi_Grid_Group_Getters_Positive_Non_Member_Functions") {
int num_devices = 0;
HIP_CHECK(hipGetDeviceCount(&num_devices));
num_devices = min(num_devices, kMaxGPUs);
std::vector<hipDeviceProp_t> device_properties(num_devices);
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipGetDeviceProperties(&device_properties[i], i));
if (!device_properties[i].cooperativeMultiDeviceLaunch) {
HipTest::HIP_SKIP_TEST("Device doesn't support cooperative launch!");
return;
}
}
const auto test_case = GENERATE(range(0, 20));
std::vector<dim3> grid_dims(num_devices);
std::vector<dim3> block_dims(num_devices);
for (int i = 0; i < num_devices; i++) {
get_multi_grid_dims(grid_dims[i], block_dims[i], i, test_case);
if (!CheckDimensions(i, multi_grid_group_size_getter<cg::multi_grid_group>, grid_dims[i],
block_dims[i]))
return;
INFO("Grid dimensions dev " << i << " : x " << grid_dims[i].x << ", y " << grid_dims[i].y
<< ", z " << grid_dims[i].z);
INFO("Block dimensions dev " << i << " : x " << block_dims[i].x << ", y " << block_dims[i].y
<< ", z " << block_dims[i].z);
}
CPUMultiGrid multi_grid(num_devices, grid_dims.data(), block_dims.data());
std::vector<StreamGuard> streams;
std::vector<LinearAllocGuard<unsigned int>> uint_arr_dev;
std::vector<LinearAllocGuard<unsigned int>> uint_arr;
std::vector<unsigned int*> uint_arr_dev_ptr(num_devices);
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
HIP_CHECK(hipDeviceSynchronize());
streams.emplace_back(Streams::created);
uint_arr_dev.emplace_back(LinearAllocs::hipMalloc,
multi_grid.grids_[i].thread_count_ * sizeof(unsigned int));
uint_arr_dev_ptr[i] = uint_arr_dev[i].ptr();
uint_arr.emplace_back(LinearAllocs::hipHostMalloc,
multi_grid.grids_[i].thread_count_ * sizeof(unsigned int));
}
// Launch Kernel
std::vector<hipLaunchParams> launchParamsList(num_devices);
std::vector<void*> args(num_devices);
for (int i = 0; i < num_devices; i++) {
args[i] = &uint_arr_dev_ptr[i];
launchParamsList[i].func = reinterpret_cast<void*>(multi_grid_group_non_member_size_getter);
launchParamsList[i].gridDim = grid_dims[i];
launchParamsList[i].blockDim = block_dims[i];
launchParamsList[i].sharedMem = 0;
launchParamsList[i].stream = streams[i].stream();
launchParamsList[i].args = &args[i];
}
HIP_CHECK(hipLaunchCooperativeKernelMultiDevice(launchParamsList.data(), num_devices, 0));
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
HIP_CHECK(hipMemcpy(uint_arr[i].ptr(), uint_arr_dev[i].ptr(),
multi_grid.grids_[i].thread_count_ * sizeof(*uint_arr[i].ptr()),
hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
launchParamsList[i].func =
reinterpret_cast<void*>(multi_grid_group_non_member_thread_rank_getter);
}
HIP_CHECK(hipLaunchCooperativeKernelMultiDevice(launchParamsList.data(), num_devices, 0));
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
// Verify multi_grid_group.size() values
ArrayFindIfNot(uint_arr[i].ptr(), multi_grid.thread_count_, multi_grid.grids_[i].thread_count_);
HIP_CHECK(hipMemcpy(uint_arr[i].ptr(), uint_arr_dev[i].ptr(),
multi_grid.grids_[i].thread_count_ * sizeof(*uint_arr[i].ptr()),
hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
// Verify multi_grid_group.thread_rank() values
const auto multi_grid_thread0_rank = multi_grid.thread0_rank_in_multi_grid(i);
ArrayAllOf(uint_arr[i].ptr(), multi_grid.grids_[i].thread_count_,
[rank_0 = multi_grid_thread0_rank](uint32_t j) { return rank_0 + j; });
}
}
/**
* Test Description
* ------------------------
* - Launches a kernel to multiple gpus which tests sync of separate grids and sync of the entire
* multi grid. The last thread in a block in a grid atomically increments a global variable within a
* work loop. The value returned from this atomic increment entirely depends on the order the
* threads arrive at the atomic instruction. Each thread then stores the result in the global array
* based on its block id. A wait loop is inserted into the last thread so that it runs behind all
* other threads. If the grid sync doesn't work, the other threads will increment the atomic
* variable many times before the last thread gets to it and it will read a very large value. If the
* grid sync works, each thread will increment the variable once per loop iteration and the last
* thread will contain total number of blocks * loop iteration. In the end of the work loop, a value
* is added into grid's own global array entry during even iterations and during odd iterations, a
* value of the next grid is multiplied. A wait loop is inserted into the last thread in the entire
* multi-grid so that it runs behind all the other threads. If the multi grid sync doesn't work the
* two global array entries will end up being out of sync, because the intermingling of adds and
* multiplies will not be aligned between the devices.
* Test source
* ------------------------
* - unit/cooperativeGrps/multi_grid_group.c
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
* - Devices support cooperative multi device launch
*/
TEST_CASE("Unit_Multi_Grid_Group_Positive_Sync") {
int num_devices = 0;
HIP_CHECK(hipGetDeviceCount(&num_devices));
num_devices = min(num_devices, kMaxGPUs);
std::vector<hipDeviceProp_t> device_properties(num_devices);
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipGetDeviceProperties(&device_properties[i], i));
if (!device_properties[i].cooperativeMultiDeviceLaunch) {
HipTest::HIP_SKIP_TEST("Device doesn't support cooperative launch!");
return;
}
}
auto loops = GENERATE(2, 4, 8, 16);
const auto test_case = GENERATE(range(0, 20));
std::vector<dim3> grid_dims(num_devices);
std::vector<dim3> block_dims(num_devices);
for (int i = 0; i < num_devices; i++) {
get_multi_grid_dims(grid_dims[i], block_dims[i], i, test_case);
if (!CheckDimensions(i, sync_kernel, grid_dims[i], block_dims[i])) return;
INFO("Grid dimensions dev " << i << " : x " << grid_dims[i].x << ", y " << grid_dims[i].y
<< ", z " << grid_dims[i].z);
INFO("Block dimensions dev " << i << " : x " << block_dims[i].x << ", y " << block_dims[i].y
<< ", z " << block_dims[i].z);
}
CPUMultiGrid multi_grid(num_devices, grid_dims.data(), block_dims.data());
std::vector<StreamGuard> streams;
std::vector<LinearAllocGuard<unsigned int>> uint_arr_dev;
std::vector<LinearAllocGuard<unsigned int>> uint_arr;
std::vector<LinearAllocGuard<unsigned int>> atomic_val;
std::vector<unsigned int*> uint_arr_dev_ptr(num_devices);
std::vector<unsigned int*> atomic_val_ptr(num_devices);
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
HIP_CHECK(hipDeviceSynchronize());
streams.emplace_back(Streams::created);
// Allocate grid sync arrays
unsigned int array_len = multi_grid.grids_[i].block_count_ * loops;
uint_arr_dev.emplace_back(LinearAllocs::hipMalloc, array_len * sizeof(unsigned int));
uint_arr_dev_ptr[i] = uint_arr_dev[i].ptr();
uint_arr.emplace_back(LinearAllocs::hipHostMalloc, array_len * sizeof(unsigned int));
atomic_val.emplace_back(LinearAllocs::hipMalloc, sizeof(unsigned int));
HIP_CHECK(hipMemset(atomic_val[i].ptr(), 0, sizeof(unsigned int)));
atomic_val_ptr[i] = atomic_val[i].ptr();
}
// Allocate multi_grid sync array
LinearAllocGuard<unsigned int> global_arr(LinearAllocs::hipHostMalloc,
num_devices * sizeof(unsigned int));
HIP_CHECK(hipMemset(global_arr.ptr(), 0, num_devices * sizeof(unsigned int)));
unsigned int* global_arr_ptr = global_arr.ptr();
std::vector<std::vector<void*>> dev_params(num_devices, std::vector<void*>(4, nullptr));
std::vector<hipLaunchParams> md_params(num_devices);
for (int i = 0; i < num_devices; i++) {
dev_params[i][0] = reinterpret_cast<void*>(&atomic_val_ptr[i]);
dev_params[i][1] = reinterpret_cast<void*>(&global_arr_ptr);
dev_params[i][2] = reinterpret_cast<void*>(&uint_arr_dev_ptr[i]);
dev_params[i][3] = reinterpret_cast<void*>(&loops);
md_params[i].func = reinterpret_cast<void*>(sync_kernel);
md_params[i].gridDim = grid_dims[i];
md_params[i].blockDim = block_dims[i];
md_params[i].sharedMem = 0;
md_params[i].stream = streams[i].stream();
md_params[i].args = dev_params[i].data();
}
// Launch Kernel
HIP_CHECK(hipLaunchCooperativeKernelMultiDevice(md_params.data(), num_devices, 0));
HIP_CHECK(hipDeviceSynchronize());
// Read back the grid sync buffer to host
for (int i = 0; i < num_devices; i++) {
HIP_CHECK(hipSetDevice(i));
unsigned int array_len = multi_grid.grids_[i].block_count_ * loops;
HIP_CHECK(hipMemcpy(uint_arr[i].ptr(), uint_arr_dev[i].ptr(), array_len * sizeof(unsigned int),
hipMemcpyDeviceToHost));
}
HIP_CHECK(hipDeviceSynchronize());
// Verify grid sync host array values
for (int i = 0; i < num_devices; i++) {
unsigned int max_in_this_loop = 0;
for (unsigned int j = 0; j < loops; j++) {
max_in_this_loop += multi_grid.grids_[i].block_count_;
unsigned int k = 0;
for (k = 0; k < multi_grid.grids_[i].block_count_ - 1; k++) {
REQUIRE(uint_arr[i].ptr()[j * multi_grid.grids_[i].block_count_ + k] < max_in_this_loop);
}
REQUIRE(uint_arr[i].ptr()[j * multi_grid.grids_[i].block_count_ + k] == max_in_this_loop - 1);
}
}
// Verify multi_grid sync array values
const auto f = [loops](unsigned int) -> unsigned int {
unsigned int desired_val = 0;
for (int j = 0; j < loops; j++) {
if (j % 2 == 0) {
desired_val += 2;
} else {
desired_val *= 2;
}
}
return desired_val;
};
ArrayAllOf(global_arr.ptr(), num_devices, f);
}
+3 -2
Ver Arquivo
@@ -3,7 +3,7 @@ set(TEST_SRC
hipChooseDevice.cc
hipDeviceComputeCapability.cc
hipDeviceGetByPCIBusId.cc
hipDeviceGetLimit.cc
hipDeviceGetLimit_old.cc
hipDeviceGetName.cc
hipDeviceGetPCIBusId.cc
hipDeviceSetGetCacheConfig.cc
@@ -20,7 +20,8 @@ set(TEST_SRC
hipDeviceCanAccessPeer.cc
hipDeviceEnableDisablePeerAccess.cc
hipExtGetLinkTypeAndHopCount.cc
hipDeviceSetLimit.cc
hipDeviceSetLimit_old.cc
hipDeviceSetGetLimit.cc
hipDeviceSetGetSharedMemConfig.cc
hipDeviceReset.cc
hipDeviceSetGetMemPool.cc
+190
Ver Arquivo
@@ -0,0 +1,190 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
/**
* @addtogroup hipDeviceSetLimit hipDeviceSetLimit
* @{
* @ingroup DeviceTest
* `hipDeviceSetLimit(enum hipLimit_t limit, size_t value)` -
* Set Resource limits of current device.
*/
void DeviceSetLimitTest(hipLimit_t limit) {
size_t old_val;
HIP_CHECK(hipDeviceGetLimit(&old_val, limit));
REQUIRE(old_val != 0);
HIP_CHECK(hipDeviceSetLimit(limit, old_val + 8));
size_t new_val;
HIP_CHECK(hipDeviceGetLimit(&new_val, limit));
REQUIRE(new_val >= old_val + 8);
}
/**
* Test Description
* ------------------------
* - Basic set-get test for `hipLimitStackSize`.
* Test source
* ------------------------
* - unit/device/hipDeviceSetGetLimit.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.3
*/
TEST_CASE("Unit_hipDeviceSetLimit_Positive_StackSize") { DeviceSetLimitTest(hipLimitStackSize); }
#if HT_NVIDIA
__device__ __managed__ bool stop = false;
/**
* Test Description
* ------------------------
* - Basic set-get test for `hipLimitPrintfFifoSize`.
* Test source
* ------------------------
* - unit/device/hipDeviceSetGetLimit.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.3
*/
TEST_CASE("Unit_hipDeviceSetLimit_Positive_PrintfFifoSize") {
DeviceSetLimitTest(hipLimitPrintfFifoSize);
}
__global__ void PrintfKernel() {
while (!stop) printf("");
}
/**
* Test Description
* ------------------------
* - Tests scenario where we try to set `hipLimitPrintfFifoSize` while a kernel that calls
* `printf()` is running.
* Test source
* ------------------------
* - unit/device/hipDeviceSetGetLimit.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.3
*/
TEST_CASE("Unit_hipDeviceSetLimit_Negative_PrintfFifoSize") {
PrintfKernel<<<1, 1>>>();
HIP_CHECK_ERROR(hipDeviceSetLimit(hipLimitPrintfFifoSize, 1024), hipErrorInvalidValue);
stop = true;
HIP_CHECK(hipDeviceSynchronize());
stop = false;
}
/**
* Test Description
* ------------------------
* - Basic set-get test for `hipLimitMallocHeapSize`.
* Test source
* ------------------------
* - unit/device/hipDeviceSetGetLimit.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.3
*/
TEST_CASE("Unit_hipDeviceSetLimit_Positive_MallocHeapSize") {
DeviceSetLimitTest(hipLimitMallocHeapSize);
}
__global__ void MallocKernel() {
while (!stop) free(malloc(1));
}
/**
* Test Description
* ------------------------
* - Tests scenario where we try to set `hipLimitMallocHeapSize` while a kernel that calls
* `malloc()` and `free()` is running.
* Test source
* ------------------------
* - unit/device/hipDeviceSetGetLimit.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.3
*/
TEST_CASE("Unit_hipDeviceSetLimit_Negative_MallocHeapSize") {
MallocKernel<<<1, 1>>>();
HIP_CHECK_ERROR(hipDeviceSetLimit(hipLimitMallocHeapSize, 1024), hipErrorInvalidValue);
stop = true;
HIP_CHECK(hipDeviceSynchronize());
stop = false;
}
#endif
/**
* Test Description
* ------------------------
* - Negative parameters test for `hipDeviceSetLimit`.
* Test source
* ------------------------
* - unit/device/hipDeviceSetGetLimit.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.3
*/
TEST_CASE("Unit_hipDeviceSetLimit_Negative_Parameters") {
HIP_CHECK_ERROR(hipDeviceSetLimit(static_cast<hipLimit_t>(-1), 1024), hipErrorUnsupportedLimit);
}
/**
* End doxygen group hipDeviceSetLimit.
* @}
*/
/**
* @addtogroup hipDeviceGetLimit hipDeviceGetLimit
* @{
* @ingroup DeviceTest
* `hipDeviceGetLimit(size_t* pValue, enum hipLimit_t limit)` -
* Get Resource limits of current device.
*/
/**
* Test Description
* ------------------------
* - Negative parameters test for `hipDeviceGetLimit`.
* Test source
* ------------------------
* - unit/device/hipDeviceSetGetLimit.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipDeviceGetLimit_Negative_Parameters") {
SECTION("nullptr") {
HIP_CHECK_ERROR(hipDeviceGetLimit(nullptr, hipLimitStackSize), hipErrorInvalidValue);
}
SECTION("unsupported limit") {
size_t val;
HIP_CHECK_ERROR(hipDeviceGetLimit(&val, static_cast<hipLimit_t>(-1)), hipErrorUnsupportedLimit);
}
}
+58
Ver Arquivo
@@ -0,0 +1,58 @@
# Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Common Tests - Test independent of all platforms
set(TEST_SRC
memcpy.cc
memset.cc
)
if(HIP_PLATFORM MATCHES "nvidia")
set(LINKER_LIBS nvrtc)
elseif(HIP_PLATFORM MATCHES "amd")
set(LINKER_LIBS hiprtc)
endif()
if(HIP_PLATFORM MATCHES "amd")
hip_add_exe_to_target(NAME DeviceMemoryTest
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests
LINKER_LIBS ${LINKER_LIBS}
PROPERTY CXX_STANDARD 17)
elseif (HIP_PLATFORM MATCHES "nvidia")
hip_add_exe_to_target(NAME DeviceMemoryTest
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests
LINKER_LIBS ${LINKER_LIBS}
COMPILE_OPTIONS -std=c++17)
endif()
# This test fails in PSDB
#add_test(NAME Unit_Device_memcpy_Negative
# COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/../compileAndCaptureOutput.py
# ${CMAKE_CURRENT_SOURCE_DIR} ${HIP_PLATFORM} ${HIP_PATH}
# memcpy_negative_kernels.cc 4)
# This test fails in PSDB
#add_test(NAME Unit_Device_memset_Negative
# COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/../compileAndCaptureOutput.py
# ${CMAKE_CURRENT_SOURCE_DIR} ${HIP_PLATFORM} ${HIP_PATH}
# memset_negative_kernels.cc 4)
+249
Ver Arquivo
@@ -0,0 +1,249 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "memcpy_negative_kernels_rtc.hh"
#include <hip_test_common.hh>
#include <resource_guards.hh>
#include <utils.hh>
#include <hip/hip_cooperative_groups.h>
/**
* @addtogroup memcpy memcpy
* @{
* @ingroup DeviceLanguageTest
* `memcpy(void* dst, const void* src, size_t size)` -
* copies device accessible data inside a kernel
*/
template <typename T> using kernel_sig = void (*)(T*, T*, const size_t);
template <typename T>
__global__ void memcpy_at_once_kernel(T* dst, T* src, const size_t alloc_size) {
memcpy(dst, src, alloc_size);
}
template <typename T> __global__ void memcpy_one_by_one_kernel(T* dst, T* src, const size_t N) {
const auto tid = cooperative_groups::this_grid().thread_rank();
const auto stride = cooperative_groups::this_grid().size();
for (auto i = tid; i < N; i += stride) {
memcpy(dst + tid, src + tid, sizeof(T));
}
}
template <typename T> void MemcpyDeviceToDeviceCommon(kernel_sig<T> memcpy_kernel) {
const auto allocation_size = GENERATE(kPageSize / 2, kPageSize, kPageSize * 2);
const auto element_count = allocation_size / sizeof(T);
LinearAllocGuard<T> input(LinearAllocs::hipHostMalloc, allocation_size);
LinearAllocGuard<T> result(LinearAllocs::hipHostMalloc, allocation_size);
LinearAllocGuard<T> src_allocation(LinearAllocs::hipMalloc, allocation_size);
LinearAllocGuard<T> dst_allocation(LinearAllocs::hipMalloc, allocation_size);
/* fill input data */
for (auto i = 0; i < element_count; i++) {
input.host_ptr()[i] = static_cast<T>(i);
}
/* Copy input data to device memory */
HIP_CHECK(
hipMemcpy(src_allocation.ptr(), input.host_ptr(), allocation_size, hipMemcpyHostToDevice));
/* Launch appropriate kernel*/
if (memcpy_kernel == &memcpy_at_once_kernel<T>) {
memcpy_at_once_kernel<T><<<1, 1>>>(dst_allocation.ptr(), src_allocation.ptr(), allocation_size);
} else {
constexpr auto thread_count = 1024;
const auto block_count = element_count / thread_count + 1;
memcpy_one_by_one_kernel<T>
<<<thread_count, block_count>>>(dst_allocation.ptr(), src_allocation.ptr(), element_count);
}
/* Copy filled device memory to result */
HIP_CHECK(
hipMemcpy(result.host_ptr(), dst_allocation.ptr(), allocation_size, hipMemcpyDeviceToHost));
ArrayMismatch(input.host_ptr(), result.host_ptr(), element_count);
}
template <typename T> void MemcpyPinnedToDeviceCommon(kernel_sig<T> memcpy_kernel) {
const auto allocation_size = GENERATE(kPageSize / 2, kPageSize, kPageSize * 2);
const auto element_count = allocation_size / sizeof(T);
LinearAllocGuard<T> input(LinearAllocs::hipHostMalloc, allocation_size);
LinearAllocGuard<T> result(LinearAllocs::hipHostMalloc, allocation_size);
LinearAllocGuard<T> dst_allocation(LinearAllocs::hipMalloc, allocation_size);
/* fill input data */
for (auto i = 0; i < element_count; i++) {
input.host_ptr()[i] = static_cast<T>(i);
}
/* Launch appropriate kernel*/
if (memcpy_kernel == &memcpy_at_once_kernel<T>) {
memcpy_at_once_kernel<T><<<1, 1>>>(dst_allocation.ptr(), input.host_ptr(), allocation_size);
} else {
constexpr auto thread_count = 1024;
const auto block_count = element_count / thread_count + 1;
memcpy_one_by_one_kernel<T>
<<<thread_count, block_count>>>(dst_allocation.ptr(), input.host_ptr(), element_count);
}
/* Copy filled device memory to result */
HIP_CHECK(
hipMemcpy(result.host_ptr(), dst_allocation.ptr(), allocation_size, hipMemcpyDeviceToHost));
ArrayMismatch(input.host_ptr(), result.host_ptr(), element_count);
}
template <typename T> void MemcpyDeviceToPinnedCommon(kernel_sig<T> memcpy_kernel) {
const auto allocation_size = GENERATE(kPageSize / 2, kPageSize, kPageSize * 2);
const auto element_count = allocation_size / sizeof(T);
LinearAllocGuard<T> input(LinearAllocs::hipHostMalloc, allocation_size);
LinearAllocGuard<T> result(LinearAllocs::hipHostMalloc, allocation_size);
LinearAllocGuard<T> src_allocation(LinearAllocs::hipMalloc, allocation_size);
/* fill input data */
for (auto i = 0; i < element_count; i++) {
input.host_ptr()[i] = static_cast<T>(i);
}
/* Copy input data to device memory */
HIP_CHECK(
hipMemcpy(src_allocation.ptr(), input.host_ptr(), allocation_size, hipMemcpyHostToDevice));
/* Launch appropriate kernel*/
if (memcpy_kernel == &memcpy_at_once_kernel<T>) {
memcpy_at_once_kernel<T><<<1, 1>>>(result.host_ptr(), src_allocation.ptr(), allocation_size);
} else {
constexpr auto thread_count = 1024;
const auto block_count = element_count / thread_count + 1;
memcpy_one_by_one_kernel<T>
<<<thread_count, block_count>>>(result.host_ptr(), src_allocation.ptr(), element_count);
}
HIP_CHECK(hipStreamSynchronize(nullptr));
ArrayMismatch(input.host_ptr(), result.host_ptr(), element_count);
}
template <typename T> void MemcpyPinnedToPinnedCommon(kernel_sig<T> memcpy_kernel) {
const auto allocation_size = GENERATE(kPageSize / 2, kPageSize, kPageSize * 2);
const auto element_count = allocation_size / sizeof(T);
LinearAllocGuard<T> input(LinearAllocs::hipHostMalloc, allocation_size);
LinearAllocGuard<T> result(LinearAllocs::hipHostMalloc, allocation_size);
/* fill input data */
for (auto i = 0; i < element_count; i++) {
input.host_ptr()[i] = static_cast<T>(i);
}
/* Launch appropriate kernel*/
if (memcpy_kernel == &memcpy_at_once_kernel<T>) {
memcpy_at_once_kernel<T><<<1, 1>>>(result.host_ptr(), input.host_ptr(), allocation_size);
} else {
constexpr auto thread_count = 1024;
const auto block_count = element_count / thread_count + 1;
memcpy_one_by_one_kernel<T>
<<<thread_count, block_count>>>(result.host_ptr(), input.host_ptr(), element_count);
}
HIP_CHECK(hipStreamSynchronize(nullptr));
ArrayMismatch(input.host_ptr(), result.host_ptr(), element_count);
}
template <typename T> void DeviceMemcpyCommon(kernel_sig<T> memcpy_kernel) {
SECTION("Device to Device memory") { MemcpyDeviceToDeviceCommon<T>(memcpy_kernel); }
SECTION("Pinned to Device memory") { MemcpyPinnedToDeviceCommon<T>(memcpy_kernel); }
SECTION("Device to Pinned memory") { MemcpyDeviceToPinnedCommon<T>(memcpy_kernel); }
SECTION("Pinned to Pinned memory") { MemcpyPinnedToPinnedCommon<T>(memcpy_kernel); }
}
/**
* Test Description
* ------------------------
* - Verifies basic test cases for copying device/pinned memory inside a kernel using various data
* types and memory sizes:
* -# Copies whole memory buffer in one thread
* -# Copies memory buffer elements one by one in multiple threads/blocks
* Test source
* ------------------------
* - unit/device_memory/memcpy.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Device_memcpy_Positive", "", char, int, unsigned int, long, unsigned long,
long long, unsigned long long, float, double) {
SECTION("Memcpy whole buffer in one thread") {
DeviceMemcpyCommon<TestType>(memcpy_at_once_kernel);
}
SECTION("Memcpy buffer in multiple threads/blocks") {
DeviceMemcpyCommon<TestType>(memcpy_one_by_one_kernel);
}
}
/**
* Test Description
* ------------------------
* - RTCs kernels that pass combinations of arguments of invalid types for memcpy
* Test source
* ------------------------
* - unit/device_memory/memcpy.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device_memcpy_Negative_Parameters_RTC") {
hiprtcProgram program{};
const auto program_source = kMemcpyParam;
HIPRTC_CHECK(
hiprtcCreateProgram(&program, program_source, "memcpy_negative.cc", 0, nullptr, nullptr));
hiprtcResult result{hiprtcCompileProgram(program, 0, nullptr)};
// Get the compile log and count compiler error messages
size_t log_size{};
HIPRTC_CHECK(hiprtcGetProgramLogSize(program, &log_size));
std::string log(log_size, ' ');
HIPRTC_CHECK(hiprtcGetProgramLog(program, log.data()));
int error_count{0};
int expected_error_count{4};
std::string error_message{"error:"};
size_t n_pos = log.find(error_message, 0);
while (n_pos != std::string::npos) {
++error_count;
n_pos = log.find(error_message, n_pos + 1);
}
HIPRTC_CHECK(hiprtcDestroyProgram(&program));
HIPRTC_CHECK_ERROR(result, HIPRTC_ERROR_COMPILATION);
REQUIRE(error_count == expected_error_count);
}
@@ -0,0 +1,31 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
struct Dummy {
__device__ Dummy() {}
__device__ ~Dummy() {}
};
/*void* memcpy(void* dst, const void* src, size_t size)*/
__global__ void memcpy_n1(int* dst, const int src, size_t size) { memcpy(dst, src, size); }
__global__ void memcpy_n2(int dst, const int* src, size_t size) { memcpy(dst, src, size); }
__global__ void memcpy_n3(int* dst, const int* src, size_t* size) { memcpy(dst, src, size); }
__global__ void memcpy_n4(int* dst, const int* src, Dummy size) { memcpy(dst, src, size); }
@@ -0,0 +1,32 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
static constexpr auto kMemcpyParam{
R"(
struct Dummy {
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void memcpy_n1(int* dst, const int src, size_t size) { memcpy(dst, src, size); }
__global__ void memcpy_n2(int dst, const int* src, size_t size) { memcpy(dst, src, size); }
__global__ void memcpy_n3(int* dst, const int* src, size_t* size) { memcpy(dst, src, size); }
__global__ void memcpy_n8(int* dst, const int* src, Dummy size) { memcpy(dst, src, size); }
)"};
+172
Ver Arquivo
@@ -0,0 +1,172 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "memset_negative_kernels_rtc.hh"
#include <hip_test_common.hh>
#include <resource_guards.hh>
#include <utils.hh>
#include <hip/hip_cooperative_groups.h>
/**
* @addtogroup memset memset
* @{
* @ingroup DeviceLanguageTest
* `memset(void* ptr, int val, size_t size)` -
* sets device accessible data inside a kernel
*/
template <typename T> using kernel_sig = void (*)(T*, int, const size_t);
template <typename T>
__global__ void memset_at_once_kernel(T* dst, int value, const size_t alloc_size) {
memset(dst, value, alloc_size);
}
template <typename T> __global__ void memset_one_by_one_kernel(T* dst, int value, const size_t N) {
const auto tid = cooperative_groups::this_grid().thread_rank();
const auto stride = cooperative_groups::this_grid().size();
for (auto i = tid; i < N; i += stride) {
memset(dst + tid, value, sizeof(T));
}
}
template <typename T> void MemsetDeviceCommon(kernel_sig<T> memset_kernel) {
const auto allocation_size = GENERATE(kPageSize / 2, kPageSize, kPageSize * 2);
const auto element_count = allocation_size / sizeof(T);
LinearAllocGuard<T> reference(LinearAllocs::hipHostMalloc, allocation_size);
LinearAllocGuard<T> result(LinearAllocs::hipHostMalloc, allocation_size);
LinearAllocGuard<T> dst_allocation(LinearAllocs::hipMalloc, allocation_size);
constexpr auto thread_count = 1024;
const auto block_count = element_count / thread_count + 1;
constexpr auto expected_value = 42;
memset(reference.host_ptr(), expected_value, allocation_size);
if (memset_kernel == &memset_at_once_kernel<T>) {
memset_at_once_kernel<T><<<1, 1>>>(dst_allocation.ptr(), expected_value, allocation_size);
} else {
memset_one_by_one_kernel<T>
<<<thread_count, block_count>>>(dst_allocation.ptr(), expected_value, element_count);
}
HIP_CHECK(
hipMemcpy(result.host_ptr(), dst_allocation.ptr(), allocation_size, hipMemcpyDeviceToHost));
ArrayMismatch(reference.host_ptr(), result.host_ptr(), element_count);
}
template <typename T> void MemsetPinnedCommon(kernel_sig<T> memset_kernel) {
const auto allocation_size = GENERATE(kPageSize / 2, kPageSize, kPageSize * 2);
const auto element_count = allocation_size / sizeof(T);
LinearAllocGuard<T> reference(LinearAllocs::hipHostMalloc, allocation_size);
LinearAllocGuard<T> result(LinearAllocs::hipHostMalloc, allocation_size);
constexpr auto thread_count = 1024;
const auto block_count = element_count / thread_count + 1;
constexpr auto expected_value = 42;
memset(reference.host_ptr(), expected_value, allocation_size);
if (memset_kernel == &memset_at_once_kernel<T>) {
memset_at_once_kernel<T><<<1, 1>>>(result.host_ptr(), expected_value, allocation_size);
} else {
memset_one_by_one_kernel<T>
<<<thread_count, block_count>>>(result.host_ptr(), expected_value, element_count);
}
HIP_CHECK(hipStreamSynchronize(nullptr));
ArrayMismatch(reference.host_ptr(), result.host_ptr(), element_count);
}
template <typename T> void DeviceMemsetCommon(kernel_sig<T> memset_kernel) {
SECTION("Set Device memory") { MemsetDeviceCommon<T>(memset_kernel); }
SECTION("Set Pinned memory") { MemsetPinnedCommon<T>(memset_kernel); }
}
/**
* Test Description
* ------------------------
* - Verifies basic test cases for setting device/pinned memory inside a kernel using various data
* types and memory sizes:
* -# Set whole memory buffer in one thread
* -# Set memory buffer elements one by one in multiple threads/blocks
* Test source
* ------------------------
* - unit/device_memory/memset.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_Device_memset_Positive", "", char, int, unsigned int, long, unsigned long,
long long, unsigned long long, float, double) {
SECTION("Memset whole buffer in one thread") {
DeviceMemsetCommon<TestType>(memset_at_once_kernel);
}
SECTION("Memset buffer in multiple threads/blocks") {
DeviceMemsetCommon<TestType>(memset_one_by_one_kernel);
}
}
/**
* Test Description
* ------------------------
* - RTCs kernels that pass combinations of arguments of invalid types for memset
* Test source
* ------------------------
* - unit/device_memory/memset.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device_memset_Negative_Parameters_RTC") {
hiprtcProgram program{};
const auto program_source = kMemsetParam;
HIPRTC_CHECK(
hiprtcCreateProgram(&program, program_source, "memset_negative.cc", 0, nullptr, nullptr));
hiprtcResult result{hiprtcCompileProgram(program, 0, nullptr)};
// Get the compile log and count compiler error messages
size_t log_size{};
HIPRTC_CHECK(hiprtcGetProgramLogSize(program, &log_size));
std::string log(log_size, ' ');
HIPRTC_CHECK(hiprtcGetProgramLog(program, log.data()));
int error_count{0};
int expected_error_count{4};
std::string error_message{"error:"};
size_t n_pos = log.find(error_message, 0);
while (n_pos != std::string::npos) {
++error_count;
n_pos = log.find(error_message, n_pos + 1);
}
HIPRTC_CHECK(hiprtcDestroyProgram(&program));
HIPRTC_CHECK_ERROR(result, HIPRTC_ERROR_COMPILATION);
REQUIRE(error_count == expected_error_count);
}
@@ -0,0 +1,31 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
struct Dummy {
__device__ Dummy() {}
__device__ ~Dummy() {}
};
/*void* memset(void* ptr, int val, size_t size)*/
__global__ void memset_n1(int* ptr, int* val, size_t size) { memset(ptr, val, size); }
__global__ void memset_n2(int ptr, int val, size_t size) { memset(ptr, val, size); }
__global__ void memset_n3(int* ptr, int val, size_t* size) { memset(ptr, val, size); }
__global__ void memset_n4(int* ptr, int val, Dummy size) { memset(ptr, val, size); }
@@ -0,0 +1,32 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
static constexpr auto kMemsetParam{
R"(
struct Dummy {
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void memset_n1(int* ptr, int* val, size_t size) { memset(ptr, val, size); }
__global__ void memset_n2(int ptr, int val, size_t size) { memset(ptr, val, size); }
__global__ void memset_n3(int* ptr, int val, size_t* size) { memset(ptr, val, size); }
__global__ void memset_n4(int* ptr, int val, Dummy size) { memset(ptr, val, size); }
)"};
@@ -38,7 +38,7 @@ TEST_CASE("Unit_hipGraphicsSubResourceGetMappedArray_Positive_Basic") {
HIP_CHECK(hipGraphicsMapResources(1, &tex_resource, 0));
hipArray* image_devptr = nullptr;
hipArray_t image_devptr = nullptr;
HIP_CHECK(hipGraphicsSubResourceGetMappedArray(&image_devptr, tex_resource, 0, 0));
REQUIRE(image_devptr != nullptr);
@@ -60,7 +60,7 @@ TEST_CASE("Unit_hipGraphicsSubResourceGetMappedArray_Negative_Parameters") {
HIP_CHECK(hipGraphicsMapResources(1, &tex_resource, 0));
hipArray* image_devptr = nullptr;
hipArray_t image_devptr = nullptr;
SECTION("array == nullptr") {
HIP_CHECK(hipGraphicsSubResourceGetMappedArray(nullptr, tex_resource, 0, 0));
+2
Ver Arquivo
@@ -141,6 +141,8 @@ set(TEST_SRC
hipGraphKernelNodeSetAttribute.cc
hipGraphMemAllocNodeGetParams.cc
hipDrvGraphAddMemcpyNode.cc
hipGraphAddMemAllocNode.cc
hipGraphAddMemFreeNode.cc
)
add_custom_target(add_Kernel.code COMMAND ${CMAKE_CXX_COMPILER} --genco ${OFFLOAD_ARCH_STR} ${CMAKE_CURRENT_SOURCE_DIR}/add_Kernel.cpp -o ${CMAKE_CURRENT_BINARY_DIR}/../graph/add_Kernel.code -I${HIP_PATH}/include/ -I${CMAKE_CURRENT_SOURCE_DIR}/../../include --rocm-path=${ROCM_PATH})
+458
Ver Arquivo
@@ -0,0 +1,458 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <resource_guards.hh>
#include <utils.hh>
/**
* @addtogroup hipGraphAddMemAllocNode hipGraphAddMemAllocNode
* @{
* @ingroup GraphTest
* `hipGraphAddMemAllocNode (hipGraphNode_t *pGraphNode, hipGraph_t graph, const hipGraphNode_t
* *pDependencies, size_t numDependencies, hipMemAllocNodeParams *pNodeParams)` -
* Creates a memory allocation node and adds it to a graph.
*/
static constexpr auto element_count{512 * 1024 * 1024};
__global__ void validateGPU(int* const vec, const int value, size_t N, unsigned int* mismatch) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < N) {
if (vec[idx] != value) {
atomicAdd(mismatch, 1);
}
}
}
/**
* Test Description
* ------------------------
* - Test to verify hipGraphAddMemAllocNode behavior with invalid arguments:
* -# Null graph node
* -# Null graph node
* -# Invalid numDependencies for null list of dependencies
* -# Invalid numDependencies and valid list for dependencies
* -# Null alloc params
* -# Invalid poolProps alloc type
* -# Invalid poolProps location type
* -# Invalid poolProps location id
* -# Bytesize is max size_t
* -# Invalid accessDescCount
* Test source
* ------------------------
* - /unit/graph/hipGraphAddMemAllocNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipGraphAddMemAllocNode_Negative_Params") {
constexpr size_t N = 1024;
hipGraph_t graph;
hipGraphNode_t alloc_node;
std::vector<hipGraphNode_t> dependencies;
HIP_CHECK(hipGraphCreate(&graph, 0));
int num_dev = 0;
HIP_CHECK(hipGetDeviceCount(&num_dev));
hipMemAccessDesc desc;
memset(&desc, 0, sizeof(hipMemAccessDesc));
desc.location.type = hipMemLocationTypeDevice;
desc.location.id = 0;
desc.flags = hipMemAccessFlagsProtReadWrite;
hipMemAllocNodeParams alloc_param;
memset(&alloc_param, 0, sizeof(alloc_param));
alloc_param.bytesize = N;
alloc_param.poolProps.allocType = hipMemAllocationTypePinned;
alloc_param.poolProps.location.id = 0;
alloc_param.poolProps.location.type = hipMemLocationTypeDevice;
alloc_param.accessDescs = &desc;
alloc_param.accessDescCount = 1;
SECTION("Passing nullptr to graph node") {
HIP_CHECK_ERROR(hipGraphAddMemAllocNode(nullptr, graph, nullptr, 0, &alloc_param),
hipErrorInvalidValue);
}
SECTION("Passing nullptr to graph") {
HIP_CHECK_ERROR(hipGraphAddMemAllocNode(&alloc_node, nullptr, nullptr, 0, &alloc_param),
hipErrorInvalidValue);
}
SECTION("Pass invalid numDependencies") {
HIP_CHECK_ERROR(hipGraphAddMemAllocNode(&alloc_node, graph, nullptr, 11, &alloc_param),
hipErrorInvalidValue);
}
SECTION("Pass invalid numDependencies and valid list for dependencies") {
HIP_CHECK(hipGraphAddMemAllocNode(&alloc_node, graph, nullptr, 0, &alloc_param));
dependencies.push_back(alloc_node);
HIP_CHECK_ERROR(hipGraphAddMemAllocNode(&alloc_node, graph, dependencies.data(),
dependencies.size() + 1, &alloc_param),
hipErrorInvalidValue);
}
SECTION("Passing nullptr to alloc params") {
HIP_CHECK_ERROR(hipGraphAddMemAllocNode(&alloc_node, graph, nullptr, 0, nullptr),
hipErrorInvalidValue);
}
SECTION("Passing invalid poolProps alloc type") {
alloc_param.poolProps.allocType = hipMemAllocationTypeInvalid;
HIP_CHECK_ERROR(hipGraphAddMemAllocNode(&alloc_node, graph, nullptr, 0, &alloc_param),
hipErrorInvalidValue);
alloc_param.poolProps.allocType = hipMemAllocationTypePinned;
}
SECTION("Passing invalid poolProps location type") {
alloc_param.poolProps.location.type = hipMemLocationTypeInvalid;
HIP_CHECK_ERROR(hipGraphAddMemAllocNode(&alloc_node, graph, nullptr, 0, &alloc_param),
hipErrorInvalidValue);
alloc_param.poolProps.location.type = hipMemLocationTypeDevice;
}
SECTION("Passing invalid poolProps location id") {
alloc_param.poolProps.location.id = num_dev;
HIP_CHECK_ERROR(hipGraphAddMemAllocNode(&alloc_node, graph, nullptr, 0, &alloc_param),
hipErrorInvalidValue);
alloc_param.poolProps.location.id = 0;
}
#if HT_NVIDIA //EXSWHTEC-353
SECTION("Passing max size_t bytesize") {
alloc_param.bytesize = std::numeric_limits<size_t>::max();
HIP_CHECK_ERROR(hipGraphAddMemAllocNode(&alloc_node, graph, nullptr, 0, &alloc_param),
hipErrorOutOfMemory);
alloc_param.bytesize = N;
}
SECTION("Passing invalid accessDescCount") {
alloc_param.accessDescCount = num_dev + 1;
HIP_CHECK_ERROR(hipGraphAddMemAllocNode(&alloc_node, graph, nullptr, 0, &alloc_param),
hipErrorInvalidValue);
alloc_param.accessDescCount = 0;
}
#endif
HIP_CHECK(hipGraphDestroy(graph));
}
/**
* Test Description
* ------------------------
* - Test to verify hipGraphAddMemAllocNode unsupported behavior:
* -# More than one instantiation of the graph exist at the same time
* -# Clone graph with mem alloc node
* -# Use graph with mem alloc node in a child node
* -# Delete edge of the graph with mem alloc node
* Test source
* ------------------------
* - /unit/graph/hipGraphAddMemAllocNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipGraphAddMemAllocNode_Negative_NotSupported") {
constexpr size_t N = 1024;
hipGraph_t graph;
hipGraphNode_t alloc_node;
HIP_CHECK(hipGraphCreate(&graph, 0));
hipMemAllocNodeParams alloc_param;
memset(&alloc_param, 0, sizeof(alloc_param));
alloc_param.bytesize = N;
alloc_param.poolProps.allocType = hipMemAllocationTypePinned;
alloc_param.poolProps.location.id = 0;
alloc_param.poolProps.location.type = hipMemLocationTypeDevice;
HIP_CHECK(hipGraphAddMemAllocNode(&alloc_node, graph, nullptr, 0, &alloc_param));
SECTION("More than one instantation of the graph exists") {
hipGraphExec_t graph_exec1, graph_exec2;
HIP_CHECK(hipGraphInstantiate(&graph_exec1, graph, nullptr, nullptr, 0));
HIP_CHECK_ERROR(hipGraphInstantiate(&graph_exec2, graph, nullptr, nullptr, 0),
hipErrorNotSupported);
HIP_CHECK(hipGraphExecDestroy(graph_exec1));
}
#if HT_NVIDIA //EXSWHTEC-353
SECTION("Clone graph with mem alloc node") {
hipGraph_t cloned_graph;
HIP_CHECK_ERROR(hipGraphClone(&cloned_graph, graph), hipErrorNotSupported);
}
SECTION("Use graph in a child node") {
hipGraph_t parent_graph;
HIP_CHECK(hipGraphCreate(&parent_graph, 0));
hipGraphNode_t child_graph_node;
HIP_CHECK_ERROR(hipGraphAddChildGraphNode(&child_graph_node, parent_graph, nullptr, 0, graph),
hipErrorNotSupported);
HIP_CHECK(hipGraphDestroy(parent_graph));
}
SECTION("Delete edge of the graph") {
hipGraphNode_t empty_node;
HIP_CHECK(hipGraphAddEmptyNode(&empty_node, graph, &alloc_node, 1));
HIP_CHECK_ERROR(hipGraphRemoveDependencies(graph, &alloc_node, &empty_node, 1),
hipErrorNotSupported);
}
#endif
HIP_CHECK(hipGraphDestroy(graph));
}
/* Create graph with memory nodes that copies memset data to host array */
static void createGraph(hipGraphExec_t* graph_exec, int* A_h, int fill_value,
int** device_alloc = nullptr) {
constexpr size_t num_bytes = element_count * sizeof(int);
hipGraph_t graph;
HIP_CHECK(hipGraphCreate(&graph, 0));
hipGraphNode_t alloc_node;
hipMemAllocNodeParams alloc_param;
memset(&alloc_param, 0, sizeof(alloc_param));
alloc_param.bytesize = num_bytes;
alloc_param.poolProps.allocType = hipMemAllocationTypePinned;
alloc_param.poolProps.location.id = 0;
alloc_param.poolProps.location.type = hipMemLocationTypeDevice;
HIP_CHECK(hipGraphAddMemAllocNode(&alloc_node, graph, nullptr, 0, &alloc_param));
REQUIRE(alloc_param.dptr != nullptr);
int* A_d = reinterpret_cast<int*>(alloc_param.dptr);
hipGraphNode_t memset_node;
hipMemsetParams memset_params{};
memset(&memset_params, 0, sizeof(memset_params));
memset_params.dst = reinterpret_cast<void*>(A_d);
memset_params.value = fill_value;
memset_params.pitch = 0;
memset_params.elementSize = sizeof(int);
memset_params.width = element_count;
memset_params.height = 1;
HIP_CHECK(hipGraphAddMemsetNode(&memset_node, graph, &alloc_node, 1, &memset_params));
hipGraphNode_t memcpy_node;
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpy_node, graph, &memset_node, 1, A_h, A_d, num_bytes,
hipMemcpyDeviceToHost));
if (device_alloc == nullptr) {
hipGraphNode_t free_node;
HIP_CHECK(hipGraphAddMemFreeNode(&free_node, graph, &memcpy_node, 1, (void*)A_d));
} else {
*device_alloc = A_d;
}
// Instantiate graph
HIP_CHECK(hipGraphInstantiate(graph_exec, graph, nullptr, nullptr, 0));
HIP_CHECK(hipGraphDestroy(graph));
}
static void createFreeGraph(hipGraphExec_t* graph_exec, int* device_alloc) {
hipGraph_t graph;
hipGraphNode_t free_node;
HIP_CHECK(hipGraphCreate(&graph, 0));
HIP_CHECK(hipGraphAddMemFreeNode(&free_node, graph, nullptr, 0, (void*)device_alloc));
// Instantiate graph
HIP_CHECK(hipGraphInstantiate(graph_exec, graph, nullptr, nullptr, 0));
HIP_CHECK(hipGraphDestroy(graph));
}
/**
* Test Description
* ------------------------
* - Test to verify hipGraphAddMemAllocNode allocates memory correctly and graph behaves as
* expected when free node is added to the same graph.
* Test source
* ------------------------
* - /unit/graph/hipGraphAddMemAllocNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipGraphAddMemAllocNode_Positive_FreeInGraph") {
hipGraphExec_t graph_exec;
LinearAllocGuard<int> host_alloc =
LinearAllocGuard<int>(LinearAllocs::malloc, element_count * sizeof(int));
StreamGuard stream_guard(Streams::created);
hipStream_t stream = stream_guard.stream();
constexpr int fill_value = 11;
createGraph(&graph_exec, host_alloc.ptr(), fill_value);
HIP_CHECK(hipGraphLaunch(graph_exec, stream));
HIP_CHECK(hipStreamSynchronize(stream));
ArrayFindIfNot(host_alloc.host_ptr(), fill_value, element_count);
HIP_CHECK(hipGraphExecDestroy(graph_exec));
}
/**
* Test Description
* ------------------------
* - Test to verify hipGraphAddMemAllocNode allocates memory correctly, graph behaves as expected
* and allocated memory can can be accessed by outside the graph before memory is freed outside the
* stream.
* Test source
* ------------------------
* - /unit/graph/hipGraphAddMemAllocNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipGraphAddMemAllocNode_Positive_FreeOutsideStream") {
hipGraphExec_t graph_exec;
LinearAllocGuard<int> host_alloc(LinearAllocs::malloc, element_count * sizeof(int));
LinearAllocGuard<unsigned int> mismatch_count_h =
LinearAllocGuard<unsigned int>(LinearAllocs::malloc, sizeof(unsigned int));
LinearAllocGuard<unsigned int> mismatch_count_d =
LinearAllocGuard<unsigned int>(LinearAllocs::hipMalloc, sizeof(unsigned int));
HIP_CHECK(hipMemset(mismatch_count_d.ptr(), 0, sizeof(unsigned int)));
int* dev_p;
StreamGuard stream_guard(Streams::created);
hipStream_t stream = stream_guard.stream();
constexpr auto thread_count = 1024;
const auto block_count = element_count / thread_count + 1;
constexpr int fill_value = 12;
createGraph(&graph_exec, host_alloc.ptr(), fill_value, &dev_p);
HIP_CHECK(hipGraphLaunch(graph_exec, stream));
validateGPU<<<block_count, thread_count, 0, stream>>>(dev_p, fill_value, element_count,
mismatch_count_d.ptr());
// Since hipFree is synchronous, the stream must synchronize before freeing dev_p
HIP_CHECK(hipStreamSynchronize(stream));
HIP_CHECK(hipFree(dev_p));
HIP_CHECK(hipMemcpy(mismatch_count_h.host_ptr(), mismatch_count_d.ptr(), sizeof(unsigned int),
hipMemcpyDeviceToHost));
REQUIRE(mismatch_count_h.host_ptr()[0] == 0);
ArrayFindIfNot(host_alloc.host_ptr(), fill_value, element_count);
HIP_CHECK(hipGraphExecDestroy(graph_exec));
}
/**
* Test Description
* ------------------------
* - Test to verify hipGraphAddMemAllocNode allocates memory correctly, graph behaves as expected
* and allocated memory can can be accessed by outside the graph before memory is freed.
* Test source
* ------------------------
* - /unit/graph/hipGraphAddMemAllocNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipGraphAddMemAllocNode_Positive_FreeOutsideGraph") {
hipGraphExec_t graph_exec;
LinearAllocGuard<int> host_alloc(LinearAllocs::malloc, element_count * sizeof(int));
LinearAllocGuard<unsigned int> mismatch_count_h =
LinearAllocGuard<unsigned int>(LinearAllocs::malloc, sizeof(unsigned int));
LinearAllocGuard<unsigned int> mismatch_count_d =
LinearAllocGuard<unsigned int>(LinearAllocs::hipMalloc, sizeof(unsigned int));
HIP_CHECK(hipMemset(mismatch_count_d.ptr(), 0, sizeof(unsigned int)));
int* dev_p;
StreamGuard stream_guard(Streams::created);
hipStream_t stream = stream_guard.stream();
constexpr auto thread_count = 1024;
const auto block_count = element_count / thread_count + 1;
constexpr int fill_value = 13;
createGraph(&graph_exec, host_alloc.ptr(), fill_value, &dev_p);
HIP_CHECK(hipGraphLaunch(graph_exec, stream));
validateGPU<<<block_count, thread_count, 0, stream>>>(dev_p, fill_value, element_count,
mismatch_count_d.ptr());
HIP_CHECK(hipFreeAsync(dev_p, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HIP_CHECK(hipMemcpy(mismatch_count_h.host_ptr(), mismatch_count_d.ptr(), sizeof(unsigned int),
hipMemcpyDeviceToHost));
REQUIRE(mismatch_count_h.host_ptr()[0] == 0);
ArrayFindIfNot(host_alloc.host_ptr(), fill_value, element_count);
HIP_CHECK(hipGraphExecDestroy(graph_exec));
}
/**
* Test Description
* ------------------------
* - Test to verify hipGraphAddMemAllocNode allocates memory correctly, graph behaves as expected
* and allocated memory can can be accessed by outside the graph before memory is freed in a
* different graph.
* Test source
* ------------------------
* - /unit/graph/hipGraphAddMemAllocNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipGraphAddMemAllocNode_Positive_FreeSeparateGraph") {
hipGraphExec_t graph_exec1, graph_exec2;
LinearAllocGuard<int> host_alloc(LinearAllocs::malloc, element_count * sizeof(int));
LinearAllocGuard<unsigned int> mismatch_count_h =
LinearAllocGuard<unsigned int>(LinearAllocs::malloc, sizeof(unsigned int));
LinearAllocGuard<unsigned int> mismatch_count_d =
LinearAllocGuard<unsigned int>(LinearAllocs::hipMalloc, sizeof(unsigned int));
HIP_CHECK(hipMemset(mismatch_count_d.ptr(), 0, sizeof(unsigned int)));
int* dev_p;
StreamGuard stream_guard(Streams::created);
hipStream_t stream = stream_guard.stream();
constexpr auto thread_count = 1024;
const auto block_count = element_count / thread_count + 1;
constexpr int fill_value = 13;
createGraph(&graph_exec1, host_alloc.ptr(), fill_value, &dev_p);
createFreeGraph(&graph_exec2, dev_p);
HIP_CHECK(hipGraphLaunch(graph_exec1, stream));
validateGPU<<<block_count, thread_count, 0, stream>>>(dev_p, fill_value, element_count,
mismatch_count_d.ptr());
HIP_CHECK(hipGraphLaunch(graph_exec2, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HIP_CHECK(hipMemcpy(mismatch_count_h.host_ptr(), mismatch_count_d.ptr(), sizeof(unsigned int),
hipMemcpyDeviceToHost));
REQUIRE(mismatch_count_h.host_ptr()[0] == 0);
ArrayFindIfNot(host_alloc.host_ptr(), fill_value, element_count);
HIP_CHECK(hipGraphExecDestroy(graph_exec1));
HIP_CHECK(hipGraphExecDestroy(graph_exec2));
}
+192
Ver Arquivo
@@ -0,0 +1,192 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <resource_guards.hh>
/**
* @addtogroup hipGraphAddMemFreeNode hipGraphAddMemFreeNode
* @{
* @ingroup GraphTest
* `hipGraphAddMemFreeNode (hipGraphNode_t *pGraphNode, hipGraph_t graph, const hipGraphNode_t
* *pDependencies, size_t numDependencies, void *dev_ptr)` -
* Creates a memory free node and adds it to a graph.
*/
/**
* Test Description
* ------------------------
* - Test to verify hipGraphAddMemFreeNode behavior with invalid arguments:
* -# Null graph node
* -# Null graph
* -# Invalid numDependencies for null list of dependencies
* -# Invalid numDependencies and valid list for dependencies
* -# Null dev_ptr
* -# Invalid dev_ptr address
* -# dev_ptr not allocated with alloc node
* -# Allocation is freed twice in the same graph
* Test source
* ------------------------
* - /unit/graph/hipGraphAddMemFreeNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipGraphAddMemFreeNode_Negative_Params") {
constexpr size_t N = 1024;
hipGraph_t graph;
hipGraphNode_t alloc_node, free_node;
std::vector<hipGraphNode_t> dependencies;
HIP_CHECK(hipGraphCreate(&graph, 0));
hipMemAllocNodeParams alloc_param;
memset(&alloc_param, 0, sizeof(alloc_param));
alloc_param.bytesize = N;
alloc_param.poolProps.allocType = hipMemAllocationTypePinned;
alloc_param.poolProps.location.id = 0;
alloc_param.poolProps.location.type = hipMemLocationTypeDevice;
HIP_CHECK(hipGraphAddMemAllocNode(&alloc_node, graph, nullptr, 0, &alloc_param));
REQUIRE(alloc_param.dptr != nullptr);
int* A_d = reinterpret_cast<int*>(alloc_param.dptr);
SECTION("Passing nullptr to graph node") {
HIP_CHECK_ERROR(hipGraphAddMemFreeNode(nullptr, graph, &alloc_node, 1, (void*)A_d),
hipErrorInvalidValue);
}
SECTION("Passing nullptr to graph") {
HIP_CHECK_ERROR(hipGraphAddMemFreeNode(&free_node, nullptr, &alloc_node, 1, (void*)A_d),
hipErrorInvalidValue);
}
SECTION("Pass invalid numDependencies") {
HIP_CHECK_ERROR(hipGraphAddMemFreeNode(&free_node, graph, nullptr, 5, (void*)A_d),
hipErrorInvalidValue);
}
SECTION("Pass invalid numDependencies and valid list for dependencies") {
dependencies.push_back(alloc_node);
HIP_CHECK_ERROR(hipGraphAddMemFreeNode(&free_node, graph, dependencies.data(),
dependencies.size() + 1, (void*)A_d),
hipErrorInvalidValue);
}
SECTION("Passing nullptr to dev_ptr") {
HIP_CHECK_ERROR(hipGraphAddMemFreeNode(&alloc_node, graph, &alloc_node, 1, nullptr),
hipErrorInvalidValue);
}
SECTION("Passing invalid address to dev_ptr") {
int value;
HIP_CHECK_ERROR(hipGraphAddMemFreeNode(&alloc_node, graph, &alloc_node, 1, &value),
hipErrorInvalidValue);
}
#if HT_NVIDIA // EXSWHTEC-352
SECTION("Passing address not allocated with alloc node to dev_ptr") {
LinearAllocGuard<int> dev_alloc =
LinearAllocGuard<int>(LinearAllocs::hipMalloc, N * sizeof(int));
HIP_CHECK_ERROR(hipGraphAddMemFreeNode(&alloc_node, graph, &alloc_node, 1, dev_alloc.ptr()),
hipErrorInvalidValue);
}
SECTION("Free allocation twice in the same graph") {
HIP_CHECK(hipGraphAddMemFreeNode(&alloc_node, graph, &alloc_node, 1, (void*)A_d));
HIP_CHECK_ERROR(hipGraphAddMemFreeNode(&alloc_node, graph, &alloc_node, 1, (void*)A_d),
hipErrorInvalidValue);
}
#endif
HIP_CHECK(hipGraphDestroy(graph));
}
/**
* Test Description
* ------------------------
* - Test to verify hipGraphAddMemFreeNode unsupported behavior:
* -# More than one instantiation of the graph exist at the same time
* -# Clone graph with mem free node
* -# Use graph with mem free node in a child node
* -# Delete edge of the graph with mem free node
* Test source
* ------------------------
* - /unit/graph/hipGraphAddMemFreeNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipGraphAddMemFreeNode_Negative_NotSupported") {
constexpr size_t N = 1024;
hipGraph_t graph1, graph2;
hipGraphNode_t alloc_node, free_node;
HIP_CHECK(hipGraphCreate(&graph1, 0));
HIP_CHECK(hipGraphCreate(&graph2, 0));
hipMemAllocNodeParams alloc_param;
memset(&alloc_param, 0, sizeof(alloc_param));
alloc_param.bytesize = N;
alloc_param.poolProps.allocType = hipMemAllocationTypePinned;
alloc_param.poolProps.location.id = 0;
alloc_param.poolProps.location.type = hipMemLocationTypeDevice;
HIP_CHECK(hipGraphAddMemAllocNode(&alloc_node, graph1, nullptr, 0, &alloc_param));
REQUIRE(alloc_param.dptr != nullptr);
int* A_d = reinterpret_cast<int*>(alloc_param.dptr);
HIP_CHECK(hipGraphAddMemFreeNode(&free_node, graph2, nullptr, 0, (void*)A_d));
SECTION("More than one instantation of the graph exists") {
hipGraphExec_t graph_exec1, graph_exec2;
HIP_CHECK(hipGraphInstantiate(&graph_exec1, graph2, nullptr, nullptr, 0));
HIP_CHECK_ERROR(hipGraphInstantiate(&graph_exec2, graph2, nullptr, nullptr, 0),
hipErrorNotSupported);
HIP_CHECK(hipGraphExecDestroy(graph_exec1));
}
#if HT_NVIDIA // EXSWHTEC-352
SECTION("Clone graph with mem free node") {
hipGraph_t cloned_graph;
HIP_CHECK_ERROR(hipGraphClone(&cloned_graph, graph2), hipErrorNotSupported);
}
SECTION("Use graph in a child node") {
hipGraph_t parent_graph;
HIP_CHECK(hipGraphCreate(&parent_graph, 0));
hipGraphNode_t child_graph_node;
HIP_CHECK_ERROR(hipGraphAddChildGraphNode(&child_graph_node, parent_graph, nullptr, 0, graph2),
hipErrorNotSupported);
HIP_CHECK(hipGraphDestroy(parent_graph));
}
SECTION("Delete edge of the graph") {
hipGraphNode_t empty_node;
HIP_CHECK(hipGraphAddEmptyNode(&empty_node, graph2, &free_node, 1));
HIP_CHECK_ERROR(hipGraphRemoveDependencies(graph2, &free_node, &empty_node, 1),
hipErrorNotSupported);
}
#endif
HIP_CHECK(hipGraphDestroy(graph1));
HIP_CHECK(hipGraphDestroy(graph2));
}
+193 -122
Ver Arquivo
@@ -18,47 +18,44 @@ THE SOFTWARE.
*/
/**
* @addtogroup hipGraphMemAllocNodeGetParams hipGraphMemAllocNodeGetParams
* @{
* @ingroup GraphTest
* `hipGraphMemAllocNodeGetParams(hipGraphNode_t node, hipMemAllocNodeParams* params_out)`
* Returns a memory alloc node's parameters.
* `hipGraphMemFreeNodeGetParams(hipGraphNode_t node, void* dptr_out)` -
* Returns a memory free node's parameters.
*/
* @addtogroup hipGraphMemAllocNodeGetParams hipGraphMemAllocNodeGetParams
* @{
* @ingroup GraphTest
* `hipGraphMemAllocNodeGetParams(hipGraphNode_t node, hipMemAllocNodeParams* params_out)`
* Returns a memory alloc node's parameters.
* `hipGraphMemFreeNodeGetParams(hipGraphNode_t node, void* dptr_out)` -
* Returns a memory free node's parameters.
*/
#include <hip_test_common.hh>
#include <hip_test_checkers.hh>
#include <hip_test_kernels.hh>
#include <resource_guards.hh>
#include <utils.hh>
/**
* Test Description
* ------------------------
*  - Functional Test for API - hipGraphMemAllocNodeGetParams
* Create a graph and add a node with hipGraphAddMemAllocNode
* and hipGraphAddMemFreeNode and launch it.
* 1) Get alloc node by calling hipGraphMemAllocNodeGetParams and Validate.
* 2) Get Free Node ptr by calling hipGraphMemFreeNodeGetParams and Validate.
* 3) Check for multiple devices case.
* 4) Allocate multiple alloc node and validate by calling its get param.
* Test source
* ------------------------
*  - /unit/graph/hipGraphMemAllocNodeGetParams.cc
* Test requirements
* ------------------------
*  - HIP_VERSION >= 6.0
*/
* Test Description
* ------------------------
*  - Functional Test for API - hipGraphMemAllocNodeGetParams
* Create a graph and add a node with hipGraphAddMemAllocNode
* and hipGraphAddMemFreeNode and launch it.
* 1) Get alloc node by calling hipGraphMemAllocNodeGetParams and Validate.
* 2) Get Free Node ptr by calling hipGraphMemFreeNodeGetParams and Validate.
* 3) Check for multiple devices case.
* 4) Allocate multiple alloc node and validate by calling its get param.
* Test source
* ------------------------
*  - /unit/graph/hipGraphMemAllocNodeGetParams.cc
* Test requirements
* ------------------------
*  - HIP_VERSION >= 6.0
*/
static bool validateAllocParam(hipMemAllocNodeParams in,
hipMemAllocNodeParams out) {
if (in.bytesize != out.bytesize)
return false;
if (in.poolProps.allocType != out.poolProps.allocType)
return false;
if (in.poolProps.location.id != out.poolProps.location.id)
return false;
if (in.poolProps.location.type != out.poolProps.location.type)
return false;
static bool validateAllocParam(hipMemAllocNodeParams in, hipMemAllocNodeParams out) {
if (in.bytesize != out.bytesize) return false;
if (in.poolProps.allocType != out.poolProps.allocType) return false;
if (in.poolProps.location.id != out.poolProps.location.id) return false;
if (in.poolProps.location.type != out.poolProps.location.type) return false;
return true;
}
@@ -85,7 +82,7 @@ static void hipGraphMemAllocNodeGetParams_Functional(unsigned deviceId = 0) {
params_in.poolProps.location.type = hipMemLocationTypeDevice;
HIP_CHECK(hipGraphAddMemAllocNode(&allocNodeA, graph, NULL, 0, &params_in));
int *A_d = reinterpret_cast<int *>(params_in.dptr);
int* A_d = reinterpret_cast<int*>(params_in.dptr);
REQUIRE(A_d != nullptr);
HIP_CHECK(hipGraphAddMemFreeNode(&freeNodeA, graph, &allocNodeA, 1, A_d));
@@ -105,21 +102,21 @@ static void hipGraphMemAllocNodeGetParams_Functional(unsigned deviceId = 0) {
}
/**
* Test Description
* ------------------------
*  - Functional Test for API - hipGraphMemAllocNodeGetParams
* Create a graph and add a node with hipGraphAddMemAllocNode
* and hipGraphAddMemFreeNode and launch it.
* 1) Get alloc node by calling hipGraphMemAllocNodeGetParams and Validate it.
* 2) Get Free node ptr by calling hipGraphMemFreeNodeGetParams and Validate it.
* 3) Check for multiple devices case.
* Test source
* ------------------------
*  - /unit/graph/hipGraphMemAllocNodeGetParams.cc
* Test requirements
* ------------------------
*  - HIP_VERSION >= 6.0
*/
* Test Description
* ------------------------
*  - Functional Test for API - hipGraphMemAllocNodeGetParams
* Create a graph and add a node with hipGraphAddMemAllocNode
* and hipGraphAddMemFreeNode and launch it.
* 1) Get alloc node by calling hipGraphMemAllocNodeGetParams and Validate it.
* 2) Get Free node ptr by calling hipGraphMemFreeNodeGetParams and Validate it.
* 3) Check for multiple devices case.
* Test source
* ------------------------
*  - /unit/graph/hipGraphMemAllocNodeGetParams.cc
* Test requirements
* ------------------------
*  - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Functional") {
hipGraphMemAllocNodeGetParams_Functional();
@@ -130,7 +127,7 @@ TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Functional_MultiDevice") {
HIP_CHECK(hipGetDeviceCount(&numDevices));
if (numDevices > 0) {
for ( int i = 0; i < numDevices; ++i ) {
for (int i = 0; i < numDevices; ++i) {
hipGraphMemAllocNodeGetParams_Functional(i);
}
} else {
@@ -139,19 +136,19 @@ TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Functional_MultiDevice") {
}
/**
* Test Description
* ------------------------
*  - Functional Test for API - hipGraphMemAllocNodeGetParams
* Create a graph and add multiple node with hipGraphAddMemAllocNode
* and hipGraphAddMemFreeNode and launch it.
* 1) Allocate multiple alloc node and validate by calling its get param.
* Test source
* ------------------------
*  - /unit/graph/hipGraphMemAllocNodeGetParams.cc
* Test requirements
* ------------------------
*  - HIP_VERSION >= 6.0
*/
* Test Description
* ------------------------
*  - Functional Test for API - hipGraphMemAllocNodeGetParams
* Create a graph and add multiple node with hipGraphAddMemAllocNode
* and hipGraphAddMemFreeNode and launch it.
* 1) Allocate multiple alloc node and validate by calling its get param.
* Test source
* ------------------------
*  - /unit/graph/hipGraphMemAllocNodeGetParams.cc
* Test requirements
* ------------------------
*  - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Functional_2") {
constexpr size_t N = 1024 * 1024;
@@ -173,8 +170,7 @@ TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Functional_2") {
int *A_d, *B_d, *C_d;
int *A_h, *B_h, *C_h;
HipTest::initArrays<int>(nullptr, nullptr, nullptr,
&A_h, &B_h, &C_h, N, false);
HipTest::initArrays<int>(nullptr, nullptr, nullptr, &A_h, &B_h, &C_h, N, false);
HIP_CHECK(hipGraphCreate(&graph, 0));
HIP_CHECK(hipStreamCreate(&stream));
@@ -187,49 +183,46 @@ TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Functional_2") {
HIP_CHECK(hipGraphAddMemAllocNode(&allocNodeA, graph, NULL, 0, &params_in));
REQUIRE(params_in.dptr != nullptr);
A_d = reinterpret_cast<int *>(params_in.dptr);
HIP_CHECK(hipGraphAddMemAllocNode(&allocNodeB, graph,
&allocNodeA, 1, &params_in));
A_d = reinterpret_cast<int*>(params_in.dptr);
HIP_CHECK(hipGraphAddMemAllocNode(&allocNodeB, graph, &allocNodeA, 1, &params_in));
REQUIRE(params_in.dptr != nullptr);
B_d = reinterpret_cast<int *>(params_in.dptr);
HIP_CHECK(hipGraphAddMemAllocNode(&allocNodeC, graph,
&allocNodeB, 1, &params_in));
B_d = reinterpret_cast<int*>(params_in.dptr);
HIP_CHECK(hipGraphAddMemAllocNode(&allocNodeC, graph, &allocNodeB, 1, &params_in));
REQUIRE(params_in.dptr != nullptr);
C_d = reinterpret_cast<int *>(params_in.dptr);
C_d = reinterpret_cast<int*>(params_in.dptr);
// Check shows that A_d, B_d & C_d DON'T share any virtual address each other
REQUIRE(A_d != B_d);
REQUIRE(B_d != C_d);
REQUIRE(A_d != C_d);
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, &allocNodeC, 1, A_d,
A_h, Nbytes, hipMemcpyHostToDevice));
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_B, graph, &allocNodeC, 1, B_d,
B_h, Nbytes, hipMemcpyHostToDevice));
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, &allocNodeC, 1, A_d, A_h, Nbytes,
hipMemcpyHostToDevice));
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_B, graph, &allocNodeC, 1, B_d, B_h, Nbytes,
hipMemcpyHostToDevice));
void* kernelArgs[] = {&A_d, &B_d, &C_d, reinterpret_cast<void *>(&NElem)};
kernelNodeParams.func = reinterpret_cast<void *>(HipTest::vectorADD<int>);
void* kernelArgs[] = {&A_d, &B_d, &C_d, reinterpret_cast<void*>(&NElem)};
kernelNodeParams.func = reinterpret_cast<void*>(HipTest::vectorADD<int>);
kernelNodeParams.gridDim = dim3(blocks);
kernelNodeParams.blockDim = dim3(threadsPerBlock);
kernelNodeParams.sharedMemBytes = 0;
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgs);
kernelNodeParams.extra = nullptr;
HIP_CHECK(hipGraphAddKernelNode(&kernel_vecAdd, graph, nullptr, 0,
&kernelNodeParams));
HIP_CHECK(hipGraphAddKernelNode(&kernel_vecAdd, graph, nullptr, 0, &kernelNodeParams));
// Create dependencies
HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, &kernel_vecAdd, 1));
HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_B, &kernel_vecAdd, 1));
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_C, graph, &kernel_vecAdd, 1,
C_h, C_d, Nbytes, hipMemcpyDeviceToHost));
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_C, graph, &kernel_vecAdd, 1, C_h, C_d, Nbytes,
hipMemcpyDeviceToHost));
HIP_CHECK(hipGraphAddMemFreeNode(&freeNodeA, graph, &memcpyD2H_C,
1, reinterpret_cast<void *>(A_d)));
HIP_CHECK(hipGraphAddMemFreeNode(&freeNodeB, graph, &memcpyD2H_C,
1, reinterpret_cast<void *>(B_d)));
HIP_CHECK(hipGraphAddMemFreeNode(&freeNodeC, graph, &memcpyD2H_C,
1, reinterpret_cast<void *>(C_d)));
HIP_CHECK(
hipGraphAddMemFreeNode(&freeNodeA, graph, &memcpyD2H_C, 1, reinterpret_cast<void*>(A_d)));
HIP_CHECK(
hipGraphAddMemFreeNode(&freeNodeB, graph, &memcpyD2H_C, 1, reinterpret_cast<void*>(B_d)));
HIP_CHECK(
hipGraphAddMemFreeNode(&freeNodeC, graph, &memcpyD2H_C, 1, reinterpret_cast<void*>(C_d)));
HIP_CHECK(hipGraphMemAllocNodeGetParams(allocNodeA, &params_out));
REQUIRE(true == validateAllocParam(params_in, params_out));
@@ -239,12 +232,9 @@ TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Functional_2") {
REQUIRE(true == validateAllocParam(params_in, params_out));
int temp[] = {0};
HIP_CHECK(hipGraphMemFreeNodeGetParams(freeNodeA,
reinterpret_cast<void *>(temp)));
HIP_CHECK(hipGraphMemFreeNodeGetParams(freeNodeB,
reinterpret_cast<void *>(temp)));
HIP_CHECK(hipGraphMemFreeNodeGetParams(freeNodeC,
reinterpret_cast<void *>(temp)));
HIP_CHECK(hipGraphMemFreeNodeGetParams(freeNodeA, reinterpret_cast<void*>(temp)));
HIP_CHECK(hipGraphMemFreeNodeGetParams(freeNodeB, reinterpret_cast<void*>(temp)));
HIP_CHECK(hipGraphMemFreeNodeGetParams(freeNodeC, reinterpret_cast<void*>(temp)));
HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0));
HIP_CHECK(hipGraphLaunch(graphExec, stream));
@@ -261,27 +251,111 @@ TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Functional_2") {
}
/**
* Test Description
* ------------------------
*  - Negative Test for API - hipGraphMemAllocNodeGetParams
* 1) Pass MemAllocNode as nullptr
* 2) Pass MemAllocNode as empty node
* 3) Pass params_out as nullptr
* 4) Pass MemFreeNode inplace of MemAllocNode in 1st arguments
* - Negative Test for API - hipGraphMemFreeNodeGetParams
* 1) Pass MemFreeNode as nullptr
* 2) Pass MemFreeNode as empty node
* 3) Pass free pointer as nullptr
* 4) Pass free pointer as invalid pointer
* 5) Pass MemAllocNode inplace of MemFreeNode in 1st arguments
* Test source
* ------------------------
*  - /unit/graph/hipGraphMemAllocNodeGetParams.cc
* Test requirements
* ------------------------
*  - HIP_VERSION >= 6.0
*/
* Test Description
* ------------------------
* - Functional Test for API - hipGraphMemAllocNodeGetParams. Create a graph and add a node with
* hipGraphAddMemAllocNode and hipGraphAddMemFreeNode and launch it. Check both pool props and
* access descriptor.
* Test source
* ------------------------
* - /unit/graph/hipGraphMemAllocNodeGetParams.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Functional_3") {
constexpr auto element_count{512 * 1024 * 1024};
constexpr size_t num_bytes = element_count * sizeof(int);
hipGraphExec_t graph_exec;
hipGraph_t graph;
LinearAllocGuard<int> A_h =
LinearAllocGuard<int>(LinearAllocs::malloc, element_count * sizeof(int));
StreamGuard stream_guard(Streams::created);
hipStream_t stream = stream_guard.stream();
HIP_CHECK(hipGraphCreate(&graph, 0));
hipMemAccessDesc desc;
memset(&desc, 0, sizeof(hipMemAccessDesc));
desc.location.type = hipMemLocationTypeDevice;
desc.location.id = 0;
desc.flags = hipMemAccessFlagsProtReadWrite;
hipGraphNode_t alloc_node;
hipMemAllocNodeParams alloc_param;
memset(&alloc_param, 0, sizeof(alloc_param));
alloc_param.bytesize = num_bytes;
alloc_param.poolProps.allocType = hipMemAllocationTypePinned;
alloc_param.poolProps.location.id = 0;
alloc_param.poolProps.location.type = hipMemLocationTypeDevice;
alloc_param.accessDescs = &desc;
alloc_param.accessDescCount = 1;
HIP_CHECK(hipGraphAddMemAllocNode(&alloc_node, graph, nullptr, 0, &alloc_param));
REQUIRE(alloc_param.dptr != nullptr);
int* A_d = reinterpret_cast<int*>(alloc_param.dptr);
hipMemAllocNodeParams get_alloc_params;
HIP_CHECK(hipGraphMemAllocNodeGetParams(alloc_node, &get_alloc_params));
REQUIRE(memcmp(&alloc_param, &get_alloc_params, sizeof(hipMemAllocNodeParams)) == 0);
constexpr int fill_value = 11;
hipGraphNode_t memset_node;
hipMemsetParams memset_params{};
memset(&memset_params, 0, sizeof(memset_params));
memset_params.dst = reinterpret_cast<void*>(A_d);
memset_params.value = fill_value;
memset_params.pitch = 0;
memset_params.elementSize = sizeof(int);
memset_params.width = element_count;
memset_params.height = 1;
HIP_CHECK(hipGraphAddMemsetNode(&memset_node, graph, &alloc_node, 1, &memset_params));
hipGraphNode_t memcpy_node;
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpy_node, graph, &memset_node, 1, A_h.host_ptr(), A_d,
num_bytes, hipMemcpyDeviceToHost));
hipGraphNode_t free_node;
HIP_CHECK(hipGraphAddMemFreeNode(&free_node, graph, &memcpy_node, 1, (void*)A_d));
void* dptr_out;
HIP_CHECK(hipGraphMemFreeNodeGetParams(free_node, &dptr_out));
REQUIRE(A_d == static_cast<int*>(dptr_out));
// Instantiate graph
HIP_CHECK(hipGraphInstantiate(&graph_exec, graph, nullptr, nullptr, 0));
HIP_CHECK(hipGraphLaunch(graph_exec, stream));
HIP_CHECK(hipStreamSynchronize(stream));
ArrayFindIfNot(A_h.host_ptr(), fill_value, element_count);
HIP_CHECK(hipGraphExecDestroy(graph_exec));
HIP_CHECK(hipGraphDestroy(graph));
}
/**
* Test Description
* ------------------------
*  - Negative Test for API - hipGraphMemAllocNodeGetParams
* 1) Pass MemAllocNode as nullptr
* 2) Pass MemAllocNode as empty node
* 3) Pass params_out as nullptr
* 4) Pass MemFreeNode inplace of MemAllocNode in 1st arguments
* - Negative Test for API - hipGraphMemFreeNodeGetParams
* 1) Pass MemFreeNode as nullptr
* 2) Pass MemFreeNode as empty node
* 3) Pass free pointer as nullptr
* 4) Pass free pointer as invalid pointer
* 5) Pass MemAllocNode inplace of MemFreeNode in 1st arguments
* Test source
* ------------------------
*  - /unit/graph/hipGraphMemAllocNodeGetParams.cc
* Test requirements
* ------------------------
*  - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Negative") {
hipError_t ret;
constexpr size_t N = 1024 * 1024;
@@ -303,7 +377,7 @@ TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Negative") {
params_in.poolProps.location.type = hipMemLocationTypeDevice;
HIP_CHECK(hipGraphAddMemAllocNode(&allocNodeA, graph, NULL, 0, &params_in));
int *A_d = reinterpret_cast<int *>(params_in.dptr);
int* A_d = reinterpret_cast<int*>(params_in.dptr);
REQUIRE(A_d != nullptr);
HIP_CHECK(hipGraphAddMemFreeNode(&freeNodeA, graph, &allocNodeA, 1, A_d));
@@ -328,14 +402,12 @@ TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Negative") {
int temp[] = {0};
SECTION("Pass MemFreeNode as nullptr") {
ret = hipGraphMemFreeNodeGetParams(nullptr,
reinterpret_cast<void *>(temp));
ret = hipGraphMemFreeNodeGetParams(nullptr, reinterpret_cast<void*>(temp));
REQUIRE(hipErrorInvalidValue == ret);
}
SECTION("Pass MemFreeNode as empty node") {
hipGraphNode_t freeNode_empty{};
ret = hipGraphMemFreeNodeGetParams(freeNode_empty,
reinterpret_cast<void *>(temp));
ret = hipGraphMemFreeNodeGetParams(freeNode_empty, reinterpret_cast<void*>(temp));
REQUIRE(hipErrorInvalidValue == ret);
}
SECTION("Pass free pointer as nullptr") {
@@ -343,8 +415,7 @@ TEST_CASE("Unit_hipGraphMem_Alloc_Free_NodeGetParams_Negative") {
REQUIRE(hipErrorInvalidValue == ret);
}
SECTION("Pass MemAllocNode inplace of MemFreeNode in 1st arguments") {
ret = hipGraphMemFreeNodeGetParams(allocNodeA,
reinterpret_cast<void *>(temp));
ret = hipGraphMemFreeNodeGetParams(allocNodeA, reinterpret_cast<void*>(temp));
REQUIRE(hipErrorInvalidValue == ret);
}
+37
Ver Arquivo
@@ -0,0 +1,37 @@
# Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Common Tests - Test independent of all platforms
set(TEST_SRC
hip_hc_8pk.cc
)
hip_add_exe_to_target(NAME HipSpecificTest
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests
LINKER_LIBS hiprtc
PROPERTY CXX_STANDARD 17)
# This test fails in PSDB
#add_test(NAME Unit_Device__hip_hc_8pk_Negative
# COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/../compileAndCaptureOutput.py
# ${CMAKE_CURRENT_SOURCE_DIR} ${HIP_PLATFORM} ${HIP_PATH}
# hip_hc_8pk_negative_kernels.cc 90)
+172
Ver Arquivo
@@ -0,0 +1,172 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "hip_hc_8pk_negative_kernels_rtc.hh"
#include <hip_test_common.hh>
#include <resource_guards.hh>
/**
* @addtogroup hip_hc_8pk hip_hc_8pk
* @{
* @ingroup DeviceLanguageTest
*/
__global__ void __hip_hc_add8pk_kernel(char4* out, char4 in1, char4 in2) {
out[0] = __hip_hc_add8pk(in1, in2);
}
/**
* Test Description
* ------------------------
* - Sanity test for `__hip_hc_add8pk(in1, in2)`.
*
* Test source
* ------------------------
* - unit/hip_specific/hip_hc_8pk.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device__hip_hc_add8pk_Sanity_Positive") {
const char input1[] = {-0x70, -0x50, -0x30, -0x0f, 0x0, 0x01, 0x10, 0x20, 0x70, 0x7f};
const char input2[] = {-0x05, -0x11, -0x20, -0x03, 0x0, 0x30, 0x05, 0x33, 0x0f, 0x7a};
const char reference[] = {-0x75, -0x61, -0x50, -0x12, 0x0, 0x31, 0x15, 0x53, 0x7f, -0x07};
LinearAllocGuard<char4> out(LinearAllocs::hipMallocManaged, sizeof(char4));
for (int i = 0; i < 10; ++i) {
__hip_hc_add8pk_kernel<<<1, 1>>>(out.ptr(), make_char4(0, 0, 0, input1[i]),
make_char4(0, 0, 0, input2[i]));
HIP_CHECK(hipDeviceSynchronize());
REQUIRE(out.ptr()[0].x == 0);
REQUIRE(out.ptr()[0].y == 0);
REQUIRE(out.ptr()[0].z == 0);
REQUIRE(out.ptr()[0].w == reference[i]);
}
}
__global__ void __hip_hc_sub8pk_kernel(char4* out, char4 in1, char4 in2) {
out[0] = __hip_hc_sub8pk(in1, in2);
}
/**
* Test Description
* ------------------------
* - Sanity test for `__hip_hc_sub8pk(in1, in2)`.
*
* Test source
* ------------------------
* - unit/hip_specific/hip_hc_8pk.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device__hip_hc_sub8pk_Sanity_Positive") {
const char input1[] = {-0x70, -0x50, -0x30, -0x0f, 0x0, 0x30, 0x10, 0x33, 0x70, 0x7a};
const char input2[] = {-0x05, -0x11, -0x20, -0x03, 0x0, 0x01, 0x05, 0x20, 0x0f, 0x7f};
const char reference[] = {-0x6b, -0x3f, -0x10, -0x0c, 0x0, 0x2f, 0x0b, 0x13, 0x61, -0x05};
LinearAllocGuard<char4> out(LinearAllocs::hipMallocManaged, sizeof(char4));
for (int i = 0; i < 10; ++i) {
__hip_hc_sub8pk_kernel<<<1, 1>>>(out.ptr(), make_char4(0, 0, 0, input1[i]),
make_char4(0, 0, 0, input2[i]));
HIP_CHECK(hipDeviceSynchronize());
REQUIRE(out.ptr()[0].x == 0);
REQUIRE(out.ptr()[0].y == 0);
REQUIRE(out.ptr()[0].z == 0);
REQUIRE(out.ptr()[0].w == reference[i]);
}
}
__global__ void __hip_hc_mul8pk_kernel(char4* out, char4 in1, char4 in2) {
out[0] = __hip_hc_mul8pk(in1, in2);
}
/**
* Test Description
* ------------------------
* - Sanity test for `__hip_hc_mul8pk(in1, in2)`.
*
* Test source
* ------------------------
* - unit/hip_specific/hip_hc_8pk.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device__hip_hc_mul8pk_Sanity_Positive") {
const char input1[] = {-0x70, -0x50, -0x30, -0x0f, 0x0, 0x01, 0x10, 0x20, 0x70, 0x7f};
const char input2[] = {0x05, -0x11, 0x22, -0x03, 0x0, 0x30, 0x05, 0x33, 0x0f, 0x7a};
const char reference[] = {-0x30, 0x50, -0x60, 0x2d, 0x0, 0x30, 0x50, 0x60, -0x70, -0x7a};
LinearAllocGuard<char4> out(LinearAllocs::hipMallocManaged, sizeof(char4));
for (int i = 0; i < 10; ++i) {
__hip_hc_mul8pk_kernel<<<1, 1>>>(out.ptr(), make_char4(0, 0, 0, input1[i]),
make_char4(0, 0, 0, input2[i]));
HIP_CHECK(hipDeviceSynchronize());
REQUIRE(out.ptr()[0].x == 0);
REQUIRE(out.ptr()[0].y == 0);
REQUIRE(out.ptr()[0].z == 0);
REQUIRE(out.ptr()[0].w == reference[i]);
}
}
/**
* Test Description
* ------------------------
* - RTCs kernels that pass combinations of arguments of invalid types for
* __hip_hc_<add/sub/mul>8pk
* Test source
* ------------------------
* - unit/hip_specific/hip_hc_8pk.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Device__hip_hc_8pk_Negative_Parameters_RTC") {
hiprtcProgram program{};
const auto program_source = GENERATE(kHipHcAdd8pkBasic, kHipHcAdd8pkVector, kHipHcSub8pkBasic,
kHipHcSub8pkVector, kHipHcMul8pkBasic, kHipHcMul8pkVector);
HIPRTC_CHECK(
hiprtcCreateProgram(&program, program_source, "hip_hc_8pk_negative.cc", 0, nullptr, nullptr));
hiprtcResult result{hiprtcCompileProgram(program, 0, nullptr)};
// Get the compile log and count compiler error messages
size_t log_size{};
HIPRTC_CHECK(hiprtcGetProgramLogSize(program, &log_size));
std::string log(log_size, ' ');
HIPRTC_CHECK(hiprtcGetProgramLog(program, log.data()));
int error_count{0};
int expected_error_count{15};
std::string error_message{"error:"};
size_t n_pos = log.find(error_message, 0);
while (n_pos != std::string::npos) {
++error_count;
n_pos = log.find(error_message, n_pos + 1);
}
HIPRTC_CHECK(hiprtcDestroyProgram(&program));
HIPRTC_CHECK_ERROR(result, HIPRTC_ERROR_COMPILATION);
REQUIRE(error_count == expected_error_count);
}
@@ -0,0 +1,121 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
struct Dummy {
__device__ Dummy() {}
__device__ ~Dummy() {}
};
#define NEGATIVE_KERNELS_SHELL(func_name) \
__global__ void func_name##_char_n1(char4* out, char in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_char_n2(char4* out, char4 in1, char in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_char_n3(char* out, char4 in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_int_n1(char4* out, int in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_int_n2(char4* out, char4 in1, int in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_int_n3(int* out, char4 in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_long_n1(char4* out, long in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_long_n2(char4* out, char4 in1, long in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_long_n3(long* out, char4 in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_float_n1(char4* out, float in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_float_n2(char4* out, char4 in1, float in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_float_n3(float* out, char4 in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_char4_n1(char4* out, char4 in1, char4 in2) { \
out = func_name(in1, in2); \
} \
__global__ void func_name##_char4_n2(char4* out, char4 in1, char4 in2) { \
*out = func_name(&in1, in2); \
} \
__global__ void func_name##_char4_n3(char4* out, char4 in1, char4 in2) { \
*out = func_name(in1, &in2); \
} \
__global__ void func_name##_char2_n1(char4* out, char2 in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_char2_n2(char4* out, char4 in1, char2 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_char2_n3(char2* out, char4 in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_int4_n1(char4* out, int4 in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_int4_n2(char4* out, char4 in1, int4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_int4_n3(int4* out, char4 in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_long4_n1(char4* out, long4 in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_long4_n2(char4* out, char4 in1, long4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_long4_n3(long4* out, char4 in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_float4_n1(char4* out, float4 in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_float4_n2(char4* out, char4 in1, float4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_float4_n3(float4* out, char4 in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_dummy_n1(char4* out, Dummy in1, char4 in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_dummy_n2(char4* out, char4 in1, Dummy in2) { \
*out = func_name(in1, in2); \
} \
__global__ void func_name##_dummy_n3(Dummy* out, char4 in1, char4 in2) { \
*out = func_name(in1, in2); \
}
NEGATIVE_KERNELS_SHELL(__hip_hc_add8pk)
NEGATIVE_KERNELS_SHELL(__hip_hc_sub8pk)
NEGATIVE_KERNELS_SHELL(__hip_hc_mul8pk)
@@ -0,0 +1,149 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
static constexpr auto kHipHcAdd8pkBasic{
R"(
struct Dummy {
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hip_hc_add8pk_char_n1(char4* out, char in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_char_n2(char4* out, char4 in1, char in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_char_n3(char* out, char4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_int_n1(char4* out, int in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_int_n2(char4* out, char4 in1, int in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_int_n3(int* out, char4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_long_n1(char4* out, long in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_long_n2(char4* out, char4 in1, long in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_long_n3(long* out, char4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_float_n1(char4* out, float in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_float_n2(char4* out, char4 in1, float in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_float_n3(float* out, char4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_dummy_n1(char4* out, Dummy in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_dummy_n2(char4* out, char4 in1, Dummy in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_dummy_n3(Dummy* out, char4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
)"};
static constexpr auto kHipHcAdd8pkVector{
R"(
__global__ void hip_hc_add8pk_char4_n1(char4* out, char4 in1, char4 in2) { out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_char4_n2(char4* out, char4 in1, char4 in2) { *out = __hip_hc_add8pk(&in1, in2); }
__global__ void hip_hc_add8pk_char4_n3(char4* out, char4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, &in2); }
__global__ void hip_hc_add8pk_char2_n1(char4* out, char2 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_char2_n2(char4* out, char4 in1, char2 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_char2_n3(char2* out, char4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_int4_n1(char4* out, int4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_int4_n2(char4* out, char4 in1, int4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_int4_n3(int4* out, char4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_long4_n1(char4* out, long4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_long4_n2(char4* out, char4 in1, long4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_long4_n3(long4* out, char4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_float4_n1(char4* out, float4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_float4_n2(char4* out, char4 in1, float4 in2) { *out = __hip_hc_add8pk(in1, in2); }
__global__ void hip_hc_add8pk_float4_n3(float4* out, char4 in1, char4 in2) { *out = __hip_hc_add8pk(in1, in2); }
)"};
static constexpr auto kHipHcSub8pkBasic{
R"(
struct Dummy {
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hip_hc_sub8pk_char_n1(char4* out, char in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_char_n2(char4* out, char4 in1, char in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_char_n3(char* out, char4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_int_n1(char4* out, int in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_int_n2(char4* out, char4 in1, int in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_int_n3(int* out, char4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_long_n1(char4* out, long in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_long_n2(char4* out, char4 in1, long in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_long_n3(long* out, char4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_float_n1(char4* out, float in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_float_n2(char4* out, char4 in1, float in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_float_n3(float* out, char4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_dummy_n1(char4* out, Dummy in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_dummy_n2(char4* out, char4 in1, Dummy in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_dummy_n3(Dummy* out, char4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
)"};
static constexpr auto kHipHcSub8pkVector{
R"(
__global__ void hip_hc_sub8pk_char4_n1(char4* out, char4 in1, char4 in2) { out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_char4_n2(char4* out, char4 in1, char4 in2) { *out = __hip_hc_sub8pk(&in1, in2); }
__global__ void hip_hc_sub8pk_char4_n3(char4* out, char4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, &in2); }
__global__ void hip_hc_sub8pk_char2_n1(char4* out, char2 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_char2_n2(char4* out, char4 in1, char2 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_char2_n3(char2* out, char4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_int4_n1(char4* out, int4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_int4_n2(char4* out, char4 in1, int4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_int4_n3(int4* out, char4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_long4_n1(char4* out, long4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_long4_n2(char4* out, char4 in1, long4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_long4_n3(long4* out, char4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_float4_n1(char4* out, float4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_float4_n2(char4* out, char4 in1, float4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
__global__ void hip_hc_sub8pk_float4_n3(float4* out, char4 in1, char4 in2) { *out = __hip_hc_sub8pk(in1, in2); }
)"};
static constexpr auto kHipHcMul8pkBasic{
R"(
struct Dummy {
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void hip_hc_mul8pk_char_n1(char4* out, char in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_char_n2(char4* out, char4 in1, char in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_char_n3(char* out, char4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_int_n1(char4* out, int in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_int_n2(char4* out, char4 in1, int in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_int_n3(int* out, char4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_long_n1(char4* out, long in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_long_n2(char4* out, char4 in1, long in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_long_n3(long* out, char4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_float_n1(char4* out, float in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_float_n2(char4* out, char4 in1, float in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_float_n3(float* out, char4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_dummy_n1(char4* out, Dummy in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_dummy_n2(char4* out, char4 in1, Dummy in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_dummy_n3(Dummy* out, char4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
)"};
static constexpr auto kHipHcMul8pkVector{
R"(
__global__ void hip_hc_mul8pk_char4_n1(char4* out, char4 in1, char4 in2) { out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_char4_n2(char4* out, char4 in1, char4 in2) { *out = __hip_hc_mul8pk(&in1, in2); }
__global__ void hip_hc_mul8pk_char4_n3(char4* out, char4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, &in2); }
__global__ void hip_hc_mul8pk_char2_n1(char4* out, char2 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_char2_n2(char4* out, char4 in1, char2 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_char2_n3(char2* out, char4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_int4_n1(char4* out, int4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_int4_n2(char4* out, char4 in1, int4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_int4_n3(int4* out, char4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_long4_n1(char4* out, long4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_long4_n2(char4* out, char4 in1, long4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_long4_n3(long4* out, char4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_float4_n1(char4* out, float4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_float4_n2(char4* out, char4 in1, float4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
__global__ void hip_hc_mul8pk_float4_n3(float4* out, char4 in1, char4 in2) { *out = __hip_hc_mul8pk(in1, in2); }
)"};
+9 -1
Ver Arquivo
@@ -107,6 +107,12 @@ set(TEST_SRC
hipMemcpyFromSymbol.cc
hipPtrGetAttribute.cc
hipMemPoolApi.cc
hipMemPoolSetGetAccess.cc
hipMemPoolSetGetAttribute.cc
hipMemPoolCreate.cc
hipMemPoolDestroy.cc
hipMemPoolTrimTo.cc
hipMallocFromPoolAsync.cc
hipMemcpyPeer.cc
hipMemcpyPeer_old.cc
hipMemcpyPeerAsync.cc
@@ -151,7 +157,9 @@ set(TEST_SRC
hipStreamAttachMemAsync.cc
hipMemRangeGetAttributes_old.cc
hipMemGetAddressRange.cc
hipArrayGetDescriptor.cc)
hipArrayGetDescriptor.cc
hipMallocMipmappedArray.cc
hipFreeMipmappedArray.cc)
set(NOT_FOR_MI200_AND_ABOVE_TEST hipMallocArray.cc hipArrayCreate.cc) # tests not for MI200+
set(MI200_AND_ABOVE_TARGETS gfx90a gfx940 gfx941 gfx942)
+50 -15
Ver Arquivo
@@ -21,24 +21,59 @@ THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <resource_guards.hh>
#include <utils.hh>
TEST_CASE("Unit_hipFreeAsync_negative") {
HIP_CHECK(hipSetDevice(0));
void* p = nullptr;
hipStream_t stream{nullptr};
HIP_CHECK(hipStreamCreate(&stream));
/**
* @addtogroup hipFreeAsync hipFreeAsync
* @{
* @ingroup StreamOTest
* `hipFreeAsync(void* dev_ptr, hipStream_t stream)`
* - Frees memory with stream ordered semantics
*/
SECTION("dev_ptr is nullptr") { REQUIRE(hipFreeAsync(nullptr, stream) != hipSuccess); }
SECTION("invalid stream handle") {
HIP_CHECK(hipMallocAsync(static_cast<void**>(&p), 100, stream));
HIP_CHECK(hipStreamSynchronize(stream));
hipError_t error = hipFreeAsync(p, reinterpret_cast<hipStream_t>(-1));
HIP_CHECK(hipFreeAsync(p, stream));
HIP_CHECK(hipStreamSynchronize(stream));
REQUIRE(error != hipSuccess);
/**
* Test Description
* ------------------------
* - Test to verify hipFreeAsync behavior with invalid arguments:
* -# Nullptr dev_ptr
* -# Invalid stream handle
* -# Double hipFreeAsync
*
* Test source
* ------------------------
* - /unit/memory/hipFreeAsync.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipFreeAsync_Negative_Parameters") {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
int* p = nullptr;
size_t alloc_size = 1024;
StreamGuard stream(Streams::created);
SECTION("dev_ptr is nullptr") {
HIP_CHECK_ERROR(hipFreeAsync(nullptr, stream.stream()), hipErrorInvalidValue);
}
HIP_CHECK(hipStreamSynchronize(stream));
HIP_CHECK(hipStreamDestroy(stream));
SECTION("Invalid stream handle") {
HIP_CHECK(hipMallocAsync(reinterpret_cast<void**>(&p), alloc_size, stream.stream()));
HIP_CHECK(hipStreamSynchronize(stream.stream()));
HIP_CHECK_ERROR(hipFreeAsync(p, reinterpret_cast<hipStream_t>(-1)), hipErrorInvalidHandle);
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(p), stream.stream()));
HIP_CHECK(hipStreamSynchronize(stream.stream()));
}
SECTION("Double free") {
HIP_CHECK(hipMallocAsync(reinterpret_cast<void**>(&p), alloc_size, stream.stream()));
HIP_CHECK(hipStreamSynchronize(stream.stream()));
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(p), stream.stream()));
HIP_CHECK(hipStreamSynchronize(stream.stream()));
HIP_CHECK_ERROR(hipFreeAsync(reinterpret_cast<void*>(p), stream.stream()),
hipErrorInvalidValue);
}
}
+126
Ver Arquivo
@@ -0,0 +1,126 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include "hipArrayCommon.hh"
#include "utils.hh"
/*
* hipFreeMipmappedArray API test scenarios
* 1. Check that hipFreeMipmappedArray implicitly synchronises the device.
* 2. Perform multiple allocations and then call hipFreeMipmappedArray on each pointer concurrently (from unique
* threads) for different memory types and different allocation sizes.
* 3. Pass nullptr as argument and check that correct error code is returned.
* 4. Call hipFreeMipmappedArray twice on the same pointer and check that the implementation handles the second
* call correctly.
*/
TEMPLATE_TEST_CASE("Unit_hipFreeMipmappedArrayImplicitSyncArray", "", char, float) {
hipMipmappedArray_t arrayPtr{};
hipExtent extent{};
hipChannelFormatDesc desc = hipCreateChannelDesc<TestType>();
#if HT_AMD
const unsigned int flags = hipArrayDefault;
#else
const unsigned int flags = GENERATE(hipArrayDefault, hipArraySurfaceLoadStore);
#endif
extent.width = GENERATE(64, 256, 1024);
extent.height = GENERATE(64, 256, 1024);
extent.depth = GENERATE(0, 64, 256, 1024);
const unsigned int numLevels = GENERATE(1, 5, 7);
HIP_CHECK(hipMallocMipmappedArray(&arrayPtr, &desc, extent, numLevels, flags));
LaunchDelayKernel(std::chrono::milliseconds{50}, nullptr);
// make sure device is busy
HIP_CHECK_ERROR(hipStreamQuery(nullptr), hipErrorNotReady);
HIP_CHECK(hipFreeMipmappedArray(arrayPtr));
HIP_CHECK(hipStreamQuery(nullptr));
}
TEST_CASE("Unit_hipFreeMipmappedArray_Negative_Nullptr") {
HIP_CHECK_ERROR(hipFreeMipmappedArray(nullptr), hipErrorInvalidValue);
}
TEST_CASE("Unit_hipFreeMipmappedArray_Negative_DoubleFree") {
hipMipmappedArray_t arrayPtr{};
hipExtent extent{};
hipChannelFormatDesc desc = hipCreateChannelDesc<char>();
#if HT_AMD
const unsigned int flags = hipArrayDefault;
#else
const unsigned int flags = GENERATE(hipArrayDefault, hipArraySurfaceLoadStore);
#endif
extent.width = GENERATE(64, 512, 1024);
extent.height = GENERATE(64, 512, 1024);
extent.depth = GENERATE(0, 64, 512, 1024);
const unsigned int numLevels = GENERATE(1, 5, 7);
HIP_CHECK(hipMallocMipmappedArray(&arrayPtr, &desc, extent, numLevels, flags));
HIP_CHECK(hipFreeMipmappedArray(arrayPtr));
HIP_CHECK_ERROR(hipFreeMipmappedArray(arrayPtr), hipErrorContextIsDestroyed);
}
TEMPLATE_TEST_CASE("Unit_hipFreeMipmappedArrayMultiTArray", "", char, int) {
constexpr size_t numAllocs = 10;
std::vector<std::thread> threads;
std::vector<hipMipmappedArray_t> ptrs(numAllocs);
hipExtent extent{};
hipChannelFormatDesc desc = hipCreateChannelDesc<TestType>();
const unsigned int numLevels = GENERATE(1, 5, 7);
#if HT_AMD
const unsigned int flags = hipArrayDefault;
#else
const unsigned int flags = GENERATE(hipArrayDefault, hipArraySurfaceLoadStore);
#endif
extent.width = GENERATE(64, 256, 1024);
extent.height = GENERATE(64, 256, 1024);
extent.depth = GENERATE(0, 64, 256, 1024);
for (auto& ptr : ptrs) {
HIP_CHECK(hipMallocMipmappedArray(&ptr, &desc, extent, numLevels, flags));
}
for (auto ptr : ptrs) {
threads.emplace_back(([ptr] {
HIP_CHECK_THREAD(hipFreeMipmappedArray(ptr));
HIP_CHECK_THREAD(hipStreamQuery(nullptr));
}));
}
for (auto& t : threads) {
t.join();
}
HIP_CHECK_THREAD_FINALIZE();
}
+11
Ver Arquivo
@@ -69,7 +69,18 @@ TEST_CASE("Unit_hipMalloc3D_Basic") {
size_t height{SMALL_SIZE}, depth{SMALL_SIZE};
hipPitchedPtr devPitchedPtr;
hipExtent extent = make_hipExtent(width, height, depth);
size_t tot, avail, ptot, pavail;
HIP_CHECK(hipMemGetInfo(&pavail, &ptot));
REQUIRE(hipMalloc3D(&devPitchedPtr, extent) == hipSuccess);
HIPCHECK(hipFree(devPitchedPtr.ptr));
HIP_CHECK(hipMemGetInfo(&avail, &tot));
if (pavail != avail) {
WARN("Memory leak of hipMalloc3D API in multithreaded scenario");
REQUIRE(false);
}
}
/*
+113 -22
Ver Arquivo
@@ -17,31 +17,122 @@
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <hip_test_checkers.hh>
#include "mempool_common.hh"
#include <limits>
TEST_CASE("Unit_hipMallocAsync_negative") {
HIP_CHECK(hipSetDevice(0));
#pragma clang diagnostic ignored "-Wunused-parameter"
void* p = nullptr;
size_t max_size = std::numeric_limits<size_t>::max();
hipStream_t stream{nullptr};
HIP_CHECK(hipStreamCreate(&stream));
/**
* @addtogroup hipMallocAsync hipMallocAsync
* @{
* @ingroup StreamOTest
* `hipMallocAsync(void** dev_ptr, size_t size, hipStream_t stream)`
* - Allocates memory with stream ordered semantics
*/
SECTION("Device pointer is null") { REQUIRE(hipMallocAsync(nullptr, 100, stream) != hipSuccess); }
SECTION("stream is invalid") {
REQUIRE(hipMallocAsync(static_cast<void**>(&p), 100, reinterpret_cast<hipStream_t>(-1)) !=
hipSuccess);
}
SECTION("out of memory") {
REQUIRE(hipMallocAsync(static_cast<void**>(&p), max_size, stream) != hipSuccess);
}
HIP_CHECK(hipStreamSynchronize(stream));
HIP_CHECK(hipStreamDestroy(stream));
/**
* Test Description
* ------------------------
* - Basic test to verify proper allocation and stream ordering of hipMallocAsync when one
* memory allocation is performed.
* Test source
* ------------------------
* - /unit/memory/hipMallocAsync.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMallocAsync_Basic_OneAlloc") {
MallocMemPoolAsync_OneAlloc(
[](void** dev_ptr, size_t size, hipMemPool_t mem_pool, hipStream_t stream) {
return hipMallocAsync(dev_ptr, size, stream);
},
MemPools::dev_default);
}
/**
* Test Description
* ------------------------
* - Basic test to verify proper allocation and stream ordering of hipMallocAsync when two
* memory allocations are performed.
* Test source
* ------------------------
* - /unit/memory/hipMallocAsync.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMallocAsync_Basic_TwoAllocs") {
MallocMemPoolAsync_TwoAllocs(
[](void** dev_ptr, size_t size, hipMemPool_t mem_pool, hipStream_t stream) {
return hipMallocAsync(dev_ptr, size, stream);
},
MemPools::dev_default);
}
/**
* Test Description
* ------------------------
* - Basic test to verify that memory allocated with hipMallocAsync can be properly reused.
* Test source
* ------------------------
* - /unit/memory/hipMallocAsync.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMallocAsync_Basic_Reuse") {
MallocMemPoolAsync_Reuse([](void** dev_ptr, size_t size, hipMemPool_t mem_pool,
hipStream_t stream) { return hipMallocAsync(dev_ptr, size, stream); },
MemPools::dev_default);
}
/**
* Test Description
* ------------------------
* - Test to verify hipMallocAsync behavior with invalid arguments:
* -# Nullptr dev_ptr
* -# Invalid stream handle
* -# Size is max size_t
*
* Test source
* ------------------------
* - /unit/memory/hipMallocAsync.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMallocAsync_Negative_Parameters") {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
int mem_pool_support = 0;
HIP_CHECK(hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, 0));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
int* p = nullptr;
size_t max_size = std::numeric_limits<size_t>::max();
size_t alloc_size = 1024;
MemPoolGuard mempool(MemPools::dev_default, device_id);
StreamGuard stream(Streams::created);
SECTION("dev_ptr is nullptr") {
HIP_CHECK_ERROR(hipMallocAsync(nullptr, alloc_size, stream.stream()), hipErrorInvalidValue);
}
SECTION("invalid stream handle") {
HIP_CHECK_ERROR(
hipMallocAsync(reinterpret_cast<void**>(&p), alloc_size, reinterpret_cast<hipStream_t>(-1)),
hipErrorInvalidHandle);
}
SECTION("Size is max size_t") {
HIP_CHECK_ERROR(hipMallocAsync(reinterpret_cast<void**>(&p), max_size, stream.stream()),
hipErrorOutOfMemory);
}
}
+149
Ver Arquivo
@@ -0,0 +1,149 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "mempool_common.hh"
#include <limits>
/**
* @addtogroup hipMallocFromPoolAsync hipMallocFromPoolAsync
* @{
* @ingroup StreamOTest
* `hipMallocFromPoolAsync(void** dev_ptr, size_t size, hipMemPool_t mem_pool, hipStream_t stream)`
* - Allocates memory from a specified pool with stream ordered semantics
*/
/**
* Test Description
* ------------------------
* - Basic test to verify proper allocation and stream ordering of hipMallocFromPoolAsync when one
* memory allocation is performed.
* Test source
* ------------------------
* - /unit/memory/hipMallocFromPoolAsync.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMallocFromPoolAsync_Basic_OneAlloc") {
MallocMemPoolAsync_OneAlloc(
[](void** dev_ptr, size_t size, hipMemPool_t mem_pool, hipStream_t stream) {
return hipMallocFromPoolAsync(dev_ptr, size, mem_pool, stream);
},
MemPools::created);
}
/**
* Test Description
* ------------------------
* - Basic test to verify proper allocation and stream ordering of hipMallocFromPoolAsync when two
* memory allocations are performed.
* Test source
* ------------------------
* - /unit/memory/hipMallocFromPoolAsync.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMallocFromPoolAsync_Basic_TwoAllocs") {
MallocMemPoolAsync_TwoAllocs(
[](void** dev_ptr, size_t size, hipMemPool_t mem_pool, hipStream_t stream) {
return hipMallocFromPoolAsync(dev_ptr, size, mem_pool, stream);
},
MemPools::created);
}
/**
* Test Description
* ------------------------
* - Basic test to verify that memory allocated with hipMallocFromPoolAsync can be properly reused.
* Test source
* ------------------------
* - /unit/memory/hipMallocFromPoolAsync.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMallocFromPoolAsync_Basic_Reuse") {
MallocMemPoolAsync_Reuse(
[](void** dev_ptr, size_t size, hipMemPool_t mem_pool, hipStream_t stream) {
return hipMallocFromPoolAsync(dev_ptr, size, mem_pool, stream);
},
MemPools::created);
}
/**
* Test Description
* ------------------------
* - Test to verify hipMallocFromPoolAsync behavior with invalid arguments:
* -# Nullptr dev_ptr
* -# Nullptr mem_pool
* -# Invalid stream handle
* -# Size is max size_t
*
* Test source
* ------------------------
* - /unit/memory/hipMallocFromPoolAsync.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMallocFromPoolAsync_Negative_Parameters") {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
int mem_pool_support = 0;
HIP_CHECK(hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, 0));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
void* p = nullptr;
size_t max_size = std::numeric_limits<size_t>::max();
size_t alloc_size = 1024;
MemPoolGuard mempool(MemPools::created, device_id);
StreamGuard stream(Streams::created);
SECTION("dev_ptr is nullptr") {
HIP_CHECK_ERROR(hipMallocFromPoolAsync(nullptr, alloc_size, mempool.mempool(), stream.stream()),
hipErrorInvalidValue);
}
SECTION("Mempool not created") {
hipMemPool_t dummy_mem_pool = nullptr;
HIP_CHECK_ERROR(hipMallocFromPoolAsync(static_cast<void**>(&p), alloc_size, dummy_mem_pool,
stream.stream()),
hipErrorInvalidValue);
}
SECTION("Invalid stream handle") {
HIP_CHECK_ERROR(hipMallocFromPoolAsync(static_cast<void**>(&p), alloc_size, mempool.mempool(),
reinterpret_cast<hipStream_t>(-1)),
hipErrorInvalidHandle);
}
SECTION("Size is max size_t") {
HIP_CHECK_ERROR(hipMallocFromPoolAsync(static_cast<void**>(&p), max_size, mempool.mempool(),
stream.stream()),
hipErrorOutOfMemory);
}
}
+417
Ver Arquivo
@@ -0,0 +1,417 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/*
hipMallocMipmappedArray API test scenarios
1. Basic Functionality
2. Negative Scenarios
3. Allocating Small and big chunk data
4. Multithreaded scenario
*/
#include <array>
#include <hip_test_common.hh>
#include "hipArrayCommon.hh"
static constexpr auto ARRAY_SIZE{4};
static constexpr auto BIG_ARRAY_SIZE{100};
static constexpr auto ARRAY_LOOP{100};
/*
* This API verifies memory allocations for small and
* bigger chunks of data.
* Two scenarios are verified in this API
* 1. SmallArray: Allocates ARRAY_SIZE in a loop and
* releases the memory and verifies the meminfo.
* 2. BigArray: Allocates BIG_ARRAY_SIZE in a loop and
* releases the memory and verifies the meminfo
*
* In both cases, the memory info before allocation and
* after releasing the memory should be the same
*
*/
static void MallocMipmappedArray_DiffSizes(int gpu) {
HIP_CHECK_THREAD(hipSetDevice(gpu));
// Use of GENERATE in thead function causes random failures with multithread condition.
std::vector<size_t> runs{ARRAY_SIZE, BIG_ARRAY_SIZE};
for (const auto& size : runs) {
auto numLevelsLimit = floor(log2(size));
for (unsigned int numLevels = 0; numLevels < numLevelsLimit; numLevels++) {
size_t width{size}, height{size}, depth{size};
hipChannelFormatDesc channelDesc = hipCreateChannelDesc<float>();
std::array<hipMipmappedArray_t, ARRAY_LOOP> arr;
size_t pavail, avail, total;
HIP_CHECK_THREAD(hipMemGetInfo(&pavail, &total));
for (int i = 0; i < ARRAY_LOOP; i++) {
HIP_CHECK_THREAD(hipMallocMipmappedArray(&arr[i], &channelDesc,
make_hipExtent(width, height, depth),
(1 + numLevels), hipArrayDefault));
}
for (int i = 0; i < ARRAY_LOOP; i++) {
HIP_CHECK_THREAD(hipFreeMipmappedArray(arr[i]));
}
HIP_CHECK_THREAD(hipMemGetInfo(&avail, &total));
REQUIRE_THREAD(pavail == avail);
}
}
}
TEST_CASE("Unit_hipMallocMipmappedArray_DiffSizes") {
MallocMipmappedArray_DiffSizes(0);
HIP_CHECK_THREAD_FINALIZE();
}
/*
This testcase verifies the hipMallocMipmappedArray API in multithreaded
scenario by launching threads in parallel on multiple GPUs
and verifies the hipMallocMipmappedArray API with small and big chunks data
*/
TEST_CASE("Unit_hipMallocMipmappedArray_MultiThread") {
std::vector<std::thread> threadlist;
int devCnt = 0;
devCnt = HipTest::getDeviceCount();
for (int i = 0; i < devCnt; i++) {
threadlist.push_back(std::thread(MallocMipmappedArray_DiffSizes, i));
}
for (auto& t : threadlist) {
t.join();
}
HIP_CHECK_THREAD_FINALIZE();
}
namespace {
void checkMipmappedArrayIsExpected(hipArray_t level_array,
const hipChannelFormatDesc& expected_desc,
const hipExtent& expected_extent,
const unsigned int expected_flags) {
// hipArrayGetInfo doesn't currently exist (EXSWCPHIPT-87)
#if HT_AMD
std::ignore = level_array;
std::ignore = expected_desc;
std::ignore = expected_extent;
std::ignore = expected_flags;
#else
cudaChannelFormatDesc queried_desc;
cudaExtent queried_extent;
unsigned int queried_flags;
cudaArrayGetInfo(&queried_desc, &queried_extent, &queried_flags, level_array);
REQUIRE(expected_desc.x == queried_desc.x);
REQUIRE(expected_desc.y == queried_desc.y);
REQUIRE(expected_desc.z == queried_desc.z);
REQUIRE(expected_desc.f == queried_desc.f);
REQUIRE(expected_extent.width == queried_extent.width);
REQUIRE(expected_extent.height == queried_extent.height);
REQUIRE(expected_extent.depth == queried_extent.depth);
REQUIRE(expected_flags == queried_flags);
#endif
}
} // namespace
TEMPLATE_TEST_CASE("Unit_hipMallocMipmappedArray_happy", "", char, uint2, int4, short4, float) {
hipMipmappedArray_t array;
const auto desc = hipCreateChannelDesc<TestType>();
#if HT_AMD
const unsigned int flags = hipArrayDefault;
#else
const unsigned int flags =
GENERATE(hipArrayDefault, hipArraySurfaceLoadStore, hipArrayTextureGather);
#endif
constexpr size_t size = 64;
const unsigned int numLevels = GENERATE(1, 3, 5, 7);
std::vector<hipExtent> extents;
extents.reserve(3);
extents.push_back({size, size, 0}); // 2D array
if (flags != hipArrayTextureGather) {
extents.push_back({size, 0, 0}); // 1D array
extents.push_back({size, size, size}); // 3D array
};
for (const auto extent : extents) {
CAPTURE(flags, extent.width, extent.height, extent.depth);
HIP_CHECK(hipMallocMipmappedArray(&array, &desc, extent, numLevels, flags));
hipArray_t hipArray = nullptr;
HIP_CHECK(hipGetMipmappedArrayLevel(&hipArray, array, 0));
checkMipmappedArrayIsExpected(hipArray, desc, extent, flags);
HIP_CHECK(hipFreeMipmappedArray(array));
}
}
#if HT_AMD
constexpr std::array<unsigned int, 1> validFlags{hipArrayDefault};
#else
constexpr std::array<unsigned int, 9> validFlags{
hipArrayDefault,
hipArrayDefault | hipArraySurfaceLoadStore,
hipArrayLayered,
hipArrayLayered | hipArraySurfaceLoadStore,
hipArrayCubemap,
hipArrayCubemap | hipArrayLayered,
hipArrayCubemap | hipArraySurfaceLoadStore,
hipArrayCubemap | hipArrayLayered | hipArraySurfaceLoadStore,
hipArrayTextureGather};
#endif
hipExtent makeMipmappedExtent(unsigned int flag, size_t s) {
if (flag == hipArrayTextureGather) {
return make_hipExtent(s, s, 0);
}
return make_hipExtent(s, s, s);
}
// Providing the array pointer as nullptr should return an error
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_NullArrayPtr") {
hipChannelFormatDesc desc = hipCreateChannelDesc<float4>();
unsigned int numLevels = 1;
constexpr size_t s = 6;
const auto flag = GENERATE(from_range(std::begin(validFlags), std::end(validFlags)));
HIP_CHECK_ERROR(
hipMallocMipmappedArray(nullptr, &desc, makeMipmappedExtent(flag, s), numLevels, flag),
hipErrorInvalidValue);
}
// Providing the description pointer as nullptr should return an error
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_NullDescPtr") {
constexpr size_t s = 6; // 6 to keep cubemap happy
unsigned int numLevels = 1;
hipMipmappedArray_t array;
const auto flag = GENERATE(from_range(std::begin(validFlags), std::end(validFlags)));
HIP_CHECK_ERROR(
hipMallocMipmappedArray(&array, nullptr, makeMipmappedExtent(flag, s), numLevels, flag),
hipErrorInvalidValue);
}
// Zero width arrays are not allowed
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_ZeroWidth") {
constexpr size_t s = 6; // 6 to keep cubemap happy
unsigned int numLevels = 1;
hipMipmappedArray_t array;
hipChannelFormatDesc desc = hipCreateChannelDesc<float4>();
const auto flag = GENERATE(from_range(std::begin(validFlags), std::end(validFlags)));
HIP_CHECK_ERROR(hipMallocMipmappedArray(&array, &desc, make_hipExtent(0, s, s), numLevels, flag),
hipErrorInvalidValue);
}
// Zero height arrays are only allowed for 1D arrays and layered arrays
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_ZeroHeight") {
constexpr size_t s = 6; // 6 to keep cubemap happy
unsigned int numLevels = 1;
hipMipmappedArray_t array;
hipChannelFormatDesc desc = hipCreateChannelDesc<float4>();
std::array<unsigned int, 2> exceptions{hipArrayLayered,
hipArrayLayered | hipArraySurfaceLoadStore};
const auto flag = GENERATE(from_range(std::begin(validFlags), std::end(validFlags)));
if (std::find(std::begin(exceptions), std::end(exceptions), flag) == std::end(exceptions)) {
// flag is not in list of exceptions
HIP_CHECK_ERROR(
hipMallocMipmappedArray(&array, &desc, make_hipExtent(s, 0, s), numLevels, flag),
hipErrorInvalidValue);
}
}
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_InvalidFlags") {
constexpr size_t s = 6; // 6 to keep cubemap happy
unsigned int numLevels = 1;
hipMipmappedArray_t array;
hipChannelFormatDesc desc = hipCreateChannelDesc<float4>();
#if HT_AMD
const unsigned int flag = 0xDEADBEEF;
#else
const unsigned int flag =
GENERATE(0xDEADBEEF, hipArrayTextureGather | hipArraySurfaceLoadStore,
hipArrayTextureGather | hipArrayCubemap,
hipArrayTextureGather | hipArraySurfaceLoadStore | hipArrayCubemap);
#endif
CAPTURE(flag);
REQUIRE(std::find(std::begin(validFlags), std::end(validFlags), flag) == std::end(validFlags));
HIP_CHECK_ERROR(
hipMallocMipmappedArray(&array, &desc, makeMipmappedExtent(flag, s), numLevels, flag),
hipErrorInvalidValue);
}
void testInvalidDescriptionMipmapped(hipChannelFormatDesc desc) {
constexpr size_t s = 6; // 6 to keep cubemap happy
unsigned int numLevels = 1;
hipMipmappedArray_t array;
#if HT_NVIDIA
hipError_t expectedError = hipErrorUnknown;
#else
hipError_t expectedError = hipErrorInvalidValue;
#endif
const auto flag = GENERATE(from_range(std::begin(validFlags), std::end(validFlags)));
HIP_CHECK_ERROR(
hipMallocMipmappedArray(&array, &desc, makeMipmappedExtent(flag, s), numLevels, flag),
expectedError);
}
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_InvalidFormat") {
hipChannelFormatDesc desc = hipCreateChannelDesc<float4>();
desc.f = GENERATE(hipChannelFormatKindNone, 0xBEEF);
testInvalidDescriptionMipmapped(desc);
}
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_BadChannelLayout") {
const int bits = GENERATE(8, 16, 32);
const hipChannelFormatKind formatKind =
GENERATE(hipChannelFormatKindSigned, hipChannelFormatKindUnsigned, hipChannelFormatKindFloat);
if (bits == 8 && formatKind == hipChannelFormatKindFloat) return;
hipChannelFormatDesc desc = GENERATE_COPY(hipCreateChannelDesc(bits, bits, bits, 0, formatKind),
hipCreateChannelDesc(0, bits, bits, 0, formatKind),
hipCreateChannelDesc(0, bits, bits, bits, formatKind),
hipCreateChannelDesc(bits, 0, bits, 0, formatKind),
hipCreateChannelDesc(bits, bits, 0, bits, formatKind),
hipCreateChannelDesc(0, 0, bits, 0, formatKind),
hipCreateChannelDesc(0, 0, bits, bits, formatKind));
INFO("kind: " << channelFormatString(formatKind));
INFO("x: " << desc.x << ", y: " << desc.y << ", z: " << desc.z << ", w: " << desc.w);
testInvalidDescriptionMipmapped(desc);
}
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_8BitFloat") {
hipChannelFormatDesc desc = GENERATE(hipCreateChannelDesc(8, 0, 0, 0, hipChannelFormatKindFloat),
hipCreateChannelDesc(8, 8, 0, 0, hipChannelFormatKindFloat),
hipCreateChannelDesc(8, 8, 8, 8, hipChannelFormatKindFloat));
testInvalidDescriptionMipmapped(desc);
}
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_DifferentChannelSizes") {
const int bitsX = GENERATE(8, 16, 32);
const int bitsY = GENERATE(8, 16, 32);
const int bitsZ = GENERATE(8, 16, 32);
const int bitsW = GENERATE(8, 16, 32);
if (bitsX == bitsY && bitsY == bitsZ && bitsZ == bitsW) return; // skip when they are equal
const hipChannelFormatKind channelFormat =
GENERATE(hipChannelFormatKindSigned, hipChannelFormatKindUnsigned, hipChannelFormatKindFloat);
if (channelFormat == hipChannelFormatKindFloat &&
(bitsX == 8 || bitsY == 8 || bitsZ == 8 || bitsW == 8))
return; // 8 bit floats aren't allowed
hipChannelFormatDesc desc = hipCreateChannelDesc(bitsX, bitsY, bitsZ, bitsW, channelFormat);
INFO("format: " << channelFormatString(channelFormat) << ", x bits: " << bitsX
<< ", y bits: " << bitsY << ", z bits: " << bitsZ << ", w bits: " << bitsW);
testInvalidDescriptionMipmapped(desc);
}
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_BadChannelSize") {
const int badBits = GENERATE(-1, 0, 10, 100);
const hipChannelFormatKind formatKind =
GENERATE(hipChannelFormatKindSigned, hipChannelFormatKindUnsigned, hipChannelFormatKindFloat);
hipChannelFormatDesc desc = hipCreateChannelDesc(badBits, badBits, badBits, badBits, formatKind);
INFO("Number of bits: " << badBits);
testInvalidDescriptionMipmapped(desc);
}
// hipMallocMipmappedArray should handle the max numeric value gracefully.
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_NumericLimit") {
hipMipmappedArray_t arrayPtr;
unsigned int numLevels = 1;
hipChannelFormatDesc desc = hipCreateChannelDesc<float>();
size_t size = std::numeric_limits<size_t>::max();
const auto flag = GENERATE(from_range(std::begin(validFlags), std::end(validFlags)));
HIP_CHECK_ERROR(
hipMallocMipmappedArray(&arrayPtr, &desc, makeMipmappedExtent(flag, size), numLevels, flag),
hipErrorInvalidValue);
}
// texture gather arrays are only allowed to be 2D
TEMPLATE_TEST_CASE("Unit_hipMallocMipmappedArray_Negative_Non2DTextureGather", "", char, uchar2,
float2) {
#if HT_AMD
HipTest::HIP_SKIP_TEST("Texture Gather arrays not supported using AMD backend");
return;
#endif
hipMipmappedArray_t array;
unsigned int numLevels = 1;
const auto desc = hipCreateChannelDesc<TestType>();
constexpr unsigned int flags = hipArrayTextureGather;
constexpr size_t size = 64;
const hipExtent extent = GENERATE(make_hipExtent(size, 0, 0), make_hipExtent(size, size, size));
HIP_CHECK_ERROR(hipMallocMipmappedArray(&array, &desc, extent, numLevels, flags),
hipErrorInvalidValue);
}
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_NumLevels") {
hipMipmappedArray_t array;
constexpr size_t size = 6;
unsigned int numLevels = floor(log2(size)) + 2;
hipChannelFormatDesc desc = hipCreateChannelDesc<float>();
const auto flag = GENERATE(from_range(std::begin(validFlags), std::end(validFlags)));
HIP_CHECK_ERROR(
hipMallocMipmappedArray(&array, &desc, makeMipmappedExtent(flag, size), numLevels, flag),
hipErrorInvalidValue);
}
TEST_CASE("Unit_hipGetMipmappedArrayLevel_Negative") {
constexpr size_t s = 6;
unsigned int numLevels = 1;
hipMipmappedArray_t array;
hipArray_t level_array;
hipChannelFormatDesc desc = hipCreateChannelDesc<float>();
HIP_CHECK(
hipMallocMipmappedArray(&array, &desc, make_hipExtent(s, s, s), numLevels, hipArrayDefault));
SECTION("Level is invalid") {
HIP_CHECK_ERROR(hipGetMipmappedArrayLevel(&level_array, array, 3), hipErrorInvalidValue);
}
SECTION("Mipmapped array is nullptr") {
HIP_CHECK_ERROR(hipGetMipmappedArrayLevel(&level_array, nullptr, 1),
hipErrorInvalidResourceHandle);
}
HIP_CHECK(hipFreeMipmappedArray(array));
}
+93
Ver Arquivo
@@ -0,0 +1,93 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
/**
* @addtogroup hipMemPoolCreate hipMemPoolCreate
* @{
* @ingroup StreamOTest
* `hipMemPoolCreate(hipMemPool_t* mem_pool, const hipMemPoolProps* pool_props)` -
* Creates a memory pool and returns the handle in mem pool
*/
/**
* Test Description
* ------------------------
* - Test to verify hipMemPoolCreate behavior with invalid arguments:
* -# Nullptr mem_pool
* -# Nullptr props
* -# Invalid props alloc type
* -# Invalid props location type
* -# Invalid props location id
*
* Test source
* ------------------------
* - /unit/memory/hipMemPoolCreate.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolCreate_Negative_Parameter") {
int mem_pool_support = 0;
HIP_CHECK(hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, 0));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
int num_dev = 0;
HIP_CHECK(hipGetDeviceCount(&num_dev));
hipMemPoolProps pool_props;
pool_props.allocType = hipMemAllocationTypePinned;
pool_props.handleTypes = hipMemHandleTypeNone;
pool_props.location.type = hipMemLocationTypeDevice;
pool_props.location.id = 0;
pool_props.win32SecurityAttributes = nullptr;
memset(pool_props.reserved, 0, sizeof(pool_props.reserved));
hipMemPool_t mem_pool = nullptr;
SECTION("Passing nullptr to mem_pool") {
HIP_CHECK_ERROR(hipMemPoolCreate(nullptr, &pool_props), hipErrorInvalidValue);
}
SECTION("Passing nullptr to props") {
HIP_CHECK_ERROR(hipMemPoolCreate(&mem_pool, nullptr), hipErrorInvalidValue);
}
SECTION("Passing invalid props alloc type") {
pool_props.allocType = hipMemAllocationTypeInvalid;
HIP_CHECK_ERROR(hipMemPoolCreate(&mem_pool, &pool_props), hipErrorInvalidValue);
pool_props.allocType = hipMemAllocationTypePinned;
}
SECTION("Passing invalid props location type") {
pool_props.location.type = hipMemLocationTypeInvalid;
HIP_CHECK_ERROR(hipMemPoolCreate(&mem_pool, &pool_props), hipErrorInvalidValue);
pool_props.location.type = hipMemLocationTypeDevice;
}
SECTION("Passing invalid props location id") {
pool_props.location.id = num_dev;
HIP_CHECK_ERROR(hipMemPoolCreate(&mem_pool, &pool_props), hipErrorInvalidValue);
pool_props.location.id = 0;
}
}
+71
Ver Arquivo
@@ -0,0 +1,71 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "mempool_common.hh"
/**
* @addtogroup hipMemPoolDestroy hipMemPoolDestroy
* @{
* @ingroup StreamOTest
* `hipMemPoolDestroy(hipMemPool_t mem_pool)` -
* Destroys the specified memory pool
*/
/**
* Test Description
* ------------------------
* - Test to verify hipMemPoolCreate behavior with invalid arguments:
* -# Nullptr mem_pool
* -# Double hipMemPoolDestroy
* -# Attempt to destroy default mempool
*
* Test source
* ------------------------
* - /unit/memory/hipMemPoolDestroy.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolDestroy_Negative_Parameter") {
int mem_pool_support = 0;
HIP_CHECK(hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, 0));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
hipMemPool_t mem_pool = nullptr;
SECTION("Passing nullptr to mempool") {
HIP_CHECK_ERROR(hipMemPoolDestroy(nullptr), hipErrorInvalidValue);
}
SECTION("Double hipMemPoolDestroy") {
HIP_CHECK(hipMemPoolCreate(&mem_pool, &kPoolProps));
HIP_CHECK(hipMemPoolDestroy(mem_pool));
HIP_CHECK_ERROR(hipMemPoolDestroy(mem_pool), hipErrorInvalidValue);
}
SECTION("Attempt to destroy default mempool") {
hipMemPool_t default_mem_pool = nullptr;
int device = 0;
HIP_CHECK(hipDeviceGetDefaultMemPool(&default_mem_pool, device));
HIP_CHECK_ERROR(hipMemPoolDestroy(default_mem_pool), hipErrorInvalidValue);
}
}
+361
Ver Arquivo
@@ -0,0 +1,361 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <resource_guards.hh>
#include <utils.hh>
/**
* @addtogroup hipMemPoolSetAccess hipMemPoolSetAccess
* @{
* @ingroup StreamOTest
* `hipMemPoolSetAccess(hipMemPool_t mem_pool, const hipMemAccessDesc* desc_list, size_t count)`
* - Controls visibility of the specified pool between devices
*/
__global__ void copyP2PAndScale(int* dst, const int* src, size_t N) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < N) {
// scale & store src vector.
dst[idx] = 2 * src[idx];
}
}
static void MemPoolSetGetAccess(const MemPools mempool_type, int src_device, int dst_device,
hipMemAccessFlags access_flags) {
MemPoolGuard mempool(mempool_type, src_device);
hipMemAccessDesc desc;
memset(&desc, 0, sizeof(hipMemAccessDesc));
desc.location.type = hipMemLocationTypeDevice;
desc.location.id = dst_device;
desc.flags = access_flags;
HIP_CHECK(hipMemPoolSetAccess(mempool.mempool(), &desc, 1));
hipMemAccessFlags flags = hipMemAccessFlagsProtNone;
HIP_CHECK(hipMemPoolGetAccess(&flags, mempool.mempool(), &desc.location));
REQUIRE(flags == access_flags);
}
/**
* Test Description
* ------------------------
* - Basic test to verify hipMemPoolSetAccess/hipMemPoolGetAccess on a single device.
* Test source
* ------------------------
* - /unit/memory/hipMemPoolSetGetAccess.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolSetGetAccess_Positive_Basic") {
const auto device = GENERATE(range(0, HipTest::getDeviceCount()));
int mem_pool_support = 0;
HIP_CHECK(
hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, device));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
const auto mempool_type = GENERATE(MemPools::dev_default, MemPools::created);
MemPoolSetGetAccess(mempool_type, device, device, hipMemAccessFlagsProtReadWrite);
}
int CheckP2PMemPoolSupport(int src_device, int dst_device) {
int mem_pool_support = 0;
HIP_CHECK(
hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, src_device));
if (mem_pool_support) {
HIP_CHECK(hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported,
dst_device));
}
return mem_pool_support;
}
/**
* Test Description
* ------------------------
* - Basic test to verify hipMemPoolSetAccess/hipMemPoolGetAccess on multiple devices.
* Test source
* ------------------------
* - /unit/memory/hipMemPoolSetGetAccess.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolSetGetAccess_Positive_MultipleGPU") {
const auto device_count = HipTest::getDeviceCount();
if (device_count < 2) {
HipTest::HIP_SKIP_TEST("Skipping because devices < 2");
return;
}
const auto src_device = GENERATE(range(0, HipTest::getDeviceCount()));
const auto dst_device = GENERATE(range(0, HipTest::getDeviceCount()));
INFO("Src device: " << src_device << ", Dst device: " << dst_device);
int mem_pool_support = CheckP2PMemPoolSupport(src_device, dst_device);
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
const auto mempool_type = GENERATE(MemPools::dev_default, MemPools::created);
const auto access_flag = GENERATE(hipMemAccessFlagsProtNone, hipMemAccessFlagsProtRead,
hipMemAccessFlagsProtReadWrite);
int can_access_peer = 0;
HIP_CHECK(hipSetDevice(src_device));
HIP_CHECK(hipDeviceCanAccessPeer(&can_access_peer, src_device, dst_device));
if (can_access_peer) {
MemPoolSetGetAccess(mempool_type, src_device, dst_device, access_flag);
}
}
void MemPoolSetGetAccess_P2P(const MemPools mempool_type) {
const auto src_device = GENERATE(range(0, HipTest::getDeviceCount()));
const auto dst_device = GENERATE(range(0, HipTest::getDeviceCount()));
INFO("Src device: " << src_device << ", Dst device: " << dst_device);
const auto allocation_size = GENERATE(kPageSize / 2, kPageSize, kPageSize * 2);
int mem_pool_support = CheckP2PMemPoolSupport(src_device, dst_device);
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
int *alloc_mem1, *alloc_mem2;
int can_access_peer = 0;
HIP_CHECK(hipSetDevice(src_device));
HIP_CHECK(hipDeviceCanAccessPeer(&can_access_peer, src_device, dst_device));
if (can_access_peer) {
hipEvent_t waitOnStream1;
LinearAllocGuard<int> host_alloc(LinearAllocs::malloc, allocation_size);
HIP_CHECK(hipEventCreate(&waitOnStream1))
StreamGuard stream1(Streams::withFlags, hipStreamNonBlocking);
// Get/create mempool for src_device
MemPoolGuard mempool(mempool_type, src_device);
// Allocate memory in a stream from the pool set above
if (mempool_type == MemPools::dev_default) {
HIP_CHECK(
hipMallocAsync(reinterpret_cast<void**>(&alloc_mem1), allocation_size, stream1.stream()));
} else {
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem1), allocation_size,
mempool.mempool(), stream1.stream()));
}
const auto element_count = allocation_size / sizeof(int);
constexpr auto thread_count = 1024;
const auto block_count = element_count / thread_count + 1;
constexpr int expected_value = 15;
VectorSet<<<block_count, thread_count, 0, stream1.stream()>>>(alloc_mem1, expected_value,
element_count);
HIP_CHECK(hipEventRecord(waitOnStream1, stream1.stream()));
HIP_CHECK(hipSetDevice(dst_device));
StreamGuard stream2(Streams::withFlags, hipStreamNonBlocking);
// Allocate memory in dst device
HIP_CHECK(
hipMallocAsync(reinterpret_cast<void**>(&alloc_mem2), allocation_size, stream2.stream()));
// Setup peer mappings for dst device
hipMemAccessDesc desc;
memset(&desc, 0, sizeof(hipMemAccessDesc));
desc.location.type = hipMemLocationTypeDevice;
desc.location.id = dst_device;
desc.flags = hipMemAccessFlagsProtReadWrite;
HIP_CHECK(hipMemPoolSetAccess(mempool.mempool(), &desc, 1));
hipMemAccessFlags flags = hipMemAccessFlagsProtNone;
HIP_CHECK(hipMemPoolGetAccess(&flags, mempool.mempool(), &desc.location));
REQUIRE(flags == hipMemAccessFlagsProtReadWrite);
HIP_CHECK(hipStreamWaitEvent(stream2.stream(), waitOnStream1, 0));
copyP2PAndScale<<<block_count, thread_count, 0, stream2.stream()>>>(alloc_mem2, alloc_mem1,
element_count);
HIP_CHECK(hipMemcpyAsync(host_alloc.host_ptr(), alloc_mem2, allocation_size,
hipMemcpyDeviceToHost, stream2.stream()));
HIP_CHECK(hipFreeAsync(alloc_mem1, stream2.stream()));
HIP_CHECK(hipFreeAsync(alloc_mem2, stream2.stream()));
HIP_CHECK(hipStreamSynchronize(stream2.stream()));
ArrayFindIfNot(host_alloc.host_ptr(), 2 * expected_value, element_count);
}
}
/**
* Test Description
* ------------------------
* - Basic test to verify peer-to-peer access of stream ordered memory with hipMemPoolSetAccess.
* Test source
* ------------------------
* - /unit/memory/hipMemPoolSetGetAccess.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolSetGetAccess_Positive_P2P") {
const auto device_count = HipTest::getDeviceCount();
if (device_count < 2) {
HipTest::HIP_SKIP_TEST("Skipping because devices < 2");
return;
}
SECTION("Default MemPool") { MemPoolSetGetAccess_P2P(MemPools::dev_default); }
SECTION("Created MemPool") { MemPoolSetGetAccess_P2P(MemPools::created); }
}
/**
* Test Description
* ------------------------
* - Test to verify hipMemPoolSetAccess behavior with invalid arguments:
* -# Nullptr mem_pool
* -# Desc is nullptr and count is > 0
* -# Count > num_device
* -# Invalid desc location type
* -# Invalid desc location id
* -# Revoking access to own memory pool
*
* Test source
* ------------------------
* - /unit/memory/hipMemPoolSetGetAccess.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolSetAccess_Negative_Parameters") {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
MemPoolGuard mempool(MemPools::dev_default, device_id);
int num_dev = 0;
HIP_CHECK(hipGetDeviceCount(&num_dev));
hipMemAccessDesc desc;
memset(&desc, 0, sizeof(hipMemAccessDesc));
desc.location.type = hipMemLocationTypeDevice;
desc.location.id = device_id;
desc.flags = hipMemAccessFlagsProtReadWrite;
SECTION("Mempool is nullptr") {
HIP_CHECK_ERROR(hipMemPoolSetAccess(nullptr, &desc, 1), hipErrorInvalidValue);
}
#if HT_AMD
SECTION("Desc is nullptr and count is > 0") {
HIP_CHECK_ERROR(hipMemPoolSetAccess(mempool.mempool(), nullptr, 1), hipErrorInvalidValue);
}
#endif
SECTION("Count > num_device") {
HIP_CHECK_ERROR(hipMemPoolSetAccess(mempool.mempool(), &desc, (num_dev + 1)),
hipErrorNotSupported);
}
SECTION("Passing invalid desc location type") {
desc.location.type = hipMemLocationTypeInvalid;
HIP_CHECK_ERROR(hipMemPoolSetAccess(mempool.mempool(), &desc, 1), hipErrorNotSupported);
desc.location.type = hipMemLocationTypeDevice;
}
SECTION("Passing invalid desc location id") {
desc.location.id = num_dev;
HIP_CHECK_ERROR(hipMemPoolSetAccess(mempool.mempool(), &desc, 1), hipErrorInvalidDevice);
desc.location.id = device_id;
}
SECTION("Revoking access to own memory pool") {
desc.flags = hipMemAccessFlagsProtNone;
HIP_CHECK_ERROR(hipMemPoolSetAccess(mempool.mempool(), &desc, 1), hipErrorInvalidDevice);
desc.flags = hipMemAccessFlagsProtReadWrite;
}
}
/**
* End doxygen group hipMemPoolSetAccess.
* @}
*/
/**
* @addtogroup hipMemPoolGetAccess hipMemPoolGetAccess
* @{
* @ingroup StreamOTest
* `hipMemPoolGetAccess(hipMemAccessFlags* flags, hipMemPool_t mem_pool, hipMemLocation* location)`
* - Returns the accessibility of a pool from a device
*/
/**
* Test Description
* ------------------------
* - Test to verify hipMemPoolGetAccess behavior with invalid arguments:
* -# Nullptr mem_pool
* -# Flags is nullptr
* -# Invalid location type
* -# Invalid location id
*
* Test source
* ------------------------
* - /unit/memory/hipMemPoolSetGetAccess.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolGetAccess_Negative_Parameters") {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
MemPoolGuard mempool(MemPools::dev_default, device_id);
int num_dev = 0;
HIP_CHECK(hipGetDeviceCount(&num_dev));
hipMemAccessFlags flags = hipMemAccessFlagsProtNone;
hipMemLocation location = {hipMemLocationTypeDevice, device_id};
SECTION("Mempool is nullptr") {
HIP_CHECK_ERROR(hipMemPoolGetAccess(&flags, nullptr, &location), hipErrorInvalidValue);
}
#if HT_AMD
SECTION("Flags is nullptr") {
HIP_CHECK_ERROR(hipMemPoolGetAccess(nullptr, mempool.mempool(), &location),
hipErrorInvalidValue);
}
#endif
SECTION("Passing invalid location type") {
location.type = hipMemLocationTypeInvalid;
HIP_CHECK_ERROR(hipMemPoolGetAccess(&flags, mempool.mempool(), &location),
hipErrorInvalidValue);
location.type = hipMemLocationTypeDevice;
}
SECTION("Passing invalid location id") {
location.id = num_dev;
HIP_CHECK_ERROR(hipMemPoolGetAccess(&flags, mempool.mempool(), &location),
hipErrorInvalidValue);
location.id = device_id;
}
}
@@ -0,0 +1,590 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "mempool_common.hh"
#include <resource_guards.hh>
#include <utils.hh>
/**
* @addtogroup hipMemPoolSetAttribute hipMemPoolSetAttribute
* @{
* @ingroup StreamOTest
* `hipMemPoolSetAttribute(hipMemPool_t mem_pool, hipMemPoolAttr attr, void* value)`
* - Sets attributes of a memory pool
*/
template <typename T>
static void MemPoolSetGetAttribute(const hipMemPool_t mempool, const hipMemPoolAttr attr,
T& set_value) {
T get_value = 100;
HIP_CHECK(hipMemPoolSetAttribute(mempool, attr, &set_value));
HIP_CHECK(hipMemPoolGetAttribute(mempool, attr, &get_value));
REQUIRE(get_value == set_value);
}
/**
* Test Description
* ------------------------
* - Basic test to verify that default attribute values are correct.
* Test source
* ------------------------
* - /unit/memory/hipMemPoolSetGetAttribute.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolSetGetAttribute_Positive_Default") {
const auto device = GENERATE(range(0, HipTest::getDeviceCount()));
int mem_pool_support = 0;
HIP_CHECK(
hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, device));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
const auto mempool_type = GENERATE(MemPools::dev_default, MemPools::created);
MemPoolGuard mempool(mempool_type, device);
const auto attr_type =
GENERATE(hipMemPoolReuseFollowEventDependencies, hipMemPoolReuseAllowOpportunistic,
hipMemPoolReuseAllowInternalDependencies);
// Check default value
int def_value = 0;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr_type, &def_value));
REQUIRE(def_value == 1);
// Check if attribute can be disabled
int set_value = 0;
MemPoolSetGetAttribute(mempool.mempool(), attr_type, set_value);
}
/**
* Test Description
* ------------------------
* - Basic test to verify hipMemPoolSetAttribute/hipMemPoolGetAttribute functionality.
* Test source
* ------------------------
* - /unit/memory/hipMemPoolSetGetAttribute.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolSetGetAttribute_Positive_MemBasic") {
const auto device = GENERATE(range(0, HipTest::getDeviceCount()));
int mem_pool_support = 0;
HIP_CHECK(
hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, device));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
const auto mempool_type = GENERATE(MemPools::dev_default, MemPools::created);
MemPoolGuard mempool(mempool_type, device);
// Check hipMemPoolAttrReleaseThreshold default value
hipMemPoolAttr attr = hipMemPoolAttrReleaseThreshold;
std::uint64_t value64 = 100;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &value64));
REQUIRE(value64 == 0);
// Check setting hipMemPoolAttrReleaseThreshold to a value
std::uint64_t set_value64 = kPageSize;
MemPoolSetGetAttribute(mempool.mempool(), hipMemPoolAttrReleaseThreshold, set_value64);
// Check reset of hipMemPoolAttrReservedMemHigh and hipMemPoolAttrUsedMemHigh
set_value64 = 0;
MemPoolSetGetAttribute(mempool.mempool(), hipMemPoolAttrReservedMemHigh, set_value64);
MemPoolSetGetAttribute(mempool.mempool(), hipMemPoolAttrUsedMemHigh, set_value64);
}
/**
* Test Description
* ------------------------
* - Basic test to verify correct behavior of the Opportunistic attribute.
* Test source
* ------------------------
* - /unit/memory/hipMemPoolSetGetAttribute.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolSetAttribute_Opportunistic") {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
int mem_pool_support = 0;
HIP_CHECK(hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, 0));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
MemPoolGuard mempool(MemPools::created, device_id);
hipMemPoolAttr attr;
int blocks = 2;
int clk_rate;
if (IsGfx11()) {
HIPCHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeWallClockRate, 0));
} else {
HIPCHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeClockRate, 0));
}
int *alloc_mem1, *alloc_mem2, *alloc_mem3;
// Create 2 async non-blocking streams
StreamGuard stream1(Streams::withFlags, hipStreamNonBlocking);
StreamGuard stream2(Streams::withFlags, hipStreamNonBlocking);
size_t allocation_size = kPageSize;
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem3), allocation_size,
mempool.mempool(), stream1.stream()));
int value = 0;
SECTION("Disallow Opportunistic - No Reuse") {
allocation_size = kPageSize * kPageSize * 2;
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem1), allocation_size,
mempool.mempool(), stream1.stream()));
// Disable all default pool states
attr = hipMemPoolReuseFollowEventDependencies;
HIP_CHECK(hipMemPoolSetAttribute(mempool.mempool(), attr, &value));
attr = hipMemPoolReuseAllowOpportunistic;
HIP_CHECK(hipMemPoolSetAttribute(mempool.mempool(), attr, &value));
attr = hipMemPoolReuseAllowInternalDependencies;
HIP_CHECK(hipMemPoolSetAttribute(mempool.mempool(), attr, &value));
// Run kernel for 500 ms in the first stream
if (IsGfx11()) {
kernel_500ms_gfx11<<<32, blocks, 0, stream1.stream()>>>(alloc_mem1, clk_rate);
} else {
kernel_500ms<<<32, blocks, 0, stream1.stream()>>>(alloc_mem1, clk_rate);
}
// Not a real free, since kernel isn't done
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem1), stream1.stream()));
// Sleep for 1 second GPU should be idle by now
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// Allocate memory for the second stream
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem2), allocation_size,
mempool.mempool(), stream2.stream()));
// Without Opportunistic state runtime must allocate another buffer
REQUIRE(alloc_mem1 != alloc_mem2);
// Run kernel with the new memory in the second stream
if (IsGfx11()) {
kernel_500ms_gfx11<<<32, blocks, 0, stream2.stream()>>>(alloc_mem2, clk_rate);
} else {
kernel_500ms<<<32, blocks, 0, stream2.stream()>>>(alloc_mem2, clk_rate);
}
HIP_CHECK(hipStreamSynchronize(stream1.stream()));
HIP_CHECK(hipStreamSynchronize(stream2.stream()));
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem2), stream2.stream()));
}
SECTION("Disallow Opportunistic - Reuse") {
allocation_size = kPageSize * kPageSize * 2;
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem1), allocation_size,
mempool.mempool(), stream1.stream()));
// Disable all default pool states
attr = hipMemPoolReuseFollowEventDependencies;
HIP_CHECK(hipMemPoolSetAttribute(mempool.mempool(), attr, &value));
attr = hipMemPoolReuseAllowOpportunistic;
HIP_CHECK(hipMemPoolSetAttribute(mempool.mempool(), attr, &value));
attr = hipMemPoolReuseAllowInternalDependencies;
HIP_CHECK(hipMemPoolSetAttribute(mempool.mempool(), attr, &value));
// Run kernel for 500 ms in the first stream
if (IsGfx11()) {
kernel_500ms_gfx11<<<32, blocks, 0, stream1.stream()>>>(alloc_mem1, clk_rate);
} else {
kernel_500ms<<<32, blocks, 0, stream1.stream()>>>(alloc_mem1, clk_rate);
}
// Not a real free, since kernel isn't done
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem1), stream1.stream()));
// Sleep for 1 second GPU should be idle by now
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// Allocate memory for the second stream
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem2), allocation_size,
mempool.mempool(), stream1.stream()));
// Without Opportunistic state runtime must allocate another buffer
REQUIRE(alloc_mem1 == alloc_mem2);
// Run kernel with the new memory in the second stream
if (IsGfx11()) {
kernel_500ms_gfx11<<<32, blocks, 0, stream1.stream()>>>(alloc_mem2, clk_rate);
} else {
kernel_500ms<<<32, blocks, 0, stream1.stream()>>>(alloc_mem2, clk_rate);
}
HIP_CHECK(hipStreamSynchronize(stream1.stream()));
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem2), stream1.stream()));
}
SECTION("Allow Opportunistic - Reuse") {
allocation_size = kPageSize * kPageSize * 2;
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem1), allocation_size,
mempool.mempool(), stream1.stream()));
value = 1;
attr = hipMemPoolReuseAllowOpportunistic;
// Enable Opportunistic
HIP_CHECK(hipMemPoolSetAttribute(mempool.mempool(), attr, &value));
// Run kernel for 500 ms in the first stream
if (IsGfx11()) {
HIP_CHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeWallClockRate, 0));
kernel_500ms_gfx11<<<32, blocks, 0, stream1.stream()>>>(alloc_mem1, clk_rate);
} else {
HIP_CHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeClockRate, 0));
kernel_500ms<<<32, blocks, 0, stream1.stream()>>>(alloc_mem1, clk_rate);
}
// Not a real free, since kernel isn't done
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem1), stream1.stream()));
// Sleep for 1 second GPU should be idle by now
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// Allocate memory for the second stream
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem2), allocation_size,
mempool.mempool(), stream2.stream()));
// With Opportunistic state runtime will reuse freed buffer A
REQUIRE(alloc_mem1 == alloc_mem2);
// Run kernel with the new memory in the second stream
if (IsGfx11()) {
kernel_500ms_gfx11<<<32, blocks, 0, stream2.stream()>>>(alloc_mem2, clk_rate);
} else {
kernel_500ms<<<32, blocks, 0, stream2.stream()>>>(alloc_mem2, clk_rate);
}
HIP_CHECK(hipStreamSynchronize(stream1.stream()));
HIP_CHECK(hipStreamSynchronize(stream2.stream()));
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem2), stream2.stream()));
}
SECTION("Allow Opportunistic - No Reuse") {
allocation_size = kPageSize * kPageSize * 2;
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem1), allocation_size,
mempool.mempool(), stream1.stream()));
value = 1;
attr = hipMemPoolReuseAllowOpportunistic;
// Enable Opportunistic
HIP_CHECK(hipMemPoolSetAttribute(mempool.mempool(), attr, &value));
// Run kernel for 500 ms in the first stream
if (IsGfx11()) {
kernel_500ms_gfx11<<<32, blocks, 0, stream1.stream()>>>(alloc_mem1, clk_rate);
} else {
kernel_500ms<<<32, blocks, 0, stream1.stream()>>>(alloc_mem1, clk_rate);
}
// Not a real free, since kernel isn't done
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem1), stream1.stream()));
// Allocate memory for the second stream
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem2), allocation_size,
mempool.mempool(), stream2.stream()));
// With Opportunistic state runtime can't reuse freed buffer A, because it's still busy with the
// kernel
REQUIRE(alloc_mem1 != alloc_mem2);
// Run kernel with the new memory in the second stream
if (IsGfx11()) {
kernel_500ms_gfx11<<<32, blocks, 0, stream2.stream()>>>(alloc_mem2, clk_rate);
} else {
kernel_500ms<<<32, blocks, 0, stream2.stream()>>>(alloc_mem2, clk_rate);
}
HIP_CHECK(hipStreamSynchronize(stream1.stream()));
HIP_CHECK(hipStreamSynchronize(stream2.stream()));
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem2), stream2.stream()));
}
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem3), stream1.stream()));
}
/**
* Test Description
* ------------------------
* - Basic test to verify correct behavior of the EventDependencies attribute.
* Test source
* ------------------------
* - /unit/memory/hipMemPoolSetGetAttribute.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolSetAttribute_EventDependencies") {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
int mem_pool_support = 0;
HIP_CHECK(hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, 0));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
MemPoolGuard mempool(MemPools::created, device_id);
hipMemPoolAttr attr;
int blocks = 2;
int clk_rate;
if (IsGfx11()) {
HIPCHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeWallClockRate, 0));
} else {
HIPCHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeClockRate, 0));
}
int *alloc_mem1, *alloc_mem2, *alloc_mem3;
// Create 2 async non-blocking streams
StreamGuard stream1(Streams::withFlags, hipStreamNonBlocking);
StreamGuard stream2(Streams::withFlags, hipStreamNonBlocking);
hipEvent_t event;
HIP_CHECK(hipEventCreate(&event));
size_t allocation_size = kPageSize;
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem3), allocation_size,
mempool.mempool(), stream1.stream()));
int value = 0;
SECTION("Allow Event Dependencies - Reuse") {
allocation_size = kPageSize * kPageSize * 2;
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem1), allocation_size,
mempool.mempool(), stream1.stream()));
value = 1;
attr = hipMemPoolReuseFollowEventDependencies;
// Enable Opportunistic
HIP_CHECK(hipMemPoolSetAttribute(mempool.mempool(), attr, &value));
// Run kernel for 500 ms in the first stream
if (IsGfx11()) {
HIP_CHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeWallClockRate, 0));
kernel_500ms_gfx11<<<32, blocks, 0, stream1.stream()>>>(alloc_mem1, clk_rate);
} else {
HIP_CHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeClockRate, 0));
kernel_500ms<<<32, blocks, 0, stream1.stream()>>>(alloc_mem1, clk_rate);
}
// Not a real free, since kernel isn't done
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem1), stream1.stream()));
HIP_CHECK(hipEventRecord(event, stream1.stream()));
HIP_CHECK(hipStreamWaitEvent(stream2.stream(), event, 0));
// Allocate memory for the second stream
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem2), allocation_size,
mempool.mempool(), stream2.stream()));
// With Opportunistic state runtime will reuse freed buffer A
REQUIRE(alloc_mem1 == alloc_mem2);
// Run kernel with the new memory in the second stream
if (IsGfx11()) {
kernel_500ms_gfx11<<<32, blocks, 0, stream2.stream()>>>(alloc_mem2, clk_rate);
} else {
kernel_500ms<<<32, blocks, 0, stream2.stream()>>>(alloc_mem2, clk_rate);
}
HIP_CHECK(hipStreamSynchronize(stream1.stream()));
HIP_CHECK(hipStreamSynchronize(stream2.stream()));
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem2), stream2.stream()));
}
SECTION("Disallow Event Dependencies - No Reuse") {
allocation_size = kPageSize * kPageSize * 2;
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem1), allocation_size,
mempool.mempool(), stream1.stream()));
value = 0;
attr = hipMemPoolReuseFollowEventDependencies;
// Enable Opportunistic
HIP_CHECK(hipMemPoolSetAttribute(mempool.mempool(), attr, &value));
// Run kernel for 500 ms in the first stream
if (IsGfx11()) {
kernel_500ms_gfx11<<<32, blocks, 0, stream1.stream()>>>(alloc_mem1, clk_rate);
} else {
kernel_500ms<<<32, blocks, 0, stream1.stream()>>>(alloc_mem1, clk_rate);
}
// Not a real free, since kernel isn't done
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem1), stream1.stream()));
HIP_CHECK(hipEventRecord(event, stream1.stream()));
HIP_CHECK(hipStreamWaitEvent(stream2.stream(), event, 0));
// Allocate memory for the second stream
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem2), allocation_size,
mempool.mempool(), stream2.stream()));
// With Opportunistic state runtime can't reuse freed buffer A, because it's still busy with the
// kernel
REQUIRE(alloc_mem1 != alloc_mem2);
// Run kernel with the new memory in the second stream
if (IsGfx11()) {
kernel_500ms_gfx11<<<32, blocks, 0, stream2.stream()>>>(alloc_mem2, clk_rate);
} else {
kernel_500ms<<<32, blocks, 0, stream2.stream()>>>(alloc_mem2, clk_rate);
}
HIP_CHECK(hipStreamSynchronize(stream1.stream()));
HIP_CHECK(hipStreamSynchronize(stream2.stream()));
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem2), stream2.stream()));
}
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem3), stream1.stream()));
HIP_CHECK(hipEventDestroy(event));
}
/**
* Test Description
* ------------------------
* - Test to verify hipMemPoolSetAttribute behavior with invalid arguments:
* -# Nullptr mem_pool
* -# Attribute value is not valid
* -# Nullptr value
* -# hipMemPoolAttrReservedMemHigh set to non-zero
* -# IhipMemPoolAttrUsedMemHigh set to non-zero
*
* Test source
* ------------------------
* - /unit/memory/hipMemPoolSetGetAttribute.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolSetAttribute_Negative_Parameters") {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
MemPoolGuard mempool(MemPools::dev_default, device_id);
hipMemPoolAttr attr = hipMemPoolReuseFollowEventDependencies;
int set_value = 0;
std::uint64_t set_value64 = 0;
SECTION("Mempool is nullptr") {
HIP_CHECK_ERROR(hipMemPoolSetAttribute(nullptr, attr, &set_value), hipErrorInvalidValue);
}
SECTION("Attribute value is not valid") {
HIP_CHECK_ERROR(
hipMemPoolSetAttribute(mempool.mempool(), static_cast<hipMemPoolAttr>(0x9), &set_value),
hipErrorInvalidValue);
}
#if HT_AMD
SECTION("Set values is nullptr") {
HIP_CHECK_ERROR(hipMemPoolSetAttribute(mempool.mempool(), attr, nullptr), hipErrorInvalidValue);
}
#endif
SECTION("Set hipMemPoolAttrReservedMemHigh to non-zero") {
hipMemPoolAttr attr = hipMemPoolAttrReservedMemHigh;
set_value64 = 1;
HIP_CHECK_ERROR((hipMemPoolSetAttribute(mempool.mempool(), attr, &set_value64)),
hipErrorInvalidValue);
}
SECTION("Set hipMemPoolAttrUsedMemHigh to non-zero") {
hipMemPoolAttr attr = hipMemPoolAttrUsedMemHigh;
set_value64 = 1;
HIP_CHECK_ERROR((hipMemPoolSetAttribute(mempool.mempool(), attr, &set_value64)),
hipErrorInvalidValue);
}
}
/**
* End doxygen group hipMemPoolSetAttribute.
* @}
*/
/**
* @addtogroup hipMemPoolGetAttribute hipMemPoolGetAttribute
* @{
* @ingroup StreamOTest
* `hipMemPoolGetAttribute(hipMemPool_t mem_pool, hipMemPoolAttr attr, void* value)`
* - Gets attributes of a memory pool
*/
/**
* Test Description
* ------------------------
* - Test to verify hipMemPoolGetAttribute behavior with invalid arguments:
* -# Nullptr mem_pool
* -# Attribute value is not valid
* -# Nullptr value
*
* Test source
* ------------------------
* - /unit/memory/hipMemPoolSetGetAttribute.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolGetAttribute_Negative_Parameters") {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
MemPoolGuard mempool(MemPools::dev_default, device_id);
hipMemPoolAttr attr = hipMemPoolReuseFollowEventDependencies;
int get_value = 0;
SECTION("Mempool is nullptr") {
HIP_CHECK_ERROR(hipMemPoolGetAttribute(nullptr, attr, &get_value), hipErrorInvalidValue);
}
SECTION("Attribute value is not valid") {
HIP_CHECK_ERROR(
hipMemPoolGetAttribute(mempool.mempool(), static_cast<hipMemPoolAttr>(0x9), &get_value),
hipErrorInvalidValue);
}
SECTION("Get values is nullptr") {
HIP_CHECK_ERROR(hipMemPoolGetAttribute(mempool.mempool(), attr, nullptr), hipErrorInvalidValue);
}
}
+165
Ver Arquivo
@@ -0,0 +1,165 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "mempool_common.hh"
#include <resource_guards.hh>
#include <utils.hh>
/**
* @addtogroup hipMemPoolTrimTo hipMemPoolTrimTo
* @{
* @ingroup StreamOTest
* `hipMemPoolTrimTo(hipMemPool_t mem_pool, size_t min_bytes_to_hold)` -
* Releases freed memory back to the OS
*/
/**
* Test Description
* ------------------------
* - Test to verify hipMemPoolTrimTo behavior with invalid arguments:
* -# Nullptr mem_pool
*
* Test source
* ------------------------
* - /unit/memory/hipMemPoolTrimTo.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolTrimTo_Negative_Parameter") {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
int mem_pool_support = 0;
HIP_CHECK(hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, 0));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
size_t trim_size = 1024;
SECTION("Passing nullptr to mem_pool") {
HIP_CHECK_ERROR(hipMemPoolTrimTo(nullptr, trim_size), hipErrorInvalidValue);
}
}
/**
* Test Description
* ------------------------
* - Basic test to verify hipMemPoolTrimTo releases memory correctly to the OS.
* Test source
* ------------------------
* - /unit/memory/hipMemPoolTrimTo.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 6.0
*/
TEST_CASE("Unit_hipMemPoolTrimTo_Positive_Basic") {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
int mem_pool_support = 0;
HIP_CHECK(hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, 0));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
const size_t allocation_size1 = kPageSize * kPageSize * 2;
const size_t allocation_size2 = kPageSize / 2;
MemPoolGuard mempool(MemPools::created, device_id);
int* alloc_mem1;
int* alloc_mem2;
StreamGuard stream(Streams::created);
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem1), allocation_size1,
mempool.mempool(), stream.stream()));
HIP_CHECK(hipMallocFromPoolAsync(reinterpret_cast<void**>(&alloc_mem2), allocation_size2,
mempool.mempool(), stream.stream()));
int blocks = 2;
int clk_rate;
if (IsGfx11()) {
HIP_CHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeWallClockRate, 0));
kernel_500ms_gfx11<<<32, blocks, 0, stream.stream()>>>(alloc_mem1, clk_rate);
} else {
HIP_CHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeClockRate, 0));
kernel_500ms<<<32, blocks, 0, stream.stream()>>>(alloc_mem1, clk_rate);
}
hipMemPoolAttr attr;
attr = hipMemPoolAttrReleaseThreshold;
// The pool must hold 128MB
std::uint64_t threshold = 128 * 1024 * 1024;
HIP_CHECK(hipMemPoolSetAttribute(mempool.mempool(), attr, &threshold));
// Not a real free, since kernel isn't done
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem1), stream.stream()));
// Get reserved memory before trim
attr = hipMemPoolAttrReservedMemCurrent;
std::uint64_t res_before_trim = 0;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &res_before_trim));
size_t min_bytes_to_hold = allocation_size2;
HIP_CHECK(hipMemPoolTrimTo(mempool.mempool(), min_bytes_to_hold));
std::uint64_t res_after_trim = 0;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &res_after_trim));
// Trim must be a nop because execution isn't done
REQUIRE(res_before_trim == res_after_trim);
HIP_CHECK(hipStreamSynchronize(stream.stream()));
std::uint64_t res_after_sync = 0;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &res_after_sync));
// Since hipMemPoolAttrReleaseThreshold is 128 MB sync does nothing to the freed memory
REQUIRE(res_after_trim == res_after_sync);
HIP_CHECK(hipMemPoolTrimTo(mempool.mempool(), min_bytes_to_hold));
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &res_after_trim));
// Validate memory after real trim. The pool must hold less memory than before
REQUIRE(res_after_trim < res_after_sync);
attr = hipMemPoolAttrReleaseThreshold;
std::uint64_t value64 = 0;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &value64));
// Make sure the threshold query works
REQUIRE(threshold == value64);
attr = hipMemPoolAttrUsedMemCurrent;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &value64));
// Make sure the current usage query works - just small buffer left
REQUIRE(allocation_size2 == value64);
attr = hipMemPoolAttrUsedMemHigh;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &value64));
// Make sure the high watermark usage works - the both buffers must be reported
REQUIRE((allocation_size1 + allocation_size2) == value64);
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem2), stream.stream()));
}
+292
Ver Arquivo
@@ -0,0 +1,292 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
#include <hip_test_common.hh>
#include <resource_guards.hh>
#include <utils.hh>
namespace {
constexpr hipMemPoolProps kPoolProps = {
hipMemAllocationTypePinned, hipMemHandleTypeNone, {hipMemLocationTypeDevice, 0}, nullptr, {0}};
constexpr auto wait_ms = 500;
} // anonymous namespace
template <typename T> __global__ void kernel_500ms(T* host_res, int clk_rate) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
host_res[tid] = tid + 1;
__threadfence_system();
// expecting that the data is getting flushed to host here!
uint64_t start = clock64() / clk_rate, cur;
if (clk_rate > 1) {
do {
cur = clock64() / clk_rate - start;
} while (cur < wait_ms);
} else {
do {
cur = clock64() / start;
} while (cur < wait_ms);
}
}
template <typename T> __global__ void kernel_500ms_gfx11(T* host_res, int clk_rate) {
#if HT_AMD
int tid = threadIdx.x + blockIdx.x * blockDim.x;
host_res[tid] = tid + 1;
__threadfence_system();
// expecting that the data is getting flushed to host here!
uint64_t start = wall_clock64() / clk_rate, cur;
if (clk_rate > 1) {
do {
cur = wall_clock64() / clk_rate - start;
} while (cur < wait_ms);
} else {
do {
cur = wall_clock64() / start;
} while (cur < wait_ms);
}
#endif
}
template <typename F> void MallocMemPoolAsync_OneAlloc(F malloc_func, const MemPools mempool_type) {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
int mem_pool_support = 0;
HIP_CHECK(hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, 0));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
const auto allocation_size = GENERATE(kPageSize / 2, kPageSize, kPageSize * 2);
LinearAllocGuard<int> host_alloc(LinearAllocs::hipHostMalloc, allocation_size);
MemPoolGuard mempool(mempool_type, device_id);
int* alloc_mem;
StreamGuard stream(Streams::created);
HIP_CHECK(malloc_func(reinterpret_cast<void**>(&alloc_mem), allocation_size, mempool.mempool(),
stream.stream()));
int blocks = 1024;
int clk_rate;
hipMemPoolAttr attr;
if (IsGfx11()) {
HIP_CHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeWallClockRate, 0));
kernel_500ms_gfx11<<<32, blocks, 0, stream.stream()>>>(alloc_mem, clk_rate);
} else {
HIP_CHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeClockRate, 0));
kernel_500ms<<<32, blocks, 0, stream.stream()>>>(alloc_mem, clk_rate);
}
const auto element_count = allocation_size / sizeof(int);
constexpr auto thread_count = 1024;
const auto block_count = element_count / thread_count + 1;
constexpr int expected_value = 17;
VectorSet<<<block_count, thread_count, 0, stream.stream()>>>(alloc_mem, expected_value,
element_count);
HIP_CHECK(hipMemcpyAsync(host_alloc.host_ptr(), alloc_mem, allocation_size, hipMemcpyDeviceToHost,
stream.stream()));
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem), stream.stream()));
attr = hipMemPoolAttrReservedMemCurrent;
std::uint64_t res_before_sync = 0;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &res_before_sync));
HIP_CHECK(hipStreamSynchronize(stream.stream()));
std::uint64_t res_after_sync = 0;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &res_after_sync));
// Sync must release memory to OS
REQUIRE(res_after_sync <= res_before_sync);
std::uint64_t used_mem = 10;
attr = hipMemPoolAttrUsedMemCurrent;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &used_mem));
REQUIRE(0 == used_mem);
ArrayFindIfNot(host_alloc.host_ptr(), expected_value, element_count);
}
template <typename F>
void MallocMemPoolAsync_TwoAllocs(F malloc_func, const MemPools mempool_type) {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
int mem_pool_support = 0;
HIP_CHECK(hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, 0));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
const auto allocation_size = GENERATE(kPageSize / 2, kPageSize, kPageSize * 2);
LinearAllocGuard<int> host_alloc(LinearAllocs::hipHostMalloc, allocation_size);
MemPoolGuard mempool(mempool_type, device_id);
int* alloc_mem1;
int* alloc_mem2;
StreamGuard stream(Streams::created);
HIP_CHECK(malloc_func(reinterpret_cast<void**>(&alloc_mem1), allocation_size, mempool.mempool(),
stream.stream()));
HIP_CHECK(malloc_func(reinterpret_cast<void**>(&alloc_mem2), allocation_size, mempool.mempool(),
stream.stream()));
int blocks = 1024;
int clk_rate;
hipMemPoolAttr attr;
if (IsGfx11()) {
HIP_CHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeWallClockRate, 0));
kernel_500ms_gfx11<<<32, blocks, 0, stream.stream()>>>(alloc_mem1, clk_rate);
} else {
HIP_CHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeClockRate, 0));
kernel_500ms<<<32, blocks, 0, stream.stream()>>>(alloc_mem1, clk_rate);
}
const auto element_count = allocation_size / sizeof(int);
constexpr auto thread_count = 1024;
const auto block_count = element_count / thread_count + 1;
constexpr int expected_value = 17;
VectorSet<<<block_count, thread_count, 0, stream.stream()>>>(alloc_mem1, expected_value,
element_count);
HIP_CHECK(hipGetLastError());
HIP_CHECK(hipMemcpyAsync(alloc_mem2, alloc_mem1, allocation_size, hipMemcpyDeviceToDevice,
stream.stream()));
HIP_CHECK(hipMemcpyAsync(host_alloc.host_ptr(), alloc_mem2, allocation_size,
hipMemcpyDeviceToHost, stream.stream()));
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem1), stream.stream()));
attr = hipMemPoolAttrReservedMemCurrent;
std::uint64_t res_before_sync = 0;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &res_before_sync));
HIP_CHECK(hipStreamSynchronize(stream.stream()));
std::uint64_t res_after_sync = 0;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &res_after_sync));
// Sync must release memory to OS
REQUIRE(res_after_sync <= res_before_sync);
std::uint64_t used_mem = 0;
attr = hipMemPoolAttrUsedMemCurrent;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &used_mem));
// Make sure the current usage query works - just second buffer is left
REQUIRE(allocation_size == used_mem);
attr = hipMemPoolAttrUsedMemHigh;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &used_mem));
// Make sure the high watermark usage works - both buffers must be reported
REQUIRE((2 * allocation_size) == used_mem);
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem2), stream.stream()));
HIP_CHECK(hipStreamSynchronize(stream.stream()));
attr = hipMemPoolAttrUsedMemCurrent;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &used_mem));
// Make sure the current usage query works - none of the buffers are used
REQUIRE(0 == used_mem);
ArrayFindIfNot(host_alloc.host_ptr(), expected_value, element_count);
}
template <typename F> void MallocMemPoolAsync_Reuse(F malloc_func, const MemPools mempool_type) {
int device_id = 0;
HIP_CHECK(hipSetDevice(device_id));
int mem_pool_support = 0;
HIP_CHECK(hipDeviceGetAttribute(&mem_pool_support, hipDeviceAttributeMemoryPoolsSupported, 0));
if (!mem_pool_support) {
SUCCEED("Runtime doesn't support Memory Pool. Skip the test case.");
return;
}
MemPoolGuard mempool(mempool_type, device_id);
int *alloc_mem1, *alloc_mem2, *alloc_mem3;
StreamGuard stream(Streams::created);
size_t allocation_size1 = kPageSize * kPageSize * 2;
HIP_CHECK(malloc_func(reinterpret_cast<void**>(&alloc_mem1), allocation_size1, mempool.mempool(),
stream.stream()));
size_t allocation_size2 = kPageSize;
HIP_CHECK(malloc_func(reinterpret_cast<void**>(&alloc_mem3), allocation_size2, mempool.mempool(),
stream.stream()));
int blocks = 2;
int clk_rate;
if (IsGfx11()) {
HIP_CHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeWallClockRate, 0));
kernel_500ms_gfx11<<<32, blocks, 0, stream.stream()>>>(alloc_mem1, clk_rate);
} else {
HIP_CHECK(hipDeviceGetAttribute(&clk_rate, hipDeviceAttributeClockRate, 0));
kernel_500ms<<<32, blocks, 0, stream.stream()>>>(alloc_mem1, clk_rate);
}
hipMemPoolAttr attr;
// Not a real free, since kernel isn't done
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem1), stream.stream()));
HIP_CHECK(malloc_func(reinterpret_cast<void**>(&alloc_mem2), allocation_size1, mempool.mempool(),
stream.stream()));
// Runtime must reuse the pointer
REQUIRE(alloc_mem1 == alloc_mem2);
// Make a sync before the second kernel launch to make sure memory B isn't gone
HIP_CHECK(hipStreamSynchronize(stream.stream()));
// Second kernel launch with new memory
if (IsGfx11()) {
kernel_500ms_gfx11<<<32, blocks, 0, stream.stream()>>>(alloc_mem2, clk_rate);
} else {
kernel_500ms<<<32, blocks, 0, stream.stream()>>>(alloc_mem2, clk_rate);
}
HIP_CHECK(hipStreamSynchronize(stream.stream()));
attr = hipMemPoolAttrUsedMemCurrent;
std::uint64_t value64 = 0;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &value64));
// Make sure the current usage reports the both buffers
REQUIRE((allocation_size1 + allocation_size2) == value64);
attr = hipMemPoolAttrUsedMemHigh;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &value64));
// Make sure the high watermark usage works - the both buffers must be reported
REQUIRE((allocation_size1 + allocation_size2) == value64);
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem2), stream.stream()));
attr = hipMemPoolAttrUsedMemCurrent;
HIP_CHECK(hipMemPoolGetAttribute(mempool.mempool(), attr, &value64));
// Make sure the current usage reports just one buffer, because the above free doesn't hold memory
REQUIRE(allocation_size2 == value64);
HIP_CHECK(hipFreeAsync(reinterpret_cast<void*>(alloc_mem3), stream.stream()));
}
+24 -4
Ver Arquivo
@@ -1,13 +1,23 @@
# AMD Tests
set(TEST_SRC
printfFlags.cc
printfLength.cc
printfSpecifiers.cc
printfFlagsNonHost.cc
printfSpecifiersNonHost.cc
printfHost.cc
)
set(AMD_TEST_SRC
printfNonHost.cc)
if(HIP_PLATFORM MATCHES "nvidia")
set(LINKER_LIBS nvrtc)
elseif(HIP_PLATFORM MATCHES "amd")
set(LINKER_LIBS hiprtc)
endif()
if(UNIX)
set(AMD_TEST_SRC
printfNonHost.cc)
endif()
if(HIP_PLATFORM MATCHES "amd")
set(TEST_SRC ${TEST_SRC} ${AMD_TEST_SRC})
@@ -20,24 +30,34 @@ if(HIP_PLATFORM MATCHES "amd")
endif()
if(HIP_PLATFORM MATCHES "amd")
hip_add_exe_to_target(NAME printfTests
hip_add_exe_to_target(NAME PrintfTest
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests
LINKER_LIBS ${LINKER_LIBS}
PROPERTY CXX_STANDARD 17)
elseif (HIP_PLATFORM MATCHES "nvidia")
hip_add_exe_to_target(NAME printfTests
hip_add_exe_to_target(NAME PrintfTest
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests
LINKER_LIBS ${LINKER_LIBS}
COMPILE_OPTIONS -std=c++17)
endif()
# This test fails in PSDB
#add_test(NAME Unit_Printf_Negative
# COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/../compileAndCaptureOutput.py
# ${CMAKE_CURRENT_SOURCE_DIR} ${HIP_PLATFORM} ${HIP_PATH}
# printf_negative_kernels.cc 11)
# Standalone exes
add_executable(printfFlags_exe EXCLUDE_FROM_ALL printfFlags_exe.cc)
add_executable(printfLength_exe EXCLUDE_FROM_ALL printfLength_exe.cc)
add_executable(printfSpecifiers_exe EXCLUDE_FROM_ALL printfSpecifiers_exe.cc)
add_executable(printfFlagsNonHost_exe EXCLUDE_FROM_ALL printfFlagsNonHost_exe.cc)
add_executable(printfSpecifiersNonHost_exe EXCLUDE_FROM_ALL printfSpecifiersNonHost_exe.cc)
add_dependencies(build_tests printfFlags_exe)
add_dependencies(build_tests printfLength_exe)
add_dependencies(build_tests printfSpecifiers_exe)
add_dependencies(build_tests printfFlagsNonHost_exe)
add_dependencies(build_tests printfSpecifiersNonHost_exe)
+34 -2
Ver Arquivo
@@ -1,5 +1,5 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -23,7 +23,28 @@ THE SOFTWARE.
#include <hip_test_common.hh>
#include <hip_test_process.hh>
TEST_CASE("Unit_printf_flags") {
/**
* @addtogroup printf printf
* @{
* @ingroup PrintfTest
* `int printf()` -
* Method to print the content on output device.
*/
/**
* Test Description
* ------------------------
* - Sanity test for `printf(format, ...)` to check all format specifier flags.
*
* Test source
* ------------------------
* - unit/printf/printfFlags.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Printf_flags_Sanity_Positive") {
std::string reference(R"here(00000042
-0000042
00000042
@@ -33,8 +54,19 @@ TEST_CASE("Unit_printf_flags") {
+0000042
xyzzy
-42
42
00000042
00000042
052
0x2a
0X2A
42.000000
4.200000e+01
4.200000E+01
42.0000
42.0000
0x1.5p+5
0X1.5P+5
)here");
hip::SpawnProc proc("printfFlags_exe", true);
+1 -1
Ver Arquivo
@@ -21,7 +21,7 @@ THE SOFTWARE.
#include <hip_test_defgroups.hh>
/**
* @addtogroup printf
* @addtogroup printf printf
* @{
* @ingroup PrintfTest
* `int printf()` -
+17 -2
Ver Arquivo
@@ -1,5 +1,5 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip/hip_runtime.h>
#include <hip_test_context.hh>
__global__ void test_kernel() {
printf("%08d\n", 42);
@@ -32,8 +32,23 @@ __global__ void test_kernel() {
printf("%+08d\n", 42);
printf("%-8s\n", "xyzzy");
printf("% i\n", -42);
printf("% i\n", 42);
printf("%-16.8d\n", 42);
printf("%16.8d\n", 42);
printf("%#o\n", 42);
printf("%#x\n", 42);
printf("%#X\n", 42);
#if HT_AMD
printf("%#F\n", 42.);
#else
printf("%#f\n", 42.);
#endif
printf("%#e\n", 42.);
printf("%#E\n", 42.);
printf("%#g\n", 42.);
printf("%#G\n", 42.);
printf("%#a\n", 42.);
printf("%#A\n", 42.);
}
int main() {
+1 -1
Ver Arquivo
@@ -26,7 +26,7 @@ __global__ void run_printf(int *count) {
*count = printf("Hello World");
}
/**
* @addtogroup printf
* @addtogroup printf printf
* @{
* @ingroup PrintfTest
* `int printf()` -
+87
Ver Arquivo
@@ -0,0 +1,87 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <hip_test_process.hh>
/**
* @addtogroup printf printf
* @{
* @ingroup PrintfTest
* `int printf()` -
* Method to print the content on output device.
*/
/**
* Test Description
* ------------------------
* - Sanity test for `printf(format, ...)` to check all format specifier length sub-specifiers.
*
* Test source
* ------------------------
* - unit/printf/printfLength.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Printf_length_Sanity_Positive") {
#if HT_NVIDIA
std::string reference(R"here(-42 -42
-42 -42
-42 -42
42 52
42 52
42 52
2a 2A
2a 2A
2a 2A
123.456000
x
)here");
#else
std::string reference(R"here(-42 -42
-42 -42
-42 -42
42 52
42 52
42 52
2a 2A
2a 2A
2a 2A
123.456000
x
123.456000
-42 -42
-42 -42
-42 -42
0 0
42 52
42 52
42 52
0 0
)here");
#endif
hip::SpawnProc proc("printfLength_exe", true);
REQUIRE(0 == proc.run());
REQUIRE(proc.getOutput() == reference);
}
+62
Ver Arquivo
@@ -0,0 +1,62 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_context.hh>
#if defined(_WIN32)
#if defined(_WIN64)
typedef __int64 ssize_t;
#else // !_WIN64
typedef __int32 ssize_t;
#endif // !_WIN64
#endif /*_WIN32*/
__global__ void test_kernel() {
printf("%hd %hi\n", short(-42), short(-42));
printf("%ld %li\n", -42l, -42l);
printf("%lld %lli\n", -42ll, -42ll);
printf("%hu %ho\n", ushort(42), ushort(42));
printf("%lu %lo\n", 42l, 42l);
printf("%llu %llo\n", 42ll, 42ll);
printf("%hx %hX\n", ushort(42), ushort(42));
printf("%lx %lX\n", 42l, 42l);
printf("%llx %llX\n", 42ll, 42ll);
printf("%lf\n", 123.456);
printf("%lc\n", wint_t ('x'));
#if HT_AMD
const char* N = nullptr;
printf("%lF\n", 123.456);
printf("%hhd %hhi\n", char(-42), char(-42));
printf("%jd %ji\n", intmax_t(-42l), intmax_t(-42l));
printf("%zd %zi\n", ssize_t(-42l), ssize_t(-42l));
printf("%td %ti\n", (ptrdiff_t)N, (ptrdiff_t)N);
printf("%hhu %hho\n", static_cast<unsigned char>(42), static_cast<unsigned char>(42));
printf("%ju %jo\n", uintmax_t(42l), uintmax_t(42l));
printf("%zu %zo\n", size_t(42l), size_t(42l));
printf("%tu %to\n", (ptrdiff_t)N, (ptrdiff_t)N);
#endif
}
int main() {
test_kernel<<<1, 1>>>();
static_cast<void>(hipDeviceSynchronize());
}
+1 -1
Ver Arquivo
@@ -45,7 +45,7 @@ __global__ void kernel_printf_thread(int *count) {
}
/**
* @addtogroup printf
* @addtogroup printf printf
* @{
* @ingroup PrintfTest
* `int printf()` -
+85 -3
Ver Arquivo
@@ -1,5 +1,5 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -20,11 +20,34 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "printf_negative_kernels_rtc.hh"
#include <hip_test_common.hh>
#include <hip_test_process.hh>
TEST_CASE("Unit_printf_specifier") {
#ifdef __HIP_PLATFORM_NVIDIA__
/**
* @addtogroup printf printf
* @{
* @ingroup PrintfTest
* `int printf()` -
* Method to print the content on output device.
*/
/**
* Test Description
* ------------------------
* - Sanity test for `printf(format, ...)` to check all format specifier specifier characters and
* precision/width sub-specifiers.
*
* Test source
* ------------------------
* - unit/printf/printfSpecifier.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Printf_specifier_Sanity_Positive") {
#if HT_NVIDIA
std::string reference(R"here(xyzzy
%
hello % world
@@ -33,13 +56,19 @@ hello % world
%cxyzzy
sep
-42
-42
42
52
2a
2A
123.456000
-123.456000
-1.234560e+02
1.234560E+02
123.456
-123.456
0x1.edd2f1a9fbe77p+6
-0X1.EDD2F1A9FBE77P+6
x
(null)
(nil)
@@ -54,13 +83,19 @@ hello % world
%cxyzzy
sep
-42
-42
42
52
2a
2A
123.456000
-123.456000
-1.234560e+02
1.234560E+02
123.456
-123.456
0x1.edd2f1a9fbe77p+6
-0X1.EDD2F1A9FBE77P+6
x
(nil)
@@ -75,13 +110,19 @@ hello % world
%cxyzzy
sep
-42
-42
42
52
2a
2A
123.456000
-123.456000
-1.234560e+02
1.234560E+02
123.456
-123.456
0x1.edd2f1a9fbe77p+6
-0X1.EDD2F1A9FBE77P+6
x
0000000000000000
@@ -93,3 +134,44 @@ x
REQUIRE(0 == proc.run());
REQUIRE(proc.getOutput() == reference);
}
/**
* Test Description
* ------------------------
* - RTCs kernels that pass combinations of arguments of invalid types for printf
* Test source
* ------------------------
* - unit/printf/printfSpecifiers.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_Printf_Negative_Parameters_RTC") {
hiprtcProgram program{};
const auto program_source = kPrintfParam;
HIPRTC_CHECK(
hiprtcCreateProgram(&program, program_source, "printf_negative.cc", 0, nullptr, nullptr));
hiprtcResult result{hiprtcCompileProgram(program, 0, nullptr)};
// Get the compile log and count compiler error messages
size_t log_size{};
HIPRTC_CHECK(hiprtcGetProgramLogSize(program, &log_size));
std::string log(log_size, ' ');
HIPRTC_CHECK(hiprtcGetProgramLog(program, log.data()));
int error_count{0};
int expected_error_count{11};
std::string error_message{"error:"};
size_t n_pos = log.find(error_message, 0);
while (n_pos != std::string::npos) {
++error_count;
n_pos = log.find(error_message, n_pos + 1);
}
HIPRTC_CHECK(hiprtcDestroyProgram(&program));
HIPRTC_CHECK_ERROR(result, HIPRTC_ERROR_COMPILATION);
REQUIRE(error_count == expected_error_count);
}
+10 -4
Ver Arquivo
@@ -1,5 +1,5 @@
/*
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip/hip_runtime.h>
#include <hip_test_context.hh>
__global__ void test_kernel() {
const char* N = nullptr;
@@ -36,9 +36,13 @@ __global__ void test_kernel() {
printf("%%c%s\n", "xyzzy");
printf("%c%c%c\n", 's', 'e', 'p');
printf("%d\n", -42);
printf("%i\n", -42);
printf("%u\n", 42);
printf("%o\n", 42);
printf("%x\n", 42);
printf("%X\n", 42);
printf("%f\n", 123.456);
#ifdef __HIP_PLATFORM_AMD__
#if HT_AMD
printf("%F\n", -123.456);
#else
printf("%f\n", -123.456);
@@ -47,10 +51,12 @@ __global__ void test_kernel() {
printf("%E\n", 123.456);
printf("%g\n", 123.456);
printf("%G\n", -123.456);
printf("%a\n", 123.456);
printf("%A\n", -123.456);
printf("%c\n", 'x');
printf("%s\n", N);
printf("%p\n", (void *)N);
#ifdef __HIP_PLATFORM_AMD__
#if HT_AMD
printf("%.*f %*.*s %p\n", 8, 3.14159, 8, 5, s, (void*)0xf01dab1eca55e77e);
#else
// In Cuda, printf doesn't support %.*, %*.*
+41
Ver Arquivo
@@ -0,0 +1,41 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
struct Dummy {
__device__ Dummy() {}
__device__ ~Dummy() {}
};
/*int printf(T*)*/
__global__ void printf_n1(int* p) { printf(p); }
__global__ void printf_n2(unsigned int* p) { printf(p); }
__global__ void printf_n3(short* p) { printf(p); }
__global__ void printf_n4(long* p) { printf(p); }
__global__ void printf_n5(unsigned long* p) { printf(p); }
__global__ void printf_n6(long long* p) { printf(p); }
__global__ void printf_n7(unsigned long long* p) { printf(p); }
__global__ void printf_n8(float* p) { printf(p); }
__global__ void printf_n9(double* p) { printf(p); }
__global__ void printf_n10(long double* p) { printf(p); }
__global__ void printf_n11(Dummy* p) { printf(p); }
@@ -0,0 +1,42 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
static constexpr auto kPrintfParam{
R"(
struct Dummy {
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void printf_n1(int* p) { printf(p); }
__global__ void printf_n2(unsigned int* p) { printf(p); }
__global__ void printf_n3(short* p) { printf(p); }
__global__ void printf_n4(long* p) { printf(p); }
__global__ void printf_n5(unsigned long* p) { printf(p); }
__global__ void printf_n6(long long* p) { printf(p); }
__global__ void printf_n7(unsigned long long* p) { printf(p); }
__global__ void printf_n8(float* p) { printf(p); }
__global__ void printf_n9(double* p) { printf(p); }
__global__ void printf_n10(long double* p) { printf(p); }
__global__ void printf_n11(Dummy* p) { printf(p); }
)"};
+2
Ver Arquivo
@@ -23,6 +23,8 @@ set(TEST_SRC
hipSurfaceObj1D.cc
hipSurfaceObj2D.cc
hipSurfaceObj3D.cc
hipCreateSurfaceObject.cc
hipDestroySurfaceObject.cc
)
hip_add_exe_to_target(NAME SurfaceTest
+85
Ver Arquivo
@@ -0,0 +1,85 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
/**
* @addtogroup hipCreateSurfaceObject hipCreateSurfaceObject
* @{
* @ingroup SurfaceTest
*/
/**
* Test Description
* ------------------------
* - Negative parameters test for `hipCreateSurfaceObject`.
* Test source
* ------------------------
* - unit/texture/hipCreateSurfaceObject.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.7
*/
TEST_CASE("Unit_hipCreateSurfaceObject_Negative_Parameters") {
hipArray_t array;
hipChannelFormatDesc desc = hipCreateChannelDesc<float>();
HIP_CHECK(hipMallocArray(&array, &desc, 64, 0, hipArraySurfaceLoadStore));
hipSurfaceObject_t surf;
hipResourceDesc resc = {};
resc.resType = hipResourceTypeArray;
resc.res.array.array = array;
SECTION("pSurfObject is nullptr") {
HIP_CHECK_ERROR(hipCreateSurfaceObject(nullptr, &resc), hipErrorInvalidValue);
}
SECTION("pResDesc is nullptr") {
HIP_CHECK_ERROR(hipCreateSurfaceObject(&surf, nullptr), hipErrorInvalidValue);
}
SECTION("invalid resource type") {
resc.resType = hipResourceTypeLinear;
HIP_CHECK_ERROR(hipCreateSurfaceObject(&surf, &resc), hipErrorInvalidValue);
}
#if HT_NVIDIA // DIsalbed due to defect EXSWHTEC-366
SECTION("array handle is nullptr") {
resc.res.array.array = nullptr;
HIP_CHECK_ERROR(hipCreateSurfaceObject(&surf, &resc), hipErrorInvalidHandle);
}
#endif
#if HT_NVIDIA // Disalbed due to defect EXSWHTEC-367
SECTION("freed array handle") {
hipArray_t invalid_array;
HIP_CHECK(hipMallocArray(&invalid_array, &desc, 64, 0, hipArraySurfaceLoadStore));
HIP_CHECK(hipFreeArray(invalid_array));
resc.res.array.array = invalid_array;
HIP_CHECK_ERROR(hipCreateSurfaceObject(&surf, &resc), hipErrorContextIsDestroyed);
}
#endif
HIP_CHECK(hipFreeArray(array));
}
@@ -0,0 +1,66 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
/**
* @addtogroup hipDestroySurfaceObject hipDestroySurfaceObject
* @{
* @ingroup SurfaceTest
*/
/**
* Test Description
* ------------------------
* - Negative parameters test for `hipDestroySurfaceObject`.
* Test source
* ------------------------
* - unit/texture/hipDestroySurfaceObject.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.7
*/
TEST_CASE("Unit_hipDestroySurfaceObject_Negative_Parameters") {
SECTION("surfObject is NULL") {
HIP_CHECK(hipDestroySurfaceObject(static_cast<hipSurfaceObject_t>(0)));
}
SECTION("double free") {
hipArray_t array;
hipChannelFormatDesc desc = hipCreateChannelDesc<float>();
HIP_CHECK(hipMallocArray(&array, &desc, 64, 0, hipArraySurfaceLoadStore));
hipSurfaceObject_t surf;
hipResourceDesc resc = {};
resc.resType = hipResourceTypeArray;
resc.res.array.array = array;
HIP_CHECK(hipCreateSurfaceObject(&surf, &resc));
HIP_CHECK(hipDestroySurfaceObject(surf));
HIP_CHECK_ERROR(hipDestroySurfaceObject(surf), hipErrorInvalidValue);
HIP_CHECK(hipFreeArray(array));
}
}
+6
Ver Arquivo
@@ -45,6 +45,12 @@ set(TEST_SRC
hipTexObjectTests.cc
hipTextureObjectTests.cc
hipBindTextureToMipmappedArray.cc
hipMallocMipmappedArray.cc
hipFreeMipmappedArray.cc
hipGetMipmappedArrayLevel.cc
hipMipmappedArrayCreate.cc
hipMipmappedArrayDestroy.cc
hipMipmappedArrayGetLevel.cc
)
if(WIN32)
+73
Ver Arquivo
@@ -0,0 +1,73 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
#include <cmath>
template <size_t fractional_bits> class FixedPoint {
public:
FixedPoint() = default;
FixedPoint(float x) { fixed_point_ = static_cast<int16_t>(roundf(x * (1 << fractional_bits))); }
operator float() const {
return (static_cast<float>(fixed_point_) / static_cast<float>(1 << fractional_bits));
}
FixedPoint operator+(FixedPoint other) const {
FixedPoint<fractional_bits> res;
res.fixed_point_ = fixed_point_ + other.fixed_point_;
return res;
}
FixedPoint operator-(FixedPoint other) const {
FixedPoint<fractional_bits> res;
res.fixed_point_ = fixed_point_ - other.fixed_point_;
return res;
}
FixedPoint operator*(FixedPoint other) const {
constexpr auto K = 1 << (fractional_bits - 1);
FixedPoint<fractional_bits> res;
int32_t temp;
temp = static_cast<int32_t>(fixed_point_) * static_cast<int32_t>(other.fixed_point_);
temp += K;
res.fixed_point_ = Sat16(temp >> fractional_bits);
return res;
}
private:
int16_t fixed_point_;
int16_t Sat16(int32_t x) const {
if (x > 0x7FFF)
return 0x7FFF;
else if (x < -0x8000)
return -0x8000;
else
return (int16_t)x;
}
};
+60
Ver Arquivo
@@ -0,0 +1,60 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
/**
* @addtogroup hipFreeMipmappedArray hipFreeMipmappedArray
* @{
* @ingroup TextureTest
*/
/**
* Test Description
* ------------------------
* - Negative parameters test for `hipFreeMipmappedArray`.
* Test source
* ------------------------
* - unit/texture/hipFreeMipmappedArray.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.7
*/
TEST_CASE("Unit_hipFreeMipmappedArray_Negative_Parameters") {
CHECK_IMAGE_SUPPORT;
SECTION("array is nullptr") {
HIP_CHECK_ERROR(hipFreeMipmappedArray(nullptr), hipErrorInvalidValue);
}
SECTION("double free") {
hipMipmappedArray_t array;
hipChannelFormatDesc desc = hipCreateChannelDesc<float>();
hipExtent extent = make_hipExtent(4, 4, 6);
unsigned int levels = 4;
HIP_CHECK(hipMallocMipmappedArray(&array, &desc, extent, levels, 0));
HIP_CHECK(hipFreeMipmappedArray(array));
HIP_CHECK_ERROR(hipFreeMipmappedArray(array), hipErrorContextIsDestroyed);
}
}
@@ -0,0 +1,67 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
/**
* @addtogroup hipGetMipmappedArrayLevel hipGetMipmappedArrayLevel
* @{
* @ingroup TextureTest
*/
/**
* Test Description
* ------------------------
* - Negative parameters test for `hipGetMipmappedArrayLevel`.
* Test source
* ------------------------
* - unit/texture/hipGetMipmappedArrayLevel.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.7
*/
TEST_CASE("Unit_hipGetMipmappedArrayLevel_Negative_Parameters") {
CHECK_IMAGE_SUPPORT;
hipMipmappedArray_t array;
hipChannelFormatDesc desc = hipCreateChannelDesc<float>();
hipExtent extent = make_hipExtent(4, 4, 6);
unsigned int levels = 4;
HIP_CHECK(hipMallocMipmappedArray(&array, &desc, extent, levels, 0));
hipArray_t levelArray;
SECTION("levelArray is nullptr") {
HIP_CHECK_ERROR(hipGetMipmappedArrayLevel(nullptr, array, 2), hipErrorInvalidValue);
}
SECTION("mipmappedArray is nullptr") {
HIP_CHECK_ERROR(hipGetMipmappedArrayLevel(&levelArray, nullptr, 2), hipErrorInvalidHandle);
}
SECTION("level index is greater than number of levels") {
HIP_CHECK_ERROR(hipGetMipmappedArrayLevel(&levelArray, array, 4), hipErrorInvalidValue);
}
HIP_CHECK(hipFreeMipmappedArray(array));
}
+117
Ver Arquivo
@@ -0,0 +1,117 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_test_common.hh>
/**
* @addtogroup hipMallocMipmappedArray hipMallocMipmappedArray
* @{
* @ingroup TextureTest
*/
/**
* Test Description
* ------------------------
* - Negative parameters test for `hipMallocMipmappedArray`.
* Test source
* ------------------------
* - unit/texture/hipMallocMipmappedArray.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.7
*/
TEST_CASE("Unit_hipMallocMipmappedArray_Negative_Parameters") {
CHECK_IMAGE_SUPPORT;
hipMipmappedArray_t array;
hipChannelFormatDesc desc = hipCreateChannelDesc<float>();
hipExtent extent = make_hipExtent(4, 4, 6);
unsigned int levels = 4;
SECTION("mipmappedArray is nullptr") {
HIP_CHECK_ERROR(hipMallocMipmappedArray(nullptr, &desc, extent, levels, 0),
hipErrorInvalidValue);
}
SECTION("desc is nullptr") {
HIP_CHECK_ERROR(hipMallocMipmappedArray(&array, nullptr, extent, levels, 0),
hipErrorInvalidValue);
}
SECTION("extent is zero") {
extent = {};
HIP_CHECK_ERROR(hipMallocMipmappedArray(&array, &desc, extent, levels, 0),
hipErrorInvalidValue);
}
SECTION("invalid flags") {
HIP_CHECK_ERROR(
hipMallocMipmappedArray(&array, &desc, extent, levels, static_cast<unsigned int>(-1)),
hipErrorInvalidValue);
}
SECTION("hipArrayCubemap && depth != height") {
extent.height = 5;
HIP_CHECK_ERROR(hipMallocMipmappedArray(&array, &desc, extent, levels, hipArrayCubemap),
hipErrorInvalidValue);
}
SECTION("hipArrayCubemap && depth != 6") {
extent.depth = 12;
HIP_CHECK_ERROR(hipMallocMipmappedArray(&array, &desc, extent, levels, hipArrayCubemap),
hipErrorInvalidValue);
}
SECTION("hipArrayCubemap && hipArrayLayered && depth is not a multiple of 6") {
extent.depth = 13;
HIP_CHECK_ERROR(
hipMallocMipmappedArray(&array, &desc, extent, levels, hipArrayCubemap | hipArrayLayered),
hipErrorInvalidValue);
}
SECTION("hipArrayTextureGather && 1D array") {
extent.height = 0;
extent.depth = 0;
HIP_CHECK_ERROR(hipMallocMipmappedArray(&array, &desc, extent, levels, hipArrayTextureGather),
hipErrorInvalidValue);
}
SECTION("hipArrayTextureGather && 3D array") {
HIP_CHECK_ERROR(hipMallocMipmappedArray(&array, &desc, extent, levels, hipArrayTextureGather),
hipErrorInvalidValue);
}
#if HT_NVIDIA // Disabled due to defect EXSWHTEC-365
SECTION("hipArraySparse && 1D array") {
extent.height = 0;
extent.depth = 0;
HIP_CHECK_ERROR(hipMallocMipmappedArray(&array, &desc, extent, levels, cudaArraySparse),
hipErrorInvalidValue);
}
SECTION("hipArraySparse && cubemap array") {
HIP_CHECK_ERROR(
hipMallocMipmappedArray(&array, &desc, extent, levels, hipArrayCubemap | cudaArraySparse),
hipErrorInvalidValue);
}
#endif
}
+118
Ver Arquivo
@@ -0,0 +1,118 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_array_common.hh>
#include <hip_test_common.hh>
/**
* @addtogroup hipMipmappedArrayCreate hipMipmappedArrayCreate
* @{
* @ingroup TextureTest
*/
/**
* Test Description
* ------------------------
* - Negative parameters test for `hipMipmappedArrayCreate`.
* Test source
* ------------------------
* - unit/texture/hipMipmappedArrayCreate.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.7
*/
TEST_CASE("Unit_hipMipmappedArrayCreate_Negative_Parameters") {
CHECK_IMAGE_SUPPORT;
hipmipmappedArray array;
HIP_ARRAY3D_DESCRIPTOR desc = {};
using vec_info = vector_info<float>;
desc.Format = vec_info::format;
desc.NumChannels = vec_info::size;
desc.Width = 4;
desc.Height = 4;
desc.Depth = 6;
desc.Flags = 0;
unsigned int levels = 4;
HIP_CHECK(hipFree(0));
SECTION("mipmappedArray is nullptr") {
HIP_CHECK_ERROR(hipMipmappedArrayCreate(nullptr, &desc, levels), hipErrorInvalidValue);
}
SECTION("desc is nullptr") {
HIP_CHECK_ERROR(hipMipmappedArrayCreate(&array, nullptr, levels), hipErrorInvalidValue);
}
SECTION("extent is zero") {
desc.Width = 0;
desc.Height = 0;
desc.Depth = 0;
HIP_CHECK_ERROR(hipMipmappedArrayCreate(&array, &desc, levels), hipErrorInvalidValue);
}
SECTION("invalid flags") {
desc.Flags = static_cast<unsigned int>(-1);
HIP_CHECK_ERROR(hipMipmappedArrayCreate(&array, &desc, levels), hipErrorInvalidValue);
}
SECTION("hipArrayCubemap && depth != 6") {
desc.Depth = 5;
desc.Flags = hipArrayCubemap;
HIP_CHECK_ERROR(hipMipmappedArrayCreate(&array, &desc, levels), hipErrorInvalidValue);
}
SECTION("hipArrayCubemap && hipArrayLayered && depth is not a multiple of 6") {
desc.Depth = 13;
desc.Flags = hipArrayCubemap | hipArrayLayered;
HIP_CHECK_ERROR(hipMipmappedArrayCreate(&array, &desc, levels), hipErrorInvalidValue);
}
SECTION("hipArrayTextureGather && 1D array") {
desc.Height = 0;
desc.Depth = 0;
desc.Flags = hipArrayTextureGather;
HIP_CHECK_ERROR(hipMipmappedArrayCreate(&array, &desc, levels), hipErrorInvalidValue);
}
SECTION("hipArrayTextureGather && 3D array") {
desc.Flags = hipArrayTextureGather;
HIP_CHECK_ERROR(hipMipmappedArrayCreate(&array, &desc, levels), hipErrorInvalidValue);
}
#if HT_NVIDIA // Disabled due to defect EXSWHTEC-365
SECTION("hipArraySparse && 1D array") {
desc.Height = 0;
desc.Depth = 0;
desc.Flags = cudaArraySparse;
HIP_CHECK_ERROR(hipMipmappedArrayCreate(&array, &desc, levels), hipErrorInvalidValue);
}
SECTION("hipArraySparse && cubemap array") {
desc.Flags = hipArrayCubemap | cudaArraySparse;
HIP_CHECK_ERROR(hipMipmappedArrayCreate(&array, &desc, levels), hipErrorInvalidValue);
}
#endif
}
@@ -0,0 +1,71 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_array_common.hh>
#include <hip_test_common.hh>
/**
* @addtogroup hipMipmappedArrayDestroy hipMipmappedArrayDestroy
* @{
* @ingroup TextureTest
*/
/**
* Test Description
* ------------------------
* - Negative parameters test for `hipMipmappedArrayDestroy`.
* Test source
* ------------------------
* - unit/texture/hipMipmappedArrayDestroy.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.7
*/
TEST_CASE("Unit_hipMipmappedArrayDestroy_Negative_Parameters") {
CHECK_IMAGE_SUPPORT;
HIP_CHECK(hipFree(0));
SECTION("array is nullptr") {
HIP_CHECK_ERROR(hipMipmappedArrayDestroy(nullptr), hipErrorInvalidHandle);
}
SECTION("double free") {
hipmipmappedArray array;
HIP_ARRAY3D_DESCRIPTOR desc = {};
using vec_info = vector_info<float>;
desc.Format = vec_info::format;
desc.NumChannels = vec_info::size;
desc.Width = 4;
desc.Height = 4;
desc.Depth = 6;
desc.Flags = 0;
unsigned int levels = 4;
HIP_CHECK(hipMipmappedArrayCreate(&array, &desc, levels));
HIP_CHECK(hipMipmappedArrayDestroy(array));
HIP_CHECK_ERROR(hipMipmappedArrayDestroy(array), hipErrorContextIsDestroyed);
}
}
@@ -0,0 +1,77 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <hip_array_common.hh>
#include <hip_test_common.hh>
/**
* @addtogroup hipMipmappedArrayGetLevel hipMipmappedArrayGetLevel
* @{
* @ingroup TextureTest
*/
/**
* Test Description
* ------------------------
* - Negative parameters test for `hipMipmappedArrayGetLevel`.
* Test source
* ------------------------
* - unit/texture/hipMipmappedArrayGetLevel.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.7
*/
TEST_CASE("Unit_hipMipmappedArrayGetLevel_Negative_Parameters") {
CHECK_IMAGE_SUPPORT;
hipmipmappedArray array;
HIP_ARRAY3D_DESCRIPTOR desc = {};
using vec_info = vector_info<float>;
desc.Format = vec_info::format;
desc.NumChannels = vec_info::size;
desc.Width = 4;
desc.Height = 4;
desc.Depth = 6;
desc.Flags = 0;
unsigned int levels = 4;
HIP_CHECK(hipFree(0));
HIP_CHECK(hipMipmappedArrayCreate(&array, &desc, levels));
hipArray_t levelArray;
SECTION("levelArray is nullptr") {
HIP_CHECK_ERROR(hipMipmappedArrayGetLevel(nullptr, array, 2), hipErrorInvalidValue);
}
SECTION("mipmappedArray is nullptr") {
HIP_CHECK_ERROR(hipMipmappedArrayGetLevel(&levelArray, nullptr, 2), hipErrorInvalidHandle);
}
SECTION("level index is greater than number of levels") {
HIP_CHECK_ERROR(hipMipmappedArrayGetLevel(&levelArray, array, 4), hipErrorInvalidValue);
}
HIP_CHECK(hipMipmappedArrayDestroy(array));
}
+107
Ver Arquivo
@@ -0,0 +1,107 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
#include <hip/hip_runtime_api.h>
#include <hip/hip_cooperative_groups.h>
namespace cg = cooperative_groups;
__host__ __device__ inline float GetCoordinate(size_t iteration, size_t N, size_t dim,
size_t num_subdivisions, bool normalized_coords) {
float x = (static_cast<float>(iteration) - N / 2) / num_subdivisions;
return normalized_coords ? x / dim : x;
}
template <typename TexelType>
__global__ void tex1DKernel(TexelType* const out, size_t N, hipTextureObject_t tex_obj,
size_t width, size_t num_subdivisions, bool normalized_coords) {
const auto tid = cg::this_grid().thread_rank();
if (tid >= N) return;
float x = GetCoordinate(tid, N, width, num_subdivisions, normalized_coords);
out[tid] = tex1D<TexelType>(tex_obj, x);
}
template <typename TexelType>
__global__ void tex2DKernel(TexelType* const out, size_t N_x, size_t N_y,
hipTextureObject_t tex_obj, size_t width, size_t height,
size_t num_subdivisions, bool normalized_coords) {
const auto tid_x = blockIdx.x * blockDim.x + threadIdx.x;
if (tid_x >= N_x) return;
const auto tid_y = blockIdx.y * blockDim.y + threadIdx.y;
if (tid_y >= N_y) return;
float x = GetCoordinate(tid_x, N_x, width, num_subdivisions, normalized_coords);
float y = GetCoordinate(tid_y, N_y, height, num_subdivisions, normalized_coords);
out[tid_y * N_x + tid_x] = tex2D<TexelType>(tex_obj, x, y);
}
template <typename TexelType>
__global__ void tex3DKernel(TexelType* const out, size_t N_x, size_t N_y, size_t N_z,
hipTextureObject_t tex_obj, size_t width, size_t height, size_t depth,
size_t num_subdivisions, bool normalized_coords) {
const auto tid_x = blockIdx.x * blockDim.x + threadIdx.x;
if (tid_x >= N_x) return;
const auto tid_y = blockIdx.y * blockDim.y + threadIdx.y;
if (tid_y >= N_y) return;
const auto tid_z = blockIdx.z * blockDim.z + threadIdx.z;
if (tid_z >= N_z) return;
float x = GetCoordinate(tid_x, N_x, width, num_subdivisions, normalized_coords);
float y = GetCoordinate(tid_y, N_y, height, num_subdivisions, normalized_coords);
float z = GetCoordinate(tid_z, N_z, depth, num_subdivisions, normalized_coords);
out[tid_z * N_x * N_y + tid_y * N_x + tid_x] = tex3D<TexelType>(tex_obj, x, y, z);
}
template <typename TexelType>
__global__ void tex1DLayeredKernel(TexelType* const out, size_t N, hipTextureObject_t tex_obj,
size_t width, size_t num_subdivisions, bool normalized_coords,
size_t layer) {
const auto tid = cg::this_grid().thread_rank();
if (tid >= N) return;
float x = GetCoordinate(tid, N, width, num_subdivisions, normalized_coords);
out[tid] = tex1DLayered<TexelType>(tex_obj, x, layer);
}
template <typename TexelType>
__global__ void tex2DLayeredKernel(TexelType* const out, size_t N_x, size_t N_y,
hipTextureObject_t tex_obj, size_t width, size_t height,
size_t num_subdivisions, bool normalized_coords, size_t layer) {
const auto tid_x = blockIdx.x * blockDim.x + threadIdx.x;
if (tid_x >= N_x) return;
const auto tid_y = blockIdx.y * blockDim.y + threadIdx.y;
if (tid_y >= N_y) return;
float x = GetCoordinate(tid_x, N_x, width, num_subdivisions, normalized_coords);
float y = GetCoordinate(tid_y, N_y, height, num_subdivisions, normalized_coords);
out[tid_y * N_x + tid_x] = tex2DLayered<TexelType>(tex_obj, x, y, layer);
}
+150
Ver Arquivo
@@ -0,0 +1,150 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
#include <hip_test_common.hh>
#include <resource_guards.hh>
#include "texture_reference.hh"
#include "utils.hh"
#include "vec4.hh"
template <typename TestType> struct TextureTestParams {
hipExtent extent;
size_t layers;
size_t num_subdivisions;
hipTextureDesc tex_desc;
size_t Size() const {
return extent.width * (extent.height ?: 1) * (extent.depth ?: 1) * (layers ?: 1);
}
size_t NumItersX() const { return 3 * extent.width * num_subdivisions * 2 + 1; }
size_t NumItersY() const { return 3 * extent.height * num_subdivisions * 2 + 1; }
size_t NumItersZ() const { return 3 * extent.depth * num_subdivisions * 2 + 1; }
size_t NumIters() const { return NumItersX() * NumItersY() * NumItersZ(); }
size_t Width() const { return extent.width; }
size_t Height() const { return extent.height; }
size_t Depth() const { return extent.depth; }
hipExtent LayeredExtent() const {
return Layered() ? make_hipExtent(Width(), Height(), layers) : extent;
}
bool Layered() const { return layers > 1; }
void GenerateTextureDesc(decltype(hipReadModeElementType) read_mode = hipReadModeElementType) {
constexpr bool is_floating_point = std::is_floating_point_v<TestType>;
memset(&tex_desc, 0, sizeof(tex_desc));
tex_desc.readMode = read_mode;
tex_desc.filterMode = hipFilterModePoint;
if (is_floating_point || tex_desc.readMode == hipReadModeNormalizedFloat) {
tex_desc.filterMode = GENERATE(hipFilterModePoint, hipFilterModeLinear);
}
tex_desc.normalizedCoords = GENERATE(false, true);
auto address_mode_x = hipAddressModeClamp;
auto address_mode_y = address_mode_x;
auto address_mode_z = address_mode_y;
if (tex_desc.normalizedCoords) {
address_mode_x = GENERATE(hipAddressModeClamp, hipAddressModeBorder, hipAddressModeWrap,
hipAddressModeMirror);
if (extent.height)
address_mode_y = GENERATE(hipAddressModeClamp, hipAddressModeBorder, hipAddressModeWrap,
hipAddressModeMirror);
if (extent.depth)
address_mode_z = GENERATE(hipAddressModeClamp, hipAddressModeBorder, hipAddressModeWrap,
hipAddressModeMirror);
} else {
address_mode_x = GENERATE(hipAddressModeClamp, hipAddressModeBorder);
if (extent.height) address_mode_y = GENERATE(hipAddressModeClamp, hipAddressModeBorder);
if (extent.depth) address_mode_z = GENERATE(hipAddressModeClamp, hipAddressModeBorder);
}
tex_desc.addressMode[0] = address_mode_x;
if (extent.height) tex_desc.addressMode[1] = address_mode_y;
if (extent.depth) tex_desc.addressMode[2] = address_mode_z;
}
};
template <typename TestType, bool normalized_read = false> struct TextureTestFixture {
using VecType = vec4<TestType>;
using OutType = std::conditional_t<normalized_read, vec4<float>, VecType>;
TextureTestParams<TestType> params;
hipResourceDesc res_desc;
LinearAllocGuard<VecType> host_alloc;
TextureReference<VecType> tex_h;
ArrayAllocGuard<VecType> tex_alloc_d;
TextureGuard tex;
LinearAllocGuard<OutType> out_alloc_d;
std::vector<OutType> out_alloc_h;
TextureTestFixture(const TextureTestParams<TestType>& p)
: params{p},
host_alloc{LinearAllocs::hipHostMalloc, sizeof(VecType) * params.Size()},
tex_h{host_alloc.ptr(), params.extent, params.layers},
tex_alloc_d{params.LayeredExtent(), params.Layered() ? hipArrayLayered : 0u},
tex{ResDesc(), &params.tex_desc},
out_alloc_d{LinearAllocs::hipMalloc, sizeof(OutType) * params.NumIters()},
out_alloc_h(params.NumIters()) {}
hipResourceDesc* ResDesc() {
constexpr int test_value_offset = 7;
for (auto i = 0u; i < params.Size(); ++i) {
SetVec4<TestType>(host_alloc.ptr()[i], i + test_value_offset);
}
hipMemcpy3DParms memcpy_params = {};
memcpy_params.dstArray = tex_alloc_d.ptr();
memcpy_params.extent = params.LayeredExtent();
memcpy_params.extent.height = memcpy_params.extent.height ?: 1;
memcpy_params.extent.depth = memcpy_params.extent.depth ?: 1;
memcpy_params.srcPtr = make_hipPitchedPtr(tex_h.ptr(0), sizeof(VecType) * params.Width(),
params.Width(), params.Height() ?: 1);
memcpy_params.kind = hipMemcpyHostToDevice;
HIP_CHECK(hipMemcpy3D(&memcpy_params));
memset(&res_desc, 0, sizeof(res_desc));
res_desc.resType = hipResourceTypeArray;
res_desc.res.array.array = tex_alloc_d.ptr();
return &res_desc;
}
void LoadOutput() {
HIP_CHECK(hipMemcpy(out_alloc_h.data(), out_alloc_d.ptr(), sizeof(OutType) * params.NumIters(),
hipMemcpyDeviceToHost));
HIP_CHECK(hipDeviceSynchronize());
}
};
+253
Ver Arquivo
@@ -0,0 +1,253 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
#include <cmath>
#include "fixed_point.hh"
template <typename TexelType> class TextureReference {
public:
TextureReference(TexelType* alloc, hipExtent extent, size_t layers)
: alloc_{alloc}, extent_{extent}, layers_{layers} {}
TexelType Tex1D(float x, const hipTextureDesc& tex_desc) const {
return Tex1DLayered(x, 0, tex_desc);
}
TexelType Tex2D(float x, float y, const hipTextureDesc& tex_desc) const {
return Tex2DLayered(x, y, 0, tex_desc);
}
TexelType Tex3D(float x, float y, float z, const hipTextureDesc& tex_desc) const {
x = tex_desc.normalizedCoords ? x * extent_.width : x;
y = tex_desc.normalizedCoords ? y * extent_.height : y;
z = tex_desc.normalizedCoords ? z * extent_.depth : z;
if (tex_desc.filterMode == hipFilterModePoint) {
return Sample(floorf(x), floorf(y), floorf(z), tex_desc.addressMode);
} else if (tex_desc.filterMode == hipFilterModeLinear) {
return LinearFiltering(x, y, z, tex_desc.addressMode);
} else {
throw std::invalid_argument("Invalid hipFilterMode value");
}
}
TexelType Tex1DLayered(float x, int layer, const hipTextureDesc& tex_desc) const {
x = tex_desc.normalizedCoords ? x * extent_.width : x;
if (tex_desc.filterMode == hipFilterModePoint) {
return Sample(floorf(x), layer, tex_desc.addressMode);
} else if (tex_desc.filterMode == hipFilterModeLinear) {
return LinearFiltering(x, layer, tex_desc.addressMode);
} else {
throw std::invalid_argument("Invalid hipFilterMode value");
}
}
TexelType Tex2DLayered(float x, float y, int layer, const hipTextureDesc& tex_desc) const {
x = tex_desc.normalizedCoords ? x * extent_.width : x;
y = tex_desc.normalizedCoords ? y * extent_.height : y;
if (tex_desc.filterMode == hipFilterModePoint) {
return Sample(floorf(x), floorf(y), layer, tex_desc.addressMode);
} else if (tex_desc.filterMode == hipFilterModeLinear) {
return LinearFiltering(x, y, layer, tex_desc.addressMode);
} else {
throw std::invalid_argument("Invalid hipFilterMode value");
}
}
TexelType* ptr(size_t layer) const {
return alloc_ + layer * extent_.width * (extent_.height ?: 1);
}
size_t width() const { return extent_.width; }
size_t height() const { return extent_.height; }
size_t depth() const { return extent_.depth; }
private:
TexelType* const alloc_;
const hipExtent extent_;
const size_t layers_;
template <typename T> TexelType Vec4Sum(T arg) const { return Vec4Add(arg, Zero()); }
template <typename T, typename... Ts> TexelType Vec4Sum(T arg, Ts... args) const {
return Vec4Add(arg, Vec4Sum(args...));
}
TexelType Zero() const {
TexelType ret;
memset(&ret, 0, sizeof(ret));
return ret;
}
float ApplyAddressMode(float coord, size_t dim, hipTextureAddressMode address_mode) const {
switch (address_mode) {
case hipAddressModeClamp:
return ApplyClamp(coord, dim);
case hipAddressModeBorder:
if (CheckBorder(coord, dim)) {
return std::numeric_limits<float>::quiet_NaN();
}
case hipAddressModeWrap:
return ApplyWrap(coord, dim);
case hipAddressModeMirror:
return ApplyMirror(coord, dim);
default:
throw std::invalid_argument("Invalid hipAddressMode value");
}
}
TexelType Sample(float x, int layer, const hipTextureAddressMode* address_mode) const {
x = ApplyAddressMode(x, extent_.width, address_mode[0]);
if (std::isnan(x)) {
return Zero();
}
return ptr(layer)[static_cast<size_t>(x)];
}
TexelType Sample(float x, float y, int layer, const hipTextureAddressMode* address_mode) const {
x = ApplyAddressMode(x, extent_.width, address_mode[0]);
y = ApplyAddressMode(y, extent_.height, address_mode[1]);
if (std::isnan(x) || std::isnan(y)) {
return Zero();
}
return ptr(layer)[static_cast<size_t>(y) * extent_.width + static_cast<size_t>(x)];
}
TexelType Sample(float x, float y, float z, const hipTextureAddressMode* address_mode) const {
x = ApplyAddressMode(x, extent_.width, address_mode[0]);
y = ApplyAddressMode(y, extent_.height, address_mode[1]);
z = ApplyAddressMode(z, extent_.depth, address_mode[2]);
if (std::isnan(x) || std::isnan(y) || std::isnan(z)) {
return Zero();
}
return ptr(0)[static_cast<size_t>(z) * extent_.width * extent_.height +
static_cast<size_t>(y) * extent_.width + static_cast<size_t>(x)];
}
TexelType LinearFiltering(float x, int layer, const hipTextureAddressMode* address_mode) const {
const auto [i, alpha] = GetLinearFilteringParams(x);
const auto T_i0 = Sample(i, layer, address_mode);
const auto T_i1 = Sample(i + 1.0f, layer, address_mode);
const auto term_i0 = Vec4Scale((1.0f - alpha), T_i0);
const auto term_i1 = Vec4Scale(alpha, T_i1);
return Vec4Sum(term_i0, term_i1);
}
TexelType LinearFiltering(float x, float y, int layer,
const hipTextureAddressMode* address_mode) const {
const auto [i, alpha] = GetLinearFilteringParams(x);
const auto [j, beta] = GetLinearFilteringParams(y);
const auto T_i0j0 = Sample(i, j, layer, address_mode);
const auto T_i1j0 = Sample(i + 1.0f, j, layer, address_mode);
const auto T_i0j1 = Sample(i, j + 1.0f, layer, address_mode);
const auto T_i1j1 = Sample(i + 1.0f, j + 1.0f, layer, address_mode);
const auto term_i0j0 = Vec4Scale((1.0f - alpha) * (1.0f - beta), T_i0j0);
const auto term_i1j0 = Vec4Scale(alpha * (1.0f - beta), T_i1j0);
const auto term_i0j1 = Vec4Scale((1.0f - alpha) * beta, T_i0j1);
const auto term_i1j1 = Vec4Scale(alpha * beta, T_i1j1);
return Vec4Sum(term_i0j0, term_i1j0, term_i0j1, term_i1j1);
}
TexelType LinearFiltering(float x, float y, float z,
const hipTextureAddressMode* address_mode) const {
const auto [i, alpha] = GetLinearFilteringParams(x);
const auto [j, beta] = GetLinearFilteringParams(y);
const auto [k, gamma] = GetLinearFilteringParams(z);
const auto T_i0j0k0 = Sample(i, j, k, address_mode);
const auto T_i1j0k0 = Sample(i + 1.0f, j, k, address_mode);
const auto T_i0j1k0 = Sample(i, j + 1.0f, k, address_mode);
const auto T_i1j1k0 = Sample(i + 1.0f, j + 1.0f, k, address_mode);
const auto T_i0j0k1 = Sample(i, j, k + 1.0f, address_mode);
const auto T_i1j0k1 = Sample(i + 1.0f, j, k + 1.0f, address_mode);
const auto T_i0j1k1 = Sample(i, j + 1.0f, k + 1.0f, address_mode);
const auto T_i1j1k1 = Sample(i + 1.0f, j + 1.0f, k + 1.0f, address_mode);
const auto term_i0j0k0 = Vec4Scale((1.0f - alpha) * (1.0f - beta) * (1.0f - gamma), T_i0j0k0);
const auto term_i1j0k0 = Vec4Scale(alpha * (1.0f - beta) * (1.0f - gamma), T_i1j0k0);
const auto term_i0j1k0 = Vec4Scale((1.0f - alpha) * beta * (1.0f - gamma), T_i0j1k0);
const auto term_i1j1k0 = Vec4Scale(alpha * beta * (1.0f - gamma), T_i1j1k0);
const auto term_i0j0k1 = Vec4Scale((1.0f - alpha) * (1.0f - beta) * gamma, T_i0j0k1);
const auto term_i1j0k1 = Vec4Scale(alpha * (1.0f - beta) * gamma, T_i1j0k1);
const auto term_i0j1k1 = Vec4Scale((1.0f - alpha) * beta * gamma, T_i0j1k1);
const auto term_i1j1k1 = Vec4Scale(alpha * beta * gamma, T_i1j1k1);
return Vec4Sum(term_i0j0k0, term_i1j0k0, term_i0j1k0, term_i1j1k0, term_i0j0k1, term_i1j0k1,
term_i0j1k1, term_i1j1k1);
}
float ApplyClamp(float coord, size_t dim) const {
return max(min(coord, static_cast<float>(dim - 1)), 0.0f);
}
bool CheckBorder(float coord, size_t dim) const { return coord > dim - 1 || coord < 0.0f; }
float ApplyWrap(float coord, size_t dim) const {
coord /= dim;
coord = coord - floorf(coord);
coord *= dim;
return coord;
}
float ApplyMirror(float coord, size_t dim) const {
coord /= dim;
const float frac = coord - floor(coord);
const bool is_reversing = static_cast<ssize_t>(floorf(coord)) % 2;
coord = is_reversing ? 1.0f - frac : frac;
coord *= dim;
coord -= (coord == truncf(coord)) * is_reversing;
return coord;
}
template <size_t N> float FloatToNBitFractional(float x) const {
constexpr size_t mult = 1 << N;
const auto x_trunc = std::trunc(x);
const auto x_frac = std::round((x - x_trunc) * mult) / mult;
return x_trunc + x_frac;
}
std::tuple<float, float> GetLinearFilteringParams(float coord) const {
const auto coordB = FloatToNBitFractional<8>(coord - 0.5f);
const auto index = floorf(coordB);
const auto coeff = coordB - index;
return {index, coeff};
}
};
+85
Ver Arquivo
@@ -0,0 +1,85 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
#include <algorithm>
#include <cmath>
#include <hip_test_common.hh>
class TextureGuard {
public:
TextureGuard(hipResourceDesc* res_desc, hipTextureDesc* tex_desc) {
HIP_CHECK(hipCreateTextureObject(&tex_obj_, res_desc, tex_desc, nullptr));
}
~TextureGuard() { static_cast<void>(hipDestroyTextureObject(tex_obj_)); }
TextureGuard(const TextureGuard&) = delete;
TextureGuard& operator=(const TextureGuard&) = delete;
hipTextureObject_t object() const { return tex_obj_; }
private:
hipTextureObject_t tex_obj_ = 0;
};
template <typename T> std::enable_if_t<std::is_integral_v<T>, float> NormalizeInteger(const T x) {
// On the GPU, -1.0 will be returned both for the minimum value of a signed type and its
// successor e.g. for char, -1.0 will be returned for both -128 and -127.
auto xf = std::abs(static_cast<float>(x));
xf = std::min<float>(xf, std::numeric_limits<T>::max());
return std::copysign(xf / std::numeric_limits<T>::max(), x);
}
inline std::tuple<size_t, size_t> GetLaunchConfig(size_t max_num_threads, size_t num_iters) {
auto num_threads = std::min<size_t>(max_num_threads, num_iters);
auto num_blocks = (num_iters + num_threads - 1) / num_threads;
return {num_threads, num_blocks};
}
inline std::string AddressModeToString(decltype(hipAddressModeClamp) address_mode) {
switch (address_mode) {
case hipAddressModeClamp:
return "hipAddressModeClamp";
case hipAddressModeBorder:
return "hipAddressModeBorder";
case hipAddressModeWrap:
return "hipAddressModeWrap";
case hipAddressModeMirror:
return "hipAddressModeMirror";
default:
throw std::invalid_argument("Invalid hipAddressMode value");
}
}
inline std::string FilteringModeToString(decltype(hipFilterModePoint) filter_mode) {
switch (filter_mode) {
case hipFilterModePoint:
return "hipFilterModePoint";
case hipFilterModeLinear:
return "hipFilterModeLinear";
default:
throw std::invalid_argument("Invalid hipFilterMode value");
}
}
+106
Ver Arquivo
@@ -0,0 +1,106 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
#include <hip/hip_runtime_api.h>
template <typename T> struct vec4_struct { using type = void; };
#define DEFINE_VEC4_OVERLOAD(base_type, vec_type) \
template <> struct vec4_struct<base_type> { using type = vec_type; }
DEFINE_VEC4_OVERLOAD(char, char4);
DEFINE_VEC4_OVERLOAD(short, short4);
DEFINE_VEC4_OVERLOAD(int, int4);
DEFINE_VEC4_OVERLOAD(long, long4);
DEFINE_VEC4_OVERLOAD(long long, longlong4);
DEFINE_VEC4_OVERLOAD(unsigned char, uchar4);
DEFINE_VEC4_OVERLOAD(unsigned short, ushort4);
DEFINE_VEC4_OVERLOAD(unsigned int, uint4);
DEFINE_VEC4_OVERLOAD(unsigned long, ulong4);
DEFINE_VEC4_OVERLOAD(unsigned long long, ulonglong4);
DEFINE_VEC4_OVERLOAD(float, float4);
DEFINE_VEC4_OVERLOAD(double, float4);
template <typename T> using vec4 = typename vec4_struct<T>::type;
template <typename T> inline void SetVec4(vec4<T>& vec, const T val) {
vec.x = val;
vec.y = val;
vec.z = val;
vec.w = val;
}
template <typename T>
inline void SetVec4(vec4<T>& vec, const T x, const T y, const T z, const T w) {
vec.x = x;
vec.y = y;
vec.z = z;
vec.w = w;
}
template <typename T> inline auto MakeVec4(const T val) {
vec4<T> vec;
SetVec4(vec, val);
return vec;
}
template <typename T> inline void MakeVec4(const T x, const T y, const T z, const T w) {
vec4<T> vec;
SetVec4(vec, x, y, z, w);
return vec;
}
template <typename T, typename F> inline auto Vec4Map(const vec4<T>& vec, F f) {
vec4<decltype(f(vec.x))> ret;
ret.x = f(vec.x);
ret.y = f(vec.y);
ret.z = f(vec.z);
ret.w = f(vec.w);
return ret;
}
template <typename T> inline __host__ __device__ auto Vec4Scale(float s, const T& vec) {
T ret;
ret.x = s * vec.x;
ret.y = s * vec.y;
ret.z = s * vec.z;
ret.w = s * vec.w;
return ret;
}
template <typename T> inline __host__ __device__ auto Vec4Add(const T& vec1, const T& vec2) {
T ret;
ret.x = vec1.x + vec2.x;
ret.y = vec1.y + vec2.y;
ret.z = vec1.z + vec2.z;
ret.w = vec1.w + vec2.w;
return ret;
}
+5
Ver Arquivo
@@ -2,6 +2,11 @@
set(TEST_SRC
warp_shfl_xor.cc
warp_shfl.cc
warp_shfl_up.cc
warp_shfl_down.cc
warp_ballot.cc
warp_any.cc
warp_all.cc
)
hip_add_exe_to_target(NAME WarpTest
+128
Ver Arquivo
@@ -0,0 +1,128 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "warp_vote_common.hh"
#include <bitset>
/**
* @addtogroup all all
* @{
* @ingroup DeviceLanguageTest
* `int __all(int predicate)` -
* Contains unit test for warp vote all function
*/
namespace cg = cooperative_groups;
static bool check_if_all(uint64_t predicate_mask, uint64_t active_mask, size_t partition_size) {
if (!(predicate_mask & active_mask)) return false;
for (int i = 0; i < partition_size; i++) {
if (active_mask & (static_cast<uint64_t>(1) << i)) {
if (!(predicate_mask & (static_cast<uint64_t>(1) << i))) return false;
}
}
return true;
}
__global__ void kernel_all(int* const out, const uint64_t* const active_masks, uint64_t predicate) {
if (deactivate_thread(active_masks)) {
return;
}
const auto grid = cg::this_grid();
const auto warp = cg::tiled_partition(cg::this_thread_block(), warpSize);
out[grid.thread_rank()] = __all((predicate & (static_cast<uint64_t>(1) << warp.thread_rank())));
}
class WarpAll : public WarpVoteTest<WarpAll, int> {
public:
void launch_kernel(int* const arr_dev, const uint64_t* const active_masks) {
auto test_case = GENERATE(range(0, 5));
predicate_mask_ = get_predicate_mask(test_case, this->warp_size_);
INFO("Predicate mask: " << predicate_mask_);
kernel_all<<<this->grid_.grid_dim_, this->grid_.block_dim_>>>(arr_dev, active_masks,
predicate_mask_);
}
void validate(const int* const arr) {
ArrayAllOf(arr, this->grid_.thread_count_, [this](unsigned int i) -> std::optional<int> {
const auto rank_in_block = this->grid_.thread_rank_in_block(i).value();
const auto rank_in_warp = rank_in_block % this->warp_size_;
const auto warp_idx = this->warps_in_block_ * (i / this->grid_.threads_in_block_count_) +
rank_in_block / this->warp_size_;
const auto block_rank = warp_idx / this->warps_in_block_;
const std::bitset<sizeof(uint64_t) * 8> active_mask(this->active_masks_[warp_idx]);
auto partition_size = this->warp_size_;
// If the number of threads in a block is not a multiple of warp size, the
// last warp will have inactive threads and partition size must be recalculated
if (warp_idx == this->warps_in_block_ * (block_rank + 1) - 1) {
partition_size =
this->grid_.threads_in_block_count_ - (this->warps_in_block_ - 1) * this->warp_size_;
}
if (!active_mask.test(rank_in_warp))
return std::nullopt;
else {
// Active predicate mask must be calculated as partition can be smaller than warp_size
auto active_predicate = get_active_predicate(predicate_mask_, partition_size);
return check_if_all(active_predicate, this->active_masks_[warp_idx], partition_size);
}
});
}
private:
uint64_t predicate_mask_;
};
/**
* Test Description
* ------------------------
* - Validates the warp vote all function behavior. Threads are deactivated based on the passed
* active mask. The predicate for each thread is determined according to the generated predicate
* mask.
* Test source
* ------------------------
* - unit/warp/warp_all.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
* - Device supports warp vote
*/
TEST_CASE("Unit_Warp_Vote_All_Positive_Basic") {
int device;
hipDeviceProp_t device_properties;
HIP_CHECK(hipGetDevice(&device));
HIP_CHECK(hipGetDeviceProperties(&device_properties, device));
if (!device_properties.arch.hasWarpVote) {
HipTest::HIP_SKIP_TEST("Device doesn't support Warp Vote!");
return;
}
SECTION("Warp Vote All with specified active mask") {
WarpAll().run(false);
}
SECTION("Warp Vote All with random active mask") {
WarpAll().run(true);
}
}
+119
Ver Arquivo
@@ -0,0 +1,119 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "warp_vote_common.hh"
#include <bitset>
/**
* @addtogroup any any
* @{
* @ingroup DeviceLanguageTest
* `int __any(int predicate)` -
* Contains unit test for warp vote any function
*/
namespace cg = cooperative_groups;
__global__ void kernel_any(int* const out, const uint64_t* const active_masks, uint64_t predicate) {
if (deactivate_thread(active_masks)) {
return;
}
const auto grid = cg::this_grid();
const auto warp = cg::tiled_partition(cg::this_thread_block(), warpSize);
out[grid.thread_rank()] = __any((predicate & (static_cast<uint64_t>(1) << warp.thread_rank())));
}
class WarpAny : public WarpVoteTest<WarpAny, int> {
public:
void launch_kernel(int* const arr_dev, const uint64_t* const active_masks) {
auto test_case = GENERATE(range(0, 5));
predicate_mask_ = get_predicate_mask(test_case, this->warp_size_);
INFO("Predicate mask: " << predicate_mask_);
kernel_any<<<this->grid_.grid_dim_, this->grid_.block_dim_>>>(arr_dev, active_masks,
predicate_mask_);
}
void validate(const int* const arr) {
ArrayAllOf(arr, this->grid_.thread_count_, [this](unsigned int i) -> std::optional<int> {
const auto rank_in_block = this->grid_.thread_rank_in_block(i).value();
const auto rank_in_warp = rank_in_block % this->warp_size_;
const auto warp_idx = this->warps_in_block_ * (i / this->grid_.threads_in_block_count_) +
rank_in_block / this->warp_size_;
const auto block_rank = warp_idx / this->warps_in_block_;
const std::bitset<sizeof(uint64_t) * 8> active_mask(this->active_masks_[warp_idx]);
auto partition_size = this->warp_size_;
// If the number of threads in a block is not a multiple of warp size, the
// last warp will have inactive threads and partition size must be recalculated
if (warp_idx == this->warps_in_block_ * (block_rank + 1) - 1) {
partition_size =
this->grid_.threads_in_block_count_ - (this->warps_in_block_ - 1) * this->warp_size_;
}
if (!active_mask.test(rank_in_warp))
return std::nullopt;
else {
// Active predicate mask must be calculated as partition can be smaller than warp_size
auto active_predicate = get_active_predicate(predicate_mask_, partition_size);
return ((active_predicate & this->active_masks_[warp_idx]) != 0);
}
});
}
private:
uint64_t predicate_mask_;
};
/**
* Test Description
* ------------------------
* - Validates the warp vote any function behavior. Threads are deactivated based on the passed
* active mask. The predicate for each thread is determined according to the generated predicate
* mask.
* Test source
* ------------------------
* - unit/warp/warp_any.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
* - Device supports warp vote
*/
TEST_CASE("Unit_Warp_Vote_Any_Positive_Basic") {
int device;
hipDeviceProp_t device_properties;
HIP_CHECK(hipGetDevice(&device));
HIP_CHECK(hipGetDeviceProperties(&device_properties, device));
if (!device_properties.arch.hasWarpVote) {
HipTest::HIP_SKIP_TEST("Device doesn't support Warp Vote!");
return;
}
SECTION("Warp Vote Any with specified active mask") {
WarpAny().run(false);
}
SECTION("Warp Vote Any with random active mask") {
WarpAny().run(true);
}
}
+120
Ver Arquivo
@@ -0,0 +1,120 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "warp_vote_common.hh"
#include <bitset>
/**
* @addtogroup ballot ballot
* @{
* @ingroup DeviceLanguageTest
* `unsigned long long int __ballot(int predicate)` -
* Contains unit test for warp ballot function
*/
namespace cg = cooperative_groups;
__global__ void kernel_ballot(uint64_t* const out, const uint64_t* const active_masks,
uint64_t predicate) {
if (deactivate_thread(active_masks)) {
return;
}
const auto grid = cg::this_grid();
const auto warp = cg::tiled_partition(cg::this_thread_block(), warpSize);
out[grid.thread_rank()] =
__ballot((predicate & (static_cast<uint64_t>(1) << warp.thread_rank())));
}
class WarpBallot : public WarpVoteTest<WarpBallot, uint64_t> {
public:
void launch_kernel(uint64_t* const arr_dev, const uint64_t* const active_masks) {
auto test_case = GENERATE(range(0, 5));
predicate_mask_ = get_predicate_mask(test_case, this->warp_size_);
INFO("Predicate mask: " << predicate_mask_);
kernel_ballot<<<this->grid_.grid_dim_, this->grid_.block_dim_>>>(arr_dev, active_masks,
predicate_mask_);
}
void validate(const uint64_t* const arr) {
ArrayAllOf(arr, this->grid_.thread_count_, [this](unsigned int i) -> std::optional<uint64_t> {
const auto rank_in_block = this->grid_.thread_rank_in_block(i).value();
const auto rank_in_warp = rank_in_block % this->warp_size_;
const auto warp_idx = this->warps_in_block_ * (i / this->grid_.threads_in_block_count_) +
rank_in_block / this->warp_size_;
const auto block_rank = warp_idx / this->warps_in_block_;
const std::bitset<sizeof(uint64_t) * 8> active_mask(this->active_masks_[warp_idx]);
auto partition_size = this->warp_size_;
// If the number of threads in a block is not a multiple of warp size, the
// last warp will have inactive threads and partition size must be recalculated
if (warp_idx == this->warps_in_block_ * (block_rank + 1) - 1) {
partition_size =
this->grid_.threads_in_block_count_ - (this->warps_in_block_ - 1) * this->warp_size_;
}
if (!active_mask.test(rank_in_warp))
return std::nullopt;
else {
// Active predicate mask must be calculated as partition can be smaller than warp_size
auto active_predicate = get_active_predicate(predicate_mask_, partition_size);
return (active_predicate & this->active_masks_[warp_idx]);
}
});
}
private:
uint64_t predicate_mask_;
};
/**
* Test Description
* ------------------------
* - Validates the warp ballot function behavior. Threads are deactivated based on the passed
* active mask. The predicate for each thread is determined according to the generated predicate
* mask.
* Test source
* ------------------------
* - unit/warp/warp_ballot.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
* - Device supports warp ballot
*/
TEST_CASE("Unit_Warp_Ballot_Positive_Basic") {
int device;
hipDeviceProp_t device_properties;
HIP_CHECK(hipGetDevice(&device));
HIP_CHECK(hipGetDeviceProperties(&device_properties, device));
if (!device_properties.arch.hasWarpBallot) {
HipTest::HIP_SKIP_TEST("Device doesn't support Warp Ballot!");
return;
}
SECTION("Warp Ballot with specified active mask") {
WarpBallot().run(false);
}
SECTION("Warp Ballot with random active mask") {
WarpBallot().run(true);
}
}
+121
Ver Arquivo
@@ -0,0 +1,121 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "warp_shfl_common.hh"
#include <bitset>
/**
* @addtogroup shfl_down shfl_down
* @{
* @ingroup DeviceLanguageTest
* `T __shfl_down(T var, unsigned int lane_delta, int width = warpSize)` -
* Contains unit test for warp shfl_down function
*/
namespace cg = cooperative_groups;
template <typename T>
__global__ void shfl_down(T* const out, const T* const in, const uint64_t* const active_masks,
const unsigned int* const deltas, const int width) {
if (deactivate_thread(active_masks)) {
return;
}
const auto grid = cg::this_grid();
const auto block = cg::this_thread_block();
T var = in[grid.thread_rank()];
out[grid.thread_rank()] = __shfl_down(var, deltas[block.thread_rank() % width], width);
}
template <typename T> class WarpShflDown : public WarpShflTest<WarpShflDown<T>, T> {
public:
void launch_kernel(T* const arr_dev, T* const input_dev, const uint64_t* const active_masks) {
width_ = generate_width(this->warp_size_);
INFO("Width: " << width_);
const auto alloc_size = width_ * sizeof(unsigned int);
LinearAllocGuard<unsigned int> deltas_dev(LinearAllocs::hipMalloc, alloc_size);
deltas_.resize(width_);
std::generate(deltas_.begin(), deltas_.end(),
[this] { return GenerateRandomInteger(0u, static_cast<unsigned int>(width_)); });
HIP_CHECK(hipMemcpy(deltas_dev.ptr(), deltas_.data(), alloc_size, hipMemcpyHostToDevice));
shfl_down<<<this->grid_.grid_dim_, this->grid_.block_dim_>>>(arr_dev, input_dev, active_masks,
deltas_dev.ptr(), width_);
}
void validate(const T* const arr, const T* const input) {
ArrayAllOf(arr, this->grid_.thread_count_, [this, &input](unsigned int i) -> std::optional<T> {
const int rank_in_block = this->grid_.thread_rank_in_block(i).value();
const auto rank_in_warp = rank_in_block % this->warp_size_;
const auto rank_in_partition = rank_in_block % width_;
const auto mask_idx = this->warps_in_block_ * (i / this->grid_.threads_in_block_count_) +
rank_in_block / this->warp_size_;
const unsigned int delta = deltas_[rank_in_partition] % width_;
const std::bitset<sizeof(uint64_t) * 8> active_mask(this->active_masks_[mask_idx]);
const int target = rank_in_block % width_ + delta;
if (!active_mask.test(rank_in_warp) ||
(target < width_ && !active_mask.test(rank_in_warp + delta)) ||
(target < width_ && rank_in_block + delta >= this->grid_.threads_in_block_count_)) {
return std::nullopt;
}
return (target >= width_ ? input[i] : input[i + delta]);
});
};
private:
std::vector<unsigned int> deltas_;
int width_;
};
/**
* Test Description
* ------------------------
* - Validates the warp shuffle down behavior for all valid width sizes {2, 4, 8, 16, 32,
* 64(if supported)} for generated delta values. The threads are deactivated based on the
* passed active mask. The test is run for all overloads of shfl_down.
* Test source
* ------------------------
* - unit/warp/warp_shfl_down.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
* - Device supports warp shuffle
*/
TEMPLATE_TEST_CASE("Unit_Warp_Shfl_Down_Positive_Basic", "", int, unsigned int, long, unsigned long,
long long, unsigned long long, float, double) {
int device;
hipDeviceProp_t device_properties;
HIP_CHECK(hipGetDevice(&device));
HIP_CHECK(hipGetDeviceProperties(&device_properties, device));
if (!device_properties.arch.hasWarpShuffle) {
HipTest::HIP_SKIP_TEST("Device doesn't support Warp Shuffle!");
return;
}
SECTION("Shfl Down with specified active mask and input values") {
WarpShflDown<TestType>().run(false);
}
SECTION("Shfl Down with random active mask and input values") {
WarpShflDown<TestType>().run(true);
}
}
+120
Ver Arquivo
@@ -0,0 +1,120 @@
/*
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "warp_shfl_common.hh"
#include <bitset>
/**
* @addtogroup shfl_up shfl_up
* @{
* @ingroup DeviceLanguageTest
* `T __shfl_up(T var, unsigned int lane_delta, int width = warpSize)` -
* Contains unit test for warp shfl_up function
*/
namespace cg = cooperative_groups;
template <typename T>
__global__ void shfl_up(T* const out, const T* const in, const uint64_t* const active_masks,
const unsigned int* const deltas, const int width) {
if (deactivate_thread(active_masks)) {
return;
}
const auto grid = cg::this_grid();
const auto block = cg::this_thread_block();
T var = in[grid.thread_rank()];
out[grid.thread_rank()] = __shfl_up(var, deltas[block.thread_rank() % width], width);
}
template <typename T> class WarpShflUp : public WarpShflTest<WarpShflUp<T>, T> {
public:
void launch_kernel(T* const arr_dev, T* const input_dev, const uint64_t* const active_masks) {
width_ = generate_width(this->warp_size_);
INFO("Width: " << width_);
const auto alloc_size = width_ * sizeof(unsigned int);
LinearAllocGuard<unsigned int> deltas_dev(LinearAllocs::hipMalloc, alloc_size);
deltas_.resize(width_);
std::generate(deltas_.begin(), deltas_.end(),
[this] { return GenerateRandomInteger(0u, static_cast<unsigned int>(width_)); });
HIP_CHECK(hipMemcpy(deltas_dev.ptr(), deltas_.data(), alloc_size, hipMemcpyHostToDevice));
shfl_up<<<this->grid_.grid_dim_, this->grid_.block_dim_>>>(arr_dev, input_dev, active_masks,
deltas_dev.ptr(), width_);
}
void validate(const T* const arr, const T* const input) {
ArrayAllOf(arr, this->grid_.thread_count_, [this, &input](unsigned int i) -> std::optional<T> {
const auto rank_in_block = this->grid_.thread_rank_in_block(i).value();
const auto rank_in_warp = rank_in_block % this->warp_size_;
const auto rank_in_partition = rank_in_block % width_;
const auto mask_idx = this->warps_in_block_ * (i / this->grid_.threads_in_block_count_) +
rank_in_block / this->warp_size_;
const unsigned int delta = deltas_[rank_in_partition] % width_;
const std::bitset<sizeof(uint64_t) * 8> active_mask(this->active_masks_[mask_idx]);
const int target = rank_in_block % width_ - delta;
if (!active_mask.test(rank_in_warp) ||
(target >= 0 && !active_mask.test(rank_in_warp - delta))) {
return std::nullopt;
}
return (target < 0 ? input[i] : input[i - delta]);
});
};
private:
std::vector<unsigned int> deltas_;
int width_;
};
/**
* Test Description
* ------------------------
* - Validates the warp shuffle up behavior for all valid width sizes {2, 4, 8, 16, 32,
* 64(if supported)} for generated delta values. The threads are deactivated based on the
* passed active mask. The test is run for all overloads of shfl_up.
* Test source
* ------------------------
* - unit/warp/warp_shfl_up.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
* - Device supports warp shuffle
*/
TEMPLATE_TEST_CASE("Unit_Warp_Shfl_Up_Positive_Basic", "", int, unsigned int, long, unsigned long,
long long, unsigned long long, float, double) {
int device;
hipDeviceProp_t device_properties;
HIP_CHECK(hipGetDevice(&device));
HIP_CHECK(hipGetDeviceProperties(&device_properties, device));
if (!device_properties.arch.hasWarpShuffle) {
HipTest::HIP_SKIP_TEST("Device doesn't support Warp Shuffle!");
return;
}
SECTION("Shfl Up with specified active mask and input values") {
WarpShflUp<TestType>().run(false);
}
SECTION("Shfl Down with random active mask and input values") {
WarpShflUp<TestType>().run(true);
}
}

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais