SWDEV-1 - Merge github PRs to amd-staging
- https://github.com/ROCm/hip-tests/pull/154 - https://github.com/ROCm/hip-tests/pull/438 - https://github.com/ROCm/hip-tests/pull/425 - https://github.com/ROCm/hip-tests/pull/424 - https://github.com/ROCm/hip-tests/pull/423 - https://github.com/ROCm/hip-tests/pull/365 - https://github.com/ROCm/hip-tests/pull/356 - https://github.com/ROCm/hip-tests/pull/279 - https://github.com/ROCm/hip-tests/pull/274 - https://github.com/ROCm/hip-tests/pull/190 - https://github.com/ROCm/hip-tests/pull/189 - https://github.com/ROCm/hip-tests/pull/188 - https://github.com/ROCm/hip-tests/pull/156 - https://github.com/ROCm/hip-tests/pull/49 - https://github.com/ROCm/hip-tests/pull/439 - https://github.com/ROCm/hip-tests/pull/437 - https://github.com/ROCm/hip-tests/pull/436 - https://github.com/ROCm/hip-tests/pull/435 - https://github.com/ROCm/hip-tests/pull/193 Change-Id: I2529d0baf0f8d47d6215863321720cde2b1a846c
Esse commit está contido em:
@@ -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 ===",
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
)"};
|
||||
@@ -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);
|
||||
}
|
||||
)"};
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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); }
|
||||
)"};
|
||||
@@ -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));
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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, ¶ms_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, ¶ms_in));
|
||||
REQUIRE(params_in.dptr != nullptr);
|
||||
A_d = reinterpret_cast<int *>(params_in.dptr);
|
||||
HIP_CHECK(hipGraphAddMemAllocNode(&allocNodeB, graph,
|
||||
&allocNodeA, 1, ¶ms_in));
|
||||
A_d = reinterpret_cast<int*>(params_in.dptr);
|
||||
HIP_CHECK(hipGraphAddMemAllocNode(&allocNodeB, graph, &allocNodeA, 1, ¶ms_in));
|
||||
REQUIRE(params_in.dptr != nullptr);
|
||||
B_d = reinterpret_cast<int *>(params_in.dptr);
|
||||
HIP_CHECK(hipGraphAddMemAllocNode(&allocNodeC, graph,
|
||||
&allocNodeB, 1, ¶ms_in));
|
||||
B_d = reinterpret_cast<int*>(params_in.dptr);
|
||||
HIP_CHECK(hipGraphAddMemAllocNode(&allocNodeC, graph, &allocNodeB, 1, ¶ms_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, ¶ms_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, ¶ms_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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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); }
|
||||
)"};
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -21,7 +21,7 @@ THE SOFTWARE.
|
||||
#include <hip_test_defgroups.hh>
|
||||
|
||||
/**
|
||||
* @addtogroup printf
|
||||
* @addtogroup printf printf
|
||||
* @{
|
||||
* @ingroup PrintfTest
|
||||
* `int printf()` -
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -26,7 +26,7 @@ __global__ void run_printf(int *count) {
|
||||
*count = printf("Hello World");
|
||||
}
|
||||
/**
|
||||
* @addtogroup printf
|
||||
* @addtogroup printf printf
|
||||
* @{
|
||||
* @ingroup PrintfTest
|
||||
* `int printf()` -
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
@@ -45,7 +45,7 @@ __global__ void kernel_printf_thread(int *count) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @addtogroup printf
|
||||
* @addtogroup printf printf
|
||||
* @{
|
||||
* @ingroup PrintfTest
|
||||
* `int printf()` -
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 %.*, %*.*
|
||||
|
||||
@@ -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); }
|
||||
)"};
|
||||
@@ -23,6 +23,8 @@ set(TEST_SRC
|
||||
hipSurfaceObj1D.cc
|
||||
hipSurfaceObj2D.cc
|
||||
hipSurfaceObj3D.cc
|
||||
hipCreateSurfaceObject.cc
|
||||
hipDestroySurfaceObject.cc
|
||||
)
|
||||
|
||||
hip_add_exe_to_target(NAME SurfaceTest
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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(), ¶ms.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());
|
||||
}
|
||||
};
|
||||
@@ -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};
|
||||
}
|
||||
};
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
Referência em uma Nova Issue
Bloquear um usuário