Merge 'develop' into 'amd-staging'

Change-Id: I037144dd2fbf4e26f88525f2a820997fc3a23546


[ROCm/hip-tests commit: 4295c33aa2]
Этот коммит содержится в:
Jenkins
2023-07-16 23:09:54 +00:00
родитель 5e55d8e136 d7c774b709
Коммит c5c3441e02
74 изменённых файлов: 6047 добавлений и 1202 удалений
+2 -1
Просмотреть файл
@@ -2160,7 +2160,8 @@ PREDEFINED = TEMPLATE_TEST_CASE(x)=x() \
__linux__ \
HT_AMD \
HT_NVIDIA \
__HIP_PLATFORM_NVCC__
__HIP_PLATFORM_NVCC__ \
__GNUC__
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
+11 -14
Просмотреть файл
@@ -5,21 +5,18 @@
"Unit_hipMallocManaged_OverSubscription",
"Unit_hipDeviceGetPCIBusId_Negative_PartialFill",
"Unit_hipInit_Negative",
"Unit_BuiltinAtomicsRTC_fmaxCoherentGlobalMem",
"Unit_BuiltinAtomicsRTC__fminCoherentGlobalMem",
"Unit_BuiltInAtomicAdd_CoherentGlobalMemWithRtc",
"Unit_hipMemGetAddressRange_Negative",
"Unit_hipExternalMemoryGetMappedBuffer_Vulkan_Positive_Read_Write",
"Unit_hipExternalMemoryGetMappedBuffer_Vulkan_Negative_Parameters",
"Unit_hipImportExternalMemory_Vulkan_Negative_Parameters",
"Unit_hipWaitExternalSemaphoresAsync_Vulkan_Positive_Binary_Semaphore",
"Unit_hipWaitExternalSemaphoresAsync_Vulkan_Positive_Multiple_Semaphores",
"Unit_hipWaitExternalSemaphoresAsync_Vulkan_Negative_Parameters",
"Unit_hipSignalExternalSemaphoresAsync_Vulkan_Positive_Binary_Semaphore",
"Unit_hipSignalExternalSemaphoresAsync_Vulkan_Positive_Multiple_Semaphores",
"Unit_hipSignalExternalSemaphoresAsync_Vulkan_Negative_Parameters",
"Unit_hipImportExternalSemaphore_Vulkan_Negative_Parameters",
"Unit_hipDestroyExternalSemaphore_Vulkan_Negative_Parameters"
"Unit_hipExternalMemoryGetMappedBuffer_Vulkan_Positive_Read_Write",
"Unit_hipExternalMemoryGetMappedBuffer_Vulkan_Negative_Parameters",
"Unit_hipImportExternalMemory_Vulkan_Negative_Parameters",
"Unit_hipWaitExternalSemaphoresAsync_Vulkan_Positive_Binary_Semaphore",
"Unit_hipWaitExternalSemaphoresAsync_Vulkan_Positive_Multiple_Semaphores",
"Unit_hipWaitExternalSemaphoresAsync_Vulkan_Negative_Parameters",
"Unit_hipSignalExternalSemaphoresAsync_Vulkan_Positive_Binary_Semaphore",
"Unit_hipSignalExternalSemaphoresAsync_Vulkan_Positive_Multiple_Semaphores",
"Unit_hipSignalExternalSemaphoresAsync_Vulkan_Negative_Parameters",
"Unit_hipImportExternalSemaphore_Vulkan_Negative_Parameters",
"Unit_hipDestroyExternalSemaphore_Vulkan_Negative_Parameters"
]
}
+37 -3
Просмотреть файл
@@ -13,6 +13,19 @@
"Unit_hipInit_Negative",
"Unit_hipDeviceReset_Positive_Basic",
"Unit_hipDeviceReset_Positive_Threaded",
"Unit_hipFuncSetCacheConfig_Positive_Basic",
"Unit_hipFuncSetCacheConfig_Negative_Parameters",
"Unit_hipFuncSetSharedMemConfig_Positive_Basic",
"Unit_hipFuncSetSharedMemConfig_Negative_Parameters",
"Unit_hipFuncSetAttribute_Positive_MaxDynamicSharedMemorySize",
"Unit_hipFuncSetAttribute_Positive_PreferredSharedMemoryCarveout",
"Unit_hipFuncSetAttribute_Positive_Parameters",
"Unit_hipFuncSetAttribute_Negative_Parameters",
"NOTE: The following 4 tests are disabled due to defect - EXSWHTEC-240",
"Unit_hipFuncSetCacheConfig_Negative_Not_Supported",
"Unit_hipFuncSetSharedMemConfig_Negative_Not_Supported",
"Unit_hipFuncSetAttribute_Positive_MaxDynamicSharedMemorySize_Not_Supported",
"Unit_hipFuncSetAttribute_Positive_PreferredSharedMemoryCarveout_Not_Supported",
"Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Negative_Parameters",
"Unit_hipGraphMemcpyNodeSetParamsToSymbol_Positive_Basic",
"Unit_hipGraphExecMemcpyNodeSetParamsToSymbol_Positive_Basic",
@@ -26,7 +39,6 @@
"Unit_hipDrvMemcpy3DAsync_Positive_Array",
"Unit_hipMemRangeGetAttribute_Positive_AccessedBy_Basic",
"Unit_hipMemRangeGetAttribute_Positive_AccessedBy_Partial_Range",
"Unit_hipMemRangeGetAttributes_Negative_Parameters",
"Unit_hipStreamAttachMemAsync_Positive_Basic",
"Unit_hipStreamAttachMemAsync_Positive_AttachGlobal",
"Unit_hipStreamAttachMemAsync_Negative_Parameters",
@@ -34,6 +46,7 @@
"Unit_hipGraphAddMemcpyNode1D_Negative_Basic",
"intermittent issue: corrupted double-linked list",
"Unit_hipGraphRetainUserObject_Functional_2",
"Unit_ChannelDescriptor_Positive_16BitFloatingPoint",
"intermittent issue: failure expected but sucess returned",
"Unit_hipMemAdvise_NegtveTsts",
"Note: Following four tests disabled due to defect - EXSWHTEC-203",
@@ -44,7 +57,6 @@
"Unit_hipIpcGetMemHandle_Positive_Unique_Handles_Separate_Allocations",
"Unit_hipStreamCreateWithFlags_DefaultStreamInteraction",
"Unit_hipStreamWaitEvent_UninitializedStream_Negative",
"Unit_hipDeviceSetSharedMemConfig_Negative_Parameters",
"Unit_hipMemset3DSync",
"Unit_hipStreamAddCallback_StrmSyncTiming",
"Disabling test tracked SWDEV-394199",
@@ -85,6 +97,28 @@
"=== Below tests fail in stress test on 30/06/23 ===",
"Unit_hipStreamValue_Wait32_Blocking_NoMask_Nor",
"Unit_hipStreamValue_Write - TestParams<uint32_t, PtrType::HostPtr>",
"Unit_hipMemcpyParam2DAsync_multiDevice-StreamOnDiffDevice"
"Unit_hipMemcpyParam2DAsync_multiDevice-StreamOnDiffDevice",
"=== Below tests fail in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/96 ===",
"Unit_hipHostGetDevicePointer_Negative",
"=== Below tests fail in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/215 ===",
"Unit_ChannelDescriptor_Positive_Basic_1D - long",
"Unit_ChannelDescriptor_Positive_Basic_1D - unsigned long",
"Unit_ChannelDescriptor_Positive_Basic_1D - ulong1",
"Unit_ChannelDescriptor_Positive_Basic_1D - signed long",
"Unit_ChannelDescriptor_Positive_Basic_1D - long1",
"Unit_ChannelDescriptor_Positive_Basic_2D - ulong2",
"Unit_ChannelDescriptor_Positive_Basic_2D - long2",
"Unit_ChannelDescriptor_Positive_Basic_4D - ulong4",
"Unit_ChannelDescriptor_Positive_Basic_4D - long4",
"Unit_hipExtModuleLaunchKernel_NonUniformWorkGroup",
"=== Below tests fail in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/18 ===",
"Unit_hipMemcpyAsync_Negative_Parameters",
"Unit_hipMemcpyDtoHAsync_Negative_Parameters",
"Unit_hipMemcpyHtoDAsync_Negative_Parameters",
"Unit_hipMemcpyDtoDAsync_Negative_Parameters",
"=== Below tests fail in stress test on 13/07/23 ===",
"Unit_deviceAllocation_Malloc_ComplexDataType",
"Unit_deviceAllocation_New_ComplexDataType",
"Unit_hipStreamValue_Wait32_Blocking_Mask_Eq_1"
]
}
+35 -2
Просмотреть файл
@@ -95,6 +95,19 @@
"Unit_hipStreamSynchronize_NullStreamAndStreamPerThread",
"Note: intermittent Seg fault failure ",
"Unit_hipGraphAddEventRecordNode_Functional_WithoutFlags",
"Unit_hipFuncSetCacheConfig_Positive_Basic",
"Unit_hipFuncSetCacheConfig_Negative_Parameters",
"Unit_hipFuncSetSharedMemConfig_Positive_Basic",
"Unit_hipFuncSetSharedMemConfig_Negative_Parameters",
"Unit_hipFuncSetAttribute_Positive_MaxDynamicSharedMemorySize",
"Unit_hipFuncSetAttribute_Positive_PreferredSharedMemoryCarveout",
"Unit_hipFuncSetAttribute_Positive_Parameters",
"Unit_hipFuncSetAttribute_Negative_Parameters",
"NOTE: The following 4 tests are disabled due to defect - EXSWHTEC-240",
"Unit_hipFuncSetCacheConfig_Negative_Not_Supported",
"Unit_hipFuncSetSharedMemConfig_Negative_Not_Supported",
"Unit_hipFuncSetAttribute_Positive_MaxDynamicSharedMemorySize_Not_Supported",
"Unit_hipFuncSetAttribute_Positive_PreferredSharedMemoryCarveout_Not_Supported",
"Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Negative_Parameters",
"Unit_hipGraphMemcpyNodeSetParamsToSymbol_Positive_Basic",
"Unit_hipGraphExecMemcpyNodeSetParamsToSymbol_Positive_Basic",
@@ -137,6 +150,7 @@
"Unit_hipStreamQuery_WithFinishedWork",
"Unit_hipLaunchHostFunc_Graph",
"Unit_hipLaunchHostFunc_KernelHost",
"Unit_ChannelDescriptor_Positive_16BitFloatingPoint",
"Unit_hipStreamSetCaptureDependencies_Positive_Functional",
"Note: Following four tests disabled due to defect - EXSWHTEC-203",
"Unit_hipGraphAddMemsetNode_Positive_Basic - uint16_t",
@@ -150,7 +164,6 @@
"Unit_hipGraphExecMemsetNodeSetParams_Positive_Basic - uint32_t",
"Unit_hipGraphMemsetNodeSetParams_Positive_Basic - uint8_t",
"Unit_hipStreamWaitEvent_UninitializedStream_Negative",
"Unit_hipDeviceSetSharedMemConfig_Negative_Parameters",
"Unit_hipDeviceGetUuid_Positive",
"Disabling test tracked SWDEV-394199",
"Unit_hipStreamCreateWithPriority_MulthreadNonblockingflag",
@@ -172,6 +185,26 @@
"SWDEV-398981 fails in stress test",
"Unit_hipStreamCreateWithPriority_MulthreadDefaultflag",
"Note: UUID returned empty on some windows nodes",
"Unit_hipDeviceGetUuid_Positive"
"Unit_hipDeviceGetUuid_Positive",
"=== Below tests fail in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/96 ===",
"Unit_hipHostGetDevicePointer_Negative",
"=== Below tests fail in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/215 ===",
"Unit_ChannelDescriptor_Positive_Basic_1D - long",
"Unit_ChannelDescriptor_Positive_Basic_1D - unsigned long",
"Unit_ChannelDescriptor_Positive_Basic_1D - ulong1",
"Unit_ChannelDescriptor_Positive_Basic_1D - signed long",
"Unit_ChannelDescriptor_Positive_Basic_1D - long1",
"Unit_ChannelDescriptor_Positive_Basic_2D - ulong2",
"Unit_ChannelDescriptor_Positive_Basic_2D - long2",
"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_hipExtModuleLaunchKernel_NonUniformWorkGroup",
"=== Below tests fail in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/18 ===",
"Unit_hipMemcpyAsync_Negative_Parameters",
"Unit_hipMemcpyDtoHAsync_Negative_Parameters",
"Unit_hipMemcpyHtoDAsync_Negative_Parameters",
"Unit_hipMemcpyDtoDAsync_Negative_Parameters"
]
}
+25
Просмотреть файл
@@ -0,0 +1,25 @@
{
"DisabledTests":
[
"Unit_hipFuncSetCacheConfig_Negative_Not_Supported",
"Unit_hipFuncSetSharedMemConfig_Negative_Not_Supported",
"Unit_hipFuncSetAttribute_Positive_MaxDynamicSharedMemorySize_Not_Supported",
"Unit_hipFuncSetAttribute_Positive_PreferredSharedMemoryCarveout_Not_Supported",
"=== Below test fails in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/85 ===",
"Unit_hipFuncSetAttribute_Negative_Parameters",
"=== Below test fails in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/215 ===",
"Unit_ChannelDescriptor_Positive_Basic_1D - long",
"Unit_ChannelDescriptor_Positive_Basic_1D - unsigned long",
"Unit_ChannelDescriptor_Positive_Basic_1D - ulong1",
"Unit_ChannelDescriptor_Positive_Basic_1D - signed long",
"Unit_ChannelDescriptor_Positive_Basic_1D - long1",
"Unit_ChannelDescriptor_Positive_Basic_2D - ulong2",
"Unit_ChannelDescriptor_Positive_Basic_2D - long2",
"Unit_ChannelDescriptor_Positive_Basic_3D - ulong3",
"Unit_ChannelDescriptor_Positive_Basic_3D - long3",
"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"
]
}
+21
Просмотреть файл
@@ -0,0 +1,21 @@
{
"DisabledTests":
[
"Unit_hipFuncSetCacheConfig_Negative_Not_Supported",
"Unit_hipFuncSetSharedMemConfig_Negative_Not_Supported",
"Unit_hipFuncSetAttribute_Positive_MaxDynamicSharedMemorySize_Not_Supported",
"Unit_hipFuncSetAttribute_Positive_PreferredSharedMemoryCarveout_Not_Supported",
"=== Below test fails in external CI for PR https://github.com/ROCm-Developer-Tools/hip-tests/pull/215 ===",
"Unit_ChannelDescriptor_Positive_Basic_1D - long",
"Unit_ChannelDescriptor_Positive_Basic_1D - unsigned long",
"Unit_ChannelDescriptor_Positive_Basic_1D - ulong1",
"Unit_ChannelDescriptor_Positive_Basic_1D - signed long",
"Unit_ChannelDescriptor_Positive_Basic_1D - long1",
"Unit_ChannelDescriptor_Positive_Basic_2D - ulong2",
"Unit_ChannelDescriptor_Positive_Basic_2D - long2",
"Unit_ChannelDescriptor_Positive_Basic_3D - ulong3",
"Unit_ChannelDescriptor_Positive_Basic_3D - long3",
"Unit_ChannelDescriptor_Positive_Basic_4D - ulong4",
"Unit_ChannelDescriptor_Positive_Basic_4D - long4"
]
}
+36 -1
Просмотреть файл
@@ -1,5 +1,5 @@
/*
Copyright (c) 2021 - 2022 Advanced Micro Devices, Inc. All rights reserved.
Copyright (c) 2021 - 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
@@ -72,6 +72,20 @@ THE SOFTWARE.
* @}
*/
/**
* @defgroup DeviceLanguageTest Device Language
* @{
* This section describes tests for the Device Language API.
* @}
*/
/**
* @defgroup ExecutionTest Execution Control
* @{
* This section describes tests for the execution control functions of HIP runtime API.
* @}
*/
/**
* @defgroup ShflTest warp shuffle function Management
* @{
@@ -93,3 +107,24 @@ THE SOFTWARE.
* This section describes the stream management types & functions of HIP runtime API.
* @}
*/
/**
* @defgroup DynamicLoadingTest Kernel Loading Management
* @{
* This section describes the different kernel launch approaches.
* @}
*/
/**
* @defgroup MemoryTest memory Management APIs
* @{
* This section describes the memory management types & functions of HIP runtime API.
* @}
*/
/**
* @defgroup KernelTest Kernel Functions Management
* @{
* This section describes the various kernel functions invocation.
* @}
*/
+43 -264
Просмотреть файл
@@ -81,13 +81,16 @@ static void TstCoherency(int *Ptr, bool HmmMem) {
// Getting gpu frequency
if (IsGfx11()) {
HIPCHECK(hipDeviceGetAttribute(&peak_clk, hipDeviceAttributeWallClockRate, 0));
HIPCHECK(hipDeviceGetAttribute(&peak_clk,
hipDeviceAttributeWallClockRate, 0));
} else {
HIPCHECK(hipDeviceGetAttribute(&peak_clk, hipDeviceAttributeClockRate, 0));
HIPCHECK(hipDeviceGetAttribute(&peak_clk,
hipDeviceAttributeClockRate, 0));
}
if (!HmmMem) {
HIP_CHECK(hipHostGetDevicePointer(reinterpret_cast<void **>(&Dptr), Ptr, 0));
HIP_CHECK(hipHostGetDevicePointer(reinterpret_cast<void **>(&Dptr),
Ptr, 0));
if (IsGfx11()) {
CoherentTst_gfx11<<<1, 1, 0, strm>>>(Dptr, peak_clk);
} else {
@@ -122,58 +125,13 @@ static void TstCoherency(int *Ptr, bool HmmMem) {
// The following test is failing on Nvidia platform hence disabled it for now
#if HT_AMD
TEST_CASE("Unit_malloc_CoherentTst") {
if ((setenv("HSA_XNACK", "1", 1)) != 0) {
WARN("Unable to turn on HSA_XNACK, hence terminating the Test case!");
REQUIRE(false);
}
// The following code block is used to check for gfx906/8 so as to skip if
// any of the gpus available
int fd1[2]; // Used to store two ends of first pipe
pid_t p;
if (pipe(fd1) == -1) {
fprintf(stderr, "Pipe Failed");
REQUIRE(false);
}
/* GpuId[0] for gfx90a exists--> 1 for yes and 0 for no*/
int GpuId[1] = {0};
p = fork();
if (p < 0) {
fprintf(stderr, "fork Failed");
REQUIRE(false);
} else if (p > 0) { // parent process
close(fd1[1]); // Close writing end of first pipe
// Wait for child to send a string
wait(NULL);
// Read string from child and close reading end.
read(fd1[0], GpuId, 2 * sizeof(int));
close(fd1[0]);
if (GpuId[0] == 0) {
WARN("This test is applicable for MI200."
"Skipping the test!!");
exit(0);
}
} else { // child process
close(fd1[0]); // Close read end of first pipe
hipDeviceProp_t prop;
HIPCHECK(hipGetDeviceProperties(&prop, 0));
char *p = NULL;
if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, prop.gcnArchName)) {
WARN("gfx90a gpu found on this system!!");
GpuId[0] = 1;
}
// Write concatenated string and close writing end
write(fd1[1], GpuId, 2 * sizeof(int));
close(fd1[1]);
exit(0);
}
// Test Case execution begins from here
int stat = 0;
if (fork() == 0) {
hipDeviceProp_t prop;
HIPCHECK(hipGetDeviceProperties(&prop, 0));
char *p = NULL;
p = strstr(prop.gcnArchName, "xnack+");
if (p) {
// Test Case execution begins from here
int stat = 0;
int managed = 0;
HIPCHECK(hipDeviceGetAttribute(&managed, hipDeviceAttributeManagedMemory,
0));
@@ -185,23 +143,10 @@ TEST_CASE("Unit_malloc_CoherentTst") {
Ptr = reinterpret_cast<int*>(malloc(SIZE));
TstCoherency(Ptr, HmmMem);
free(Ptr);
if (YES_COHERENT) {
// exit() with code 10 which indicates pass
exit(10);
} else {
// exit() with code 9 which indicates fail
exit(9);
}
} else {
SUCCEED("GPU 0 doesn't support hipDeviceAttributeManagedMemory "
"attribute. Hence skipping the testing with Pass result.\n");
}
REQUIRE(YES_COHERENT);
}
} else {
wait(&stat);
int Result = WEXITSTATUS(stat);
if (Result != 10) {
REQUIRE(false);
}
HipTest::HIP_SKIP_TEST("GPU is not xnack enabled hence skipping the test...\n");
}
}
#endif
@@ -212,55 +157,12 @@ TEST_CASE("Unit_malloc_CoherentTst") {
// The following test is failing on Nvidia platform hence disabling it for now
#if HT_AMD
TEST_CASE("Unit_malloc_CoherentTstWthAdvise") {
if ((setenv("HSA_XNACK", "1", 1)) != 0) {
WARN("Unable to turn on HSA_XNACK, hence terminating the Test case!");
REQUIRE(false);
}
// The following code block is used to check for gfx906/8 so as to skip if
// any of the gpus available
int fd1[2]; // Used to store two ends of first pipe
pid_t p;
if (pipe(fd1) == -1) {
fprintf(stderr, "Pipe Failed");
REQUIRE(false);
}
/* GpuId[0] for gfx90a exists--> 1 for yes and 0 for no */
int GpuId[1] = {0};
p = fork();
if (p < 0) {
fprintf(stderr, "fork Failed");
REQUIRE(false);
} else if (p > 0) { // parent process
close(fd1[1]); // Close writing end of first pipe
// Wait for child to send a string
wait(NULL);
// Read string from child and close reading end.
read(fd1[0], GpuId, 2 * sizeof(int));
close(fd1[0]);
if (GpuId[0] == 0) {
WARN("This test is applicable for MI200."
"Skipping the test!!");
exit(0);
}
} else { // child process
close(fd1[0]); // Close read end of first pipe
hipDeviceProp_t prop;
HIPCHECK(hipGetDeviceProperties(&prop, 0));
char *p = NULL;
p = strstr(prop.gcnArchName, "gfx90a");
if (p) {
WARN("gfx90a gpu found on this system!!");
GpuId[0] = 1;
}
// Write concatenated string and close writing end
write(fd1[1], GpuId, 2 * sizeof(int));
close(fd1[1]);
exit(0);
}
int stat = 0;
if (fork() == 0) {
hipDeviceProp_t prop;
HIPCHECK(hipGetDeviceProperties(&prop, 0));
char *p = NULL;
p = strstr(prop.gcnArchName, "xnack+");
if (p) {
int stat = 0;
int managed = 0;
HIP_CHECK(hipDeviceGetAttribute(&managed, hipDeviceAttributeManagedMemory,
0));
@@ -275,25 +177,10 @@ TEST_CASE("Unit_malloc_CoherentTstWthAdvise") {
SquareKrnl<<<1, 1, 0, strm>>>(Ptr);
HIP_CHECK(hipStreamSynchronize(strm));
HIP_CHECK(hipStreamDestroy(strm));
if (*Ptr == 16) {
// exit() with code 10 which indicates pass
free(Ptr);
exit(10);
} else {
// exit() with code 9 which indicates fail
free(Ptr);
exit(9);
}
} else {
SUCCEED("GPU 0 doesn't support hipDeviceAttributeManagedMemory "
"attribute. Hence skipping the testing with Pass result.\n");
REQUIRE (*Ptr == 16);
}
} else {
wait(&stat);
int Result = WEXITSTATUS(stat);
if (Result != 10) {
REQUIRE(false);
}
HipTest::HIP_SKIP_TEST("GPU is not xnack enabled hence skipping the test...\n");
}
}
#endif
@@ -303,55 +190,12 @@ TEST_CASE("Unit_malloc_CoherentTstWthAdvise") {
// The following test is failing on Nvidia platform hence disabling it for now
#if HT_AMD
TEST_CASE("Unit_mmap_CoherentTst") {
if ((setenv("HSA_XNACK", "1", 1)) != 0) {
WARN("Unable to turn on HSA_XNACK, hence terminating the Test case!");
REQUIRE(false);
}
// The following code block is used to check for gfx906/8 so as to skip if
// any of the gpus available
int fd1[2]; // Used to store two ends of first pipe
pid_t p;
if (pipe(fd1) == -1) {
fprintf(stderr, "Pipe Failed");
REQUIRE(false);
}
/* GpuId[0] for gfx90a exists--> 1 for yes and 0 for no */
int GpuId[1] = {0};
p = fork();
if (p < 0) {
fprintf(stderr, "fork Failed");
REQUIRE(false);
} else if (p > 0) { // parent process
close(fd1[1]); // Close writing end of first pipe
// Wait for child to send a string
wait(NULL);
// Read string from child and close reading end.
read(fd1[0], GpuId, 2 * sizeof(int));
close(fd1[0]);
if (GpuId[0] == 0) {
WARN("This test is not applicable for MI200."
"Skipping the test!!");
exit(0);
}
} else { // child process
close(fd1[0]); // Close read end of first pipe
hipDeviceProp_t prop;
HIPCHECK(hipGetDeviceProperties(&prop, 0));
char *p = NULL;
p = strstr(prop.gcnArchName, "gfx90a");
if (p) {
WARN("gfx90a gpu found on this system!!");
GpuId[0] = 1;
}
// Write concatenated string and close writing end
write(fd1[1], GpuId, 2 * sizeof(int));
close(fd1[1]);
exit(0);
}
int stat = 0;
if (fork() == 0) {
hipDeviceProp_t prop;
HIPCHECK(hipGetDeviceProperties(&prop, 0));
char *p = NULL;
p = strstr(prop.gcnArchName, "xnack+");
if (p) {
int stat = 0;
int managed = 0;
HIP_CHECK(hipDeviceGetAttribute(&managed, hipDeviceAttributeManagedMemory,
0));
@@ -371,21 +215,10 @@ TEST_CASE("Unit_mmap_CoherentTst") {
if (err != 0) {
WARN("munmap failed\n");
}
if (YES_COHERENT) {
exit(10);
} else {
exit(9);
}
} else {
SUCCEED("GPU 0 doesn't support hipDeviceAttributeManagedMemory "
"attribute. Hence skipping the testing with Pass result.\n");
}
REQUIRE(YES_COHERENT);
}
} else {
wait(&stat);
int Result = WEXITSTATUS(stat);
if (Result != 10) {
REQUIRE(false);
}
HipTest::HIP_SKIP_TEST("GPU is not xnack enabled hence skipping the test...\n");
}
}
#endif
@@ -395,55 +228,12 @@ TEST_CASE("Unit_mmap_CoherentTst") {
// The following test is failing on Nvidia platform hence disabling it for now
#if HT_AMD
TEST_CASE("Unit_mmap_CoherentTstWthAdvise") {
if ((setenv("HSA_XNACK", "1", 1)) != 0) {
WARN("Unable to turn on HSA_XNACK, hence terminating the Test case!");
REQUIRE(false);
}
// The following code block is used to check for gfx906/8 so as to skip if
// any of the gpus available
int fd1[2]; // Used to store two ends of first pipe
pid_t p;
if (pipe(fd1) == -1) {
fprintf(stderr, "Pipe Failed");
REQUIRE(false);
}
/* GpuId[0] for gfx90a exists--> 1 for yes and 0 for no */
int GpuId[1] = {0};
p = fork();
if (p < 0) {
fprintf(stderr, "fork Failed");
REQUIRE(false);
} else if (p > 0) { // parent process
close(fd1[1]); // Close writing end of first pipe
// Wait for child to send a string
wait(NULL);
// Read string from child and close reading end.
read(fd1[0], GpuId, 2 * sizeof(int));
close(fd1[0]);
if (GpuId[0] == 0) {
WARN("This test is applicable for MI200."
"Skipping the test!!");
exit(0);
}
} else { // child process
close(fd1[0]); // Close read end of first pipe
hipDeviceProp_t prop;
HIPCHECK(hipGetDeviceProperties(&prop, 0));
char *p = NULL;
p = strstr(prop.gcnArchName, "gfx90a");
if (p) {
WARN("gfx90a gpu found on this system!!");
GpuId[0] = 1;
}
// Write concatenated string and close writing end
write(fd1[1], GpuId, 2 * sizeof(int));
close(fd1[1]);
exit(0);
}
int stat = 0;
if (fork() == 0) {
hipDeviceProp_t prop;
HIPCHECK(hipGetDeviceProperties(&prop, 0));
char *p = NULL;
p = strstr(prop.gcnArchName, "xnack+");
if (p) {
int stat = 0;
int managed = 0;
HIP_CHECK(hipDeviceGetAttribute(&managed, hipDeviceAttributeManagedMemory,
0));
@@ -466,26 +256,15 @@ TEST_CASE("Unit_mmap_CoherentTstWthAdvise") {
bool IfTstPassed = false;
if (*Ptr == 81) {
IfTstPassed = true;
}
}
int err = munmap(Ptr, SIZE);
if (err != 0) {
WARN("munmap failed\n");
}
if (IfTstPassed) {
exit(10);
} else {
exit(9);
}
} else {
SUCCEED("GPU 0 doesn't support hipDeviceAttributeManagedMemory "
"attribute. Hence skipping the testing with Pass result.\n");
}
REQUIRE(IfTstPassed);
}
} else {
wait(&stat);
int Result = WEXITSTATUS(stat);
if (Result != 10) {
REQUIRE(false);
}
HipTest::HIP_SKIP_TEST("GPU is not xnack enabled hence skipping the test...\n");
}
}
#endif
+7 -1
Просмотреть файл
@@ -1,4 +1,4 @@
# Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved.
# Copyright (c) 2021-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
@@ -36,6 +36,12 @@ add_subdirectory(compiler)
add_subdirectory(errorHandling)
add_subdirectory(cooperativeGrps)
add_subdirectory(context)
add_subdirectory(dynamicLoading)
add_subdirectory(g++)
add_subdirectory(module)
add_subdirectory(channelDescriptor)
add_subdirectory(executionControl)
if(HIP_PLATFORM STREQUAL "amd")
add_subdirectory(callback)
#add_subdirectory(clock)
+27
Просмотреть файл
@@ -0,0 +1,27 @@
# 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.
set(TEST_SRC
channel_descriptor.cc
)
hip_add_exe_to_target(NAME ChannelDescriptorTest
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests)
+194
Просмотреть файл
@@ -0,0 +1,194 @@
/*
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 "channel_descriptor_common.hh"
/**
* @addtogroup hipCreateChannelDesc hipCreateChannelDesc
* @{
* @ingroup DeviceLanguageTest
* `hipCreateChannelDesc<T>()` -
* Creates a dedicated channel descriptor based on passed built-in or vector type T.
*/
/**
* Test Description
* ------------------------
* - Validates that 1D channel descriptor is created as expected.
* - Compares channel descriptor with the manually created one.
* - Takes into consideration following 1D built-in and vector types:
* -# char (signed and unsigned)
* -# short (signed and unsigned)
* -# int (signed and unsigned)
* -# float
* -# long (signed and unsigned)
* Test source
* ------------------------
* - unit/channelDescriptor/channel_descriptor.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_ChannelDescriptor_Positive_Basic_1D", "", char, unsigned char, uchar1,
signed char, char1, unsigned short, ushort1, short, signed short, short1, int,
unsigned int, uint1, signed int, int1, float, float1, long, unsigned long,
ulong1, signed long, long1) {
ChannelDescriptorTest1D<TestType> channel_desc_test;
channel_desc_test.Run();
}
/**
* Test Description
* ------------------------
* - Validates that 2D channel descriptor is created as expected.
* - Compares channel descriptor with the manually created one.
* - Takes into consideration following 2D built-in and vector types:
* -# char (signed and unsigned)
* -# short (signed and unsigned)
* -# int (signed and unsigned)
* -# float
* -# long (signed and unsigned)
* Test source
* ------------------------
* - unit/channelDescriptor/channel_descriptor.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_ChannelDescriptor_Positive_Basic_2D", "", uchar2, char2, ushort2, short2,
uint2, int2, float2, ulong2, long2) {
ChannelDescriptorTest2D<TestType> channel_desc_test;
channel_desc_test.Run();
}
#ifndef __GNUC__
/**
* Test Description
* ------------------------
* - Validates that 3D channel descriptor is created as expected.
* - Compares channel descriptor with the manually created one.
* - Takes into consideration following 3D built-in and vector types:
* -# char (signed and unsigned)
* -# short (signed and unsigned)
* -# int (signed and unsigned)
* -# float
* -# long (signed and unsigned)
* Test source
* ------------------------
* - unit/channelDescriptor/channel_descriptor.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
* - Available for non-GNUC compilers.
*/
TEMPLATE_TEST_CASE("Unit_ChannelDescriptor_Positive_Basic_3D", "", uchar3, char3, ushort3, short3,
uint3, int3, float3, ulong3, long3) {
ChannelDescriptorTest3D<TestType> channel_desc_test;
channel_desc_test.Run();
}
#endif
/**
* Test Description
* ------------------------
* - Validates that 4D channel descriptor is created as expected.
* - Compares channel descriptor with the manually created one.
* - Takes into consideration following 4D built-in and vector types:
* -# char (signed and unsigned)
* -# short (signed and unsigned)
* -# int (signed and unsigned)
* -# float
* -# long (signed and unsigned)
* Test source
* ------------------------
* - unit/channelDescriptor/channel_descriptor.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_ChannelDescriptor_Positive_Basic_4D", "", uchar4, char4, ushort4, short4,
uint4, int4, float4, ulong4, long4) {
ChannelDescriptorTest4D<TestType> channel_desc_test;
channel_desc_test.Run();
}
/**
* Test Description
* ------------------------
* - Validates that an empty channel descriptor is created as expected.
* - Compares channel descriptor with the manually created one.
* - Takes into consideration all dimensions of the following built-in and vector types:
* -# long long (signed and unsigned)
* -# double
* Test source
* ------------------------
* - unit/channelDescriptor/channel_descriptor.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEMPLATE_TEST_CASE("Unit_ChannelDescriptor_Positive_FormatNone", "", long long, signed long long,
unsigned long long, longlong1, longlong2, longlong3, longlong4, ulonglong1,
ulonglong2, ulonglong3, ulonglong4, double1, double2, double3, double4) {
ChannelDescriptorTestNone<TestType> channel_desc_test;
channel_desc_test.Run();
}
#if HT_AMD
/**
* Test Description
* ------------------------
* - Validates that the channel descriptor is created as expected.
* - Compares channel descriptor with the manually created one.
* - Takes into consideration 16-bit floating-point type.
* -# Creates 1D channel descriptor.
* -# Creates 2D channel descriptor.
* Test source
* ------------------------
* - unit/channelDescriptor/channel_descriptor.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_ChannelDescriptor_Positive_16BitFloatingPoint") {
int size = static_cast<int>(sizeof(unsigned short) * 8);
hipChannelFormatKind kind = hipChannelFormatKindFloat;
hipChannelFormatDesc channel_desc{};
hipChannelFormatDesc referent_channel_desc{};
SECTION("hipCreateChannelDescHalf") {
referent_channel_desc = {size, 0, 0, 0, kind};
channel_desc = hipCreateChannelDescHalf();
}
SECTION("hipCreateChannelDescHalf1") {
referent_channel_desc = {size, 0, 0, 0, kind};
channel_desc = hipCreateChannelDescHalf1();
}
SECTION("hipCreateChannelDescHalf2") {
referent_channel_desc = {size, size, 0, 0, kind};
channel_desc = hipCreateChannelDescHalf2();
}
REQUIRE(channel_desc.x == referent_channel_desc.x);
REQUIRE(channel_desc.y == referent_channel_desc.y);
REQUIRE(channel_desc.z == referent_channel_desc.z);
REQUIRE(channel_desc.w == referent_channel_desc.w);
REQUIRE(channel_desc.f == referent_channel_desc.f);
}
#endif
+221
Просмотреть файл
@@ -0,0 +1,221 @@
/*
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>
enum class ChannelDimension { OneDim, TwoDim, ThreeDim, FourDim };
template <typename T> class ChannelDescriptorTestShell {
protected:
int size;
hipChannelFormatKind kind;
ChannelDimension dimension;
virtual void SetSizeAndKind() = 0;
public:
void Run() {
hipChannelFormatDesc channel_desc{};
SetSizeAndKind();
hipChannelFormatDesc referent_channel_desc{0, 0, 0, 0, kind};
switch (dimension) {
case ChannelDimension::FourDim:
referent_channel_desc.w = size;
case ChannelDimension::ThreeDim:
referent_channel_desc.z = size;
case ChannelDimension::TwoDim:
referent_channel_desc.y = size;
default:
referent_channel_desc.x = size;
}
channel_desc = hipCreateChannelDesc<T>();
REQUIRE(channel_desc.x == referent_channel_desc.x);
REQUIRE(channel_desc.y == referent_channel_desc.y);
REQUIRE(channel_desc.z == referent_channel_desc.z);
REQUIRE(channel_desc.w == referent_channel_desc.w);
REQUIRE(channel_desc.f == referent_channel_desc.f);
}
ChannelDescriptorTestShell(const ChannelDimension dimension)
: size(0), kind(hipChannelFormatKindNone), dimension(dimension) {}
ChannelDescriptorTestShell(const ChannelDescriptorTestShell&) = delete;
ChannelDescriptorTestShell(ChannelDescriptorTestShell&&) = delete;
};
template <typename T> class ChannelDescriptorTest1D : public ChannelDescriptorTestShell<T> {
public:
ChannelDescriptorTest1D() : ChannelDescriptorTestShell<T>(ChannelDimension::OneDim) {}
protected:
void SetSizeAndKind() {
if (std::is_same_v<char, T>) {
this->size = static_cast<int>(sizeof(char) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<unsigned char, T> || std::is_same_v<uchar1, T>) {
this->size = static_cast<int>(sizeof(unsigned char) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<signed char, T> || std::is_same_v<char1, T>) {
this->size = static_cast<int>(sizeof(signed char) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<unsigned short, T> || std::is_same_v<ushort1, T>) {
this->size = static_cast<int>(sizeof(unsigned short) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<short, T> || std::is_same_v<signed short, T> ||
std::is_same_v<short1, T>) {
this->size = static_cast<int>(sizeof(signed short) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<unsigned int, T> || std::is_same_v<uint1, T>) {
this->size = static_cast<int>(sizeof(unsigned int) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<int, T> || std::is_same_v<signed int, T> || std::is_same_v<int1, T>) {
this->size = static_cast<int>(sizeof(signed int) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<float, T> || std::is_same_v<float1, T>) {
this->size = static_cast<int>(sizeof(float) * 8);
this->kind = hipChannelFormatKindFloat;
} else if (std::is_same_v<unsigned long, T> || std::is_same_v<ulong1, T>) {
this->size = static_cast<int>(sizeof(unsigned long) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<long, T> || std::is_same_v<signed long, T> ||
std::is_same_v<long1, T>) {
this->size = static_cast<int>(sizeof(signed long) * 8);
this->kind = hipChannelFormatKindSigned;
}
}
};
template <typename T> class ChannelDescriptorTest2D : public ChannelDescriptorTestShell<T> {
public:
ChannelDescriptorTest2D() : ChannelDescriptorTestShell<T>(ChannelDimension::TwoDim) {}
protected:
void SetSizeAndKind() {
if (std::is_same_v<uchar2, T>) {
this->size = static_cast<int>(sizeof(unsigned char) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<char2, T>) {
this->size = static_cast<int>(sizeof(signed char) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<ushort2, T>) {
this->size = static_cast<int>(sizeof(unsigned short) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<short2, T>) {
this->size = static_cast<int>(sizeof(signed short) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<uint2, T>) {
this->size = static_cast<int>(sizeof(unsigned int) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<int2, T>) {
this->size = static_cast<int>(sizeof(signed int) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<float2, T>) {
this->size = static_cast<int>(sizeof(float) * 8);
this->kind = hipChannelFormatKindFloat;
} else if (std::is_same_v<ulong2, T>) {
this->size = static_cast<int>(sizeof(unsigned long) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<long2, T>) {
this->size = static_cast<int>(sizeof(signed long) * 8);
this->kind = hipChannelFormatKindSigned;
}
}
};
#ifndef __GNUC__
template <typename T> class ChannelDescriptorTest3D : public ChannelDescriptorTestShell<T> {
public:
ChannelDescriptorTest3D() : ChannelDescriptorTestShell<T>(ChannelDimension::ThreeDim) {}
protected:
void SetSizeAndKind() {
if (std::is_same_v<uchar3, T>) {
this->size = static_cast<int>(sizeof(unsigned char) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<char3, T>) {
this->size = static_cast<int>(sizeof(signed char) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<ushort3, T>) {
this->size = static_cast<int>(sizeof(unsigned short) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<short3, T>) {
this->size = static_cast<int>(sizeof(signed short) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<uint3, T>) {
this->size = static_cast<int>(sizeof(unsigned int) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<int3, T>) {
this->size = static_cast<int>(sizeof(signed int) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<float3, T>) {
this->size = static_cast<int>(sizeof(float) * 8);
this->kind = hipChannelFormatKindFloat;
} else if (std::is_same_v<ulong3, T>) {
this->size = static_cast<int>(sizeof(unsigned long) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<long3, T>) {
this->size = static_cast<int>(sizeof(signed long) * 8);
this->kind = hipChannelFormatKindSigned;
}
}
};
#endif
template <typename T> class ChannelDescriptorTest4D : public ChannelDescriptorTestShell<T> {
public:
ChannelDescriptorTest4D() : ChannelDescriptorTestShell<T>(ChannelDimension::FourDim) {}
protected:
void SetSizeAndKind() {
if (std::is_same_v<uchar4, T>) {
this->size = static_cast<int>(sizeof(unsigned char) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<char4, T>) {
this->size = static_cast<int>(sizeof(signed char) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<ushort4, T>) {
this->size = static_cast<int>(sizeof(unsigned short) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<short4, T>) {
this->size = static_cast<int>(sizeof(signed short) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<uint4, T>) {
this->size = static_cast<int>(sizeof(unsigned int) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<int4, T>) {
this->size = static_cast<int>(sizeof(signed int) * 8);
this->kind = hipChannelFormatKindSigned;
} else if (std::is_same_v<float4, T>) {
this->size = static_cast<int>(sizeof(float) * 8);
this->kind = hipChannelFormatKindFloat;
} else if (std::is_same_v<ulong4, T>) {
this->size = static_cast<int>(sizeof(unsigned long) * 8);
this->kind = hipChannelFormatKindUnsigned;
} else if (std::is_same_v<long4, T>) {
this->size = static_cast<int>(sizeof(signed long) * 8);
this->kind = hipChannelFormatKindSigned;
}
}
};
template <typename T> class ChannelDescriptorTestNone : public ChannelDescriptorTestShell<T> {
public:
ChannelDescriptorTestNone() : ChannelDescriptorTestShell<T>(ChannelDimension::OneDim) {}
protected:
void SetSizeAndKind() {}
};
+49
Просмотреть файл
@@ -0,0 +1,49 @@
# 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.
if(UNIX)
set(TEST_SRC ${TEST_SRC}
complex_loading_behavior.cc)
set(AMD_TEST_SRC
hipApiDynamicLoad.cc)
if(HIP_PLATFORM MATCHES "amd")
set(TEST_SRC ${TEST_SRC} ${AMD_TEST_SRC})
endif()
hip_add_exe_to_target(NAME dynamicLoading
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests)
if(HIP_PLATFORM MATCHES "amd")
add_custom_target(libLazyLoad.so COMMAND ${CMAKE_CXX_COMPILER} -fPIC -lpthread -shared ${OFFLOAD_ARCH_STR} ${CMAKE_CURRENT_SOURCE_DIR}/liblazyLoad.cc -I${CMAKE_CURRENT_SOURCE_DIR}/../../include -I${CMAKE_CURRENT_SOURCE_DIR}/../../external/Catch2 -o libLazyLoad.so)
elseif(HIP_PLATFORM MATCHES "nvidia")
add_custom_target(libLazyLoad.so COMMAND ${CMAKE_CXX_COMPILER} -Xcompiler -fPIC -lpthread -shared ${CMAKE_CURRENT_SOURCE_DIR}/liblazyLoad.cc -I${CMAKE_CURRENT_SOURCE_DIR}/../../include -I${CMAKE_CURRENT_SOURCE_DIR}/../../external/Catch2 -o libLazyLoad.so)
endif()
add_custom_target(bit_extract_kernel.code COMMAND ${CMAKE_CXX_COMPILER} --genco ${OFFLOAD_ARCH_STR} ${CMAKE_CURRENT_SOURCE_DIR}/bit_extract_kernel.cpp -o ${CMAKE_CURRENT_BINARY_DIR}/../dynamicLoading/bit_extract_kernel.code -I${CMAKE_CURRENT_SOURCE_DIR}/../../../../include/ -I${CMAKE_CURRENT_SOURCE_DIR}/../../include)
if(HIP_PLATFORM MATCHES "amd")
hip_add_exe_to_target(NAME Dynamic
TEST_SRC ${LINUX_TEST_SRC}
TEST_TARGET_NAME build_tests
LINKER_LIBS ${CMAKE_DL_LIBS})
endif()
add_dependencies(build_tests bit_extract_kernel.code libLazyLoad.so)
endif()
+32
Просмотреть файл
@@ -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 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/hip_runtime.h>
extern "C" __global__ void bit_extract_kernel(uint32_t* C_d, const uint32_t*
A_d, size_t N) {
size_t offset = (blockIdx.x * blockDim.x + threadIdx.x);
size_t stride = blockDim.x * gridDim.x;
for (size_t i = offset; i < N; i += stride) {
#if HT_AMD
C_d[i] = __bitextract_u32(A_d[i], 8, 4);
#else /* defined __HIP_PLATFORM_NVIDIA__ or other path */
C_d[i] = ((A_d[i] & 0xf00) >> 8);
#endif
}
}
+147
Просмотреть файл
@@ -0,0 +1,147 @@
/*
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 <dlfcn.h>
#include <hip_test_defgroups.hh>
/**
* @addtogroup hipLaunchKernelGGL hipLaunchCooperativeKernel
* @{
* @ingroup DynamicLoading
* `hipLaunchKernelGGL(F kernel, const dim3& numBlocks, const dim3& dimBlocks,
std::uint32_t sharedMemBytes, hipStream_t stream, Args... args)` -
* launches Kernel with launch parameters and shared memory on stream with arguments passed
* `hipError_t hipLaunchCooperativeKernel(const void* f, dim3 gridDim, dim3 blockDimX,
void** kernelParams, unsigned int sharedMemBytes,
hipStream_t stream))` -
* launches kernel f with launch parameters and shared memory on stream with arguments passed
* to kernelparams or extra, where thread blocks can cooperate and synchronize as they execute
*/
/**
* Test Description
* ------------------------
* - Test case to verify locally loaded kernels and dynamically loaded kernels from the library.
* Test source
* ------------------------
* - catch/unit/dynamicLoading/complex_loading_behavior.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
__global__ static void vector_add(float* C, float* A, float* B, size_t N) {
size_t offset = blockIdx.x * blockDim.x + threadIdx.x;
size_t stride = blockDim.x * gridDim.x;
for (size_t i = offset; i < N; i += stride) {
C[i] = A[i] + B[i];
}
}
static bool launch_local_kernel() {
bool testResult = true;
float *A_d, *B_d, *C_d;
float *A_h, *B_h, *C_h;
size_t N = 1000000;
size_t Nbytes = N * sizeof(float);
static int device = 0;
HIPCHECK(hipSetDevice(device));
hipDeviceProp_t props;
HIPCHECK(hipGetDeviceProperties(&props, device));
A_h = reinterpret_cast<float*>(malloc(Nbytes));
HIPCHECK(A_h == nullptr ? hipErrorOutOfMemory : hipSuccess);
B_h = reinterpret_cast<float*>(malloc(Nbytes));
HIPCHECK(B_h == nullptr ? hipErrorOutOfMemory : hipSuccess);
C_h = reinterpret_cast<float*>(malloc(Nbytes));
HIPCHECK(C_h == nullptr ? hipErrorOutOfMemory : hipSuccess);
// Fill with Phi + i
for (size_t i = 0; i < N; i++) {
A_h[i] = 1.618f + i;
B_h[i] = 1.618f + i;
}
HIPCHECK(hipMalloc(&A_d, Nbytes));
HIPCHECK(hipMalloc(&B_d, Nbytes));
HIPCHECK(hipMalloc(&C_d, Nbytes));
HIPCHECK(hipMemcpy(A_d, A_h, Nbytes, hipMemcpyHostToDevice));
HIPCHECK(hipMemcpy(B_d, B_h, Nbytes, hipMemcpyHostToDevice));
const unsigned blocks = 512;
const unsigned threadsPerBlock = 256;
hipLaunchKernelGGL(vector_add, dim3(blocks), dim3(threadsPerBlock),
0, 0, C_d, A_d, B_d, N);
HIPCHECK(hipMemcpy(C_h, C_d, Nbytes, hipMemcpyDeviceToHost));
for (size_t i=0; i < N ; i++) {
if (C_h[i] != (A_h[i] + B_h[i])) {
testResult = false;
break;
}
}
HIPCHECK(hipFree(A_d));
HIPCHECK(hipFree(B_d));
HIPCHECK(hipFree(C_d));
free(A_h);
free(B_h);
free(C_h);
return testResult;
}
static bool launch_dynamically_loaded_kernel() {
bool testResult = true;
int ret = 1;
void* handle = dlopen("./libLazyLoad.so", RTLD_LAZY);
if (!handle) {
INFO("dlopen Error: " << dlerror() << "\n");
testResult = false;
return testResult;
}
void* sym = dlsym(handle, "lazyLoad");
if (!sym) {
INFO("unable to locate lazyLoad within lazyLoad.so\n");
dlclose(handle);
testResult = false;
return testResult;
}
int(*fp)() = reinterpret_cast<int(*)()>(sym);
ret = fp();
if (ret == 0) {
testResult = false;
}
dlclose(handle);
return testResult;
}
TEST_CASE("Unit_dynamic_loading_device_kernels_from_library") {
bool testResult = true;
testResult &= launch_local_kernel();
testResult &= launch_dynamically_loaded_kernel();
REQUIRE(testResult == true);
}
+169
Просмотреть файл
@@ -0,0 +1,169 @@
/*
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_test_defgroups.hh>
#include <stdio.h>
#include <dlfcn.h>
#include <vector>
#include <iostream>
#include <fstream>
#define fileName "bit_extract_kernel.code"
#define LEN 64
#define SIZE LEN * sizeof(float)
/**
* @addtogroup dyn_hipModuleLoad dyn_hipModuleGetFunction dyn_hipModuleLaunchKernel
* @{
* @ingroup DynamicLoading
* ` hipError_t (*dyn_hipModuleLoad)(hipModule_t*, const char*) = reinterpret_cast
<hipError_t (*)(hipModule_t*, const char*)>(sym_hipModuleLoad)` -
* Loads code object from file into a module the currrent context
* `hipError_t (*dyn_hipModuleGetFunction)(hipFunction_t*, hipModule_t,
const char*) = reinterpret_cast < hipError_t (*)(hipFunction_t*,
hipModule_t, const char*)>(sym_hipModuleGetFunction)` -
* Function with kernelname will be extracted if present in module
* `hipError_t (*dyn_hipModuleLaunchKernel)(hipFunction_t, unsigned int,
unsigned int, unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int, hipStream_t, void**, void**)
= reinterpret_cast<hipError_t(*) (hipFunction_t,
unsigned int, unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int, unsigned int, hipStream_t,
void**, void**)>(sym_hipModuleLaunchKernel)` -
* launches Kernel with launch parameters and shared memory on stream with arguments passed
*/
/**
* Test Description
* ------------------------
* - Test is to load hip runtime using dlopen and get function pointer using dlsym for hip apis.
* Test source
* ------------------------
* - catch/unit/dynamicLoading/hipApiDynamicLoad.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
TEST_CASE("Unit_hipApiDynamicLoad") {
uint32_t *A_d, *C_d;
uint32_t *A_h, *C_h;
size_t N = 1000000;
size_t Nbytes = N * sizeof(uint32_t);
void* handle = dlopen("libamdhip64.so", RTLD_LAZY);
REQUIRE(handle != NULL);
void* sym_hipGetDevice = dlsym(handle, "hipGetDevice");
void* sym_hipMalloc = dlsym(handle, "hipMalloc");
void* sym_hipMemcpyHtoD = dlsym(handle, "hipMemcpyHtoD");
void* sym_hipMemcpyDtoH = dlsym(handle, "hipMemcpyDtoH");
void* sym_hipModuleLoad = dlsym(handle, "hipModuleLoad");
void* sym_hipGetDeviceProperties = dlsym(handle, "hipGetDeviceProperties");
void* sym_hipModuleGetFunction = dlsym(handle, "hipModuleGetFunction");
void* sym_hipModuleLaunchKernel = dlsym(handle, "hipModuleLaunchKernel");
dlclose(handle);
hipError_t (*dyn_hipGetDevice)(hipDevice_t*, int) = reinterpret_cast
<hipError_t (*)(hipDevice_t*, int)>(sym_hipGetDevice);
hipError_t (*dyn_hipMalloc)(void**, uint32_t) = reinterpret_cast
<hipError_t (*)(void**, uint32_t)>(sym_hipMalloc);
hipError_t (*dyn_hipMemcpyHtoD)(hipDeviceptr_t, void*, size_t) =
reinterpret_cast<hipError_t (*)(hipDeviceptr_t, void*,
size_t)>(sym_hipMemcpyHtoD);
hipError_t (*dyn_hipMemcpyDtoH)(void*, hipDeviceptr_t, size_t) =
reinterpret_cast<hipError_t (*)(void*, hipDeviceptr_t,
size_t)>(sym_hipMemcpyDtoH);
hipError_t (*dyn_hipModuleLoad)(hipModule_t*, const char*) = reinterpret_cast
<hipError_t (*)(hipModule_t*, const char*)>(sym_hipModuleLoad);
hipError_t (*dyn_hipGetDeviceProperties)(hipDeviceProp_t*, int) =
reinterpret_cast<hipError_t (*)(hipDeviceProp_t*, int)>
(sym_hipGetDeviceProperties);
hipError_t (*dyn_hipModuleGetFunction)(hipFunction_t*, hipModule_t,
const char*) = reinterpret_cast < hipError_t (*)(hipFunction_t*,
hipModule_t, const char*)>(sym_hipModuleGetFunction);
hipError_t (*dyn_hipModuleLaunchKernel)(hipFunction_t, unsigned int,
unsigned int, unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int, hipStream_t, void**, void**)
= reinterpret_cast<hipError_t(*) (hipFunction_t,
unsigned int, unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int, unsigned int, hipStream_t,
void**, void**)>(sym_hipModuleLaunchKernel);
hipDevice_t device;
HIPCHECK(dyn_hipGetDevice(&device, 0));
hipDeviceProp_t props;
HIPCHECK(dyn_hipGetDeviceProperties(&props, device));
A_h = reinterpret_cast<uint32_t*>(malloc(Nbytes));
REQUIRE(A_h != NULL);
C_h = reinterpret_cast<uint32_t*>(malloc(Nbytes));
REQUIRE(C_h != NULL);
for (size_t i = 0; i < N; i++) {
A_h[i] = i;
}
HIPCHECK(dyn_hipMalloc(reinterpret_cast<void**>(&A_d), Nbytes));
HIPCHECK(dyn_hipMalloc(reinterpret_cast<void**>(&C_d), Nbytes));
HIPCHECK(dyn_hipMemcpyHtoD((hipDeviceptr_t)(A_d), A_h, Nbytes));
struct {
void* _Cd;
void* _Ad;
size_t _N;
} args;
args._Cd = reinterpret_cast<void**> (C_d);
args._Ad = reinterpret_cast<void**> (A_d);
args._N = static_cast<size_t> (N);
size_t size = sizeof(args);
void* config[] = {HIP_LAUNCH_PARAM_BUFFER_POINTER, &args,
HIP_LAUNCH_PARAM_BUFFER_SIZE, &size, HIP_LAUNCH_PARAM_END};
hipModule_t Module;
HIPCHECK(dyn_hipModuleLoad(&Module, fileName));
hipFunction_t Function;
HIPCHECK(dyn_hipModuleGetFunction(&Function, Module, "bit_extract_kernel"));
HIPCHECK(dyn_hipModuleLaunchKernel(Function, 1, 1, 1, LEN, 1, 1, 0, 0, NULL,
reinterpret_cast<void**>(&config)));
HIPCHECK(dyn_hipMemcpyDtoH(C_h, (hipDeviceptr_t)(C_d), Nbytes));
for (size_t i = 0; i < N; i++) {
unsigned Agold = ((A_h[i] & 0xf00) >> 8);
REQUIRE(C_h[i] == Agold);
}
HIPCHECK(hipFree(A_d));
HIPCHECK(hipFree(C_d));
free(A_h);
free(C_h);
}
+212
Просмотреть файл
@@ -0,0 +1,212 @@
/*
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/hip_runtime.h>
#include <hip/hip_runtime_api.h>
#define CHECK_RET_VAL(cmd) \
{ \
hipError_t error = cmd;\
if (error != hipSuccess) {\
fprintf(stderr, "error: '%s'(%d) at %s:%d\n", hipGetErrorString(error), \
error, __FILE__, __LINE__);\
exit(EXIT_FAILURE);\
}\
}
__global__ static void addition(float* C, float* A, float* B, size_t N) {
size_t offset = hipBlockIdx_x * hipBlockDim_x + hipThreadIdx_x;
size_t stride = hipBlockDim_x * hipGridDim_x;
for (size_t i = offset; i < N; i += stride) {
C[i] = A[i] + B[i];
}
}
static int vectorAddKernelTest() {
int testResult = 1;
float *A_d, *B_d, *C_d;
float *A_h, *B_h, *C_h;
size_t N = 1000000;
size_t Nbytes = N * sizeof(float);
static int device = 0;
CHECK_RET_VAL(hipSetDevice(device));
hipDeviceProp_t props;
CHECK_RET_VAL(hipGetDeviceProperties(&props, device));
A_h = reinterpret_cast<float*>(malloc(Nbytes));
CHECK_RET_VAL(A_h == nullptr ? hipErrorOutOfMemory : hipSuccess);
B_h = reinterpret_cast<float*>(malloc(Nbytes));
CHECK_RET_VAL(B_h == nullptr ? hipErrorOutOfMemory : hipSuccess);
C_h = reinterpret_cast<float*>(malloc(Nbytes));
CHECK_RET_VAL(C_h == nullptr ? hipErrorOutOfMemory : hipSuccess);
// Fill with Phi + i
for (size_t i = 0; i < N; i++) {
A_h[i] = 1.618f + i;
B_h[i] = 1.618f + i;
}
CHECK_RET_VAL(hipMalloc(&A_d, Nbytes));
CHECK_RET_VAL(hipMalloc(&B_d, Nbytes));
CHECK_RET_VAL(hipMalloc(&C_d, Nbytes));
CHECK_RET_VAL(hipMemcpy(A_d, A_h, Nbytes, hipMemcpyHostToDevice));
CHECK_RET_VAL(hipMemcpy(B_d, B_h, Nbytes, hipMemcpyHostToDevice));
const unsigned blocks = 512;
const unsigned threadsPerBlock = 256;
hipLaunchKernelGGL(addition, dim3(blocks), dim3(threadsPerBlock),
0, 0, C_d, A_d, B_d, N);
CHECK_RET_VAL(hipMemcpy(C_h, C_d, Nbytes, hipMemcpyDeviceToHost));
for (size_t i=0; i < N ; i++) {
if (C_h[i] != (A_h[i] + B_h[i])) {
testResult = 0;
break;
}
}
CHECK_RET_VAL(hipFree(A_d));
CHECK_RET_VAL(hipFree(B_d));
CHECK_RET_VAL(hipFree(C_d));
free(A_h);
free(B_h);
free(C_h);
return testResult;
}
#include "hip/hip_cooperative_groups.h"
namespace cg = cooperative_groups;
static const uint BufferSizeInDwords = 448 * 1024 * 1024;
__global__ static void test_gws(uint* buf, uint bufSize,
int64_t* tmpBuf, int64_t* result) {
extern __shared__ int64_t tmp[];
uint offset = blockIdx.x * blockDim.x + threadIdx.x;
uint stride = gridDim.x * blockDim.x;
cg::grid_group gg = cg::this_grid();
int64_t sum = 0;
for (uint i = offset; i < bufSize; i += stride) {
sum += buf[i];
}
tmp[threadIdx.x] = sum;
__syncthreads();
if (threadIdx.x == 0) {
sum = 0;
for (uint i = 0; i < blockDim.x; i++) {
sum += tmp[i];
}
tmpBuf[blockIdx.x] = sum;
}
gg.sync();
if (offset == 0) {
for (uint i = 1; i < gridDim.x; ++i) {
sum += tmpBuf[i];
}
*result = sum;
}
}
static int cooperativeKernelTest() {
int testResult = 1;
uint* dA;
int64_t* dB;
int64_t* dC;
int64_t* Ah;
hipDeviceProp_t deviceProp;
hipGetDeviceProperties(&deviceProp, 0);
if (!deviceProp.cooperativeLaunch) {
return testResult;
}
uint32_t* init = new uint32_t[BufferSizeInDwords];
for (uint32_t i = 0; i < BufferSizeInDwords; ++i) {
init[i] = i;
}
size_t SIZE = BufferSizeInDwords * sizeof(uint);
CHECK_RET_VAL(hipMalloc(reinterpret_cast<void**>(&dA), SIZE));
CHECK_RET_VAL(hipMalloc(reinterpret_cast<void**>(&dC), sizeof(int64_t)));
CHECK_RET_VAL(hipMemcpy(dA, init, SIZE, hipMemcpyHostToDevice));
Ah = reinterpret_cast<int64_t*>(malloc(sizeof(int64_t)));
hipStream_t stream;
CHECK_RET_VAL(hipStreamCreate(&stream));
dim3 dimBlock = dim3(1);
dim3 dimGrid = dim3(1);
int numBlocks = 0;
uint workgroups[4] = {32, 64, 128, 256};
for (uint i = 0; i < 4; ++i) {
dimBlock.x = workgroups[i];
/* Calculate the device occupancy to know how many blocks can be
run concurrently */
hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlocks,
test_gws, dimBlock.x * dimBlock.y * dimBlock.z, dimBlock.x *
sizeof(int64_t));
dimGrid.x = deviceProp.multiProcessorCount * std::min(numBlocks, 32);
CHECK_RET_VAL(hipMalloc(reinterpret_cast<void**>(&dB),
dimGrid.x * sizeof(int64_t)));
void *params[4];
params[0] = reinterpret_cast<void*>(&dA);
params[1] = (void*)(&BufferSizeInDwords); // NOLINT
params[2] = reinterpret_cast<void*>(&dB);
params[3] = reinterpret_cast<void*>(&dC);
CHECK_RET_VAL(hipLaunchCooperativeKernel(reinterpret_cast<void*>(test_gws),
dimGrid, dimBlock, params,
dimBlock.x * sizeof(int64_t), stream));
CHECK_RET_VAL(hipMemcpy(Ah, dC, sizeof(int64_t), hipMemcpyDeviceToHost));
if (*Ah != (((int64_t)(BufferSizeInDwords) * (BufferSizeInDwords - 1))
/ 2)) {
CHECK_RET_VAL(hipFree(dB));
testResult = 0;
break;
} else {
CHECK_RET_VAL(hipFree(dB));
}
}
CHECK_RET_VAL(hipStreamDestroy(stream));
CHECK_RET_VAL(hipFree(dC));
CHECK_RET_VAL(hipFree(dA));
delete [] init;
free(Ah);
return testResult;
}
extern "C" int lazyLoad() {
return vectorAddKernelTest() & cooperativeKernelTest();
}
+5 -2
Просмотреть файл
@@ -158,7 +158,9 @@ TEST_CASE("Unit_hipEventElapsedTime_NotReady_Negative") {
// Record start event
HIP_CHECK(hipEventRecord(start, nullptr));
HipTest::runKernelForDuration(std::chrono::milliseconds(1000));
HipTest::BlockingContext b_context{nullptr};
b_context.block_stream(); // blocked stream
REQUIRE(b_context.is_blocked());
// Record stop event
HIP_CHECK(hipEventRecord(stop, nullptr));
@@ -166,7 +168,8 @@ TEST_CASE("Unit_hipEventElapsedTime_NotReady_Negative") {
// stop event has not been completed
float tElapsed = 1.0f;
HIP_CHECK_ERROR(hipEventQuery(stop), hipErrorNotReady);
HIP_ASSERT(hipEventElapsedTime(&tElapsed,start,stop) == hipErrorNotReady);
HIP_ASSERT(hipEventElapsedTime(&tElapsed, start, stop) == hipErrorNotReady);
b_context.unblock_stream();
HIP_CHECK(hipStreamSynchronize(nullptr));
HIP_CHECK(hipEventDestroy(start));
+7 -63
Просмотреть файл
@@ -19,57 +19,6 @@ THE SOFTWARE.
#include <hip_test_common.hh>
/**
* @addtogroup hipEventQuery hipEventQuery
* @{
* @ingroup EventTest
* `hipEventQuery(hipEvent_t event)` -
* Query the status of the specified event.
* ________________________
* Test cases from other modules:
* - @ref Unit_hipEventIpc
*/
// Since we can not use atomic*_system on every gpu, we will use wait based on clock rate.
// This wont be accurate since current clock rate of a GPU varies depending on many variables
// including thermals, load, utilization etc
__global__ void waitKernel(int clockRate, int seconds) {
auto start = clock();
auto ms = seconds * 1000;
long long waitTill = clockRate * (long long)ms;
while (1) {
auto end = clock();
if ((end - start) > waitTill) {
return;
}
}
}
__global__ void waitKernel_gfx11(int clockRate, int seconds) {
#if HT_AMD
auto start = wall_clock64();
auto ms = seconds * 1000;
long long waitTill = clockRate * (long long)ms;
while (1) {
auto end = wall_clock64();
if ((end - start) > waitTill) {
return;
}
}
#endif
}
/**
* Test Description
* ------------------------
* - Query events with a single and with multiple devices.
* Test source
* ------------------------
* - unit/event/Unit_hipEventQuery.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipEventQuery_DifferentDevice") {
hipEvent_t event1{}, event2{};
HIP_CHECK(hipEventCreate(&event1));
@@ -81,19 +30,14 @@ TEST_CASE("Unit_hipEventQuery_DifferentDevice") {
HIP_CHECK(hipStreamCreate(&stream));
REQUIRE(stream != nullptr);
hipDeviceProp_t prop{};
HIP_CHECK(hipGetDeviceProperties(&prop, 0));
auto clockRate = prop.clockRate;
// Start kernel on 1st device
HipTest::BlockingContext b_context1{stream}; // og context
// Block stream
{
HIP_CHECK(hipSetDevice(0));
HIP_CHECK(hipEventRecord(event1, stream));
auto waitKernel_used = IsGfx11() ? waitKernel_gfx11 : waitKernel;
// Start kernel and wait for 3 seconds
// Make sure you increase this time if you add more tests here
waitKernel_used<<<1, 1, 0, stream>>>(clockRate, 3);
b_context1.block_stream(); // blocked stream
REQUIRE(b_context1.is_blocked());
HIP_CHECK(hipEventRecord(event2, stream));
@@ -101,7 +45,7 @@ TEST_CASE("Unit_hipEventQuery_DifferentDevice") {
HIP_CHECK(hipEventQuery(event1)); // Should be done
HIP_CHECK_ERROR(hipEventQuery(event2),
hipErrorNotReady); // Wont be done since kernel is waiting
hipErrorNotReady); // Wont be done since stream is blocked
}
// If other devices are available, set it
@@ -114,8 +58,8 @@ TEST_CASE("Unit_hipEventQuery_DifferentDevice") {
HIP_CHECK(hipEventQuery(event1));
HIP_CHECK_ERROR(hipEventQuery(event2), hipErrorNotReady);
// Sync
// if it hangs here it means GPU kernel cant see the value update by atomic store
b_context1.unblock_stream();
HIP_CHECK(hipEventSynchronize(event2));
// Query, should be done now
+11
Просмотреть файл
@@ -0,0 +1,11 @@
set(TEST_SRC
execution_control_common.cc
hipFuncSetCacheConfig.cc
hipFuncSetSharedMemConfig.cc
hipFuncSetAttribute.cc
)
hip_add_exe_to_target(NAME ExecutionControlTest
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests
COMPILE_OPTIONS -std=c++17)
+27
Просмотреть файл
@@ -0,0 +1,27 @@
/*
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 "execution_control_common.hh"
#include <hip_test_common.hh>
__global__ void kernel() {}
+25
Просмотреть файл
@@ -0,0 +1,25 @@
/*
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.
*/
#pragma once
__global__ void kernel();
+260
Просмотреть файл
@@ -0,0 +1,260 @@
/*
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 "execution_control_common.hh"
#include <hip_test_common.hh>
#include <hip/hip_runtime_api.h>
/**
* @addtogroup hipFuncSetAttribute hipFuncSetAttribute
* @{
* @ingroup ExecutionTest
* `hipFuncSetAttribute(const void* func, hipFuncAttribute attr, int value)` -
* Set attribute for a specific function.
*/
/**
* Test Description
* ------------------------
* - Sets maximum dynamic shared memory size to the non-default value.
* - Expected output: return `hipSuccess`
* Test source
* ------------------------
* - unit/executionControl/hipFuncSetAttribute.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipFuncSetAttribute_Positive_MaxDynamicSharedMemorySize") {
HIP_CHECK(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributeMaxDynamicSharedMemorySize, 1024));
hipFuncAttributes attributes;
HIP_CHECK(hipFuncGetAttributes(&attributes, reinterpret_cast<void*>(kernel)));
REQUIRE(attributes.maxDynamicSharedSizeBytes == 1024);
}
/**
* Test Description
* ------------------------
* - Sets preferred shared memory carveout to the non-default value.
* - Expected output: return `hipSuccess`
* Test source
* ------------------------
* - unit/executionControl/hipFuncSetAttribute.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipFuncSetAttribute_Positive_PreferredSharedMemoryCarveout") {
HIP_CHECK(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributePreferredSharedMemoryCarveout, 50));
hipFuncAttributes attributes;
HIP_CHECK(hipFuncGetAttributes(&attributes, reinterpret_cast<void*>(kernel)));
REQUIRE(attributes.preferredShmemCarveout == 50);
}
/**
* Test Description
* ------------------------
* - Validates handling of valid arguments:
* -# When `hipFuncAttributeMaxDynamicSharedMemorySize == 0`
* - Expected output: return `hipSuccess`
* -# When `hipFuncAttributeMaxDynamicSharedMemorySize == maxSharedMemoryPerBlock - sharedSizeBytes`
* - Expected output: return `hipSuccess`
* -# When `hipFuncAttributePreferredSharedMemoryCarveout` is 0%
* - Expected output: return `hipSuccess`
* -# When `hipFuncAttributePreferredSharedMemoryCarveout` is 100%
* - Expected output: return `hipSuccess`
* -# When `hipFuncAttributePreferredSharedMemoryCarveout` is default (-1)
* - Expected output: return `hipSuccess`
* Test source
* ------------------------
* - unit/executionControl/hipFuncSetAttribute.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipFuncSetAttribute_Positive_Parameters") {
SECTION("hipFuncAttributeMaxDynamicSharedMemorySize == 0") {
HIP_CHECK(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributeMaxDynamicSharedMemorySize, 0));
}
SECTION(
"hipFuncAttributeMaxDynamicSharedMemorySize == maxSharedMemoryPerBlock - sharedSizeBytes") {
// The sum of this value and the function attribute sharedSizeBytes cannot exceed the device
// attribute cudaDevAttrMaxSharedMemoryPerBlockOptin
int max_shared;
HIP_CHECK(hipDeviceGetAttribute(&max_shared, hipDeviceAttributeMaxSharedMemoryPerBlock, 0));
hipFuncAttributes attributes;
HIP_CHECK(hipFuncGetAttributes(&attributes, reinterpret_cast<void*>(kernel)));
HIP_CHECK(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributeMaxDynamicSharedMemorySize,
max_shared - attributes.sharedSizeBytes));
}
SECTION("hipFuncAttributePreferredSharedMemoryCarveout == 0") {
HIP_CHECK(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributePreferredSharedMemoryCarveout, 0));
}
SECTION("hipFuncAttributePreferredSharedMemoryCarveout == 100") {
HIP_CHECK(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributePreferredSharedMemoryCarveout, 100));
}
SECTION("hipFuncAttributePreferredSharedMemoryCarveout == -1 (default)") {
HIP_CHECK(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributePreferredSharedMemoryCarveout, -1));
}
}
/**
* Test Description
* ------------------------
* - Validates handling of invalid arguments:
* -# When pointer to the kernel function is `nullptr`
* - Expected output: return `hipErrorInvalidDeviceFunction`
* -# When the attribute is invalid
* - Expected output: return `hipErrorInvalidValue`
* -# When `hipFuncAttributeMaxDynamicSharedMemorySize < 0`
* - Expected output: return `hipErrorInvalidValue`
* -# When `hipFuncAttributeMaxDynamicSharedMemorySize > maxSharedMemoryPerBlock - sharedSizeBytes`
* - Expected output: return `hipErrorInvalidValue`
* -# When `hipFuncAttributePreferredSharedMemoryCarveout` is negative
* - Expected output: return `hipErrorInvalidValue`
* -# When `hipFuncAttributePreferredSharedMemoryCarveout` is above 100%
* - Expected output: return `hipErrorInvalidValue`
* Test source
* ------------------------
* - unit/executionControl/hipFuncSetAttribute.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipFuncSetAttribute_Negative_Parameters") {
SECTION("func == nullptr") {
HIP_CHECK_ERROR(hipFuncSetAttribute(nullptr, hipFuncAttributePreferredSharedMemoryCarveout, 50),
hipErrorInvalidDeviceFunction);
}
SECTION("invalid attribute") {
HIP_CHECK_ERROR(
hipFuncSetAttribute(reinterpret_cast<void*>(kernel), static_cast<hipFuncAttribute>(-1), 50),
hipErrorInvalidValue);
}
SECTION("hipFuncAttributeMaxDynamicSharedMemorySize < 0") {
HIP_CHECK_ERROR(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributeMaxDynamicSharedMemorySize, -1),
hipErrorInvalidValue);
}
SECTION(
"hipFuncAttributeMaxDynamicSharedMemorySize > maxSharedMemoryPerBlock - sharedSizeBytes") {
// The sum of this value and the function attribute sharedSizeBytes cannot exceed the device
// attribute cudaDevAttrMaxSharedMemoryPerBlockOptin
int max_shared;
HIP_CHECK(hipDeviceGetAttribute(&max_shared, hipDeviceAttributeMaxSharedMemoryPerBlock, 0));
hipFuncAttributes attributes;
HIP_CHECK(hipFuncGetAttributes(&attributes, reinterpret_cast<void*>(kernel)));
HIP_CHECK_ERROR(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributeMaxDynamicSharedMemorySize,
max_shared - attributes.sharedSizeBytes + 1),
hipErrorInvalidValue);
}
SECTION("hipFuncAttributePreferredSharedMemoryCarveout < -1") {
HIP_CHECK_ERROR(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributePreferredSharedMemoryCarveout, -2),
hipErrorInvalidValue);
}
SECTION("hipFuncAttributePreferredSharedMemoryCarveout > 100") {
HIP_CHECK_ERROR(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributePreferredSharedMemoryCarveout, 101),
hipErrorInvalidValue);
}
}
/**
* Test Description
* ------------------------
* - Sets `hipFuncAttributeMaxDynamicSharedMemorySize` to the non-supported value
* - Expected output: return `hipErrorNotSupported`
* Test source
* ------------------------
* - unit/executionControl/hipFuncSetAttribute.cc
* Test requirements
* ------------------------
* - Platform specific (AMD)
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipFuncSetAttribute_Positive_MaxDynamicSharedMemorySize_Not_Supported") {
hipFuncAttributes old_attributes;
HIP_CHECK(hipFuncGetAttributes(&old_attributes, reinterpret_cast<void*>(kernel)));
HIP_CHECK_ERROR(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributeMaxDynamicSharedMemorySize, 1024),
hipErrorNotSupported);
hipFuncAttributes new_attributes;
HIP_CHECK(hipFuncGetAttributes(&new_attributes, reinterpret_cast<void*>(kernel)));
REQUIRE(old_attributes.maxDynamicSharedSizeBytes == new_attributes.maxDynamicSharedSizeBytes);
}
/**
* Test Description
* ------------------------
* - Sets `hipFuncAttributePreferredSharedMemoryCarveout` to the non-supported value
* - Expected output: return `hipErrorNotSupported`
* Test source
* ------------------------
* - unit/executionControl/hipFuncSetAttribute.cc
* Test requirements
* ------------------------
* - Platform specific (AMD)
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipFuncSetAttribute_Positive_PreferredSharedMemoryCarveout_Not_Supported") {
hipFuncAttributes old_attributes;
HIP_CHECK(hipFuncGetAttributes(&old_attributes, reinterpret_cast<void*>(kernel)));
HIP_CHECK_ERROR(hipFuncSetAttribute(reinterpret_cast<void*>(kernel),
hipFuncAttributePreferredSharedMemoryCarveout, 50),
hipErrorNotSupported);
hipFuncAttributes new_attributes;
HIP_CHECK(hipFuncGetAttributes(&new_attributes, reinterpret_cast<void*>(kernel)));
REQUIRE(old_attributes.preferredShmemCarveout == new_attributes.preferredShmemCarveout);
}
+105
Просмотреть файл
@@ -0,0 +1,105 @@
/*
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 "execution_control_common.hh"
#include <hip_test_common.hh>
#include <hip/hip_runtime_api.h>
/**
* @addtogroup hipFuncSetCacheConfig hipFuncSetCacheConfig
* @{
* @ingroup ExecutionTest
* `hipFuncSetCacheConfig(const void* func, hipFuncCache_t config)` -
* Set Cache configuration for a specific function.
*/
namespace {
constexpr std::array<hipFuncCache_t, 4> kCacheConfigs{
hipFuncCachePreferNone, hipFuncCachePreferShared, hipFuncCachePreferL1,
hipFuncCachePreferEqual};
} // anonymous namespace
/**
* Test Description
* ------------------------
* - Sets cache config for every cache config enumeration.
* Test source
* ------------------------
* - unit/executionControl/hipFuncSetCacheConfig.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipFuncSetCacheConfig_Positive_Basic") {
const auto cache_config = GENERATE(from_range(begin(kCacheConfigs), end(kCacheConfigs)));
HIP_CHECK(hipFuncSetCacheConfig(reinterpret_cast<void*>(kernel), cache_config));
kernel<<<1, 1>>>();
HIP_CHECK(hipDeviceSynchronize());
}
/**
* Test Description
* ------------------------
* - Validates handling of invalid arguments:
* -# When pointer to the kernel function is `nullptr`
* - Expected output: return `hipErrorInvalidDeviceFunction`
* -# When cache config enumeration is invalid
* - Expected output: return `hipErrorInvalidValue`
* Test source
* ------------------------
* - unit/executionControl/hipFuncSetCacheConfig.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipFuncSetCacheConfig_Negative_Parameters") {
SECTION("func == nullptr") {
HIP_CHECK_ERROR(hipFuncSetCacheConfig(nullptr, hipFuncCachePreferNone),
hipErrorInvalidDeviceFunction);
}
SECTION("invalid cache config") {
HIP_CHECK_ERROR(
hipFuncSetCacheConfig(reinterpret_cast<void*>(kernel), static_cast<hipFuncCache_t>(-1)),
hipErrorInvalidValue);
}
}
/**
* Test Description
* ------------------------
* - Sets cache config that is not supported.
* - Expected output: return `hipErrorNotSupported`
* Test source
* ------------------------
* - unit/executionControl/hipFuncSetCacheConfig.cc
* Test requirements
* ------------------------
* - Platform specific (AMD)
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipFuncSetCacheConfig_Negative_Not_Supported") {
HIP_CHECK_ERROR(hipFuncSetCacheConfig(reinterpret_cast<void*>(kernel), hipFuncCachePreferNone),
hipErrorNotSupported);
}
+106
Просмотреть файл
@@ -0,0 +1,106 @@
/*
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 "execution_control_common.hh"
#include <hip_test_common.hh>
#include <hip/hip_runtime_api.h>
/**
* @addtogroup hipFuncSetSharedMemConfig hipFuncSetSharedMemConfig
* @{
* @ingroup ExecutionTest
* `hipFuncSetSharedMemConfig(const void* func, hipSharedMemConfig config)` -
* Set shared memory configuation for a specific function.
*/
namespace {
constexpr std::array<hipSharedMemConfig, 3> kSharedMemConfigs{
hipSharedMemBankSizeDefault, hipSharedMemBankSizeFourByte, hipSharedMemBankSizeEightByte};
} // anonymous namespace
/**
* Test Description
* ------------------------
* - Sets cache config for every shared memory config enumeration.
* Test source
* ------------------------
* - unit/executionControl/hipFuncSetSharedMemConfig.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipFuncSetSharedMemConfig_Positive_Basic") {
const auto shared_mem_config =
GENERATE(from_range(begin(kSharedMemConfigs), end(kSharedMemConfigs)));
HIP_CHECK(hipFuncSetSharedMemConfig(reinterpret_cast<void*>(kernel), shared_mem_config));
kernel<<<1, 1>>>();
HIP_CHECK(hipDeviceSynchronize());
}
/**
* Test Description
* ------------------------
* - Validates handling of invalid arguments:
* -# When pointer to the kernel function is `nullptr`
* - Expected output: return `hipErrorInvalidDeviceFunction`
* -# When shared memory config enumeration is invalid
* - Expected output: return `hipErrorInvalidValue`
* Test source
* ------------------------
* - unit/executionControl/hipFuncSetSharedMemConfig.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipFuncSetSharedMemConfig_Negative_Parameters") {
SECTION("func == nullptr") {
HIP_CHECK_ERROR(hipFuncSetSharedMemConfig(nullptr, hipSharedMemBankSizeDefault),
hipErrorInvalidDeviceFunction);
}
SECTION("invalid shared mem config") {
HIP_CHECK_ERROR(hipFuncSetSharedMemConfig(reinterpret_cast<void*>(kernel),
static_cast<hipSharedMemConfig>(-1)),
hipErrorInvalidValue);
}
}
/**
* Test Description
* ------------------------
* - Sets shared memory config that is not supported.
* - Expected output: return `hipErrorNotSupported`
* Test source
* ------------------------
* - unit/executionControl/hipFuncSetSharedMemConfig.cc
* Test requirements
* ------------------------
* - Platform specific (AMD)
* - HIP_VERSION >= 5.2
*/
TEST_CASE("Unit_hipFuncSetSharedMemConfig_Negative_Not_Supported") {
HIP_CHECK_ERROR(
hipFuncSetSharedMemConfig(reinterpret_cast<void*>(kernel), hipSharedMemBankSizeDefault),
hipErrorNotSupported);
}
+19
Просмотреть файл
@@ -0,0 +1,19 @@
# AMD specific test
if(HIP_PLATFORM MATCHES "amd")
if(UNIX)
set(TEST_SRC
hipMalloc.cc
)
# Creating Custom object file
add_custom_target(malloc_custom COMMAND g++ -c ${CMAKE_CURRENT_SOURCE_DIR}/hipMalloc.cpp -I${HIP_PATH}/include -D__HIP_PLATFORM_AMD__ -o malloc.o BYPRODUCTS malloc.o)
add_library(malloc_gpp OBJECT IMPORTED)
set_property(TARGET malloc_gpp PROPERTY IMPORTED_OBJECTS "${CMAKE_CURRENT_BINARY_DIR}/malloc.o")
hip_add_exe_to_target(NAME gppTests
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests
LINKER_LIBS malloc_gpp)
add_dependencies(gppTests malloc_custom)
endif()
endif()
+49
Просмотреть файл
@@ -0,0 +1,49 @@
/*
* 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 <hip_test_defgroups.hh>
#include "hipMalloc.h"
/**
* @addtogroup hipMalloc hipMalloc
* @{
* @ingroup MemoryTest
* `hipError_t hipMalloc(void** ptr, size_t size)` -
* Allocate memory on the default accelerator.
* @}
*/
/**
* Test Description
* ------------------------
* - Allocate memory by using hipMalloc API and verify hipSuccess is returned.
* Test source
* ------------------------
* - catch/unit/g++/hipMalloc.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
TEST_CASE("Unit_hipMalloc_gpptest") {
printf("calling cpp function from here\n");
int result = MallocFunc();
REQUIRE(result == 1);
}
+35
Просмотреть файл
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2019 - 2021 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/hip_runtime_api.h>
#include <iostream>
#include "hipMalloc.h"
int MallocFunc() {
int* Ad;
hipError_t err;
err = hipMalloc(reinterpret_cast<void**>(&Ad), 1024);
if (err == hipSuccess) {
std::cout <<"PASSED!" <<std::endl;
return 1;
} else {
std::cout <<"FAILED!" <<std::endl;
return 0;
}
}
+22
Просмотреть файл
@@ -0,0 +1,22 @@
/*
* 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 <iostream>
extern int MallocFunc();
+4
Просмотреть файл
@@ -130,6 +130,8 @@ set(TEST_SRC
hipGraphKernelNodeGetAttribute.cc
hipGraphKernelNodeSetAttribute.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${CMAKE_CURRENT_SOURCE_DIR}/../../../../include/ -I${CMAKE_CURRENT_SOURCE_DIR}/../../include --rocm-path=${ROCM_PATH})
hip_add_exe_to_target(NAME GraphsTest2
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests)
@@ -138,3 +140,5 @@ if(HIP_PLATFORM MATCHES "amd")
add_custom_target(hipMatMul COMMAND ${CMAKE_CXX_COMPILER} --genco ${OFFLOAD_ARCH_STR} ${CMAKE_CURRENT_SOURCE_DIR}/hipMatMul.cc -o ${CMAKE_CURRENT_BINARY_DIR}/../../unit/graph/hipMatMul.code -I${CMAKE_CURRENT_SOURCE_DIR}/../../../../include/ -I${CMAKE_CURRENT_SOURCE_DIR}/../../include --rocm-path=${ROCM_PATH})
add_dependencies(build_tests hipMatMul)
endif()
add_dependencies(build_tests add_Kernel.code)
+24
Просмотреть файл
@@ -0,0 +1,24 @@
/*
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/hip_runtime.h"
extern "C" __global__ void Add(int* a, int* b, int* c) {
size_t tx = (blockIdx.x * blockDim.x + threadIdx.x);
c[tx] = a[tx] + b[tx];
}
+378 -19
Просмотреть файл
@@ -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
in the Software without restriction, including without limitation the rights
@@ -18,12 +18,47 @@ 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_kernels.hh>
#include <hip_test_checkers.hh>
#include <hip_test_defgroups.hh>
/* Test verifies hipGraphAddKernelNode API Negative scenarios.
#define CODEOBJ_FILE "add_Kernel.code"
#define KERNEL_NAME "Add"
#define THREADS_PER_BLOCK 512
/**
* @addtogroup hipGraphAddKernelNode hipModuleLoad hipModuleGetFunction
* @{
* @ingroup GraphTest
* `hipError_t hipGraphAddKernelNode(hipGraphNode_t* pGraphNode, hipGraph_t graph,
const hipGraphNode_t* pDependencies, size_t numDependencies,
const hipKernelNodeParams* pNodeParams)` -
* Creates a kernel execution node and adds it to a graph
* `hipError_t hipModuleLoad(hipModule_t* module, const char* fname)` -
* Loads code object from file into a module the currrent context
* `hipError_t hipModuleGetFunction(hipFunction_t* function, hipModule_t module, const char* kname)` -
* Function with kname will be extracted if present in module
*/
/**
* Test Description
* ------------------------
* - Test case to verify negative scenarios of hipGraphAddKernelNode API.
* Test source
* ------------------------
* - catch/unit/graph/hipGraphAddKernelNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
constexpr size_t size = 1 << 12;
enum fnType {
normal,
object
};
TEST_CASE("Unit_hipGraphAddKernelNode_Negative") {
constexpr int N = 1024;
size_t NElem{N};
@@ -48,46 +83,46 @@ TEST_CASE("Unit_hipGraphAddKernelNode_Negative") {
kNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgs);
SECTION("Pass pGraphNode as nullptr") {
HIP_CHECK_ERROR(hipGraphAddKernelNode(nullptr, graph, nullptr, 0, &kNodeParams),
hipErrorInvalidValue);
HIP_CHECK_ERROR(hipGraphAddKernelNode(nullptr, graph, nullptr,
0, &kNodeParams), hipErrorInvalidValue);
}
SECTION("Pass Graph as nullptr") {
HIP_CHECK_ERROR(hipGraphAddKernelNode(&kNode, nullptr, nullptr, 0, &kNodeParams),
hipErrorInvalidValue);
HIP_CHECK_ERROR(hipGraphAddKernelNode(&kNode, nullptr, nullptr,
0, &kNodeParams), hipErrorInvalidValue);
}
SECTION("Pass invalid numDependencies") {
HIP_CHECK_ERROR(hipGraphAddKernelNode(&kNode, graph, nullptr, 11, &kNodeParams),
hipErrorInvalidValue);
HIP_CHECK_ERROR(hipGraphAddKernelNode(&kNode, graph, nullptr, 11,
&kNodeParams), hipErrorInvalidValue);
}
SECTION("Pass invalid numDependencies and valid list for dependencies") {
HIP_CHECK(hipGraphAddKernelNode(&kNode, graph, nullptr, 0, &kNodeParams));
dependencies.push_back(kNode);
HIP_CHECK_ERROR(hipGraphAddKernelNode(&kNode, graph, dependencies.data(),
dependencies.size() + 1, &kNodeParams),
hipErrorInvalidValue);
dependencies.size() + 1,
&kNodeParams), hipErrorInvalidValue);
}
SECTION("Pass NodeParams as nullptr") {
HIP_CHECK_ERROR(
hipGraphAddKernelNode(&kNode, graph, dependencies.data(), dependencies.size(), nullptr),
hipErrorInvalidValue);
hipGraphAddKernelNode(&kNode, graph, dependencies.data(),
dependencies.size(), nullptr), hipErrorInvalidValue);
}
#if HT_NVIDIA // on AMD this returns hipErrorInvalidValue
SECTION("Pass NodeParams func data member as nullptr") {
kNodeParams.func = nullptr;
HIP_CHECK_ERROR(hipGraphAddKernelNode(&kNode, graph, nullptr, 0, &kNodeParams),
hipErrorInvalidDeviceFunction);
HIP_CHECK_ERROR(hipGraphAddKernelNode(&kNode, graph, nullptr, 0,
&kNodeParams), hipErrorInvalidDeviceFunction);
}
#endif
SECTION("Pass kernelParams data member as nullptr") {
kNodeParams.kernelParams = nullptr;
HIP_CHECK_ERROR(hipGraphAddKernelNode(&kNode, graph, nullptr, 0, &kNodeParams),
hipErrorInvalidValue);
HIP_CHECK_ERROR(hipGraphAddKernelNode(&kNode, graph, nullptr, 0,
&kNodeParams), hipErrorInvalidValue);
}
#if HT_AMD // On Cuda setup this test case getting failed
@@ -95,8 +130,8 @@ TEST_CASE("Unit_hipGraphAddKernelNode_Negative") {
hipGraph_t destroyed_graph;
HIP_CHECK(hipGraphCreate(&destroyed_graph, 0));
HIP_CHECK(hipGraphDestroy(destroyed_graph));
HIP_CHECK_ERROR(hipGraphAddKernelNode(&kNode, destroyed_graph, nullptr, 0, &kNodeParams),
hipErrorInvalidValue);
HIP_CHECK_ERROR(hipGraphAddKernelNode(&kNode, destroyed_graph, nullptr,
0, &kNodeParams), hipErrorInvalidValue);
}
#endif
@@ -105,3 +140,327 @@ TEST_CASE("Unit_hipGraphAddKernelNode_Negative") {
HIP_CHECK(hipFree(C_d));
HIP_CHECK(hipGraphDestroy(graph));
}
#if HT_AMD
static __global__ void Add(int* A_d, int* B_d, int* C_d) {
size_t tx = (blockIdx.x * blockDim.x + threadIdx.x);
C_d[tx] = A_d[tx] + B_d[tx];
}
static void validateOutput(const hipGraph_t &graph , int* A_h,
int* B_h, int* C_h,
size_t inputSize) {
hipStream_t streamForGraph;
HIP_CHECK(hipStreamCreate(&streamForGraph));
hipGraphExec_t graphExec;
HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0));
HIP_CHECK(hipGraphLaunch(graphExec, streamForGraph));
HIP_CHECK(hipStreamSynchronize(streamForGraph));
HIP_CHECK(hipGraphExecDestroy(graphExec));
HIP_CHECK(hipStreamDestroy(streamForGraph));
// Verify output
for (size_t i = 0; i < inputSize; i++) {
REQUIRE((A_h[i] + B_h[i]) == C_h[i]);
}
}
static void kernelFnChange(int* A_d, int* A_h,
int* B_d, int* B_h, int* C_d, int* C_h,
size_t inputSize, size_t numOfBlocks, enum fnType fn) {
hipGraph_t graph;
std::vector<hipGraphNode_t> nodeDependencies;
hipGraphNode_t memcpyNode, memcpyNode1, memcpyNode2, kernelNode;
hipModule_t Module;
hipFunction_t Function;
HIPCHECK(hipModuleLoad(&Module, CODEOBJ_FILE));
HIPCHECK(hipModuleGetFunction(&Function, Module, KERNEL_NAME));
HIP_CHECK(hipGraphCreate(&graph, 0));
// Add MemCpy nodes H2D
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyNode, graph, nullptr, 0, A_d,
A_h, sizeof(int)*inputSize, hipMemcpyHostToDevice));
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyNode1, graph, nullptr, 0, B_d,
B_h, sizeof(int)*inputSize, hipMemcpyHostToDevice));
nodeDependencies.push_back(memcpyNode);
nodeDependencies.push_back(memcpyNode1);
// kernel node.
hipKernelNodeParams kernelNodeParams{}, kernelNodeParamsUpdate{};
void* kernelArgs[4] = {reinterpret_cast<void*>(&A_d),
reinterpret_cast<void*>(&B_d),
reinterpret_cast<void*>(&C_d),
&numOfBlocks};
if (fn == normal) { // normal function
kernelNodeParams.func = reinterpret_cast<void*>(Add);
} else { // Code Object function
kernelNodeParams.func = reinterpret_cast<void*>(Function);
}
kernelNodeParams.gridDim = dim3(inputSize / THREADS_PER_BLOCK, 1, 1);
kernelNodeParams.blockDim = dim3(THREADS_PER_BLOCK, 1, 1);
kernelNodeParams.sharedMemBytes = 0;
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgs);
kernelNodeParams.extra = nullptr;
HIP_CHECK(hipGraphAddKernelNode(&kernelNode, graph, nodeDependencies.data(),
nodeDependencies.size(), &kernelNodeParams));
if (fn == normal) {
kernelNodeParamsUpdate.func = reinterpret_cast<void*>(Function);
} else {
kernelNodeParamsUpdate.func = reinterpret_cast<void*>(Add);
}
kernelNodeParamsUpdate.gridDim = dim3(inputSize / THREADS_PER_BLOCK, 1, 1);
kernelNodeParamsUpdate.blockDim = dim3(THREADS_PER_BLOCK, 1, 1);
kernelNodeParamsUpdate.sharedMemBytes = 0;
kernelNodeParamsUpdate.kernelParams = reinterpret_cast<void**>(kernelArgs);
kernelNodeParamsUpdate.extra = nullptr;
HIP_CHECK(hipGraphKernelNodeSetParams(kernelNode, &kernelNodeParamsUpdate));
nodeDependencies.clear();
nodeDependencies.push_back(kernelNode);
// Add MemCpy nodes D2H
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyNode2, graph,
nodeDependencies.data(), nodeDependencies.size(), C_h,
C_d, sizeof(int)*inputSize, hipMemcpyDeviceToHost));
nodeDependencies.clear();
// Validation
validateOutput(graph, A_h, B_h, C_h, inputSize);
HIP_CHECK(hipGraphDestroy(graph));
HIPCHECK(hipModuleUnload(Module));
}
/**
* Test Description
* ------------------------
* - Test case to verify kernel function output in the graph, cloned graph by adding
* hipGraphAddKernelNode by loading kernerl function through hipModuleLoad,
* hipModuleGetFunction from the code object file.
* Test source
* ------------------------
* - catch/unit/graph/hipGraphAddKernelNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
TEST_CASE("Unit_hipGraphAddKernelNode_moduleLoadKernelFn_graphNclonedGraph") {
int *A_d, *B_d, *C_d;
int *A_h, *B_h, *C_h;
HipTest::initArrays<int>(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, size, false);
hipGraph_t graph, clonedGraph;
std::vector<hipGraphNode_t> nodeDependencies;
hipGraphNode_t memcpyNode, memcpyNode1, memcpyNode2, kernelNode;
HIP_CHECK(hipGraphCreate(&graph, 0));
hipModule_t Module;
hipFunction_t Function;
HIPCHECK(hipModuleLoad(&Module, CODEOBJ_FILE));
HIPCHECK(hipModuleGetFunction(&Function, Module, KERNEL_NAME));
// Add MemCpy nodes H2D
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyNode, graph, nullptr, 0, A_d,
A_h, sizeof(int)*size, hipMemcpyHostToDevice));
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyNode1, graph, nullptr, 0, B_d,
B_h, sizeof(int)*size, hipMemcpyHostToDevice));
nodeDependencies.push_back(memcpyNode);
nodeDependencies.push_back(memcpyNode1);
// Add Kernel Node
hipKernelNodeParams kernelNodeParams{};
void* kernelArgs[3] = {reinterpret_cast<void*>(&A_d),
reinterpret_cast<void*>(&B_d),
reinterpret_cast<void*>(&C_d)};
kernelNodeParams.func = reinterpret_cast<void*>(Function);
kernelNodeParams.gridDim = dim3(size / THREADS_PER_BLOCK, 1, 1);
kernelNodeParams.blockDim = dim3(THREADS_PER_BLOCK, 1, 1);
kernelNodeParams.sharedMemBytes = 0;
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgs);
kernelNodeParams.extra = nullptr;
HIP_CHECK(hipGraphAddKernelNode(&kernelNode, graph, nodeDependencies.data(),
nodeDependencies.size(), &kernelNodeParams));
nodeDependencies.clear();
nodeDependencies.push_back(kernelNode);
// Add MemCpy nodes D2H
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyNode2, graph,
nodeDependencies.data(), nodeDependencies.size(), C_h,
C_d, sizeof(int)*size, hipMemcpyDeviceToHost));
nodeDependencies.clear();
SECTION("Original Graph") {
// Original Graph validation
validateOutput(graph, A_h, B_h, C_h, size);
}
SECTION("Cloned Graph") {
// Clone the graph
HIP_CHECK(hipGraphClone(&clonedGraph, graph));
// Cloned graph Validation
validateOutput(clonedGraph, A_h, B_h, C_h, size);
HIP_CHECK(hipGraphDestroy(clonedGraph));
}
HIP_CHECK(hipGraphDestroy(graph));
HIPCHECK(hipModuleUnload(Module));
HipTest::freeArrays<int>(A_d, B_d, C_d, A_h, B_h, C_h, false);
}
/**
* Test Description
* ------------------------
* - Test case to verify kernel function output by adding hipGraphAddKernelNode and updating the
* kernel functions from normal to Code object and vice versa in the graph by loading kernerl
* function through hipModuleLoad, hipModuleGetFunction from code object file.
* Test source
* ------------------------
* - catch/unit/graph/hipGraphAddKernelNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
TEST_CASE("Unit_hipGraphAddKernelNode_moduleLoadKernelFn_kernelFnUpdate") {
size_t maxBlocks = 512;
int *A_d, *B_d, *C_d; // Device pointers
int *A_h, *B_h, *C_h; // Host Pointers
HipTest::initArrays<int>(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, size, false);
SECTION("Kernel function change from Normal fn to Code object fn") {
kernelFnChange(A_d, A_h, B_d, B_h, C_d, C_h, size, maxBlocks, object);
}
SECTION("Kernel function change from Code object fn to normal fn") {
kernelFnChange(A_d, A_h, B_d, B_h, C_d, C_h, size, maxBlocks, normal);
}
HipTest::freeArrays<int>(A_d, B_d, C_d, A_h, B_h, C_h, false);
}
/**
* Test Description
* ------------------------
* - Test case to verify kernel function output in the child graph and cloned graph by adding
* hipGraphAddKernelNode by loading kernerl function through hipModuleLoad,
* hipModuleGetFunction from the code object file.
* Test source
* ------------------------
* - catch/unit/graph/hipGraphAddKernelNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
TEST_CASE("Unit_hipGraphAddKernelNode_moduleLoadKernelFn_childGraph") {
int *A_d, *B_d, *C_d; // Device pointers
int *A_h, *B_h, *C_h; // Host Pointers
HipTest::initArrays<int>(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, size, false);
hipGraph_t graph, childgraph, clonedGraph;
std::vector<hipGraphNode_t> nodeDependencies;
hipGraphNode_t memcpyh2d1, memcpyh2d2, memcpyd2h, childGraphNode, kernelNode;
hipModule_t Module;
hipFunction_t Function;
HIPCHECK(hipModuleLoad(&Module, CODEOBJ_FILE));
HIPCHECK(hipModuleGetFunction(&Function, Module, KERNEL_NAME));
// Create child graph
HIP_CHECK(hipGraphCreate(&childgraph, 0));
// kerrel params.
hipKernelNodeParams kernelNodeParams{};
void* kernelArgs[3] = {reinterpret_cast<void*>(&A_d),
reinterpret_cast<void*>(&B_d),
reinterpret_cast<void*>(&C_d)};
kernelNodeParams.func = reinterpret_cast<void*>(Function);
kernelNodeParams.gridDim = dim3(size / THREADS_PER_BLOCK, 1, 1);
kernelNodeParams.blockDim = dim3(THREADS_PER_BLOCK, 1, 1);
kernelNodeParams.sharedMemBytes = 0;
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgs);
kernelNodeParams.extra = nullptr;
HIP_CHECK(hipGraphAddKernelNode(&kernelNode, childgraph, nullptr,
0, &kernelNodeParams));
HIP_CHECK(hipGraphCreate(&graph, 0));
// Add MemCpy nodes H2D
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyh2d1, graph, nullptr, 0, A_d,
A_h, sizeof(int)*size, hipMemcpyHostToDevice));
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyh2d2, graph, nullptr, 0, B_d,
B_h, sizeof(int)*size, hipMemcpyHostToDevice));
nodeDependencies.push_back(memcpyh2d1);
nodeDependencies.push_back(memcpyh2d2);
// Add child graph node
HIP_CHECK(hipGraphAddChildGraphNode(&childGraphNode, graph,
nullptr,
0, childgraph));
nodeDependencies.push_back(childGraphNode);
// Add MemCpy nodes D2H
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyd2h, graph,
nodeDependencies.data(), nodeDependencies.size(), C_h,
C_d, sizeof(int)*size, hipMemcpyDeviceToHost));
nodeDependencies.clear();
SECTION("Original Graph") {
// Original Graph validation
validateOutput(graph, A_h, B_h, C_h, size);
}
SECTION("Cloned Graph") {
// Clone the graph
HIP_CHECK(hipGraphClone(&clonedGraph, graph));
// Cloned Graph validation
validateOutput(clonedGraph, A_h, B_h, C_h, size);
HIP_CHECK(hipGraphDestroy(clonedGraph));
}
HIP_CHECK(hipGraphDestroy(graph));
HIPCHECK(hipModuleUnload(Module));
HipTest::freeArrays<int>(A_d, B_d, C_d, A_h, B_h, C_h, false);
}
/**
* Test Description
* ------------------------
* - Test case to verify kernel function output in the graph which is created by stream capture.
* The kernel function is loading through hipModuleLoad, hipModuleGetFunction from code object file
* Test source
* ------------------------
* - catch/unit/graph/hipGraphAddKernelNode.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
TEST_CASE("Unit_hipGraphAddKernelNode_moduleLoadKernelFn_streamCapture") {
size_t maxBlocks = 512;
size_t Nbytes = sizeof(int)*maxBlocks;
int *A_d, *B_d, *C_d; // Device pointers
int *A_h, *B_h, *C_h; // Host Pointers
HipTest::initArrays<int>(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, maxBlocks,
false);
hipGraph_t graph;
hipStream_t stream;
hipModule_t Module;
hipFunction_t Function;
HIPCHECK(hipModuleLoad(&Module, CODEOBJ_FILE));
HIPCHECK(hipModuleGetFunction(&Function, Module, KERNEL_NAME));
HIP_CHECK(hipStreamCreate(&stream));
HIP_CHECK(hipStreamBeginCapture(stream, hipStreamCaptureModeGlobal));
// MemCpy node H2D
HIP_CHECK(hipMemcpyAsync(A_d, A_h, Nbytes, hipMemcpyHostToDevice,
stream));
HIP_CHECK(hipMemcpyAsync(B_d, B_h, Nbytes, hipMemcpyHostToDevice,
stream));
// kerrel params.
void* kernelArgs[] = {&A_d, &B_d, &C_d};
// Kernel node
HIP_CHECK(hipModuleLaunchKernel(Function, 1, 1, 1, maxBlocks, 1, 1, 0,
stream, kernelArgs, nullptr));
// MemCpy nodes D2H
HIP_CHECK(hipMemcpyAsync(C_h, C_d, Nbytes, hipMemcpyDeviceToHost,
stream));
HIP_CHECK(hipStreamEndCapture(stream, &graph));
HIP_CHECK(hipStreamDestroy(stream));
// validation
validateOutput(graph, A_h, B_h, C_h, maxBlocks);
HIP_CHECK(hipGraphDestroy(graph));
HIPCHECK(hipModuleUnload(Module));
HipTest::freeArrays<int>(A_d, B_d, C_d, A_h, B_h, C_h, false);
}
#endif
+18
Просмотреть файл
@@ -23,7 +23,25 @@ set(TEST_SRC
hipMemFaultStackAllocation.cc
hipLaunchBounds.cc
hipShflTests.cc
hipTestConstant.cc
hipTestGlobalVariable.cc
hipTestMemKernel.cc
launch_bounds.cc
inline_asm_vadd.cc
)
if(UNIX)
set(TEST_SRC ${TEST_SRC}
hipPrintfKernel.cc)
endif()
string(FIND "${OFFLOAD_ARCH_STR}" "gfx1030" RESULT)
if ("${RESULT}" EQUAL "-1")
set(AMD_TEST_SRC
inline_asm_vmac.cc)
endif()
if(HIP_PLATFORM MATCHES "amd")
set(TEST_SRC ${TEST_SRC} ${AMD_TEST_SRC})
endif()
# only for AMD
if(HIP_PLATFORM MATCHES "amd")
+67
Просмотреть файл
@@ -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 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_test_defgroups.hh>
#include <cstring>
#include "../kernel/printf_common.h"
#define HIP_ENABLE_PRINTF
__global__ void run_printf() {
printf("Hello World\n");
}
/**
* @addtogroup hipLaunchKernelGGL
* @{
* @ingroup KernelTest
* `void hipLaunchKernelGGL(F kernel, const dim3& numBlocks, const dim3& dimBlocks,
std::uint32_t sharedMemBytes, hipStream_t stream, Args... args)` -
* Method to invocate kernel functions
*/
/**
* Test Description
* ------------------------
* - Test case to check printf function via kernel call.
* Test source
* ------------------------
* - catch/unit/kernel/hipPrintfKernel.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
TEST_CASE("Unit_kernel_ChkPrintf") {
int device_count = 0;
CaptureStream capture(stdout);
HIP_CHECK(hipGetDeviceCount(&device_count));
std::string st = "Hello World";
const char * check = st.c_str();
for (int i = 0; i < device_count; ++i) {
HIP_CHECK(hipSetDevice(i));
hipLaunchKernelGGL(run_printf, dim3(1), dim3(1), 0, 0);
HIP_CHECK(hipDeviceSynchronize());
char* data = new char[st.size()];;
std::ifstream CapturedData = capture.getCapturedData();
CapturedData.getline(data, st.size()+1);
int result = strcmp(data, check);
REQUIRE(result == 0);
delete [] data;
}
}
+76
Просмотреть файл
@@ -0,0 +1,76 @@
/*
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_test_defgroups.hh>
#define LEN 512
#define SIZE 2048
__constant__ int Value[LEN];
static __global__ void Get(int* Ad) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
Ad[tid] = Value[tid];
}
/**
* @addtogroup hipLaunchKernelGGL
* @{
* @ingroup KernelTest
* `void hipLaunchKernelGGL(F kernel, const dim3& numBlocks, const dim3& dimBlocks,
std::uint32_t sharedMemBytes, hipStream_t stream, Args... args)` -
* Method to invocate kernel functions
*/
/**
* Test Description
* ------------------------
* - Test case to check const variable via kernel call.
* Test source
* ------------------------
* - catch/unit/kernel/hipTestConstant.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
TEST_CASE("Unit_kernel_chkConstantViaKernel") {
int *A, *B, *Ad;
A = new int[LEN];
B = new int[LEN];
for (unsigned i = 0; i < LEN; i++) {
A[i] = -1 * i;
B[i] = 0;
}
HIP_CHECK(hipMalloc(reinterpret_cast<void**>(&Ad), SIZE));
HIP_CHECK(hipMemcpyToSymbol(HIP_SYMBOL(Value), A, SIZE, 0,
hipMemcpyHostToDevice));
hipLaunchKernelGGL(Get, dim3(1, 1, 1), dim3(LEN, 1, 1), 0, 0, Ad);
HIP_CHECK(hipMemcpy(B, Ad, SIZE, hipMemcpyDeviceToHost));
for (unsigned i = 0; i < LEN; i++) {
REQUIRE(A[i] == B[i]);
}
delete [] A;
delete [] B;
HIP_CHECK(hipFree(Ad));
}
+101
Просмотреть файл
@@ -0,0 +1,101 @@
/*
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_test_defgroups.hh>
#define LEN 512
#define SIZE 2048
/**
* @addtogroup hipLaunchKernelGGL
* @{
* @ingroup KernelTest
* `void hipLaunchKernelGGL(F kernel, const dim3& numBlocks, const dim3& dimBlocks,
std::uint32_t sharedMemBytes, hipStream_t stream, Args... args)` -
* Method to invocate kernel functions
*/
/**
* Test Description
* ------------------------
* - Test case to check constant global variable and global array via kernel call.
* Test source
* ------------------------
* - catch/unit/kernel/hipTestGlobalVariable.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
__constant__ int ConstantGlobalVar = 123;
static __global__ void kernel(int* Ad) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
Ad[tid] = ConstantGlobalVar;
}
void runTestConstantGlobalVar() {
int *A, *Ad;
A = new int[LEN];
for (unsigned i = 0; i < LEN; i++) {
A[i] = 0;
}
HIP_CHECK(hipMalloc(reinterpret_cast<void**>(&Ad), SIZE));
hipLaunchKernelGGL(kernel, dim3(1, 1, 1), dim3(LEN, 1, 1), 0, 0, Ad);
HIP_CHECK(hipMemcpy(A, Ad, SIZE, hipMemcpyDeviceToHost));
for (unsigned i = 0; i < LEN; i++) {
REQUIRE(123 == A[i]);
}
delete [] A;
HIP_CHECK(hipFree(Ad));
}
__device__ int GlobalArray[LEN];
static __global__ void kernelWrite() {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
GlobalArray[tid] = tid;
}
static __global__ void kernelRead(int* Ad) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
Ad[tid] = GlobalArray[tid];
}
void runTestGlobalArray() {
int *A, *Ad;
A = new int[LEN];
for (unsigned i = 0; i < LEN; i++) {
A[i] = 0;
}
HIP_CHECK(hipMalloc(reinterpret_cast<void**>(&Ad), SIZE));
hipLaunchKernelGGL(kernelWrite, dim3(1, 1, 1), dim3(LEN, 1, 1), 0, 0);
hipLaunchKernelGGL(kernelRead, dim3(1, 1, 1), dim3(LEN, 1, 1), 0, 0, Ad);
HIP_CHECK(hipMemcpy(A, Ad, SIZE, hipMemcpyDeviceToHost));
for (unsigned i = 0; i < LEN; i++) {
REQUIRE(i == A[i]);
}
delete [] A;
HIP_CHECK(hipFree(Ad));
}
TEST_CASE("Unit_kernel_chkGlobalArrAndGlobalVaribleViaKernelFn") {
runTestConstantGlobalVar();
runTestGlobalArray();
}
+248
Просмотреть файл
@@ -0,0 +1,248 @@
/*
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_test_defgroups.hh>
#define LEN8 8 * 4
#define LEN9 9 * 4
#define LEN10 10 * 4
#define LEN11 11 * 4
#define LEN12 12 * 4
__global__ void MemCpy8(uint8_t* In, uint8_t* Out) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
memcpy(Out + tid * 8, In + tid * 8, 8);
}
__global__ void MemCpy9(uint8_t* In, uint8_t* Out) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
memcpy(Out + tid * 9, In + tid * 9, 9);
}
__global__ void MemCpy10(uint8_t* In, uint8_t* Out) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
memcpy(Out + tid * 10, In + tid * 10, 10);
}
__global__ void MemCpy11(uint8_t* In, uint8_t* Out) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
memcpy(Out + tid * 11, In + tid * 11, 11);
}
__global__ void MemCpy12(uint8_t* In, uint8_t* Out) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
memcpy(Out + tid * 12, In + tid * 12, 12);
}
__global__ void MemSet8(uint8_t* In) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
memset(In + tid * 8, 1, 8);
}
__global__ void MemSet9(uint8_t* In) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
memset(In + tid * 9, 1, 9);
}
__global__ void MemSet10(uint8_t* In) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
memset(In + tid * 10, 1, 10);
}
__global__ void MemSet11(uint8_t* In) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
memset(In + tid * 11, 1, 11);
}
__global__ void MemSet12(uint8_t* In) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
memset(In + tid * 12, 1, 12);
}
/**
* @addtogroup hipLaunchKernelGGL
* @{
* @ingroup KernelTest
* `void hipLaunchKernelGGL(F kernel, const dim3& numBlocks, const dim3& dimBlocks,
std::uint32_t sharedMemBytes, hipStream_t stream, Args... args)` -
* Method to invocate kernel functions
*/
/**
* Test Description
* ------------------------
* - Test case to check memcpy and memset via kernel call.
* Test source
* ------------------------
* - catch/unit/kernel/hipTestMemKernel.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
TEST_CASE("Unit_kernel_MemoryOperationsViaKernels") {
uint8_t *A, *Ad, *B, *Bd, *C, *Cd;
A = new uint8_t[LEN8];
B = new uint8_t[LEN8];
C = new uint8_t[LEN8];
for (uint32_t i = 0; i < LEN8; i++) {
A[i] = i;
B[i] = 0;
C[i] = 0;
}
HIP_CHECK(hipMalloc(&Ad, LEN8));
HIP_CHECK(hipMalloc(&Bd, LEN8));
HIP_CHECK(hipMalloc(&Cd, LEN8));
HIP_CHECK(hipMemcpy(Ad, A, LEN8, hipMemcpyHostToDevice));
hipLaunchKernelGGL(MemCpy8, dim3(2, 1, 1), dim3(2, 1, 1), 0, 0, Ad, Bd);
hipLaunchKernelGGL(MemSet8, dim3(2, 1, 1), dim3(2, 1, 1), 0, 0, Cd);
HIP_CHECK(hipMemcpy(B, Bd, LEN8, hipMemcpyDeviceToHost));
HIP_CHECK(hipMemcpy(C, Cd, LEN8, hipMemcpyDeviceToHost));
for (uint32_t i = 0; i < LEN8; i++) {
REQUIRE(A[i] == B[i]);
REQUIRE(C[i] == 1);
}
delete[] A;
delete[] B;
delete[] C;
HIP_CHECK(hipFree(Ad));
HIP_CHECK(hipFree(Bd));
HIP_CHECK(hipFree(Cd));
SECTION("MemCpySet1") {
A = new uint8_t[LEN9];
B = new uint8_t[LEN9];
C = new uint8_t[LEN9];
for (uint32_t i = 0; i < LEN9; i++) {
A[i] = i;
B[i] = 0;
C[i] = 0;
}
HIP_CHECK(hipMalloc(&Ad, LEN9));
HIP_CHECK(hipMalloc(&Bd, LEN9));
HIP_CHECK(hipMalloc(&Cd, LEN9));
HIP_CHECK(hipMemcpy(Ad, A, LEN9, hipMemcpyHostToDevice));
hipLaunchKernelGGL(MemCpy9, dim3(2, 1, 1), dim3(2, 1, 1), 0, 0, Ad, Bd);
hipLaunchKernelGGL(MemSet9, dim3(2, 1, 1), dim3(2, 1, 1), 0, 0, Cd);
HIP_CHECK(hipMemcpy(B, Bd, LEN9, hipMemcpyDeviceToHost));
HIP_CHECK(hipMemcpy(C, Cd, LEN9, hipMemcpyDeviceToHost));
for (uint32_t i = 0; i < LEN9; i++) {
REQUIRE(A[i] == B[i]);
REQUIRE(C[i] == 1);
}
delete[] A;
delete[] B;
delete[] C;
HIP_CHECK(hipFree(Ad));
HIP_CHECK(hipFree(Bd));
HIP_CHECK(hipFree(Cd));
}
SECTION("MemCpySet2") {
A = new uint8_t[LEN10];
B = new uint8_t[LEN10];
C = new uint8_t[LEN10];
for (uint32_t i = 0; i < LEN10; i++) {
A[i] = i;
B[i] = 0;
C[i] = 0;
}
HIP_CHECK(hipMalloc(&Ad, LEN10));
HIP_CHECK(hipMalloc(&Bd, LEN10));
HIP_CHECK(hipMalloc(&Cd, LEN10));
HIP_CHECK(hipMemcpy(Ad, A, LEN10, hipMemcpyHostToDevice));
hipLaunchKernelGGL(MemCpy10, dim3(2, 1, 1), dim3(2, 1, 1), 0, 0, Ad, Bd);
hipLaunchKernelGGL(MemSet10, dim3(2, 1, 1), dim3(2, 1, 1), 0, 0, Cd);
HIP_CHECK(hipMemcpy(B, Bd, LEN10, hipMemcpyDeviceToHost));
HIP_CHECK(hipMemcpy(C, Cd, LEN10, hipMemcpyDeviceToHost));
for (uint32_t i = 0; i < LEN10; i++) {
REQUIRE(A[i] == B[i]);
REQUIRE(C[i] == 1);
}
delete[] A;
delete[] B;
delete[] C;
HIP_CHECK(hipFree(Ad));
HIP_CHECK(hipFree(Bd));
HIP_CHECK(hipFree(Cd));
}
SECTION("MemCpySet3") {
A = new uint8_t[LEN11];
B = new uint8_t[LEN11];
C = new uint8_t[LEN11];
for (uint32_t i = 0; i < LEN11; i++) {
A[i] = i;
B[i] = 0;
C[i] = 0;
}
HIP_CHECK(hipMalloc(&Ad, LEN11));
HIP_CHECK(hipMalloc(&Bd, LEN11));
HIP_CHECK(hipMalloc(&Cd, LEN11));
HIP_CHECK(hipMemcpy(Ad, A, LEN11, hipMemcpyHostToDevice));
hipLaunchKernelGGL(MemCpy11, dim3(2, 1, 1), dim3(2, 1, 1), 0, 0, Ad, Bd);
hipLaunchKernelGGL(MemSet11, dim3(2, 1, 1), dim3(2, 1, 1), 0, 0, Cd);
HIP_CHECK(hipMemcpy(B, Bd, LEN11, hipMemcpyDeviceToHost));
HIP_CHECK(hipMemcpy(C, Cd, LEN11, hipMemcpyDeviceToHost));
for (uint32_t i = 0; i < LEN11; i++) {
REQUIRE(A[i] == B[i]);
REQUIRE(C[i] == 1);
}
delete[] A;
delete[] B;
delete[] C;
HIP_CHECK(hipFree(Ad));
HIP_CHECK(hipFree(Bd));
HIP_CHECK(hipFree(Cd));
}
SECTION("MemCpySet4") {
A = new uint8_t[LEN12];
B = new uint8_t[LEN12];
C = new uint8_t[LEN12];
for (uint32_t i = 0; i < LEN12; i++) {
A[i] = i;
B[i] = 0;
C[i] = 0;
}
HIP_CHECK(hipMalloc(&Ad, LEN12));
HIP_CHECK(hipMalloc(&Bd, LEN12));
HIP_CHECK(hipMalloc(&Cd, LEN12));
HIP_CHECK(hipMemcpy(Ad, A, LEN12, hipMemcpyHostToDevice));
hipLaunchKernelGGL(MemCpy12, dim3(2, 1, 1), dim3(2, 1, 1), 0, 0, Ad, Bd);
hipLaunchKernelGGL(MemSet12, dim3(2, 1, 1), dim3(2, 1, 1), 0, 0, Cd);
HIP_CHECK(hipMemcpy(B, Bd, LEN12, hipMemcpyDeviceToHost));
HIP_CHECK(hipMemcpy(C, Cd, LEN12, hipMemcpyDeviceToHost));
for (uint32_t i = 0; i < LEN12; i++) {
REQUIRE(A[i] == B[i]);
REQUIRE(C[i] == 1);
}
delete[] A;
delete[] B;
delete[] C;
HIP_CHECK(hipFree(Ad));
HIP_CHECK(hipFree(Bd));
HIP_CHECK(hipFree(Cd));
}
}
+136
Просмотреть файл
@@ -0,0 +1,136 @@
/*
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_test_defgroups.hh>
#define NUM 1024
#define THREADS_PER_BLOCK_X 4
// Device (Kernel) function, it must be void
__global__ void vadd_asm(float* out, float* in) {
int i = blockDim.x * blockIdx.x + threadIdx.x;
#ifdef __HIP_PLATFORM_NVIDIA__
asm volatile("add.f32 %0,%1,%2;" : "=f"(out[i]) : "f"(in[i]), "f"(out[i]));
#endif
#ifdef __HIP_PLATFORM_AMD__
asm volatile("v_add_f32_e32 %0, %1, %2" : "=v"(out[i]) : "v"(in[i]),
"v"(out[i]));
#endif
}
// CPU implementation of Vector Result
void addCPUReference(float* output, float* input) {
for (unsigned int j = 0; j < NUM; j++) {
output[j] = input[j] + output[j];
}
}
/**
* @addtogroup hipLaunchKernelGGL
* @{
* @ingroup KernelTest
* `void hipLaunchKernelGGL(F kernel, const dim3& numBlocks, const dim3& dimBlocks,
std::uint32_t sharedMemBytes, hipStream_t stream, Args... args)` -
* Method to invocate kernel functions
*/
/**
* Test Description
* ------------------------
* - Test case to check inline asm vadd instruction via kernel call.
* Test source
* ------------------------
* - catch/unit/kernel/inline_asm_vadd.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
TEST_CASE("Unit_kernel_inline_asm_vadd_Functional") {
float* VectorA;
float* ResultVector;
float* VectorB;
float* gpuVector;
float* gpuResultVector;
int i;
int errors;
VectorA = reinterpret_cast<float*>(malloc(NUM * sizeof(float)));
ResultVector = reinterpret_cast<float*>(malloc(NUM * sizeof(float)));
VectorB = reinterpret_cast<float*>(malloc(NUM * sizeof(float)));
// initialize the input data
for (i = 0; i < NUM; i++) {
VectorA[i] = static_cast<float>(i * 10.0f);
VectorB[i] = static_cast<float>(i * 30.0f);
}
// allocate the memory on the device side
HIP_CHECK(hipMalloc(reinterpret_cast<void**>(&gpuVector),
NUM * sizeof(float)));
HIP_CHECK(hipMalloc(reinterpret_cast<void**>(&gpuResultVector),
NUM * sizeof(float)));
// Memory transfer from host to device
HIP_CHECK(hipMemcpy(gpuVector, VectorA, NUM * sizeof(float),
hipMemcpyHostToDevice));
HIP_CHECK(hipMemcpy(gpuResultVector, VectorB, NUM * sizeof(float),
hipMemcpyHostToDevice));
// Lauching kernel from host
hipLaunchKernelGGL(vadd_asm, dim3(NUM / THREADS_PER_BLOCK_X),
dim3(THREADS_PER_BLOCK_X), 0, 0,
gpuResultVector, gpuVector);
// Memory transfer from device to host
HIP_CHECK(hipMemcpy(ResultVector, gpuResultVector, NUM * sizeof(float),
hipMemcpyDeviceToHost));
// CPU Result computation
addCPUReference(VectorB, VectorA);
// verify the results
errors = 0;
double eps = 1.0E-3;
for (i = 0; i < NUM; i++) {
if (std::abs(ResultVector[i] - VectorB[i]) > eps) {
errors++;
}
}
if (errors != 0) {
REQUIRE(false);
} else {
REQUIRE(true);
}
// free the resources on device side
HIP_CHECK(hipFree(gpuVector));
HIP_CHECK(hipFree(gpuResultVector));
HIP_CHECK(hipDeviceReset());
// free the resources on host side
free(VectorA);
free(ResultVector);
free(VectorB);
}
+128
Просмотреть файл
@@ -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 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_test_defgroups.hh>
#define NUM 1024
#define THREADS_PER_BLOCK_X 4
// Device (Kernel) function, it must be void
__global__ void vmac_asm(float* out, float* in, float a) {
int i = blockDim.x * blockIdx.x + threadIdx.x;
asm volatile("v_mac_f32_e32 %0, %2, %3" : "=v"(out[i]) :
"0"(out[i]), "v"(a), "v"(in[i]));
}
// CPU implementation of saxpy
void addCPUReference(float* output, float* input, float a) {
for (unsigned int j = 0; j < NUM; j++) {
output[j] = a * input[j] + output[j];
}
}
/**
* @addtogroup hipLaunchKernelGGL
* @{
* @ingroup KernelTest
* `void hipLaunchKernelGGL(F kernel, const dim3& numBlocks, const dim3& dimBlocks,
std::uint32_t sharedMemBytes, hipStream_t stream, Args... args)` -
* Method to invocate kernel functions
*/
/**
* Test Description
* ------------------------
* - Test case to check inline asm vmac instruction via kernel call.
* Test source
* ------------------------
* - catch/unit/kernel/inline_asm_vmac.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
TEST_CASE("Unit_kernel_inline_asm_vmac_Functional") {
float* VectorA;
float* ResultVector;
float* VectorB;
float* gpuVector;
float* gpuResultVector;
const float a = 10.0f;
int i;
int errors;
VectorA = reinterpret_cast<float*>(malloc(NUM * sizeof(float)));
ResultVector = reinterpret_cast<float*>(malloc(NUM * sizeof(float)));
VectorB = reinterpret_cast<float*>(malloc(NUM * sizeof(float)));
// initialize the input data
for (i = 0; i < NUM; i++) {
VectorA[i] = static_cast<float>(i * 10.0f);
VectorB[i] = static_cast<float>(i * 30.0f);
}
// allocate the memory on the device side
HIP_CHECK(hipMalloc(reinterpret_cast<void**>(&gpuVector),
NUM * sizeof(float)));
HIP_CHECK(hipMalloc(reinterpret_cast<void**>(&gpuResultVector),
NUM * sizeof(float)));
// Memory transfer from host to device
HIP_CHECK(hipMemcpy(gpuVector, VectorA, NUM * sizeof(float),
hipMemcpyHostToDevice));
HIP_CHECK(hipMemcpy(gpuResultVector, VectorB, NUM * sizeof(float),
hipMemcpyHostToDevice));
// Lauching kernel from host
hipLaunchKernelGGL(vmac_asm, dim3(NUM / THREADS_PER_BLOCK_X),
dim3(THREADS_PER_BLOCK_X), 0, 0,
gpuResultVector, gpuVector, a);
// Memory transfer from device to host
HIP_CHECK(hipMemcpy(ResultVector, gpuResultVector, NUM * sizeof(float),
hipMemcpyDeviceToHost));
// CPU Result computation
addCPUReference(VectorB, VectorA, a);
// verify the results
errors = 0;
double eps = 1.0E-3;
for (i = 0; i < NUM; i++) {
if (std::abs(ResultVector[i] - VectorB[i]) > eps) {
errors++;
}
}
if (errors != 0) {
REQUIRE(false);
} else {
REQUIRE(true);
}
// free the resources on device side
HIP_CHECK(hipFree(gpuVector));
HIP_CHECK(hipFree(gpuResultVector));
HIP_CHECK(hipDeviceReset());
// free the resources on host side
free(VectorA);
free(ResultVector);
free(VectorB);
}
+102
Просмотреть файл
@@ -0,0 +1,102 @@
/*
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_test_defgroups.hh>
constexpr size_t N = 1024;
int p_blockSize = 256;
__global__ void
__launch_bounds__(256, 2)
myKern(int* C, const int* A, int N) {
int tid = (blockIdx.x * blockDim.x + threadIdx.x);
if (tid < N) {
C[tid] = A[tid];
}
}
/**
* @addtogroup hipLaunchKernelGGL
* @{
* @ingroup KernelTest
* `void hipLaunchKernelGGL(F kernel, const dim3& numBlocks, const dim3& dimBlocks,
std::uint32_t sharedMemBytes, hipStream_t stream, Args... args)` -
* Method to invocate kernel functions
*/
/**
* Test Description
* ------------------------
* - Test case to check launch bounds via kernel call.
* Test source
* ------------------------
* - catch/unit/kernel/launch_bounds.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.6
*/
TEST_CASE("Unit_kernel_LaunchBounds_Functional") {
size_t Nbytes = N * sizeof(int);
int *A_d, *C_d, *A_h, *C_h;
HIPCHECK(hipMalloc(&A_d, Nbytes));
HIPCHECK(hipMalloc(&C_d, Nbytes));
A_h = reinterpret_cast<int*>(malloc(Nbytes));
C_h = reinterpret_cast<int*>(malloc(Nbytes));
for (int i = 0; i < N; i++) {
A_h[i] = i * 10;
C_h[i] = 0x0;
}
int blocks = N / p_blockSize;
HIPCHECK(hipMemcpy(A_d, A_h, Nbytes, hipMemcpyHostToDevice));
HIPCHECK(hipGetLastError());
hipLaunchKernelGGL(myKern, dim3(blocks), dim3(p_blockSize), 0,
0, C_d, A_d, N);
#ifdef __HIP_PLATFORM_NVIDIA__
cudaFuncAttributes attrib;
cudaFuncGetAttributes(&attrib, myKern);
printf("binaryVersion = %d\n", attrib.binaryVersion);
printf("cacheModeCA = %d\n", attrib.cacheModeCA);
printf("constSizeBytes = %zu\n", attrib.constSizeBytes);
printf("localSizeBytes = %zud\n", attrib.localSizeBytes);
printf("maxThreadsPerBlock = %d\n", attrib.maxThreadsPerBlock);
printf("numRegs = %d\n", attrib.numRegs);
printf("ptxVersion = %d\n", attrib.ptxVersion);
printf("sharedSizeBytes = %zud\n", attrib.sharedSizeBytes);
#endif
HIPCHECK(hipDeviceSynchronize());
HIPCHECK(hipGetLastError());
HIPCHECK(hipMemcpy(C_h, C_d, Nbytes, hipMemcpyDeviceToHost));
HIPCHECK(hipDeviceSynchronize());
for (int i = 0; i < N; i++) {
int goldVal = i * 10;
REQUIRE(C_h[i] == goldVal);
}
HIP_CHECK(hipFree(A_d));
HIP_CHECK(hipFree(C_d));
free(A_h);
free(C_h);
}
+99
Просмотреть файл
@@ -0,0 +1,99 @@
/*
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.
*/
#ifndef _STRESSTEST_PRINTF_COMMON_H_
#define _STRESSTEST_PRINTF_COMMON_H_
#include <errno.h>
#include <error.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <math.h>
#include <fstream>
#include <iostream>
#include <string>
struct CaptureStream {
int saved_fd;
int orig_fd;
int temp_fd;
char tempname[13] = "mytestXXXXXX";
explicit CaptureStream(FILE *original) {
orig_fd = fileno(original);
saved_fd = dup(orig_fd);
if ((temp_fd = mkstemp(tempname)) == -1) {
error(0, errno, "Error");
assert(false);
}
fflush(nullptr);
if (dup2(temp_fd, orig_fd) == -1) {
error(0, errno, "Error");
assert(false);
}
if (close(temp_fd) != 0) {
error(0, errno, "Error");
assert(false);
}
}
void restoreStream() {
if (saved_fd == -1)
return;
fflush(nullptr);
if (dup2(saved_fd, orig_fd) == -1) {
error(0, errno, "Error");
assert(false);
}
if (close(saved_fd) != 0) {
error(0, errno, "Error");
assert(false);
}
saved_fd = -1;
}
const char *getTempFilename() {
return (const char*)tempname;
}
std::ifstream getCapturedData() {
restoreStream();
std::ifstream temp(tempname);
return temp;
}
~CaptureStream() {
restoreStream();
if (remove(tempname) != 0) {
error(0, errno, "Error");
assert(false);
}
}
};
#endif // _STRESSTEST_PRINTF_COMMON_H_
+32 -17
Просмотреть файл
@@ -18,9 +18,14 @@
# 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(COMMON_SHARED_SRC DriverContext.cc)
# Common Tests - Test independent of all platforms
# FIXME: cjatin
# This is a temp hack to pass it on windows since it has a char limit for
# command line. Eventually we need to use rsp files with ninja on windows.
# But this exposes several problems with hipcc and build system on windows.
# While those are fixed, this hack should allow us to pass windows CI.
set(TEST_SRC
memset.cc
malloc.cc
@@ -63,7 +68,27 @@ set(TEST_SRC
hipMemAdviseMmap.cc
hipMallocManaged.cc
hipMemRangeGetAttribute.cc
hipMemRangeGetAttribute_old.cc
hipMemRangeGetAttribute_old.cc)
if(HIP_PLATFORM MATCHES "amd")
set(TEST_SRC
${TEST_SRC}
hipMemPtrGetInfo.cc
hipPointerGetAttributes.cc
hipMemCoherencyTst.cc
hipExtMallocWithFlags.cc
hipMallocMngdMultiThread.cc
hipArray.cc
hipMemVmm.cc)
else()
set(TEST_SRC ${TEST_SRC} hipGetSymbolSizeAddress.cc)
endif()
hip_add_exe_to_target(NAME MemoryTest1
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests COMMON_SHARED_SRC ${COMMON_SHARED_SRC})
set(TEST_SRC
hipMemcpyFromSymbol.cc
hipPtrGetAttribute.cc
hipMemPoolApi.cc
@@ -83,6 +108,8 @@ set(TEST_SRC
hipMemcpy_old.cc
hipMemcpy_derivatives.cc
hipMemcpyAsync.cc
hipMemcpyAsync_old.cc
hipMemcpyAsync_derivatives.cc
hipMemsetFunctional.cc
hipMalloc.cc
hipMallocPitch.cc
@@ -106,24 +133,12 @@ set(TEST_SRC
hipMemAdvise_old.cc
hipMemAdvise.cc
hipMemRangeGetAttributes.cc
hipFreeAsync.cc
hipMallocAsync.cc
hipStreamAttachMemAsync.cc
hipMemRangeGetAttributes_old.cc
hipMemGetAddressRange.cc)
if(HIP_PLATFORM MATCHES "amd")
set(TEST_SRC
${TEST_SRC}
hipMemPtrGetInfo.cc
hipPointerGetAttributes.cc
hipMemCoherencyTst.cc
hipExtMallocWithFlags.cc
hipMallocMngdMultiThread.cc
hipArray.cc
hipMemVmm.cc)
else()
set(TEST_SRC ${TEST_SRC} hipGetSymbolSizeAddress.cc)
endif()
hip_add_exe_to_target(NAME MemoryTest
hip_add_exe_to_target(NAME MemoryTest2
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests COMMON_SHARED_SRC ${COMMON_SHARED_SRC})
+7 -11
Просмотреть файл
@@ -49,11 +49,10 @@ using namespace std::chrono_literals;
const std::chrono::duration<uint64_t, std::milli> delay = 50ms;
constexpr size_t numAllocs = 10;
#if HT_AMD /* Disabled because frequency based wait is timing out on nvidia platforms */
TEMPLATE_TEST_CASE("Unit_hipFreeImplicitSyncDev", "", char, float, float2, float4) {
TestType* devPtr{};
TEST_CASE("Unit_hipFreeImplicitSyncDev") {
int* devPtr{};
size_t size_mult = GENERATE(1, 32, 64, 128, 256);
HIP_CHECK(hipMalloc(&devPtr, sizeof(TestType) * size_mult));
HIP_CHECK(hipMalloc(&devPtr, sizeof(*devPtr) * size_mult));
HipTest::runKernelForDuration(delay);
// make sure device is busy
@@ -62,11 +61,11 @@ TEMPLATE_TEST_CASE("Unit_hipFreeImplicitSyncDev", "", char, float, float2, float
HIP_CHECK(hipStreamQuery(nullptr));
}
TEMPLATE_TEST_CASE("Unit_hipFreeImplicitSyncHost", "", char, float, float2, float4) {
TestType* hostPtr{};
TEST_CASE("Unit_hipFreeImplicitSyncHost") {
int* hostPtr{};
size_t size_mult = GENERATE(1, 32, 64, 128, 256);
HIP_CHECK(hipHostMalloc(&hostPtr, sizeof(TestType) * size_mult));
HIP_CHECK(hipHostMalloc(&hostPtr, sizeof(*hostPtr) * size_mult));
HipTest::runKernelForDuration(delay);
// make sure device is busy
@@ -75,7 +74,7 @@ TEMPLATE_TEST_CASE("Unit_hipFreeImplicitSyncHost", "", char, float, float2, floa
HIP_CHECK(hipStreamQuery(nullptr));
}
#if HT_NVIDIA // Meaningless at the moment, since we are not running wait kernel on nvidia.
#if HT_NVIDIA
TEMPLATE_TEST_CASE("Unit_hipFreeImplicitSyncArray", "", char, float, float2, float4) {
using vec_info = vector_info<TestType>;
DriverContext ctx;
@@ -135,7 +134,6 @@ TEMPLATE_TEST_CASE("Unit_hipFreeImplicitSyncArray", "", char, float, float2, flo
}
}
#endif
#endif
// Freeing a invalid pointer with on device
@@ -166,8 +164,6 @@ TEST_CASE("Unit_hipFreeNegativeHost") {
#if HT_NVIDIA
TEST_CASE("Unit_hipFreeNegativeArray") {
DriverContext ctx;
hipArray_t arrayPtr{};
hiparray cuArrayPtr{};
SECTION("ArrayFree") { HIP_CHECK(hipFreeArray(nullptr)); }
SECTION("ArrayDestroy") {
+44
Просмотреть файл
@@ -0,0 +1,44 @@
/*
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>
TEST_CASE("Unit_hipFreeAsync_negative") {
HIP_CHECK(hipSetDevice(0));
void* p = nullptr;
hipStream_t stream{nullptr};
hipStreamCreate(&stream);
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);
}
HIP_CHECK(hipStreamSynchronize(stream));
HIP_CHECK(hipStreamDestroy(stream));
}
+27 -3
Просмотреть файл
@@ -21,11 +21,19 @@ THE SOFTWARE.
*/
#include <hip_test_common.hh>
#include <utils.hh>
TEST_CASE("Unit_hipHostGetDevicePointer_Negative") {
int* hPtr{nullptr};
int* dPtr{nullptr};
HIP_CHECK(hipHostMalloc(&hPtr, sizeof(int)));
if (!DeviceAttributesSupport(0, hipDeviceAttributeCanMapHostMemory)) {
HIP_CHECK_ERROR(hipHostGetDevicePointer(reinterpret_cast<void**>(&dPtr), hPtr, 0),
hipErrorNotSupported);
return;
}
SECTION("Nullptr as device") {
HIP_CHECK_ERROR(hipHostGetDevicePointer(nullptr, hPtr, 0), hipErrorInvalidValue);
}
@@ -36,13 +44,29 @@ TEST_CASE("Unit_hipHostGetDevicePointer_Negative") {
hipErrorInvalidValue);
}
// Not adding check for flags since CUDA spec states that there might be more values added to it
SECTION("Non pinned memory as host") {
int* hPtr = reinterpret_cast<int*>(malloc(sizeof(*hPtr)));
HIP_CHECK_ERROR(hipHostGetDevicePointer(reinterpret_cast<void**>(&dPtr), hPtr, 0),
hipErrorInvalidValue);
free(hPtr);
}
SECTION("Flags non-zero") {
HIP_CHECK_ERROR(hipHostGetDevicePointer(reinterpret_cast<void**>(&dPtr), hPtr, 1),
hipErrorInvalidValue);
}
HIP_CHECK(hipHostFree(hPtr));
}
template <typename T> __global__ void set(T* ptr, T val) { *ptr = val; }
TEST_CASE("Unit_hipHostGetDevicePointer_UseCase") {
if(!DeviceAttributesSupport(0, hipDeviceAttributeCanMapHostMemory)) {
HipTest::HIP_SKIP_TEST("Device does not support mapping host memory");
return;
}
int* hPtr{nullptr};
HIP_CHECK(hipHostMalloc(&hPtr, sizeof(int)));
@@ -71,8 +95,8 @@ TEST_CASE("Unit_hipHostGetDevicePointer_UseCase") {
HIP_CHECK(hipDeviceSynchronize());
HIP_CHECK(hipHostUnregister(&res));
REQUIRE(value == 10);
REQUIRE(res == value);
}
HIP_CHECK(hipHostFree(hPtr));
}
}
+3 -4
Просмотреть файл
@@ -27,9 +27,10 @@ This testfile verifies the following scenarios of hipHostRegister API
2. hipHostRegister and perform hipMemcpy on it.
*/
#include "hip/hip_runtime_api.h"
#include <hip_test_common.hh>
#include <hip_test_helper.hh>
#include "hip/hip_runtime_api.h"
#include <utils.hh>
#define OFFSET 128
static constexpr auto LEN{1024 * 1024};
@@ -63,9 +64,7 @@ void doMemCopy(size_t numElements, int offset, T* A, T* Bh, T* Bd, bool internal
HIP_CHECK(hipMemcpy(Bh, Bd, sizeBytes, hipMemcpyDeviceToHost));
// Make sure the copy worked
for (size_t i = 0; i < numElements; i++) {
REQUIRE(Bh[i] == A[i]);
}
ArrayMismatch(A, Bh, numElements);
if (internalRegister) {
HIP_CHECK(hipHostUnregister(A));
+6
Просмотреть файл
@@ -68,6 +68,12 @@ TEST_CASE("Unit_hipHostUnregister_NullPtr") {
HIP_CHECK_ERROR(hipHostUnregister(nullptr), hipErrorInvalidValue);
}
TEST_CASE("Unit_hipHostUnregister_Ptr_Different_Than_Specified_To_Register") {
std::vector<int> alloc(2);
HIP_CHECK(hipHostRegister(alloc.data(), alloc.size(), 0));
HIP_CHECK_ERROR(hipHostUnregister(&alloc.data()[1]), hipErrorHostMemoryNotRegistered);
}
TEST_CASE("Unit_hipHostUnregister_NotRegisteredPointer") {
auto x = std::unique_ptr<int>(new int);
HIP_CHECK_ERROR(hipHostUnregister(x.get()), hipErrorHostMemoryNotRegistered);
+47
Просмотреть файл
@@ -0,0 +1,47 @@
/*
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 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 <hip_test_checkers.hh>
#include <limits>
TEST_CASE("Unit_hipMallocAsync_negative") {
HIP_CHECK(hipSetDevice(0));
void* p = nullptr;
size_t max_size = std::numeric_limits<size_t>::max();
hipStream_t stream{nullptr};
HIP_CHECK(hipStreamCreate(&stream));
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));
}
+16 -36
Просмотреть файл
@@ -228,6 +228,21 @@ TEST_CASE("Unit_hipMallocPitch_Negative") {
}
}
TEST_CASE("Unit_hipMallocPitch_Zero_Dims") {
void* ptr = nullptr;
size_t pitch = 0;
SECTION("width == 0") {
HIP_CHECK(hipMallocPitch(&ptr, &pitch, 0, 1));
REQUIRE(ptr == nullptr);
}
SECTION("height == 0") {
HIP_CHECK(hipMallocPitch(&ptr, &pitch, 1, 0));
REQUIRE(ptr == nullptr);
}
}
TEST_CASE("Unit_hipMemAllocPitch_Negative") {
size_t pitch = 0;
hipDeviceptr_t ptr{};
@@ -360,42 +375,7 @@ static void MemoryAllocDiffSizes(int gpu) {
static void threadFunc(int gpu) {
MemoryAllocDiffSizes<float>(gpu);
}
/*
* This testcase verifies the negative scenarios of hipMallocPitch API
*/
#if 0 //TODO: Review, fix and re-enable test
TEST_CASE("Unit_hipMallocPitch_Negative") {
float* A_d;
size_t pitch_A = 0;
size_t width{NUM_W * sizeof(float)};
#if HT_NVIDIA
SECTION("NullPtr to Pitched Ptr") {
REQUIRE(hipMallocPitch(nullptr,
&pitch_A, width, NUM_H) != hipSuccess);
}
SECTION("nullptr to pitch") {
REQUIRE(hipMallocPitch(reinterpret_cast<void**>(&A_d),
nullptr, width, NUM_H) != hipSuccess);
}
#endif
SECTION("Width 0 in hipMallocPitch") {
REQUIRE(hipMallocPitch(reinterpret_cast<void**>(&A_d),
&pitch_A, 0, NUM_H) == hipSuccess);
}
SECTION("Height 0 in hipMallocPitch") {
REQUIRE(hipMallocPitch(reinterpret_cast<void**>(&A_d),
&pitch_A, width, 0) == hipSuccess);
}
SECTION("Max int values") {
REQUIRE(hipMallocPitch(reinterpret_cast<void**>(&A_d),
&pitch_A, std::numeric_limits<int>::max(),
std::numeric_limits<int>::max()) != hipSuccess);
}
}
#endif
/*
* This testcase verifies the basic scenario of
* hipMallocPitch API for different datatypes
@@ -408,6 +388,7 @@ TEMPLATE_TEST_CASE("Unit_hipMallocPitch_Basic",
size_t width{NUM_W * sizeof(TestType)};
REQUIRE(hipMallocPitch(reinterpret_cast<void**>(&A_d),
&pitch_A, width, NUM_H) == hipSuccess);
REQUIRE(width <= pitch_A);
HIP_CHECK(hipFree(A_d));
}
@@ -538,4 +519,3 @@ TEMPLATE_TEST_CASE("Unit_hipMallocPitch_KernelLaunch", ""
HipTest::freeArrays<TestType>(nullptr, nullptr, nullptr,
A_h, B_h, C_h, false);
}
+30 -63
Просмотреть файл
@@ -652,87 +652,54 @@ TEST_CASE("Unit_hipMemAdvise_TstAccessedByFlg4") {
}
}
/* Allocate memory using aligned_alloc(), assign PreferredLocation flag to
the allocated memory and launch a kernel. Kernel should get executed
successfully without hang or segfault*/
#if __linux__ && HT_AMD
TEST_CASE("Unit_hipMemAdvise_TstAlignedAllocMem") {
if ((setenv("HSA_XNACK", "1", 1)) != 0) {
WARN("Unable to turn on HSA_XNACK, hence terminating the Test case!");
REQUIRE(false);
}
// The following code block checks for gfx90a,940,941,942 so as to skip if the device is not
// The following code block checks for xnack+
// so as to skip if the device is not xnack+
hipDeviceProp_t prop;
int device;
HIP_CHECK(hipGetDevice(&device));
HIP_CHECK(hipGetDeviceProperties(&prop, device));
std::string gfxName(prop.gcnArchName);
if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_HMM, prop.gcnArchName)) {
if (gfxName.find("xnack+") != std::string::npos) {
int stat = 0;
if (fork() == 0) {
// The below part should be inside fork
int managedMem = 0, pageMemAccess = 0;
HIP_CHECK(hipDeviceGetAttribute(&pageMemAccess,
hipDeviceAttributePageableMemoryAccess, 0));
WARN("hipDeviceAttributePageableMemoryAccess:" << pageMemAccess);
HIP_CHECK(hipDeviceGetAttribute(&managedMem, hipDeviceAttributeManagedMemory, 0));
WARN("hipDeviceAttributeManagedMemory: " << managedMem);
if ((managedMem == 1) && (pageMemAccess == 1)) {
int *Mllc = nullptr, MemSz = 4096 * 4, NumElms = 4096, InitVal = 123;
// Mllc = reinterpret_cast<(int *)>(aligned_alloc(4096, MemSz));
Mllc = reinterpret_cast<int*>(aligned_alloc(4096, 4096*4));
for (int i = 0; i < NumElms; ++i) {
Mllc[i] = InitVal;
}
hipStream_t strm;
int DataMismatch = 0;
HIP_CHECK(hipStreamCreate(&strm));
// The following hipMemAdvise() call is made to know if advise on
// aligned_alloc() is causing any issue
HIP_CHECK(hipMemAdvise(Mllc, MemSz, hipMemAdviseSetPreferredLocation, 0));
HIP_CHECK(hipMemPrefetchAsync(Mllc, MemSz, 0, strm));
HIP_CHECK(hipStreamSynchronize(strm));
MemAdvise2<<<(NumElms/32), 32, 0, strm>>>(Mllc, NumElms);
HIP_CHECK(hipStreamSynchronize(strm));
int managedMem = 0, pageMemAccess = 0;
HIP_CHECK(hipDeviceGetAttribute(&pageMemAccess,
hipDeviceAttributePageableMemoryAccess, 0));
WARN("hipDeviceAttributePageableMemoryAccess:" << pageMemAccess);
HIP_CHECK(hipDeviceGetAttribute(&managedMem, hipDeviceAttributeManagedMemory, 0));
WARN("hipDeviceAttributeManagedMemory: " << managedMem);
if ((managedMem == 1) && (pageMemAccess == 1)) {
int *Mllc = nullptr, MemSz = 4096 * 4, NumElms = 4096, InitVal = 123;
// Mllc = reinterpret_cast<(int *)>(aligned_alloc(4096, MemSz));
Mllc = reinterpret_cast<int*>(aligned_alloc(4096, 4096*4));
for (int i = 0; i < NumElms; ++i) {
Mllc[i] = InitVal;
}
hipStream_t strm;
int DataMismatch = 0;
HIP_CHECK(hipStreamCreate(&strm));
// The following hipMemAdvise() call is made to know if advise on
// aligned_alloc() is causing any issue
HIP_CHECK(hipMemAdvise(Mllc, MemSz, hipMemAdviseSetPreferredLocation, 0));
HIP_CHECK(hipMemPrefetchAsync(Mllc, MemSz, 0, strm));
HIP_CHECK(hipStreamSynchronize(strm));
MemAdvise2<<<(NumElms/32), 32, 0, strm>>>(Mllc, NumElms);
HIP_CHECK(hipStreamSynchronize(strm));
for (int i = 0; i < NumElms; ++i) {
if (Mllc[i] != (InitVal + 10)) {
DataMismatch++;
}
}
if (DataMismatch != 0) {
WARN("DataMismatch observed!!");
exit(9); // 9 for failure
} else {
exit(10); // 10 for Pass result
}
} else {
SUCCEED("GPU 0 doesn't support ManagedMemory with hipDeviceAttributePageableMemoryAccess "
"attribute. Hence skipping the testing with Pass result.\n");
exit(Catch::ResultDisposition::ContinueOnFailure);
}
} else {
wait(&stat);
int Result = WEXITSTATUS(stat);
if (Result == Catch::ResultDisposition::ContinueOnFailure) {
WARN("GPU 0 doesn't support ManagedMemory with hipDeviceAttributePageableMemoryAccess "
"attribute. Hence skipping the testing with Pass result.\n");
} else {
if (Result != 10) {
REQUIRE(false);
}
}
}
REQUIRE(DataMismatch == 0);
}
} else {
SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gx941, gfx942, Hence"
"skipping the testcase for this GPU " << device);
WARN("Memory model feature is only supported for gfx90a, gfx940, gx941, gfx942, Hence"
"skipping the testcase for this GPU " << device);
}
HipTest::HIP_SKIP_TEST("GPU is not xnack enabled hence skipping the test...\n");
}
}
#endif
+127 -372
Просмотреть файл
@@ -1,13 +1,15 @@
/*
Copyright (c) 2022 - present Advanced Micro Devices, Inc. All rights reserved.
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
@@ -17,392 +19,145 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/*
This testcase verifies the following scenarios
1. hipMemcpyAsync with kernel launch
2. H2D-D2D-D2H-H2PinnMem and device context change scenarios
3. This test launches multiple threads which uses same stream to deploy kernel
and also launch hipMemcpyAsync() api. This test case is simulate the scenario
reported in SWDEV-181598.
*/
#include <hip_test_common.hh>
#include <hip_test_kernels.hh>
#include <hip_test_checkers.hh>
#include <atomic>
#include <hip/hip_runtime_api.h>
#include <memcpy1d_tests_common.hh>
#include <resource_guards.hh>
#include <utils.hh>
#define NUM_THREADS 16
TEST_CASE("Unit_hipMemcpyAsync_Positive_Basic") {
using namespace std::placeholders;
const auto stream_type = GENERATE(Streams::nullstream, Streams::perThread, Streams::created);
const StreamGuard stream_guard(stream_type);
const hipStream_t stream = stream_guard.stream();
static constexpr auto NUM_ELM{1024 * 1024};
static constexpr size_t N_ELMTS{32 * 1024};
std::atomic<size_t> Thread_count { 0 };
static unsigned blocksPerCU{6}; // to hide latency
static unsigned threadsPerBlock{256};
template<typename T>
void Thread_func(T *A_d, T *B_d, T* C_d, T* C_h, size_t Nbytes,
hipStream_t mystream) {
unsigned blocks = HipTest::setNumBlocks(blocksPerCU,
threadsPerBlock, N_ELMTS);
hipLaunchKernelGGL(HipTest::vector_square, dim3(blocks),
dim3(threadsPerBlock), 0,
mystream, A_d, C_d, N_ELMTS);
HIP_CHECK(hipGetLastError());
HIP_CHECK(hipMemcpyAsync(C_h, C_d, Nbytes, hipMemcpyDeviceToHost, mystream));
// The following two MemcpyAsync calls are for sole
// purpose of loading stream with multiple async calls
HIP_CHECK(hipMemcpyAsync(B_d, A_d, Nbytes,
hipMemcpyDeviceToDevice, mystream));
HIP_CHECK(hipMemcpyAsync(B_d, A_d, Nbytes,
hipMemcpyDeviceToDevice, mystream));
Thread_count++;
MemcpyWithDirectionCommonTests<true>(std::bind(hipMemcpyAsync, _1, _2, _3, _4, stream));
}
template<typename T>
void Thread_func_MultiStream() {
int Data_mismatch = 0;
T *A_d{nullptr}, *B_d{nullptr}, *C_d{nullptr};
T *A_h{nullptr}, *B_h{nullptr}, *C_h{nullptr};
size_t Nbytes = N_ELMTS * sizeof(T);
unsigned blocks = HipTest::setNumBlocks(blocksPerCU,
threadsPerBlock, N_ELMTS);
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N_ELMTS, false);
hipStream_t mystream;
HIP_CHECK(hipStreamCreateWithFlags(&mystream, hipStreamNonBlocking));
HIP_CHECK(hipMemcpyAsync(A_d, A_h, Nbytes, hipMemcpyHostToDevice, mystream));
hipLaunchKernelGGL((HipTest::vector_square), dim3(blocks),
dim3(threadsPerBlock), 0,
mystream, A_d, C_d, N_ELMTS);
HIP_CHECK(hipGetLastError());
HIP_CHECK(hipMemcpyAsync(C_h, C_d, Nbytes, hipMemcpyDeviceToHost, mystream));
// The following hipMemcpyAsync() is called only to
// load stream with multiple Async calls
HIP_CHECK(hipMemcpyAsync(B_d, A_d, Nbytes,
hipMemcpyDeviceToDevice, mystream));
Thread_count++;
TEST_CASE("Unit_hipMemcpyAsync_Positive_Synchronization_Behavior") {
using namespace std::placeholders;
HIP_CHECK(hipDeviceSynchronize());
HIP_CHECK(hipStreamSynchronize(mystream));
HIP_CHECK(hipStreamDestroy(mystream));
// Verifying result of the kernel computation
for (size_t i = 0; i < N_ELMTS; i++) {
if (C_h[i] != A_h[i] * A_h[i]) {
Data_mismatch++;
}
}
// Releasing resources
HipTest::freeArrays<T>(A_d, B_d, C_d, A_h, B_h, C_h, false);
REQUIRE(Data_mismatch == 0);
}
/*
This testcase verifies hipMemcpyAsync API
Initializes device variables
Launches kernel and performs the sum of device variables
copies the result to host variable and validates the result.
*/
TEMPLATE_TEST_CASE("Unit_hipMemcpyAsync_KernelLaunch", "", int, float,
double) {
size_t Nbytes = NUM_ELM * sizeof(TestType);
TestType *A_d{nullptr}, *B_d{nullptr}, *C_d{nullptr};
TestType *A_h{nullptr}, *B_h{nullptr}, *C_h{nullptr};
HIP_CHECK(hipSetDevice(0));
hipStream_t stream;
HIP_CHECK(hipStreamCreate(&stream));
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, NUM_ELM, false);
HIP_CHECK(hipMemcpyAsync(A_d, A_h, Nbytes, hipMemcpyHostToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_d, B_h, Nbytes, hipMemcpyHostToDevice, stream));
HIP_CHECK(hipStreamSynchronize(stream));
hipLaunchKernelGGL(HipTest::vectorADD, dim3(1), dim3(1), 0, 0,
static_cast<const TestType*>(A_d),
static_cast<const TestType*>(B_d), C_d, NUM_ELM);
HIP_CHECK(hipGetLastError());
HIP_CHECK(hipMemcpyAsync(C_h, C_d, Nbytes, hipMemcpyDeviceToHost, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HIP_CHECK(hipStreamDestroy(stream));
HipTest::checkVectorADD(A_h, B_h, C_h, NUM_ELM);
HipTest::freeArrays<TestType>(A_d, B_d, C_d, A_h, B_h, C_h, false);
}
/*
This testcase verifies the following scenarios
1. H2H,H2PinMem and PinnedMem2Host
2. H2D-D2D-D2H in same GPU
3. Pinned Host Memory to device variables in same GPU
4. Device context change
5. H2D-D2D-D2H peer GPU
*/
TEMPLATE_TEST_CASE("Unit_hipMemcpyAsync_H2H-H2D-D2H-H2PinMem", "", char, int,
float, double) {
TestType *A_d{nullptr}, *B_d{nullptr};
TestType *A_h{nullptr}, *B_h{nullptr};
TestType *A_Ph{nullptr}, *B_Ph{nullptr};
HIP_CHECK(hipSetDevice(0));
hipStream_t stream;
HIP_CHECK(hipStreamCreate(&stream));
HipTest::initArrays<TestType>(&A_d, &B_d, nullptr,
&A_h, &B_h, nullptr,
NUM_ELM*sizeof(TestType));
HipTest::initArrays<TestType>(nullptr, nullptr, nullptr,
&A_Ph, &B_Ph, nullptr,
NUM_ELM*sizeof(TestType), true);
SECTION("H2H, H2PinMem and PinMem2H") {
HIP_CHECK(hipMemcpyAsync(B_h, A_h, NUM_ELM*sizeof(TestType),
hipMemcpyHostToHost, stream));
HIP_CHECK(hipMemcpyAsync(A_Ph, B_h, NUM_ELM*sizeof(TestType),
hipMemcpyHostToHost, stream));
HIP_CHECK(hipMemcpyAsync(B_Ph, A_Ph, NUM_ELM*sizeof(TestType),
hipMemcpyHostToHost, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HipTest::checkTest(A_h, B_Ph, NUM_ELM);
SECTION("Host memory to device memory") {
// This behavior differs on NVIDIA and AMD, on AMD the hipMemcpy calls is synchronous with
// respect to the host
#if HT_AMD
HipTest::HIP_SKIP_TEST(
"EXSWCPHIPT-127 - MemcpyAsync from host to device memory behavior differs on AMD and "
"Nvidia");
return;
#endif
MemcpyHtoDSyncBehavior(std::bind(hipMemcpyAsync, _1, _2, _3, hipMemcpyHostToDevice, nullptr),
false);
}
SECTION("H2D-D2D-D2H-SameGPU") {
HIP_CHECK(hipMemcpyAsync(A_d, A_h, NUM_ELM*sizeof(TestType),
hipMemcpyHostToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_d, A_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_h, B_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToHost, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HipTest::checkTest(A_h, B_h, NUM_ELM);
SECTION("Device memory to pageable host memory") {
MemcpyDtoHPageableSyncBehavior(
std::bind(hipMemcpyAsync, _1, _2, _3, hipMemcpyDeviceToHost, nullptr), true);
}
SECTION("pH2D-D2D-D2pH-SameGPU") {
HIP_CHECK(hipMemcpyAsync(A_d, A_Ph, NUM_ELM*sizeof(TestType),
hipMemcpyHostToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_d, A_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_Ph, B_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToHost, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HipTest::checkTest(A_Ph, B_Ph, NUM_ELM);
}
SECTION("H2D-D2D-D2H-DeviceContextChange") {
int deviceCount = 0;
HIP_CHECK(hipGetDeviceCount(&deviceCount));
if (deviceCount < 2) {
SUCCEED("deviceCount less then 2");
} else {
int canAccessPeer = 0;
HIP_CHECK(hipDeviceCanAccessPeer(&canAccessPeer, 0, 1));
if (canAccessPeer) {
HIP_CHECK(hipSetDevice(1));
HIP_CHECK(hipMemcpyAsync(A_d, A_h, NUM_ELM*sizeof(TestType),
hipMemcpyHostToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_d, A_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_h, B_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToHost, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HipTest::checkTest(A_h, B_h, NUM_ELM);
} else {
SUCCEED("P2P capability is not present");
}
}
SECTION("Device memory to pinned host memory") {
MemcpyDtoHPinnedSyncBehavior(
std::bind(hipMemcpyAsync, _1, _2, _3, hipMemcpyDeviceToHost, nullptr), false);
}
SECTION("H2D-D2D-D2H-PeerGPU") {
int deviceCount = 0;
HIP_CHECK(hipGetDeviceCount(&deviceCount));
if (deviceCount < 2) {
SUCCEED("deviceCount less then 2");
} else {
int canAccessPeer = 0;
HIP_CHECK(hipDeviceCanAccessPeer(&canAccessPeer, 0, 1));
if (canAccessPeer) {
HIP_CHECK(hipSetDevice(1));
TestType *C_d{nullptr};
HipTest::initArrays<TestType>(nullptr, nullptr, &C_d,
nullptr, nullptr, nullptr,
NUM_ELM*sizeof(TestType));
HIP_CHECK(hipMemcpyAsync(A_d, A_h, NUM_ELM*sizeof(TestType),
hipMemcpyHostToDevice, stream));
HIP_CHECK(hipMemcpyAsync(C_d, A_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_h, C_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToHost, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HipTest::checkTest(A_h, B_h, NUM_ELM);
HIP_CHECK(hipFree(C_d));
} else {
SUCCEED("P2P capability is not present");
}
}
SECTION("Device memory to device memory") {
MemcpyDtoDSyncBehavior(std::bind(hipMemcpyAsync, _1, _2, _3, hipMemcpyDeviceToDevice, nullptr),
false);
}
HIP_CHECK(hipStreamDestroy(stream));
HipTest::freeArrays<TestType>(A_d, B_d, nullptr, A_h, B_h, nullptr, false);
HipTest::freeArrays<TestType>(nullptr, nullptr, nullptr, A_Ph,
B_Ph, nullptr, true);
}
// This test launches multiple threads which uses same stream to deploy kernel
// and also launch hipMemcpyAsync() api. This test case is simulate the scenario
// reported in SWDEV-181598
TEMPLATE_TEST_CASE("Unit_hipMemcpyAsync_hipMultiMemcpyMultiThread", "",
int, float, double) {
size_t Nbytes = N_ELMTS * sizeof(TestType);
int Data_mismatch = 0;
hipStream_t mystream;
TestType *A_d{nullptr}, *B_d{nullptr}, *C_d{nullptr};
TestType *A_h{nullptr}, *B_h{nullptr}, *C_h{nullptr};
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N_ELMTS, false);
HIP_CHECK(hipStreamCreateWithFlags(&mystream, hipStreamNonBlocking));
HIP_CHECK(hipMemcpyAsync(A_d, A_h, Nbytes, hipMemcpyHostToDevice, mystream));
std::thread T[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
T[i] = std::thread(Thread_func<TestType>, A_d, B_d, C_d,
C_h, Nbytes, mystream);
}
// Wait until all the threads finish their execution
for (int i = 0; i < NUM_THREADS; i++) {
T[i].join();
}
HIP_CHECK(hipStreamSynchronize(mystream));
HIP_CHECK(hipStreamDestroy(mystream));
// Verifying the result of the kernel computation
for (size_t i = 0; i < N_ELMTS; i++) {
if (C_h[i] != A_h[i] * A_h[i]) {
Data_mismatch++;
}
}
REQUIRE(Thread_count.load() == NUM_THREADS);
REQUIRE(Data_mismatch == 0);
HipTest::freeArrays<TestType>(A_d, B_d, C_d, A_h, B_h, C_h, false);
Thread_count.exchange(0);
}
TEMPLATE_TEST_CASE("Unit_hipMemcpyAsync_hipMultiMemcpyMultiThreadMultiStream",
"", int, float, double) {
std::thread T[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
T[i] = std::thread(Thread_func_MultiStream<TestType>);
}
// Wait until all the threads finish their execution
for (int i = 0; i < NUM_THREADS; i++) {
T[i].join();
}
REQUIRE(Thread_count.load() == NUM_THREADS);
Thread_count.exchange(0);
}
/*
This testcase verifies hipMemcpy API with pinnedMemory and hostRegister
along with kernel launches
*/
TEMPLATE_TEST_CASE("Unit_hipMemcpyAsync_PinnedRegMemWithKernelLaunch",
"", int, float, double) {
int numDevices = 0;
HIP_CHECK(hipGetDeviceCount(&numDevices));
if (numDevices < 2) {
SUCCEED("No of devices are less than 2");
} else {
// 1 refers to pinned Memory
// 2 refers to register Memory
int MallocPinType = GENERATE(0, 1);
size_t Nbytes = NUM_ELM * sizeof(TestType);
unsigned blocks = HipTest::setNumBlocks(blocksPerCU,
threadsPerBlock, NUM_ELM);
TestType *A_d{nullptr}, *B_d{nullptr}, *C_d{nullptr};
TestType *X_d{nullptr}, *Y_d{nullptr}, *Z_d{nullptr};
TestType *A_h{nullptr}, *B_h{nullptr}, *C_h{nullptr};
if (MallocPinType) {
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, NUM_ELM, true);
} else {
A_h = reinterpret_cast<TestType*>(malloc(Nbytes));
HIP_CHECK(hipHostRegister(A_h, Nbytes, hipHostRegisterDefault));
B_h = reinterpret_cast<TestType*>(malloc(Nbytes));
HIP_CHECK(hipHostRegister(B_h, Nbytes, hipHostRegisterDefault));
C_h = reinterpret_cast<TestType*>(malloc(Nbytes));
HIP_CHECK(hipHostRegister(C_h, Nbytes, hipHostRegisterDefault));
HipTest::initArrays<TestType>(&A_d, &B_d, &C_d, nullptr, nullptr,
nullptr, NUM_ELM, false);
HipTest::setDefaultData<TestType>(NUM_ELM, A_h, B_h, C_h);
}
HIP_CHECK(hipMemcpy(A_d, A_h, Nbytes, hipMemcpyHostToDevice));
HIP_CHECK(hipMemcpy(B_d, B_h, Nbytes, hipMemcpyHostToDevice));
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock),
0, 0, static_cast<const TestType*>(A_d),
static_cast<const TestType*>(B_d), C_d, NUM_ELM);
HIP_CHECK(hipGetLastError());
HIP_CHECK(hipMemcpy(C_h, C_d, Nbytes, hipMemcpyDeviceToHost));
HipTest::checkVectorADD(A_h, B_h, C_h, NUM_ELM);
unsigned int seed = time(0);
HIP_CHECK(hipSetDevice(HipTest::RAND_R(&seed) % (numDevices-1)+1));
int device;
HIP_CHECK(hipGetDevice(&device));
INFO("hipMemcpy is set to happen between device 0 and device "
<< device);
HipTest::initArrays<TestType>(&X_d, &Y_d, &Z_d, nullptr,
nullptr, nullptr, NUM_ELM, false);
hipStream_t gpu1Stream;
HIP_CHECK(hipStreamCreate(&gpu1Stream));
for (int j = 0; j < NUM_ELM; j++) {
A_h[j] = 0;
B_h[j] = 0;
C_h[j] = 0;
}
HIP_CHECK(hipMemcpy(A_h, A_d, Nbytes, hipMemcpyDeviceToHost));
HIP_CHECK(hipMemcpyAsync(X_d, A_h, Nbytes, hipMemcpyHostToDevice, gpu1Stream));
HIP_CHECK(hipMemcpy(B_h, B_d, Nbytes, hipMemcpyDeviceToHost));
HIP_CHECK(hipMemcpyAsync(Y_d, B_h, Nbytes, hipMemcpyHostToDevice, gpu1Stream));
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock),
0, 0, static_cast<const TestType*>(X_d),
static_cast<const TestType*>(Y_d), Z_d, NUM_ELM);
HIP_CHECK(hipGetLastError());
HIP_CHECK(hipMemcpyAsync(C_h, Z_d, Nbytes,
hipMemcpyDeviceToHost, gpu1Stream));
HIP_CHECK(hipStreamSynchronize(gpu1Stream));
HipTest::checkVectorADD(A_h, B_h, C_h, NUM_ELM);
if (MallocPinType) {
HipTest::freeArrays<TestType>(A_d, B_d, C_d, A_h, B_h, C_h, true);
} else {
HIP_CHECK(hipHostUnregister(A_h));
free(A_h);
HIP_CHECK(hipHostUnregister(B_h));
free(B_h);
HIP_CHECK(hipHostUnregister(C_h));
free(C_h);
HipTest::freeArrays<TestType>(A_d, B_d, C_d, nullptr,
nullptr, nullptr, false);
}
HipTest::freeArrays<TestType>(X_d, Y_d, Z_d, nullptr,
nullptr, nullptr, false);
HIP_CHECK(hipStreamDestroy(gpu1Stream));
SECTION("Host memory to host memory") {
MemcpyHtoHSyncBehavior(std::bind(hipMemcpyAsync, _1, _2, _3, hipMemcpyHostToHost, nullptr),
true);
}
}
TEST_CASE("Unit_hipMemcpyAsync_Negative_Parameters") {
using namespace std::placeholders;
constexpr auto InvalidStream = [] {
StreamGuard sg(Streams::created);
return sg.stream();
};
SECTION("Host to device") {
LinearAllocGuard<int> device_alloc(LinearAllocs::hipMalloc, kPageSize);
LinearAllocGuard<int> host_alloc(LinearAllocs::hipHostMalloc, kPageSize);
MemcpyCommonNegativeTests(std::bind(hipMemcpyAsync, _1, _2, _3, hipMemcpyHostToDevice, nullptr),
device_alloc.ptr(), host_alloc.ptr(), kPageSize);
SECTION("Invalid MemcpyKind") {
HIP_CHECK_ERROR(hipMemcpyAsync(device_alloc.ptr(), host_alloc.ptr(), kPageSize,
static_cast<hipMemcpyKind>(-1), nullptr),
hipErrorInvalidMemcpyDirection);
}
SECTION("Invalid stream") {
HIP_CHECK_ERROR(hipMemcpyAsync(device_alloc.ptr(), host_alloc.ptr(), kPageSize,
hipMemcpyHostToDevice, InvalidStream()),
hipErrorContextIsDestroyed);
}
}
SECTION("Device to host") {
LinearAllocGuard<int> device_alloc(LinearAllocs::hipMalloc, kPageSize);
LinearAllocGuard<int> host_alloc(LinearAllocs::hipHostMalloc, kPageSize);
MemcpyCommonNegativeTests(std::bind(hipMemcpyAsync, _1, _2, _3, hipMemcpyDeviceToHost, nullptr),
host_alloc.ptr(), device_alloc.ptr(), kPageSize);
SECTION("Invalid MemcpyKind") {
HIP_CHECK_ERROR(hipMemcpyAsync(host_alloc.ptr(), device_alloc.ptr(), kPageSize,
static_cast<hipMemcpyKind>(-1), nullptr),
hipErrorInvalidMemcpyDirection);
}
SECTION("Invalid stream") {
HIP_CHECK_ERROR(hipMemcpyAsync(host_alloc.ptr(), device_alloc.ptr(), kPageSize,
hipMemcpyDeviceToHost, InvalidStream()),
hipErrorContextIsDestroyed);
}
}
SECTION("Host to host") {
LinearAllocGuard<int> src_alloc(LinearAllocs::hipHostMalloc, kPageSize);
LinearAllocGuard<int> dst_alloc(LinearAllocs::hipHostMalloc, kPageSize);
MemcpyCommonNegativeTests(std::bind(hipMemcpyAsync, _1, _2, _3, hipMemcpyHostToHost, nullptr),
dst_alloc.ptr(), src_alloc.ptr(), kPageSize);
SECTION("Invalid MemcpyKind") {
HIP_CHECK_ERROR(hipMemcpyAsync(dst_alloc.ptr(), src_alloc.ptr(), kPageSize,
static_cast<hipMemcpyKind>(-1), nullptr),
hipErrorInvalidMemcpyDirection);
}
SECTION("Invalid stream") {
HIP_CHECK_ERROR(hipMemcpyAsync(dst_alloc.ptr(), src_alloc.ptr(), kPageSize,
hipMemcpyHostToHost, InvalidStream()),
hipErrorContextIsDestroyed);
}
}
SECTION("Device to device") {
LinearAllocGuard<int> src_alloc(LinearAllocs::hipMalloc, kPageSize);
LinearAllocGuard<int> dst_alloc(LinearAllocs::hipMalloc, kPageSize);
MemcpyCommonNegativeTests(
std::bind(hipMemcpyAsync, _1, _2, _3, hipMemcpyDeviceToDevice, nullptr), dst_alloc.ptr(),
src_alloc.ptr(), kPageSize);
SECTION("Invalid MemcpyKind") {
HIP_CHECK_ERROR(hipMemcpyAsync(src_alloc.ptr(), dst_alloc.ptr(), kPageSize,
static_cast<hipMemcpyKind>(-1), nullptr),
hipErrorInvalidMemcpyDirection);
}
SECTION("Invalid stream") {
HIP_CHECK_ERROR(hipMemcpyAsync(dst_alloc.ptr(), src_alloc.ptr(), kPageSize,
hipMemcpyDeviceToDevice, InvalidStream()),
hipErrorContextIsDestroyed);
}
}
}
+175
Просмотреть файл
@@ -0,0 +1,175 @@
/*
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 <hip/hip_runtime_api.h>
#include <memcpy1d_tests_common.hh>
#include <resource_guards.hh>
#include <utils.hh>
static hipStream_t InvalidStream() {
StreamGuard sg(Streams::created);
return sg.stream();
}
TEST_CASE("Unit_hipMemcpyDtoHAsync_Positive_Basic") {
const auto stream_type = GENERATE(Streams::nullstream, Streams::perThread, Streams::created);
const StreamGuard stream_guard(stream_type);
const auto f = [stream = stream_guard.stream()](void* dst, void* src, size_t count) {
return hipMemcpyDtoHAsync(dst, reinterpret_cast<hipDeviceptr_t>(src), count, stream);
};
MemcpyDeviceToHostShell<true>(f, stream_guard.stream());
}
TEST_CASE("Unit_hipMemcpyDtoHAsync_Positive_Synchronization_Behavior") {
HIP_CHECK(hipDeviceSynchronize());
SECTION("Device memory to pageable host memory") {
MemcpyDtoHPageableSyncBehavior(
[](void* dst, void* src, size_t count) {
return hipMemcpyDtoHAsync(dst, reinterpret_cast<hipDeviceptr_t>(src), count, nullptr);
},
true);
}
SECTION("Device memory to pinned host memory") {
MemcpyDtoHPinnedSyncBehavior(
[](void* dst, void* src, size_t count) {
return hipMemcpyDtoHAsync(dst, reinterpret_cast<hipDeviceptr_t>(src), count, nullptr);
},
false);
}
}
TEST_CASE("Unit_hipMemcpyDtoHAsync_Negative_Parameters") {
using namespace std::placeholders;
LinearAllocGuard<int> device_alloc(LinearAllocs::hipMalloc, kPageSize);
LinearAllocGuard<int> host_alloc(LinearAllocs::hipHostMalloc, kPageSize);
MemcpyCommonNegativeTests(
[](void* dst, void* src, size_t count) {
return hipMemcpyDtoHAsync(dst, reinterpret_cast<hipDeviceptr_t>(src), count, nullptr);
},
host_alloc.ptr(), device_alloc.ptr(), kPageSize);
SECTION("Invalid stream") {
HIP_CHECK_ERROR(
hipMemcpyDtoHAsync(host_alloc.ptr(), reinterpret_cast<hipDeviceptr_t>(device_alloc.ptr()),
kPageSize, InvalidStream()),
hipErrorContextIsDestroyed);
}
}
TEST_CASE("Unit_hipMemcpyHtoDAsync_Positive_Basic") {
const auto stream_type = GENERATE(Streams::nullstream, Streams::perThread, Streams::created);
const StreamGuard stream_guard(stream_type);
const auto f = [stream = stream_guard.stream()](void* dst, void* src, size_t count) {
return hipMemcpyHtoDAsync(reinterpret_cast<hipDeviceptr_t>(dst), src, count, stream);
};
MemcpyHostToDeviceShell<true>(f, stream_guard.stream());
}
TEST_CASE("Unit_hipMemcpyHtoDAsync_Positive_Synchronization_Behavior") {
// This behavior differs on NVIDIA and AMD, on AMD the hipMemcpy calls is synchronous with
// respect to the host
#if HT_AMD
HipTest::HIP_SKIP_TEST(
"EXSWCPHIPT-127 - MemcpyAsync from host to device memory behavior differs on AMD and "
"Nvidia");
return;
#endif
MemcpyHtoDSyncBehavior(
[](void* dst, void* src, size_t count) {
return hipMemcpyHtoDAsync(reinterpret_cast<hipDeviceptr_t>(dst), src, count, nullptr);
},
false);
}
TEST_CASE("Unit_hipMemcpyHtoDAsync_Negative_Parameters") {
using namespace std::placeholders;
LinearAllocGuard<int> device_alloc(LinearAllocs::hipMalloc, kPageSize);
LinearAllocGuard<int> host_alloc(LinearAllocs::hipHostMalloc, kPageSize);
MemcpyCommonNegativeTests(
[](void* dst, void* src, size_t count) {
return hipMemcpyHtoDAsync(reinterpret_cast<hipDeviceptr_t>(dst), src, count, nullptr);
},
device_alloc.ptr(), host_alloc.ptr(), kPageSize);
SECTION("Invalid stream") {
HIP_CHECK_ERROR(hipMemcpyHtoDAsync(reinterpret_cast<hipDeviceptr_t>(device_alloc.ptr()),
host_alloc.ptr(), kPageSize, InvalidStream()),
hipErrorContextIsDestroyed);
}
}
TEST_CASE("Unit_hipMemcpyDtoDAsync_Positive_Basic") {
const auto stream_type = GENERATE(Streams::nullstream, Streams::perThread, Streams::created);
const StreamGuard stream_guard(stream_type);
SECTION("Device to device") {
SECTION("Peer access enabled") {
MemcpyDeviceToDeviceShell<true, true>(
[stream = stream_guard.stream()](void* dst, void* src, size_t count) {
return hipMemcpyDtoDAsync(reinterpret_cast<hipDeviceptr_t>(dst),
reinterpret_cast<hipDeviceptr_t>(src), count, stream);
});
}
SECTION("Peer access disabled") {
MemcpyDeviceToDeviceShell<true, false>(
[stream = stream_guard.stream()](void* dst, void* src, size_t count) {
return hipMemcpyDtoDAsync(reinterpret_cast<hipDeviceptr_t>(dst),
reinterpret_cast<hipDeviceptr_t>(src), count, stream);
});
}
}
}
TEST_CASE("Unit_hipMemcpyDtoDAsync_Positive_Synchronization_Behavior") {
MemcpyDtoDSyncBehavior(
[](void* dst, void* src, size_t count) {
return hipMemcpyDtoDAsync(reinterpret_cast<hipDeviceptr_t>(dst),
reinterpret_cast<hipDeviceptr_t>(src), count, nullptr);
},
false);
}
TEST_CASE("Unit_hipMemcpyDtoDAsync_Negative_Parameters") {
using namespace std::placeholders;
LinearAllocGuard<int> src_alloc(LinearAllocs::hipMalloc, kPageSize);
LinearAllocGuard<int> dst_alloc(LinearAllocs::hipMalloc, kPageSize);
MemcpyCommonNegativeTests(
[](void* dst, void* src, size_t count) {
return hipMemcpyDtoDAsync(reinterpret_cast<hipDeviceptr_t>(dst),
reinterpret_cast<hipDeviceptr_t>(src), count, nullptr);
},
dst_alloc.ptr(), src_alloc.ptr(), kPageSize);
SECTION("Invalid stream") {
HIP_CHECK_ERROR(hipMemcpyDtoDAsync(reinterpret_cast<hipDeviceptr_t>(dst_alloc.ptr()),
reinterpret_cast<hipDeviceptr_t>(src_alloc.ptr()), kPageSize,
InvalidStream()),
hipErrorContextIsDestroyed);
}
}
+408
Просмотреть файл
@@ -0,0 +1,408 @@
/*
Copyright (c) 2022 - present 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.
*/
/*
This testcase verifies the following scenarios
1. hipMemcpyAsync with kernel launch
2. H2D-D2D-D2H-H2PinnMem and device context change scenarios
3. This test launches multiple threads which uses same stream to deploy kernel
and also launch hipMemcpyAsync() api. This test case is simulate the scenario
reported in SWDEV-181598.
*/
#include <hip_test_common.hh>
#include <hip_test_kernels.hh>
#include <hip_test_checkers.hh>
#include <atomic>
#define NUM_THREADS 16
static constexpr auto NUM_ELM{1024 * 1024};
static constexpr size_t N_ELMTS{32 * 1024};
std::atomic<size_t> Thread_count { 0 };
static unsigned blocksPerCU{6}; // to hide latency
static unsigned threadsPerBlock{256};
template<typename T>
void Thread_func(T *A_d, T *B_d, T* C_d, T* C_h, size_t Nbytes,
hipStream_t mystream) {
unsigned blocks = HipTest::setNumBlocks(blocksPerCU,
threadsPerBlock, N_ELMTS);
hipLaunchKernelGGL(HipTest::vector_square, dim3(blocks),
dim3(threadsPerBlock), 0,
mystream, A_d, C_d, N_ELMTS);
HIP_CHECK(hipGetLastError());
HIP_CHECK(hipMemcpyAsync(C_h, C_d, Nbytes, hipMemcpyDeviceToHost, mystream));
// The following two MemcpyAsync calls are for sole
// purpose of loading stream with multiple async calls
HIP_CHECK(hipMemcpyAsync(B_d, A_d, Nbytes,
hipMemcpyDeviceToDevice, mystream));
HIP_CHECK(hipMemcpyAsync(B_d, A_d, Nbytes,
hipMemcpyDeviceToDevice, mystream));
Thread_count++;
}
template<typename T>
void Thread_func_MultiStream() {
int Data_mismatch = 0;
T *A_d{nullptr}, *B_d{nullptr}, *C_d{nullptr};
T *A_h{nullptr}, *B_h{nullptr}, *C_h{nullptr};
size_t Nbytes = N_ELMTS * sizeof(T);
unsigned blocks = HipTest::setNumBlocks(blocksPerCU,
threadsPerBlock, N_ELMTS);
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N_ELMTS, false);
hipStream_t mystream;
HIP_CHECK(hipStreamCreateWithFlags(&mystream, hipStreamNonBlocking));
HIP_CHECK(hipMemcpyAsync(A_d, A_h, Nbytes, hipMemcpyHostToDevice, mystream));
hipLaunchKernelGGL((HipTest::vector_square), dim3(blocks),
dim3(threadsPerBlock), 0,
mystream, A_d, C_d, N_ELMTS);
HIP_CHECK(hipGetLastError());
HIP_CHECK(hipMemcpyAsync(C_h, C_d, Nbytes, hipMemcpyDeviceToHost, mystream));
// The following hipMemcpyAsync() is called only to
// load stream with multiple Async calls
HIP_CHECK(hipMemcpyAsync(B_d, A_d, Nbytes,
hipMemcpyDeviceToDevice, mystream));
Thread_count++;
HIP_CHECK(hipStreamSynchronize(mystream));
HIP_CHECK(hipStreamDestroy(mystream));
// Verifying result of the kernel computation
for (size_t i = 0; i < N_ELMTS; i++) {
if (C_h[i] != A_h[i] * A_h[i]) {
Data_mismatch++;
}
}
// Releasing resources
HipTest::freeArrays<T>(A_d, B_d, C_d, A_h, B_h, C_h, false);
REQUIRE(Data_mismatch == 0);
}
/*
This testcase verifies hipMemcpyAsync API
Initializes device variables
Launches kernel and performs the sum of device variables
copies the result to host variable and validates the result.
*/
TEMPLATE_TEST_CASE("Unit_hipMemcpyAsync_KernelLaunch", "", int, float,
double) {
size_t Nbytes = NUM_ELM * sizeof(TestType);
TestType *A_d{nullptr}, *B_d{nullptr}, *C_d{nullptr};
TestType *A_h{nullptr}, *B_h{nullptr}, *C_h{nullptr};
HIP_CHECK(hipSetDevice(0));
hipStream_t stream;
HIP_CHECK(hipStreamCreate(&stream));
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, NUM_ELM, false);
HIP_CHECK(hipMemcpyAsync(A_d, A_h, Nbytes, hipMemcpyHostToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_d, B_h, Nbytes, hipMemcpyHostToDevice, stream));
HIP_CHECK(hipStreamSynchronize(stream));
hipLaunchKernelGGL(HipTest::vectorADD, dim3(1), dim3(1), 0, 0,
static_cast<const TestType*>(A_d),
static_cast<const TestType*>(B_d), C_d, NUM_ELM);
HIP_CHECK(hipGetLastError());
HIP_CHECK(hipMemcpyAsync(C_h, C_d, Nbytes, hipMemcpyDeviceToHost, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HIP_CHECK(hipStreamDestroy(stream));
HipTest::checkVectorADD(A_h, B_h, C_h, NUM_ELM);
HipTest::freeArrays<TestType>(A_d, B_d, C_d, A_h, B_h, C_h, false);
}
/*
This testcase verifies the following scenarios
1. H2H,H2PinMem and PinnedMem2Host
2. H2D-D2D-D2H in same GPU
3. Pinned Host Memory to device variables in same GPU
4. Device context change
5. H2D-D2D-D2H peer GPU
*/
TEMPLATE_TEST_CASE("Unit_hipMemcpyAsync_H2H-H2D-D2H-H2PinMem", "", char, int,
float, double) {
TestType *A_d{nullptr}, *B_d{nullptr};
TestType *A_h{nullptr}, *B_h{nullptr};
TestType *A_Ph{nullptr}, *B_Ph{nullptr};
HIP_CHECK(hipSetDevice(0));
hipStream_t stream;
HIP_CHECK(hipStreamCreate(&stream));
HipTest::initArrays<TestType>(&A_d, &B_d, nullptr,
&A_h, &B_h, nullptr,
NUM_ELM*sizeof(TestType));
HipTest::initArrays<TestType>(nullptr, nullptr, nullptr,
&A_Ph, &B_Ph, nullptr,
NUM_ELM*sizeof(TestType), true);
SECTION("H2H, H2PinMem and PinMem2H") {
HIP_CHECK(hipMemcpyAsync(B_h, A_h, NUM_ELM*sizeof(TestType),
hipMemcpyHostToHost, stream));
HIP_CHECK(hipMemcpyAsync(A_Ph, B_h, NUM_ELM*sizeof(TestType),
hipMemcpyHostToHost, stream));
HIP_CHECK(hipMemcpyAsync(B_Ph, A_Ph, NUM_ELM*sizeof(TestType),
hipMemcpyHostToHost, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HipTest::checkTest(A_h, B_Ph, NUM_ELM);
}
SECTION("H2D-D2D-D2H-SameGPU") {
HIP_CHECK(hipMemcpyAsync(A_d, A_h, NUM_ELM*sizeof(TestType),
hipMemcpyHostToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_d, A_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_h, B_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToHost, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HipTest::checkTest(A_h, B_h, NUM_ELM);
}
SECTION("pH2D-D2D-D2pH-SameGPU") {
HIP_CHECK(hipMemcpyAsync(A_d, A_Ph, NUM_ELM*sizeof(TestType),
hipMemcpyHostToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_d, A_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_Ph, B_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToHost, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HipTest::checkTest(A_Ph, B_Ph, NUM_ELM);
}
SECTION("H2D-D2D-D2H-DeviceContextChange") {
int deviceCount = 0;
HIP_CHECK(hipGetDeviceCount(&deviceCount));
if (deviceCount < 2) {
SUCCEED("deviceCount less then 2");
} else {
int canAccessPeer = 0;
HIP_CHECK(hipDeviceCanAccessPeer(&canAccessPeer, 0, 1));
if (canAccessPeer) {
HIP_CHECK(hipSetDevice(1));
HIP_CHECK(hipMemcpyAsync(A_d, A_h, NUM_ELM*sizeof(TestType),
hipMemcpyHostToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_d, A_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_h, B_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToHost, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HipTest::checkTest(A_h, B_h, NUM_ELM);
} else {
SUCCEED("P2P capability is not present");
}
}
}
SECTION("H2D-D2D-D2H-PeerGPU") {
int deviceCount = 0;
HIP_CHECK(hipGetDeviceCount(&deviceCount));
if (deviceCount < 2) {
SUCCEED("deviceCount less then 2");
} else {
int canAccessPeer = 0;
HIP_CHECK(hipDeviceCanAccessPeer(&canAccessPeer, 0, 1));
if (canAccessPeer) {
HIP_CHECK(hipSetDevice(1));
TestType *C_d{nullptr};
HipTest::initArrays<TestType>(nullptr, nullptr, &C_d,
nullptr, nullptr, nullptr,
NUM_ELM*sizeof(TestType));
HIP_CHECK(hipMemcpyAsync(A_d, A_h, NUM_ELM*sizeof(TestType),
hipMemcpyHostToDevice, stream));
HIP_CHECK(hipMemcpyAsync(C_d, A_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToDevice, stream));
HIP_CHECK(hipMemcpyAsync(B_h, C_d, NUM_ELM*sizeof(TestType),
hipMemcpyDeviceToHost, stream));
HIP_CHECK(hipStreamSynchronize(stream));
HipTest::checkTest(A_h, B_h, NUM_ELM);
HIP_CHECK(hipFree(C_d));
} else {
SUCCEED("P2P capability is not present");
}
}
}
HIP_CHECK(hipStreamDestroy(stream));
HipTest::freeArrays<TestType>(A_d, B_d, nullptr, A_h, B_h, nullptr, false);
HipTest::freeArrays<TestType>(nullptr, nullptr, nullptr, A_Ph,
B_Ph, nullptr, true);
}
// This test launches multiple threads which uses same stream to deploy kernel
// and also launch hipMemcpyAsync() api. This test case is simulate the scenario
// reported in SWDEV-181598
TEMPLATE_TEST_CASE("Unit_hipMemcpyAsync_hipMultiMemcpyMultiThread", "",
int, float, double) {
size_t Nbytes = N_ELMTS * sizeof(TestType);
int Data_mismatch = 0;
hipStream_t mystream;
TestType *A_d{nullptr}, *B_d{nullptr}, *C_d{nullptr};
TestType *A_h{nullptr}, *B_h{nullptr}, *C_h{nullptr};
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N_ELMTS, false);
HIP_CHECK(hipStreamCreateWithFlags(&mystream, hipStreamNonBlocking));
HIP_CHECK(hipMemcpyAsync(A_d, A_h, Nbytes, hipMemcpyHostToDevice, mystream));
std::thread T[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
T[i] = std::thread(Thread_func<TestType>, A_d, B_d, C_d,
C_h, Nbytes, mystream);
}
// Wait until all the threads finish their execution
for (int i = 0; i < NUM_THREADS; i++) {
T[i].join();
}
HIP_CHECK(hipStreamSynchronize(mystream));
HIP_CHECK(hipStreamDestroy(mystream));
// Verifying the result of the kernel computation
for (size_t i = 0; i < N_ELMTS; i++) {
if (C_h[i] != A_h[i] * A_h[i]) {
Data_mismatch++;
}
}
REQUIRE(Thread_count.load() == NUM_THREADS);
REQUIRE(Data_mismatch == 0);
HipTest::freeArrays<TestType>(A_d, B_d, C_d, A_h, B_h, C_h, false);
Thread_count.exchange(0);
}
TEMPLATE_TEST_CASE("Unit_hipMemcpyAsync_hipMultiMemcpyMultiThreadMultiStream",
"", int, float, double) {
std::thread T[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
T[i] = std::thread(Thread_func_MultiStream<TestType>);
}
// Wait until all the threads finish their execution
for (int i = 0; i < NUM_THREADS; i++) {
T[i].join();
}
REQUIRE(Thread_count.load() == NUM_THREADS);
Thread_count.exchange(0);
}
/*
This testcase verifies hipMemcpy API with pinnedMemory and hostRegister
along with kernel launches
*/
TEMPLATE_TEST_CASE("Unit_hipMemcpyAsync_PinnedRegMemWithKernelLaunch",
"", int, float, double) {
int numDevices = 0;
HIP_CHECK(hipGetDeviceCount(&numDevices));
if (numDevices < 2) {
SUCCEED("No of devices are less than 2");
} else {
// 1 refers to pinned Memory
// 2 refers to register Memory
int MallocPinType = GENERATE(0, 1);
size_t Nbytes = NUM_ELM * sizeof(TestType);
unsigned blocks = HipTest::setNumBlocks(blocksPerCU,
threadsPerBlock, NUM_ELM);
TestType *A_d{nullptr}, *B_d{nullptr}, *C_d{nullptr};
TestType *X_d{nullptr}, *Y_d{nullptr}, *Z_d{nullptr};
TestType *A_h{nullptr}, *B_h{nullptr}, *C_h{nullptr};
if (MallocPinType) {
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, NUM_ELM, true);
} else {
A_h = reinterpret_cast<TestType*>(malloc(Nbytes));
HIP_CHECK(hipHostRegister(A_h, Nbytes, hipHostRegisterDefault));
B_h = reinterpret_cast<TestType*>(malloc(Nbytes));
HIP_CHECK(hipHostRegister(B_h, Nbytes, hipHostRegisterDefault));
C_h = reinterpret_cast<TestType*>(malloc(Nbytes));
HIP_CHECK(hipHostRegister(C_h, Nbytes, hipHostRegisterDefault));
HipTest::initArrays<TestType>(&A_d, &B_d, &C_d, nullptr, nullptr,
nullptr, NUM_ELM, false);
HipTest::setDefaultData<TestType>(NUM_ELM, A_h, B_h, C_h);
}
HIP_CHECK(hipMemcpy(A_d, A_h, Nbytes, hipMemcpyHostToDevice));
HIP_CHECK(hipMemcpy(B_d, B_h, Nbytes, hipMemcpyHostToDevice));
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock),
0, 0, static_cast<const TestType*>(A_d),
static_cast<const TestType*>(B_d), C_d, NUM_ELM);
HIP_CHECK(hipGetLastError());
HIP_CHECK(hipMemcpy(C_h, C_d, Nbytes, hipMemcpyDeviceToHost));
HipTest::checkVectorADD(A_h, B_h, C_h, NUM_ELM);
unsigned int seed = time(0);
HIP_CHECK(hipSetDevice(HipTest::RAND_R(&seed) % (numDevices-1)+1));
int device;
HIP_CHECK(hipGetDevice(&device));
INFO("hipMemcpy is set to happen between device 0 and device "
<< device);
HipTest::initArrays<TestType>(&X_d, &Y_d, &Z_d, nullptr,
nullptr, nullptr, NUM_ELM, false);
hipStream_t gpu1Stream;
HIP_CHECK(hipStreamCreate(&gpu1Stream));
for (int j = 0; j < NUM_ELM; j++) {
A_h[j] = 0;
B_h[j] = 0;
C_h[j] = 0;
}
HIP_CHECK(hipMemcpy(A_h, A_d, Nbytes, hipMemcpyDeviceToHost));
HIP_CHECK(hipMemcpyAsync(X_d, A_h, Nbytes, hipMemcpyHostToDevice, gpu1Stream));
HIP_CHECK(hipMemcpy(B_h, B_d, Nbytes, hipMemcpyDeviceToHost));
HIP_CHECK(hipMemcpyAsync(Y_d, B_h, Nbytes, hipMemcpyHostToDevice, gpu1Stream));
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock),
0, 0, static_cast<const TestType*>(X_d),
static_cast<const TestType*>(Y_d), Z_d, NUM_ELM);
HIP_CHECK(hipGetLastError());
HIP_CHECK(hipMemcpyAsync(C_h, Z_d, Nbytes,
hipMemcpyDeviceToHost, gpu1Stream));
HIP_CHECK(hipStreamSynchronize(gpu1Stream));
HipTest::checkVectorADD(A_h, B_h, C_h, NUM_ELM);
if (MallocPinType) {
HipTest::freeArrays<TestType>(A_d, B_d, C_d, A_h, B_h, C_h, true);
} else {
HIP_CHECK(hipHostUnregister(A_h));
free(A_h);
HIP_CHECK(hipHostUnregister(B_h));
free(B_h);
HIP_CHECK(hipHostUnregister(C_h));
free(C_h);
HipTest::freeArrays<TestType>(A_d, B_d, C_d, nullptr,
nullptr, nullptr, false);
}
HipTest::freeArrays<TestType>(X_d, Y_d, Z_d, nullptr,
nullptr, nullptr, false);
HIP_CHECK(hipStreamDestroy(gpu1Stream));
}
}
+2 -3
Просмотреть файл
@@ -316,9 +316,8 @@ TEST_CASE("Unit_hipPointerGetAttribute_Negative") {
== hipErrorInvalidValue);
}
SECTION("Pass invalid attribute") {
hipPointer_attribute attr{HIP_POINTER_ATTRIBUTE_DEVICE_POINTER};
REQUIRE(hipPointerGetAttribute(&data, attr,
reinterpret_cast<hipDeviceptr_t>(A_h)) == hipErrorInvalidValue);
REQUIRE(hipPointerGetAttribute(&data, static_cast<hipPointer_attribute>(-1),
reinterpret_cast<hipDeviceptr_t>(A_h)) == hipErrorInvalidValue);
}
#if HT_AMD
SECTION("Pass HIP_POINTER_ATTRIBUTE_IS_GPU_DIRECT_RDMA_CAPABLE"
+48
Просмотреть файл
@@ -0,0 +1,48 @@
# 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
if(HIP_PLATFORM MATCHES "amd")
set(TEST_SRC
hipExtModuleLaunchKernel.cc
)
# Note to pass arch use format like -DOFFLOAD_ARCH_STR="--offload-arch=gfx900 --offload-arch=gfx906"
# having space at the start/end of OFFLOAD_ARCH_STR can cause build failures
add_custom_target(copyKernel.code
COMMAND ${CMAKE_CXX_COMPILER} -mcode-object-version=5 --genco ${OFFLOAD_ARCH_STR}
${CMAKE_CURRENT_SOURCE_DIR}/copyKernel.cc
-o ${CMAKE_CURRENT_BINARY_DIR}/../../unit/module/copyKernel.code
-I${CMAKE_CURRENT_SOURCE_DIR}/../../../../include/
-I${CMAKE_CURRENT_SOURCE_DIR}/../../include --rocm-path=${ROCM_PATH})
add_custom_target(copyKernel.s
COMMAND ${CMAKE_CXX_COMPILER} -mcode-object-version=5 -S ${CMAKE_CURRENT_SOURCE_DIR}/copyKernel.cc
-o ${CMAKE_CURRENT_BINARY_DIR}/../../unit/module/copyKernel.s
-I${CMAKE_CURRENT_SOURCE_DIR}/../../../../include/
-I${CMAKE_CURRENT_SOURCE_DIR}/../../include --rocm-path=${ROCM_PATH})
hip_add_exe_to_target(NAME ModuleTest
TEST_SRC ${TEST_SRC}
TEST_TARGET_NAME build_tests COMMON_SHARED_SRC ${COMMON_SHARED_SRC})
add_dependencies(build_tests copyKernel.code copyKernel.s)
endif()
+29
Просмотреть файл
@@ -0,0 +1,29 @@
/*
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/hip_runtime.h"
extern "C" __global__ void copy_ker(int* Ad, int *Bd, size_t size) {
int myId = threadIdx.x + blockDim.x * blockIdx.x;
if (myId < size) {
Bd[myId] = Ad[myId];
}
}
+239
Просмотреть файл
@@ -0,0 +1,239 @@
/*
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.
*/
/**
* @addtogroup hipExtModuleLaunchKernel hipExtModuleLaunchKernel
* @{
* @ingroup KernelTest
* `hipError_t hipExtModuleLaunchKernel (hipFunction_t f,
* uint32_t globalWorkSizeX,
* uint32_t globalWorkSizeY,
* uint32_t globalWorkSizeZ,
* uint32_t localWorkSizeX,
* uint32_t localWorkSizeY,
* uint32_t localWorkSizeZ,
* size_t sharedMemBytes,
* hipStream_t hStream,
* void ** kernelParams,
* void ** extra,
* hipEvent_t startEvent = nullptr,
* hipEvent_t stopEvent = nullptr,
* uint32_t flags = 0
* )` -
* Launches kernel with parameters and shared memory on stream with arguments
* passed to kernel params or extra arguments.
*/
#include <hip_test_common.hh>
#include <hip_test_defgroups.hh>
#include <iostream>
#include <fstream>
#include "hip/hip_ext.h"
#include <regex> // NOLINT
static constexpr auto totalWorkGroups{1024};
static constexpr auto localWorkSize{512};
static constexpr auto lastWorkSizeEven{256};
static constexpr auto lastWorkSizeOdd{257};
#define fileName "copyKernel.code"
#define kernel_name "copy_ker"
/**
Local Function to search a string in file.
*/
static bool searchRegExpr(const std::regex& expr, const char* filename) {
std::ifstream assemblyfile(filename, std::ifstream::binary);
REQUIRE(true == assemblyfile.is_open());
// Copy the contents of the file to buffer
assemblyfile.seekg(0, assemblyfile.end);
int len = assemblyfile.tellg();
assemblyfile.seekg(0, assemblyfile.beg);
char *fbuf = new char[len + 1];
assemblyfile.read(fbuf, len);
fbuf[len] = '\0';
// Search for uniform_work_group_size
std::smatch pattern;
std::string assemblyStr = fbuf;
bool bfound = std::regex_search(assemblyStr, pattern, expr);
delete[] fbuf;
assemblyfile.close();
return bfound;
}
/**
* Test Description
* ------------------------
* - Parse the Code Object Assembly file copyKernel.s and verify
* if .uniform_work_group_size metadata is available.
* ------------------------
* - catch\unit\module\hipExtModuleLaunchKernel.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.7
*/
TEST_CASE("Unit_hipExtModuleLaunchKernel_CheckCodeObjAttr") {
// Open copyKernel.s and read the file
const std::regex regexp("uniform_work_group_size\\s*:\\s*[0-1]");
REQUIRE(true == searchRegExpr(regexp, "copyKernel.s"));
}
/**
* Test Description
* ------------------------
* - Precondition: .uniform_work_group_size = 1. Which means uniform workgroup
* is enforced.
* - Create a buffer of size globalWorkSizeX = (non multiple of localWorkSizeX)
* and launch a kernel to perform some operations on it. If uniform work grouping
* is enforced then hipExtModuleLaunchKernel returns hipErrorInvalidValue.
* Test source
* ------------------------
* - catch\unit\module\hipExtModuleLaunchKernel.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.7
*/
TEST_CASE("Unit_hipExtModuleLaunchKernel_NonUniformWorkGroup") {
// first check if uniform_work_group_size = 1.
const std::regex regexp("uniform_work_group_size\\s*:\\s*1");
if (false == searchRegExpr(regexp, "copyKernel.s")) {
HipTest::HIP_SKIP_TEST("uniform_work_group_size != 1. Skipping test ...");
return;
}
REQUIRE(true == searchRegExpr(regexp, "copyKernel.s"));
auto isEven = GENERATE(0, 1);
// Calculate size
auto lastWorkSize = isEven ? lastWorkSizeEven : lastWorkSizeOdd;
size_t arraylength =
(totalWorkGroups - 1)*localWorkSize + lastWorkSize;
size_t sizeBytes{arraylength * sizeof(int)};
// Get module and function from module
hipModule_t Module;
hipFunction_t Function;
HIP_CHECK(hipModuleLoad(&Module, fileName));
HIP_CHECK(hipModuleGetFunction(&Function, Module, kernel_name));
// Allocate resources
int *A = new int[arraylength];
REQUIRE(A != nullptr);
int *B = new int[arraylength];
REQUIRE(B != nullptr);
// Inititialize data
for (size_t i = 0; i < arraylength; i++) {
A[i] = i;
}
int *Ad, *Bd;
HIP_CHECK(hipMalloc(&Ad, sizeBytes));
HIP_CHECK(hipMalloc(&Bd, sizeBytes));
struct {
void* _Ad;
void* _Bd;
size_t buffersize;
} args;
args._Ad = Ad;
args._Bd = Bd;
args.buffersize = arraylength;
size_t size = sizeof(args);
void* config[] = {HIP_LAUNCH_PARAM_BUFFER_POINTER, &args,
HIP_LAUNCH_PARAM_BUFFER_SIZE, &size,
HIP_LAUNCH_PARAM_END};
// Memcpy from A to Ad
HIP_CHECK(hipMemcpy(Ad, A, sizeBytes, hipMemcpyDefault));
REQUIRE(hipErrorInvalidValue == hipExtModuleLaunchKernel(Function,
arraylength, 1, 1, localWorkSize, 1, 1, 0, 0, NULL,
reinterpret_cast<void**>(&config), 0));
HIP_CHECK(hipDeviceSynchronize());
HIP_CHECK(hipFree(Ad));
HIP_CHECK(hipFree(Bd));
delete[] A;
delete[] B;
HIP_CHECK(hipModuleUnload(Module));
}
/**
* Test Description
* ------------------------
* - Create a buffer of size globalWorkSizeX = (multiple of localWorkSizeX)
* and launch a kernel to perform some operations on it. Verify the output. This
* operation should be allowed for both uniform_work_group_size = true/false.
*
* Test source
* ------------------------
* - catch\unit\module\hipExtModuleLaunchKernel.cc
* Test requirements
* ------------------------
* - HIP_VERSION >= 5.7
*/
TEST_CASE("Unit_hipExtModuleLaunchKernel_UniformWorkGroup") {
size_t arraylength = totalWorkGroups * localWorkSize;
size_t sizeBytes{arraylength * sizeof(int)};
// Get module and function from module
hipModule_t Module;
hipFunction_t Function;
HIP_CHECK(hipModuleLoad(&Module, fileName));
HIP_CHECK(hipModuleGetFunction(&Function, Module, kernel_name));
// Allocate resources
int *A = new int[arraylength];
REQUIRE(A != nullptr);
int *B = new int[arraylength];
REQUIRE(B != nullptr);
// Inititialize data
for (size_t i = 0; i < arraylength; i++) {
A[i] = i;
}
int *Ad, *Bd;
HIP_CHECK(hipMalloc(&Ad, sizeBytes));
HIP_CHECK(hipMalloc(&Bd, sizeBytes));
struct {
void* _Ad;
void* _Bd;
size_t buffersize;
} args;
args._Ad = Ad;
args._Bd = Bd;
args.buffersize = arraylength;
size_t size = sizeof(args);
void* config[] = {HIP_LAUNCH_PARAM_BUFFER_POINTER, &args,
HIP_LAUNCH_PARAM_BUFFER_SIZE, &size,
HIP_LAUNCH_PARAM_END};
// Memcpy from A to Ad
HIP_CHECK(hipMemcpy(Ad, A, sizeBytes, hipMemcpyDefault));
HIP_CHECK(hipExtModuleLaunchKernel(Function, arraylength, 1, 1,
localWorkSize, 1, 1, 0, 0, NULL,
reinterpret_cast<void**>(&config), 0));
// Memcpy results back to host
HIP_CHECK(hipMemcpy(B, Bd, sizeBytes, hipMemcpyDefault));
HIP_CHECK(hipDeviceSynchronize());
// Verify results
for (size_t i = 0; i < arraylength; i++) {
REQUIRE(B[i] == i);
}
HIP_CHECK(hipFree(Ad));
HIP_CHECK(hipFree(Bd));
delete[] A;
delete[] B;
HIP_CHECK(hipModuleUnload(Module));
}
+8 -5
Просмотреть файл
@@ -24,6 +24,8 @@ THE SOFTWARE.
#include <iostream>
#include <algorithm>
VkFence VulkanTest::CreateFence() {
VkFence fence;
VkFenceCreateInfo fence_create_info = {};
@@ -80,7 +82,7 @@ hipExternalMemoryHandleDesc VulkanTest::BuildMemoryDescriptor(VkDeviceMemory vk_
hipExternalMemoryHandleDesc mem_handle_desc = {};
mem_handle_desc.type = VulkanMemHandleTypeToHIPHandleType();
#ifdef _WIN64
mem_handle_desc.handle.win32.handle = GetMemoryHandle(ck_mem);
mem_handle_desc.handle.win32.handle = GetMemoryHandle(vk_mem);
#else
mem_handle_desc.handle.fd = GetMemoryHandle(vk_mem);
#endif
@@ -170,7 +172,7 @@ bool VulkanTest::CheckExtensionSupport(std::vector<const char*> expected_extensi
std::back_inserter(supported_extensions),
[](const auto& p) { return p.extensionName; });
constexpr auto p = [](const char* l, const char* r) { return strcmp(l, r) < 0; };
auto p = [](const char* l, const char* r) { return strcmp(l, r) < 0; };
std::sort(expected_extensions.begin(), expected_extensions.end(), p);
std::sort(supported_extensions.begin(), supported_extensions.end(), p);
@@ -328,7 +330,7 @@ int VulkanTest::GetSemaphoreHandle(VkSemaphore semaphore) {
#ifdef _WIN64
HANDLE
VulkanTest::GetMemoryHandle(VkDeviceMemory memory) {
Handle handle = 0;
HANDLE handle = 0;
VkMemoryGetWin32HandleInfoKHR vkMemoryGetWin32HandleInfoKHR = {};
vkMemoryGetWin32HandleInfoKHR.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
@@ -336,7 +338,7 @@ VulkanTest::GetMemoryHandle(VkDeviceMemory memory) {
vkMemoryGetWin32HandleInfoKHR.handleType = _mem_handle_type;
PFN_vkGetMemoryWin32HandleKHR fpGetMemoryWin32HandleKHR =
(PFN_vkGetMemoryWin32HandleKHR)vkGetDeviceProcAddr(m_device, "vkGetMemoryWin32HandleKHR");
(PFN_vkGetMemoryWin32HandleKHR)vkGetDeviceProcAddr(_device, "vkGetMemoryWin32HandleKHR");
if (!fpGetMemoryWin32HandleKHR) {
throw std::runtime_error("Failed to retrieve vkGetMemoryWin32HandleKHR");
@@ -407,4 +409,5 @@ hipExternalSemaphore_t ImportBinarySemaphore(VulkanTest& vkt) {
HIP_CHECK(hipImportExternalSemaphore(&hip_ext_semaphore, &sem_handle_desc));
return hip_ext_semaphore;
}
}
+79 -2
Просмотреть файл
@@ -20,12 +20,23 @@ THE SOFTWARE.
#pragma once
#include <vulkan/vulkan.h>
#include <vector>
#ifdef _WIN64
#include <Windows.h>
#include <winnt.h>
#include <VersionHelpers.h>
#include <winapifamily.h>
#include <dxgi1_2.h>
#include <windef.h>
#include <aclapi.h>
#include <securitybaseapi.h>
#include <vulkan/vulkan_win32.h>
#endif
#include <vector>
#include <hip_test_common.hh>
#include <hip/hip_runtime_api.h>
@@ -39,6 +50,72 @@ THE SOFTWARE.
} \
}
#ifdef _WIN64
class WindowsSecurityAttributes
{
protected:
SECURITY_ATTRIBUTES m_winSecurityAttributes;
PSECURITY_DESCRIPTOR m_winPSecurityDescriptor;
public:
WindowsSecurityAttributes::WindowsSecurityAttributes()
{
m_winPSecurityDescriptor = (PSECURITY_DESCRIPTOR)calloc(1, SECURITY_DESCRIPTOR_MIN_LENGTH + 2 * sizeof(void **));
if (!m_winPSecurityDescriptor) {
throw std::runtime_error("Failed to allocate memory for security descriptor");
}
PSID *ppSID = (PSID *)((PBYTE)m_winPSecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
PACL *ppACL = (PACL *)((PBYTE)ppSID + sizeof(PSID *));
InitializeSecurityDescriptor(m_winPSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
SID_IDENTIFIER_AUTHORITY sidIdentifierAuthority = SECURITY_WORLD_SID_AUTHORITY;
AllocateAndInitializeSid(&sidIdentifierAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, ppSID);
EXPLICIT_ACCESS explicitAccess;
ZeroMemory(&explicitAccess, sizeof(EXPLICIT_ACCESS));
explicitAccess.grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
explicitAccess.grfAccessMode = SET_ACCESS;
explicitAccess.grfInheritance = INHERIT_ONLY;
explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
explicitAccess.Trustee.ptstrName = (LPTSTR) * ppSID;
SetEntriesInAcl(1, &explicitAccess, NULL, ppACL);
SetSecurityDescriptorDacl(m_winPSecurityDescriptor, TRUE, *ppACL, FALSE);
m_winSecurityAttributes.nLength = sizeof(m_winSecurityAttributes);
m_winSecurityAttributes.lpSecurityDescriptor = m_winPSecurityDescriptor;
m_winSecurityAttributes.bInheritHandle = TRUE;
}
SECURITY_ATTRIBUTES *
WindowsSecurityAttributes::operator&()
{
return &m_winSecurityAttributes;
}
WindowsSecurityAttributes::~WindowsSecurityAttributes()
{
PSID *ppSID = (PSID *)((PBYTE)m_winPSecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
PACL *ppACL = (PACL *)((PBYTE)ppSID + sizeof(PSID *));
if (*ppSID) {
FreeSid(*ppSID);
}
if (*ppACL) {
LocalFree(*ppACL);
}
free(m_winPSecurityDescriptor);
}
};
#endif /* _WIN64 */
class VulkanTest {
public:
VulkanTest(bool enable_validation)
@@ -256,4 +333,4 @@ VulkanTest::MappedBuffer<T> VulkanTest::CreateMappedStorage(uint32_t count,
// Sometimes in CUDA the stream is not immediately ready after a semaphore has been signaled
void PollStream(hipStream_t stream, hipError_t expected, uint32_t num_iterations = 5);
hipExternalSemaphore_t ImportBinarySemaphore(VulkanTest& vkt);
hipExternalSemaphore_t ImportBinarySemaphore(VulkanTest& vkt);
+16 -26
Просмотреть файл
@@ -21,76 +21,66 @@ THE SOFTWARE.
*/
#include "hip/hip_runtime.h"
texture<char, hipTextureType2D, hipReadModeElementType> texChar;
texture<short, hipTextureType2D, hipReadModeElementType> texShort;
texture<int, hipTextureType2D, hipReadModeElementType> texInt;
texture<float, hipTextureType2D, hipReadModeElementType> texFloat;
texture<char4, hipTextureType2D, hipReadModeElementType> texChar4;
texture<short4, hipTextureType2D, hipReadModeElementType> texShort4;
texture<int4, hipTextureType2D, hipReadModeElementType> texInt4;
texture<float4, hipTextureType2D, hipReadModeElementType> texFloat4;
extern "C" __global__ void tex2dKernelChar(char* outputData, int width, int height) {
extern "C" __global__ void tex2dKernelChar(char* outputData,hipTextureObject_t texObj, int width, int height) {
#if !defined(__HIP_NO_IMAGE_SUPPORT) || !__HIP_NO_IMAGE_SUPPORT
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
outputData[y * width + x] = tex2D(texChar, x, y);
outputData[y * width + x] = tex2D<char>(texObj, x, y);
#endif
}
extern "C" __global__ void tex2dKernelShort(short* outputData, int width, int height) {
extern "C" __global__ void tex2dKernelShort(short* outputData,hipTextureObject_t texObj, int width, int height) {
#if !defined(__HIP_NO_IMAGE_SUPPORT) || !__HIP_NO_IMAGE_SUPPORT
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
outputData[y * width + x] = tex2D(texShort, x, y);
outputData[y * width + x] = tex2D<short>(texObj, x, y);
#endif
}
extern "C" __global__ void tex2dKernelInt(int* outputData, int width, int height) {
extern "C" __global__ void tex2dKernelInt(int* outputData,hipTextureObject_t texObj ,int width, int height) {
#if !defined(__HIP_NO_IMAGE_SUPPORT) || !__HIP_NO_IMAGE_SUPPORT
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
outputData[y * width + x] = tex2D(texInt, x, y);
outputData[y * width + x] = tex2D<int>(texObj, x, y);
#endif
}
extern "C" __global__ void tex2dKernelFloat(float* outputData, int width, int height) {
extern "C" __global__ void tex2dKernelFloat(float* outputData,hipTextureObject_t texObj, int width, int height) {
#if !defined(__HIP_NO_IMAGE_SUPPORT) || !__HIP_NO_IMAGE_SUPPORT
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
outputData[y * width + x] = tex2D(texFloat, x, y);
outputData[y * width + x] = tex2D<float>(texObj, x, y);
#endif
}
extern "C" __global__ void tex2dKernelChar4(char4* outputData, int width, int height) {
extern "C" __global__ void tex2dKernelChar4(char4* outputData,hipTextureObject_t texObj, int width, int height) {
#if !defined(__HIP_NO_IMAGE_SUPPORT) || !__HIP_NO_IMAGE_SUPPORT
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
outputData[y * width + x] = tex2D(texChar4, x, y);
outputData[y * width + x] = tex2D<char4>(texObj, x, y);
#endif
}
extern "C" __global__ void tex2dKernelShort4(short4* outputData, int width, int height) {
extern "C" __global__ void tex2dKernelShort4(short4* outputData,hipTextureObject_t texObj, int width, int height) {
#if !defined(__HIP_NO_IMAGE_SUPPORT) || !__HIP_NO_IMAGE_SUPPORT
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
outputData[y * width + x] = tex2D(texShort4, x, y);
outputData[y * width + x] = tex2D<short4>(texObj, x, y);
#endif
}
extern "C" __global__ void tex2dKernelInt4(int4* outputData, int width, int height) {
extern "C" __global__ void tex2dKernelInt4(int4* outputData,hipTextureObject_t texObj, int width, int height) {
#if !defined(__HIP_NO_IMAGE_SUPPORT) || !__HIP_NO_IMAGE_SUPPORT
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
outputData[y * width + x] = tex2D(texInt4, x, y);
outputData[y * width + x] = tex2D<int4>(texObj, x, y);
#endif
}
extern "C" __global__ void tex2dKernelFloat4(float4* outputData, int width, int height) {
extern "C" __global__ void tex2dKernelFloat4(float4* outputData,hipTextureObject_t texObj, int width, int height) {
#if !defined(__HIP_NO_IMAGE_SUPPORT) || !__HIP_NO_IMAGE_SUPPORT
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
outputData[y * width + x] = tex2D(texFloat4, x, y);
outputData[y * width + x] = tex2D<float4>(texObj, x, y);
#endif
}
+41 -28
Просмотреть файл
@@ -65,6 +65,19 @@ static inline constexpr int rank() {
return sizeof(T) / sizeof(decltype(T::x));
}
#ifdef __HIP_PLATFORM_NVIDIA__
template <typename T,
typename std::enable_if<std::is_same<T, int4>::value ||
std::is_same<T, short4>::value ||
std::is_same<T, char4>::value ||
std::is_same<T, float4>::value>::type *t = nullptr>
static inline bool operator!=(const T& a, const T& b)
{
return (a.x != b.x) || (a.y != b.y) || (a.z != b.z) || (a.w != b.w);
}
#endif
template<typename T>
static inline T getRandom() {
double r = 0;
@@ -139,43 +152,42 @@ bool runTest(hipModule_t &module, const char *refName, const char *funcName) {
}
}
hipArray *array;
HIP_ARRAY_DESCRIPTOR desc;
desc.Format = format;
desc.NumChannels = channels;
desc.Width = width;
desc.Height = height;
HIP_CHECK(hipArrayCreate(&array, &desc));
hipChannelFormatDesc channelDesc = hipCreateChannelDesc<T>();
hipArray_t array;
HIP_CHECK(hipMallocArray(&array, &channelDesc, width, height));
hip_Memcpy2D copyParam;
memset(&copyParam, 0, sizeof(copyParam));
copyParam.dstMemoryType = hipMemoryTypeArray;
copyParam.dstArray = array;
copyParam.srcMemoryType = hipMemoryTypeHost;
copyParam.srcHost = hData;
copyParam.srcPitch = width * sizeof(T);
copyParam.WidthInBytes = copyParam.srcPitch;
copyParam.Height = height;
HIP_CHECK(hipMemcpyParam2D(&copyParam));
const size_t spitch = width * sizeof(T);
textureReference *texref;
HIP_CHECK(hipModuleGetTexRef(&texref, module, refName));
HIP_CHECK(hipTexRefSetAddressMode(texref, 0, hipAddressModeClamp));
HIP_CHECK(hipTexRefSetAddressMode(texref, 1, hipAddressModeClamp));
HIP_CHECK(hipTexRefSetFilterMode(texref, hipFilterModePoint));
HIP_CHECK(hipTexRefSetFlags(texref, HIP_TRSF_READ_AS_INTEGER));
HIP_CHECK(hipTexRefSetFormat(texref, format, channels));
HIP_CHECK(hipTexRefSetArray(texref, array, HIP_TRSA_OVERRIDE_FORMAT));
HIP_CHECK(hipMemcpy2DToArray(array, 0, 0, hData, spitch, width * sizeof(T),
height, hipMemcpyHostToDevice));
hipResourceDesc resDesc;
memset(&resDesc, 0, sizeof(resDesc));
resDesc.resType = hipResourceTypeArray;
resDesc.res.array.array = array;
hipTextureDesc texDesc;
memset(&texDesc, 0, sizeof(texDesc));
texDesc.addressMode[0] = hipAddressModeClamp;
texDesc.addressMode[1] = hipAddressModeClamp;
texDesc.filterMode = hipFilterModePoint;
texDesc.readMode = hipReadModeElementType;
texDesc.normalizedCoords = 0;
hipTextureObject_t texObj;
HIP_CHECK(hipCreateTextureObject(&texObj, &resDesc, &texDesc, nullptr));
T *dData = NULL;
HIP_CHECK(hipMalloc((void** )&dData, size));
struct {
void *_Ad;
hipTextureObject_t _texObj;
unsigned int _Bd;
unsigned int _Cd;
} args;
args._Ad = (void*) dData;
args._texObj = texObj;
args._Bd = width;
args._Cd = height;
@@ -192,7 +204,7 @@ bool runTest(hipModule_t &module, const char *refName, const char *funcName) {
HIP_CHECK(
hipModuleLaunchKernel(Function, 16, 16, 1, temp1, temp2, 1, 0, 0, NULL,
(void** )&config));
hipDeviceSynchronize();
HIP_CHECK(hipDeviceSynchronize());
T *hOutputData = (T*) malloc(size);
memset(hOutputData, 0, size);
@@ -207,7 +219,7 @@ bool runTest(hipModule_t &module, const char *refName, const char *funcName) {
}
}
}
HIP_CHECK(hipUnbindTexture(texref));
HIP_CHECK(hipDestroyTextureObject(texObj));
HIP_CHECK(hipFree(dData));
HIP_CHECK(hipFreeArray(array));
free(hOutputData);
@@ -230,7 +242,8 @@ int main(int argc, char** argv) {
printf("Texture is not support on the device. Skipped.\n");
return 0;
}
hipInit(0);
HIP_CHECK(hipInit(0));
HIP_CHECK(hipSetDevice(0));
hipModule_t module;
HIP_CHECK(hipModuleLoad(&module, fileName));
testResult = testResult && runTest<char>(module, "texChar", "tex2dKernelChar");
+8 -1
Просмотреть файл
@@ -23,8 +23,15 @@
#include <hip/hip_runtime.h>
#include <hip/hip_runtime_api.h>
#include <iostream>
#include <stdexcept>
#define HIP_ASSERT(status) assert(status == hipSuccess)
#define HIP_ASSERT(status) \
{ \
if ((status != hipSuccess)) { \
std::cerr << "Failed in: " << __LINE__ << " on hip call: " #status << std::endl; \
throw std::runtime_error("generic failure"); \
} \
}
#define LEN 512
extern __device__ int square_me(int);
+5 -5
Просмотреть файл
@@ -30,9 +30,9 @@ all: ${SRC}
${CC} ${CPPFLAGS} $^ -o ${OBJ}
clean:
rm ${OBJ}
rm *.xml
rm -r ./coverageReportHTML/testModules
rm -r ./coverageReportHTML/testAPIs
rm ./coverageReportHTML/*.html
rm -f ${OBJ}
rm -f *.xml
rm -fr ./coverageReportHTML/testModules
rm -fr ./coverageReportHTML/testAPIs
rm -f ./coverageReportHTML/*.html
.PHONY : clean
+12
Просмотреть файл
@@ -169,6 +169,18 @@ td.coverBarOutline
background-color: #000000;
}
/* Directory view/File view (all): line count entry for files with
deprecated functions */
td.coverDeprecated
{
text-align: center;
padding-left: 10px;
padding-right: 10px;
background-color: #d2d2d2;
white-space: nowrap;
font-family: sans-serif;
}
/* Directory view/File view (all): line count entry for files with
high coverage rate */
td.coverNumHi
+733
Просмотреть файл
@@ -0,0 +1,733 @@
Atomics [
atomicCAS
atomicCAS_system
atomicAdd
atomicAdd_system
unsafeAtomicAdd
safeAtomicAdd
atomicSub
atomicSub_system
atomicExch
atomicExch_system
atomicMin
atomicMin_system
unsafeAtomicMin
safeAtomicMin
atomicMax
atomicMax_system
unsafeAtomicMax
safeAtomicMax
atomicInc
atomicDec
atomicAnd
atomicAnd_system
atomicOr
atomicOr_system
atomicXor
atomicXor_system
]
Builtin atomics [
__hip_atomic_load
__hip_atomic_store
__hip_atomic_compare_exchange_weak
__hip_atomic_compare_exchange_strong
__hip_atomic_exchange
__hip_atomic_fetch_add
__hip_atomic_fetch_and
__hip_atomic_fetch_or
__hip_atomic_fetch_xor
__hip_atomic_fetch_min
__hip_atomic_fetch_max
]
Cooperative groups [
File restriction: cooperative_groups
Device groups: (
coalesced_group_tile
coalesced_group
grid_group
multi_grid_group
thread_block_tile
thread_block
)
size
thread_rank
group_index
thread_index
shfl
shfl_up
shfl_down
shfl_xor
sync
]
Warp [
File restriction: cooperative_groups
Device groups: (
ballot
any
all
shfl_down
shfl_up
shfl
shfl_xor
)
__ballot
__any
__all
__shfl_down
__shfl_up
__shfl
__shfl_xor
]
Launch bounds [
Device groups: (
launch_bounds
)
__launch_bounds__
]
Channel descriptor [
hipCreateChannelDesc
hipCreateChannelDescHalf
hipCreateChannelDescHalf1
hipCreateChannelDescHalf2
]
Device assert [
assert
static_assert
]
Device clock [
Device groups: (
clock
)
clock
clock64
wall_clock64
]
Device printf [
printf
]
HIP specific [
Device groups: (
hip_hc_8pk
)
__hip_hc_add8pk
__hip_hc_sub8pk
__hip_hc_mul8pk
]
Device synchronization [
__syncthreads
__syncthreads_and
__syncthreads_count
__syncthreads_or
]
Memory fence [
__threadfence
__threadfence_block
__threadfence_system
]
Device memory [
memcpy
memset
]
Device math [
rsqrt
sqrt
cbrt
rcbrt
hypot
rhypot
norm3d
rnorm3d
norm4d
rnorm4d
norm
rnorm
rsqrtf
sqrtf
cbrtf
rcbrtf
hypotf
rhypotf
norm3df
rnorm3df
norm4df
rnorm4df
normf
rnormf
rsqrt
sqrt
cbrt
rcbrt
hypot
rhypot
norm3d
rnorm3d
norm4d
rnorm4d
norm
rnorm
expf
exp2f
exp10f
expm1f
frexpf
ldexpf
powf
powif
scalbnf
scalblnf
log
log2
log10
log1p
logb
ilogb
logf
log2f
log10f
log1pf
logbf
ilogbf
sin
cos
tan
sincos
sinpi
cospi
sincospi
asin
acos
atan
atan2
sinh
cosh
tanh
asinh
acosh
atanh
sinf
cosf
tanf
sincosf
sinpif
cospif
sincospif
asinf
acosf
atanf
atan2f
sinhf
coshf
tanhf
asinhf
acoshf
atanhf
erf
erfc
erfinv
erfcinv
erfcx
normcdf
normcdfinv
lgamma
tgamma
j0
j1
jn
y0
y1
yn
cyl_bessel_i0
cyl_bessel_i1
erff
erfcf
erfinvf
erfcinvf
erfcxf
normcdff
normcdfinvf
lgammaf
tgammaf
j0f
j1f
jnf
y0f
y1f
ynf
cyl_bessel_i0f
cyl_bessel_i1f
fmod
remainder
remquo
modf
fdim
trunc
round
rint
nearbyint
ceil
floor
lrint
lround
llrint
llround
fmodf
remainderf
remquof
modff
fdimf
truncf
roundf
rintf
nearbyintf
ceilf
floorf
lrintf
lroundf
llrintf
llroundf
fma
abs
fabs
copysign
fmax
fmin
nan
nextafter
signbit
fmaf
abs
fabsf
copysignf
fdividef
fmaxf
fminf
isfinite
isinf
isnan
nanf
nextafterf
signbit
__brev
__brevll
__clz
__clzll
__ffs
__ffsll
__popc
__popcll
__mul24
__umul24
__dadd_rn
__dsub_rn
__dmul_rn
__fma_rn
__drcp_rn
__dsqrt_rn
__ddiv_rn
__fadd_rn
__fsub_rn
__fmul_rn
__fmaf_rn
__frcp_rn
__fsqrt_rn
__frsqrt_rn
__fdiv_rn
__fdividef
__expf
__exp10f
__logf
__log2f
__log10f
__sinf
__cosf
__sincosf
__tanf
__powf
]
Device conversion functions [
__double2float_rd
__double2float_rn
__double2float_ru
__double2float_rz
__double2hiint
__double2loint
__double2int_rd
__double2int_rn
__double2int_ru
__double2int_rz
__double2ll_rd
__double2ll_rn
__double2ll_ru
__double2ll_rz
__double2uint_rd
__double2uint_rn
__double2uint_ru
__double2uint_rz
__double2ull_rd
__double2ull_rn
__double2ull_ru
__double2ull_rz
__double_as_longlong
__float2int_rd
__float2int_rn
__float2int_ru
__float2int_rz
__float2ll_rd
__float2ll_rn
__float2ll_ru
__float2ll_rz
__float2uint_rd
__float2uint_rn
__float2uint_ru
__float2uint_rz
__float2ull_rd
__float2ull_rn
__float2ull_ru
__float2ull_rz
__float_as_int
__float_as_uint
__hiloint2double
__int2double_rn
__int2float_rd
__int2float_rn
__int2float_ru
__int2float_rz
__int_as_float
__ll2double_rd
__ll2double_rn
__ll2double_ru
__ll2double_rz
__ll2float_rd
__ll2float_rn
__ll2float_ru
__ll2float_rz
__longlong_as_double
__uint2double_rn
__uint2float_rd
__uint2float_rn
__uint2float_ru
__uint2float_rz
__uint_as_float
__ull2double_rd
__ull2double_rn
__ull2double_ru
__ull2double_rz
__ull2float_rd
__ull2float_rn
__ull2float_ru
__ull2float_rz
]
Device complex type functions [
hipCrealf
hipCimagf
make_hipFloatComplex
hipConjf
hipCsqabsf
hipCaddf
hipCsubf
hipCmulf
hipCdivf
hipCabsf
hipCreal
hipCimag
make_hipDoubleComplex
hipConj
hipCsqabs
hipCadd
hipCsub
hipCmul
hipCdiv
hipCabs
make_hipComplex
hipComplexDoubleToFloat
hipComplexFloatToDouble
hipCfmaf
hipCfma
]
Device vector types [
make_uchar1
make_uchar2
make_uchar3
make_uchar4
make_char1
make_char2
make_char3
make_char4
make_ushort1
make_ushort2
make_ushort3
make_ushort4
make_short1
make_short2
make_short3
make_short4
make_uint1
make_uint2
make_uint3
make_uint4
make_int1
make_int2
make_int3
make_int4
make_float1
make_float2
make_float3
make_float4
make_double1
make_double2
make_double3
make_double4
make_ulong1
make_ulong2
make_ulong3
make_ulong4
make_long1
make_long2
make_long3
make_long4
make_ulonglong1
make_ulonglong2
make_ulonglong3
make_ulonglong4
make_longlong1
make_longlong2
make_longlong3
make_longlong4
]
Device surface functions [
__hipGetPixelAddr
__hipMapToNativeFloat4
__hipMapFromNativeFloat4
surf1Dread
surf1Dwrite
surf2Dread
surf2Dwrite
surf3Dread
surf3Dwrite
surf1DLayeredread
surf1DLayeredwrite
surf2DLayeredread
surf2DLayeredwrite
surfCubemapread
surfCubemapwrite
surfCubemapLayeredread
surfCubemapLayeredwrite
]
Device texture functions [
tex1Dfetch
tex1D
tex2D
tex1DLayered
tex2DLayered
tex3D
texCubemap
tex1DLod
tex2DLod
tex1DLayeredLod
tex2DLayeredLod
tex3DLod
texCubemapLod
texCubemapLayered
texCubemapLayeredLod
texCubemapGrad
texCubemapLayeredGrad
tex1DGrad
tex2DGrad
tex1DLayeredGrad
tex2DLayeredGrad
tex3DGrad
tex2Dgather
]
Device float16 functions [
make_half2
__low2half
__high2half
__half2half2
__halves2half2
__low2half2
__high2half2
__lows2half2
__highs2half2
__lowhigh2highlow
__half_as_short
__half_as_ushort
__short_as_half
__ushort_as_half
__float2half
__float2half_rn
__float2half_rz
__float2half_rd
__float2half_ru
__float2half2_rn
__floats2half2_rn
__float22half2_rn
__half2float
__low2float
__high2float
__half22float2
__half2int_rn
__half2int_rz
__half2int_rd
__half2int_ru
__int2half_rn
__int2half_rz
__int2half_rd
__int2half_ru
__half2short_rn
__half2short_rz
__half2short_rd
__half2short_ru
__short2half_rn
__short2half_rz
__short2half_rd
__short2half_ru
__half2ll_rn
__half2ll_rz
__half2ll_rd
__half2ll_ru
__ll2half_rn
__ll2half_rz
__ll2half_rd
__ll2half_ru
__half2uint_rn
__half2uint_rz
__half2uint_rd
__half2uint_ru
__uint2half_rn
__uint2half_rz
__uint2half_rd
__uint2half_ru
__half2ushort_rn
__half2ushort_rz
__half2ushort_rd
__half2ushort_ru
__ushort2half_rn
__ushort2half_rz
__ushort2half_rd
__ushort2half_ru
__half2ull_rn
__half2ull_rz
__half2ull_rd
__half2ull_ru
__ull2half_rn
__ull2half_rz
__ull2half_rd
__ull2half_ru
__ldg
__ldcg
__ldca
__ldcs
__heq
__hne
__hle
__hge
__hlt
__hgt
__hequ
__hneu
__hleu
__hgeu
__hltu
__hgtu
__heq2
__hne2
__hle2
__hge2
__hlt2
__hgt2
__hequ2
__hneu2
__hleu2
__hgeu2
__hltu2
__hgtu2
__hbeq2
__hbne2
__hble2
__hbge2
__hblt2
__hbgt2
__hbequ2
__hbneu2
__hbleu2
__hbgeu2
__hbltu2
__hbgtu2
__clamp_01
__hadd
__habs
__hsub
__hmul
__hadd_sat
__hsub_sat
__hmul_sat
__hfma
__hfma_sat
__hdiv
__hadd2
__habs2
__hsub2
__hmul2
__hadd2_sat
__hsub2_sat
__hmul2_sat
__hfma2
__hfma2_sat
__h2div
amd_mixed_dot
htrunc
hceil
hfloor
hrint
hsin
hcos
hexp
hexp2
hexp10
hlog2
hlog
hlog10
hrcp
hrsqrt
hsqrt
__hisinf
__hisnan
__hneg
h2trunc
h2ceil
h2floor
h2rint
h2sin
h2cos
h2exp
h2exp2
h2exp10
h2log2
h2log
h2log10
h2rcp
h2rsqrt
h2sqrt
__hisinf2
__hisnan2
__hneg2
]
+82 -49
Просмотреть файл
@@ -22,11 +22,20 @@ THE SOFTWARE.
#include "hipAPI.h"
FileOccurrence::FileOccurrence(std::string file_name, int line_number):
file_name{file_name}, line_number{line_number} {}
FileOccurrence::FileOccurrence(std::string file_name, int line_number)
: file_name{file_name}, line_number{line_number} {}
TestCaseOccurrence::TestCaseOccurrence(std::string test_case_name, std::string file_name, int line_number):
FileOccurrence{file_name, line_number}, test_case_name{test_case_name} {}
TestCaseOccurrence::TestCaseOccurrence(std::string test_case_name, std::string file_name,
int line_number)
: FileOccurrence{file_name, line_number}, test_case_name{test_case_name} {}
bool operator==(const TestCaseOccurrence& l_test, const TestCaseOccurrence& r_test) {
return l_test.test_case_name == r_test.test_case_name;
}
bool operator<(const TestCaseOccurrence& l_test, const TestCaseOccurrence& r_test) {
return l_test.test_case_name < r_test.test_case_name;
}
bool operator==(const HipAPI& l_hip_api, const HipAPI& r_hip_api) {
return l_hip_api.api_name == r_hip_api.api_name;
@@ -36,54 +45,53 @@ bool operator<(const HipAPI& l_hip_api, const HipAPI& r_hip_api) {
return l_hip_api.api_name < r_hip_api.api_name;
}
HipAPI::HipAPI(std::string api_name, bool deprecated_flag, std::string api_group_name):
api_name{api_name}, deprecated{deprecated_flag}, api_group_name{api_group_name} {}
std::string HipAPI::getName() const {
return api_name;
HipAPI::HipAPI(std::string api_name, bool deprecated_flag, std::string api_group_name,
std::string file_restriction)
: api_name{api_name},
deprecated{deprecated_flag},
api_group_name{api_group_name},
file_restriction{file_restriction} {
test_cases.clear();
}
std::string HipAPI::getGroupName() const {
return api_group_name;
}
std::string HipAPI::getName() const { return api_name; }
int HipAPI::getNumberOfCalls() const {
return file_occurrences.size();
}
std::string HipAPI::getGroupName() const { return api_group_name; }
int HipAPI::getNumberOfTestCases() const {
return test_cases.size();
}
int HipAPI::getNumberOfCalls() const { return file_occurrences.size(); }
std::vector<TestCaseOccurrence> HipAPI::getTestCases() const { return test_cases; }
void HipAPI::addFileOccurrence(FileOccurrence file_occurrence) {
file_occurrences.push_back(file_occurrence);
}
void HipAPI::addTestCase(TestCaseOccurrence test_case) {
test_cases.push_back(test_case);
if (std::find(test_cases.begin(), test_cases.end(), test_case) == test_cases.end()) {
test_cases.push_back(test_case);
}
}
bool HipAPI::isDeprecated() const
{
return deprecated;
}
bool HipAPI::isDeprecated() const { return deprecated; }
std::string HipAPI::getBasicStatsXML() const
{
std::string HipAPI::getBasicStatsXML() const {
std::stringstream xml_node;
xml_node << "\t\t<HIP-API>\n";
if (!deprecated) {
xml_node << "\t\t\t<NAME>" << api_name << "</NAME>\n";
} else {
xml_node << "\t\t\t<NAME>" << "[DEPRECATED] " << api_name << "</NAME>\n";
xml_node << "\t\t\t<NAME>"
<< "[DEPRECATED] " << api_name << "</NAME>\n";
}
if (!file_occurrences.empty()) {
xml_node << "\t\t\t<NUMBER-OF-API-CALLS>" << file_occurrences.size() << "</NUMBER-OF-API-CALLS>\n";
xml_node << "\t\t\t<NUMBER-OF-API-CALLS>" << file_occurrences.size()
<< "</NUMBER-OF-API-CALLS>\n";
xml_node << "\t\t\t<FILE-OCCURRENCES>\n";
for (auto const& file_occurrence: file_occurrences) {
xml_node << "\t\t\t\t<FILE-OCCURRENCE>" << file_occurrence.file_name << ":" << file_occurrence.line_number << "</FILE-OCCURRENCE>\n";
for (auto const& file_occurrence : file_occurrences) {
xml_node << "\t\t\t\t<FILE-OCCURRENCE>" << file_occurrence.file_name << ":"
<< file_occurrence.line_number << "</FILE-OCCURRENCE>\n";
}
xml_node << "\t\t\t</FILE-OCCURRENCES>\n";
}
@@ -102,13 +110,20 @@ std::string HipAPI::createHTMLReport() const {
std::string six_tabs{"\n\t\t\t\t\t\t"};
html_report << "<html lang=\"en\">";
html_report << "<head>" << one_tab << "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">";
html_report << one_tab << "<title>" << api_name << " Coverage report</title>" << one_tab << "<link rel=\"stylesheet\" type=\"text/css\" href=\"../resources/coverage.css\">" << one_tab<< "</head>";
html_report << one_tab << "<body>" << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
html_report << "<head>" << one_tab
<< "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">";
html_report << one_tab << "<title>" << api_name << " Coverage report</title>" << one_tab
<< "<link rel=\"stylesheet\" type=\"text/css\" href=\"../resources/coverage.css\">"
<< one_tab << "</head>";
html_report << one_tab << "<body>" << one_tab
<< "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
html_report << two_tabs << "<tr><td class=\"title\">" << api_name << " Coverage report</td></tr>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>\n";
html_report << two_tabs << "<tr>" << three_tabs << "<td width=\"100%\">" << four_tabs << "<table cellpading=1 border=0 width=\"100%\"";
html_report << two_tabs
<< "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 "
"height=3></td></tr>\n";
html_report << two_tabs << "<tr>" << three_tabs << "<td width=\"100%\">" << four_tabs
<< "<table cellpading=1 border=0 width=\"100%\"";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td width=\"70%\"</td>";
html_report << six_tabs << "<td width=\"10%\"></td>";
@@ -124,7 +139,8 @@ std::string HipAPI::createHTMLReport() const {
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">Calls within test source files:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << file_occurrences.size() << "</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << file_occurrences.size()
<< "</td>";
html_report << six_tabs << "<td></td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
@@ -135,13 +151,16 @@ std::string HipAPI::createHTMLReport() const {
html_report << six_tabs << "<td></td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr><td><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
html_report << five_tabs
<< "<tr><td><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
html_report << four_tabs << "</table>";
html_report << three_tabs << "</td>";
html_report << two_tabs << "</tr>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>\n";
html_report << two_tabs
<< "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 "
"height=3></td></tr>\n";
html_report << one_tab << "</table>";
html_report << one_tab << "<center>";
@@ -160,23 +179,29 @@ std::string HipAPI::createHTMLReport() const {
html_report << three_tabs << "<td class=\"tableHead\">Line number</td>";
html_report << two_tabs << "</tr>";
for (auto const& test_case: test_cases) {
for (auto const& test_case : test_cases) {
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td class=\"coverFile\">" << test_case.test_case_name << "</td>";
html_report << three_tabs << "<td class=\"coverFile\">" << test_case.test_case_name
<< "</td>";
html_report << three_tabs << "<td class=\"coverFile\">" << test_case.file_name << "</td>";
html_report << three_tabs << "<td class=\"headerCovTableEntry\">" << test_case.line_number << "</td>";
html_report << three_tabs << "<td class=\"headerCovTableEntry\">" << test_case.line_number
<< "</td>";
html_report << two_tabs << "</tr>";
}
} else {
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td class=\"headerItem\" style=\"text-align:center\"><br>There are no test cases detected within doxygen comments.</td>";
html_report << three_tabs
<< "<td class=\"headerItem\" style=\"text-align:center\"><br>There are no test "
"cases detected within doxygen comments.</td>";
html_report << two_tabs << "</tr>";
}
html_report << one_tab << "</table>";
html_report << one_tab << "<br>";
html_report << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
html_report
<< two_tabs
<< "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
html_report << one_tab << "</table>";
// Add info about API occurrences in the test files.
@@ -192,15 +217,19 @@ std::string HipAPI::createHTMLReport() const {
html_report << three_tabs << "<td class=\"tableHead\">Line number</td>";
html_report << two_tabs << "</tr>";
for (auto const& file_occurrence: file_occurrences) {
for (auto const& file_occurrence : file_occurrences) {
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td class=\"coverFile\">" << file_occurrence.file_name << "</td>";
html_report << three_tabs << "<td class=\"headerCovTableEntry\">" << file_occurrence.line_number << "</td>";
html_report << three_tabs << "<td class=\"coverFile\">" << file_occurrence.file_name
<< "</td>";
html_report << three_tabs << "<td class=\"headerCovTableEntry\">"
<< file_occurrence.line_number << "</td>";
html_report << two_tabs << "</tr>";
}
} else {
html_report << two_tabs << "<tr>";
html_report << three_tabs << "<td class=\"headerItem\" style=\"text-align:center\"><br>There are no occurrences within test source files.</td>";
html_report << three_tabs
<< "<td class=\"headerItem\" style=\"text-align:center\"><br>There are no "
"occurrences within test source files.</td>";
html_report << two_tabs << "</tr>";
}
html_report << one_tab << "</table>";
@@ -208,7 +237,9 @@ std::string HipAPI::createHTMLReport() const {
html_report << one_tab << "<br>";
html_report << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
html_report
<< two_tabs
<< "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
time_t now{time(nullptr)};
std::string date{asctime(gmtime(&now))};
@@ -220,3 +251,5 @@ std::string HipAPI::createHTMLReport() const {
return html_report.str();
}
std::string HipAPI::getFileRestriction() const { return file_restriction; }
+11 -2
Просмотреть файл
@@ -23,6 +23,7 @@ THE SOFTWARE.
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
/*
Helper class used to store information in what file has HIP API been detected,
@@ -40,6 +41,9 @@ Helper class used to store information in what file has the API Test Case been d
and on what line of code in that file.
*/
class TestCaseOccurrence : public FileOccurrence {
friend bool operator==(const TestCaseOccurrence& l_test, const TestCaseOccurrence& r_test);
friend bool operator<(const TestCaseOccurrence& l_test, const TestCaseOccurrence& r_test);
public:
std::string test_case_name;
TestCaseOccurrence(std::string test_case_name, std::string file_name, int line_number);
@@ -55,18 +59,23 @@ class HipAPI {
friend bool operator<(const HipAPI& l_hip_api, const HipAPI& r_hip_api);
public:
HipAPI(std::string api_name, bool deprecated_flag, std::string api_group_name);
HipAPI(std::string api_name, bool deprecated_flag, std::string api_group_name,
std::string file_restriction = "");
std::string getName() const;
std::string getGroupName() const;
int getNumberOfCalls() const;
int getNumberOfTestCases() const;
std::vector<TestCaseOccurrence> getTestCases() const;
void addFileOccurrence(FileOccurrence file_occurence);
void addTestCase(TestCaseOccurrence test_case);
bool isDeprecated() const;
std::string getBasicStatsXML() const;
std::string createHTMLReport() const;
std::string getFileRestriction() const;
std::vector<std::string> device_groups;
private:
std::string api_name;
std::string file_restriction;
int number_of_calls;
bool deprecated;
std::string api_group_name;
+157 -35
Просмотреть файл
@@ -42,13 +42,34 @@ void findAPICallInFile(HipAPI& hip_api, std::string test_module_file) {
std::string api_call_with_assert{"(" + hip_api.getName() + "("};
std::string api_call_with_assignment{"= " + hip_api.getName() + "("};
std::string api_call_with_parameter{", " + hip_api.getName() + "("};
std::string api_call_with_return{"return " + hip_api.getName() + "("};
std::string api_call_in_line("{ " + hip_api.getName() + "(");
std::string api_member{"." + hip_api.getName() + "("};
std::string api_newline{" " + hip_api.getName() + "("};
std::string api_templated{" " + hip_api.getName() + "<"};
std::string api_restriction{hip_api.getFileRestriction()};
bool found_restriction{false};
while (std::getline(test_module_file_handler, line)) {
++line_number;
if (api_restriction != "" && line.find(api_restriction) != std::string::npos) {
found_restriction = true;
}
if ((line.find(api_call_with_assert) != std::string::npos) ||
(line.find(api_call_with_assignment) != std::string::npos) ||
(line.find(api_call_with_parameter) != std::string::npos)) {
hip_api.addFileOccurrence(FileOccurrence(test_module_file, line_number));
(line.find(api_call_with_parameter) != std::string::npos) ||
(line.find(api_call_with_return) != std::string::npos) ||
(line.find(api_call_in_line) != std::string::npos) ||
(line.find(api_member) != std::string::npos) ||
(line.find(api_newline) != std::string::npos) ||
(line.find(hip_api.getName() + "(") == 0) ||
(line.find(api_templated) != std::string::npos)) {
if (api_restriction == "" || found_restriction) {
hip_api.addFileOccurrence(FileOccurrence(test_module_file, line_number));
}
}
}
@@ -59,7 +80,7 @@ void findAPICallInFile(HipAPI& hip_api, std::string test_module_file) {
Used to find all HIP API test cases within the passed test .cc files.
Matching test case is detected when the HIP API in defined within doxygen comment.
*/
void findAPITestCaseInFile(HipAPI& hip_api, std::string test_module_file) {
void findAPITestCaseInFileByDoxygen(HipAPI& hip_api, std::string test_module_file) {
std::fstream test_module_file_handler;
test_module_file_handler.open(test_module_file);
@@ -80,7 +101,10 @@ void findAPITestCaseInFile(HipAPI& hip_api, std::string test_module_file) {
}
if (hip_api.getName() != current_api_name) {
continue;
if (std::find(hip_api.device_groups.begin(), hip_api.device_groups.end(), current_api_name) ==
hip_api.device_groups.end()) {
continue;
}
}
if (line.find(ref_test_case) != std::string::npos) {
@@ -99,15 +123,45 @@ void findAPITestCaseInFile(HipAPI& hip_api, std::string test_module_file) {
test_module_file_handler.close();
}
/*
Used to find all HIP API test cases within the passed test .cc files.
Matching test case is detected when the HIP API in defined within doxygen comment.
*/
void findAPITestCaseInFileByAPIName(HipAPI& hip_api, std::string test_module_file) {
std::fstream test_module_file_handler;
test_module_file_handler.open(test_module_file);
int line_number{0};
std::string line;
std::string test_case_definition{"TEST_CASE("};
std::string test_case{"None"};
while (std::getline(test_module_file_handler, line)) {
++line_number;
if (line.find(test_case_definition) != std::string::npos) {
test_case = line.substr(line.find("\"") + 1);
test_case = test_case.substr(0, test_case.find("\""));
if (test_case.find("_" + hip_api.getName() + "_") != std::string::npos) {
hip_api.addTestCase(TestCaseOccurrence{test_case, test_module_file, line_number});
}
}
}
test_module_file_handler.close();
}
/*
Used to iterate through all passed test .cc files and search for passed
HIP API instance. This instance shall be used to update occurrences.
*/
void searchForAPI(HipAPI& hip_api, std::vector<std::string>& test_module_files) {
std::cout << "Searching for " << hip_api.getName() << " in test module files." << std::endl;
for (auto const& test_module_file: test_module_files) {
for (auto const& test_module_file : test_module_files) {
findAPICallInFile(hip_api, test_module_file);
findAPITestCaseInFile(hip_api, test_module_file);
findAPITestCaseInFileByDoxygen(hip_api, test_module_file);
findAPITestCaseInFileByAPIName(hip_api, test_module_file);
}
}
@@ -115,7 +169,7 @@ void searchForAPI(HipAPI& hip_api, std::vector<std::string>& test_module_files)
Used to extract all HIP APIs from the passed header file.
*/
std::vector<HipAPI> extractHipAPIs(std::string& hip_api_header_file,
std::vector<std::string>& api_group_names, bool start_groups) {
std::vector<std::string>& api_group_names, bool start_groups) {
std::fstream hip_header_file_handler;
hip_header_file_handler.open(hip_api_header_file);
@@ -148,8 +202,9 @@ std::vector<HipAPI> extractHipAPIs(std::string& hip_api_header_file,
++line_number;
// Declarations of the HIP APIs start after the HIP API group has been defined.
if ((line.find(group_definition) != std::string::npos || line.find(add_group_definition) != std::string::npos)
&& line.find(start_of_api_groups) != std::string::npos) {
if ((line.find(group_definition) != std::string::npos ||
line.find(add_group_definition) != std::string::npos) &&
line.find(start_of_api_groups) != std::string::npos) {
api_group_names_start = true;
continue;
}
@@ -167,24 +222,21 @@ std::vector<HipAPI> extractHipAPIs(std::string& hip_api_header_file,
/*
If the API is deprecated, raise a flag and go to the
next line where the API is declared.
*/
*/
if (line.find(deprecated_line) != std::string::npos) {
std::getline(hip_header_file_handler, line);
++line_number;
deprecated_flag = true;
} else {
deprecated_flag = false;
continue;
}
if (line.find(group_definition) != std::string::npos) {
std::string group_name = line.substr(line.find(group_definition) + group_definition.length() + 1);
std::string group_name =
line.substr(line.find(group_definition) + group_definition.length() + 1);
group_name = group_name.substr(group_name.find(' ') + 1);
api_group_names.push_back(group_name);
api_group_names_tracker.push_back(group_name);
}
else if (line.find(add_group_definition) != std::string::npos)
{
std::string group_name = line.substr(line.find(add_group_definition) + add_group_definition.length() + 1);
} else if (line.find(add_group_definition) != std::string::npos) {
std::string group_name =
line.substr(line.find(add_group_definition) + add_group_definition.length() + 1);
group_name = group_name.substr(group_name.find(' ') + 1);
api_group_names.push_back(group_name);
api_group_names_tracker.push_back(group_name);
@@ -196,7 +248,9 @@ std::vector<HipAPI> extractHipAPIs(std::string& hip_api_header_file,
to track the last defined group, because of the nested cases.
*/
if (line.find(end_group_definition) != std::string::npos) {
api_group_names_tracker.pop_back();
if (!api_group_names_tracker.empty()) {
api_group_names_tracker.pop_back();
}
}
/*
@@ -207,16 +261,14 @@ std::vector<HipAPI> extractHipAPIs(std::string& hip_api_header_file,
- Extract the name from that substring by finding the last "hip".
Avoid comments.
*/
if (line.find(hip_api_prefix) != std::string::npos &&
line.find("(") != std::string::npos &&
line.find(" ") != 0 &&
line.find(" *") != 0) {
if (line.find(hip_api_prefix) != std::string::npos && line.find("(") != std::string::npos &&
line.find(" ") != 0 && line.find(" *") != 0) {
std::string api_name_no_brackets{line.substr(0, line.find("("))};
/*
If there is no hip substring, then there is no valid API in that line.
*/
if (api_name_no_brackets.rfind(hip_api_prefix) == std::string::npos) {
continue;
continue;
}
/*
@@ -233,13 +285,15 @@ std::vector<HipAPI> extractHipAPIs(std::string& hip_api_header_file,
If the API is not present in the global list of HIP APIs, add it.
*/
HipAPI hip_api{api_name, deprecated_flag, api_group_names_tracker.back()};
if(std::find(hip_apis.begin(), hip_apis.end(), hip_api) == hip_apis.end())
{
hip_apis.push_back(hip_api);
if (std::find(hip_apis.begin(), hip_apis.end(), hip_api) == hip_apis.end()) {
hip_apis.push_back(hip_api);
}
} else {
std::cout << "[SKIP_FROM_COV] Group not detected for \"" << api_name << "\" in file \""
<< hip_api_header_file << "\", line " << line_number << std::endl;
<< hip_api_header_file << "\", line " << line_number << std::endl;
}
if (deprecated_flag) {
deprecated_flag = false;
}
}
}
@@ -248,14 +302,83 @@ std::vector<HipAPI> extractHipAPIs(std::string& hip_api_header_file,
return hip_apis;
}
/*
Used to extract all HIP APIs from the passed header file.
*/
std::vector<HipAPI> extractDeviceAPIs(std::string& apis_list_file,
std::vector<std::string>& api_group_names) {
std::fstream apis_list_file_handler;
apis_list_file_handler.open(apis_list_file);
std::string line;
std::vector<HipAPI> device_apis;
/*
Each HIP API has prefix hip in the name. Groups are marked with @defgroup, and the
main group that shall be considered is HIP API. Before that group is defined, lines
of code shall not be considered.
*/
int line_number{0};
bool group_start{false};
bool device_groups_start{false};
std::string restriction{""};
std::string file_restriction_definition{"File restriction: "};
std::string device_groups_definition{"Device groups: ("};
std::vector<std::string> device_groups;
while (std::getline(apis_list_file_handler, line)) {
++line_number;
if (line.find("[") != std::string::npos) {
std::string group_name = line.substr(0, line.rfind(" "));
api_group_names.push_back(group_name);
group_start = true;
continue;
}
if (line.find("]") != std::string::npos) {
group_start = false;
device_groups.clear();
restriction = "";
continue;
}
if (line.find(file_restriction_definition) != std::string::npos) {
restriction =
line.substr(line.find(file_restriction_definition) + file_restriction_definition.size());
continue;
}
if (line.find(device_groups_definition) != std::string::npos) {
std::getline(apis_list_file_handler, line);
while (line.find(")") == std::string::npos) {
std::string group_name = line;
group_name.erase(std::remove(group_name.begin(), group_name.end(), ' '), group_name.end());
device_groups.push_back(group_name);
std::getline(apis_list_file_handler, line);
}
std::getline(apis_list_file_handler, line);
}
if (group_start) {
std::string api_name = line.substr(line.rfind(" ") + 1);
HipAPI hip_api{api_name, false, api_group_names.back(), restriction};
hip_api.device_groups = device_groups;
device_apis.push_back(hip_api);
}
}
apis_list_file_handler.close();
return device_apis;
}
/*
Used to extract test .cc files from the passed tests root directory.
Goes through all subdirectories and searches for .cc and .hh files for
HIP API invocations.
Implements BFS algorithm to avoid recursion.
*/
std::vector<std::string> extractTestModuleFiles(std::string& tests_root_directory)
{
std::vector<std::string> extractTestModuleFiles(std::string& tests_root_directory) {
std::vector<std::string> directory_queue;
directory_queue.push_back(tests_root_directory);
std::vector<std::string> test_module_files;
@@ -263,11 +386,11 @@ std::vector<std::string> extractTestModuleFiles(std::string& tests_root_director
while (!directory_queue.empty()) {
std::string processed_entry = directory_queue.back();
directory_queue.pop_back();
for (const auto& entry: std::filesystem::directory_iterator(processed_entry)) {
for (const auto& entry : std::filesystem::directory_iterator(processed_entry)) {
if (std::filesystem::is_directory(entry.path())) {
directory_queue.push_back(entry.path());
} else {
if (entry.path().string().find(".cc") != std::string::npos ||
if (entry.path().string().find(".cc") != std::string::npos ||
entry.path().string().find(".hh") != std::string::npos) {
test_module_files.push_back(entry.path());
}
@@ -278,7 +401,6 @@ std::vector<std::string> extractTestModuleFiles(std::string& tests_root_director
return test_module_files;
}
std::string findAbsolutePathOfFile(std::string file_path)
{
std::string findAbsolutePathOfFile(std::string file_path) {
return std::filesystem::canonical(std::filesystem::absolute(file_path));
}
+6 -2
Просмотреть файл
@@ -25,8 +25,12 @@ THE SOFTWARE.
#include "hipAPIGroup.h"
void findAPICallInFile(HipAPI& hip_api, std::string test_module_file);
void findAPITestCaseInFile(HipAPI& hip_api, std::string test_module_file);
void findAPITestCaseInFileByDoxygen(HipAPI& hip_api, std::string test_module_file);
void findAPITestCaseInFileByAPIName(HipAPI& hip_api, std::string test_module_file);
void searchForAPI(HipAPI& hip_api, std::vector<std::string>& test_module_files);
std::vector<HipAPI> extractHipAPIs(std::string& hip_api_header_file, std::vector<std::string>& api_group_names, bool start_groups);
std::vector<HipAPI> extractHipAPIs(std::string& hip_api_header_file,
std::vector<std::string>& api_group_names, bool start_groups);
std::vector<HipAPI> extractDeviceAPIs(std::string& apis_list_file,
std::vector<std::string>& api_group_names);
std::vector<std::string> extractTestModuleFiles(std::string& tests_root_directory);
std::string findAbsolutePathOfFile(std::string file_path);
+113 -74
Просмотреть файл
@@ -26,11 +26,14 @@ bool operator==(const HipAPIGroup& l_hip_api_group, const HipAPIGroup& r_hip_api
return l_hip_api_group.group_name == r_hip_api_group.group_name;
}
HipAPIGroup::HipAPIGroup(std::string group_name, std::vector<HipAPI>& hip_apis):
group_name{group_name}, number_of_api_calls{0}, percentage_of_called_apis{0.f},
total_number_of_apis{0}, number_of_test_cases{0}
{
for (auto const& hip_api: hip_apis) {
HipAPIGroup::HipAPIGroup(std::string group_name, std::vector<HipAPI>& hip_apis)
: group_name{group_name},
number_of_api_calls{0},
percentage_of_called_apis{0.f},
total_number_of_apis{0},
number_of_test_cases{0} {
std::vector<TestCaseOccurrence> test_cases;
for (auto const& hip_api : hip_apis) {
if (hip_api.getGroupName() != group_name) {
continue;
}
@@ -46,47 +49,43 @@ HipAPIGroup::HipAPIGroup(std::string group_name, std::vector<HipAPI>& hip_apis):
}
number_of_api_calls += hip_api.getNumberOfCalls();
number_of_test_cases += hip_api.getNumberOfTestCases();
std::vector<TestCaseOccurrence> api_test_cases = hip_api.getTestCases();
test_cases.insert(test_cases.end(), api_test_cases.begin(), api_test_cases.end());
}
std::sort(test_cases.begin(), test_cases.end());
auto last = std::unique(test_cases.begin(), test_cases.end());
test_cases.erase(last, test_cases.end());
number_of_test_cases = test_cases.size();
total_number_of_apis = called_apis.size() + not_called_apis.size() + deprecated_apis.size();
if (not_called_apis.empty()) {
percentage_of_called_apis = 100.f;
} else {
percentage_of_called_apis = 100.f * called_apis.size() / (total_number_of_apis - deprecated_apis.size());
percentage_of_called_apis =
100.f * called_apis.size() / (total_number_of_apis - deprecated_apis.size());
}
}
std::string HipAPIGroup::getName() const {
return group_name;
}
std::string HipAPIGroup::getName() const { return group_name; }
int HipAPIGroup::getTotalNumberOfAPIs() const {
return total_number_of_apis;
}
int HipAPIGroup::getTotalNumberOfAPIs() const { return total_number_of_apis; }
int HipAPIGroup::getTotalNumberOfCalls() const {
return number_of_api_calls;
}
int HipAPIGroup::getTotalNumberOfCalls() const { return number_of_api_calls; }
int HipAPIGroup::getTotalNumberOfTestCases() const {
return number_of_test_cases;
}
int HipAPIGroup::getTotalNumberOfTestCases() const { return number_of_test_cases; }
int HipAPIGroup::getNumberOfCalledAPIs() const {
return called_apis.size();
}
int HipAPIGroup::getNumberOfCalledAPIs() const { return called_apis.size(); }
int HipAPIGroup::getNumberOfNotCalledAPIs() const {
return not_called_apis.size();
}
int HipAPIGroup::getNumberOfNotCalledAPIs() const { return not_called_apis.size(); }
int HipAPIGroup::getNumberOfDeprecatedAPIs() const {
return deprecated_apis.size();
}
int HipAPIGroup::getNumberOfDeprecatedAPIs() const { return deprecated_apis.size(); }
float HipAPIGroup::getPercentageOfCalledAPIs() const {
return percentage_of_called_apis;
float HipAPIGroup::getPercentageOfCalledAPIs() const { return percentage_of_called_apis; }
bool HipAPIGroup::isDeprecated() const {
return (deprecated_apis.size() == total_number_of_apis) ? true : false;
}
std::string HipAPIGroup::getBasicStatsXML() const {
@@ -100,16 +99,18 @@ std::string HipAPIGroup::getBasicStatsXML() const {
xml_node << "\n\t<COVERAGE-RESULTS>";
xml_node << "\n\t\t<TOTAL-NUMBER-OF-APIs>" << total_number_of_apis << "</TOTAL-NUMBER-OF-APIs>";
xml_node << "\n\t\t<TOTAL-NUMBER-OF-API-CALLS>" << number_of_api_calls << "</TOTAL-NUMBER-OF-API-CALLS>";
xml_node << "\n\t\t<TOTAL-NUMBER-OF-API-CALLS>" << number_of_api_calls
<< "</TOTAL-NUMBER-OF-API-CALLS>";
xml_node << "\n\t\t<CALLED-APIs>" << called_apis.size() << "</CALLED-APIs>";
xml_node << "\n\t\t<NOT-CALLED-APIs>" << not_called_apis.size() << "</NOT-CALLED-APIs>";
xml_node << "\n\t\t<DEPRECATED-APIs>" << deprecated_apis.size() << "</DEPRECATED-APIs>";
xml_node << "\n\t\t<COVERAGE-PERCENTAGE>" << percentage_of_called_apis << "%</COVERAGE-PERCENTAGE>";
xml_node << "\n\t\t<COVERAGE-PERCENTAGE>" << percentage_of_called_apis
<< "%</COVERAGE-PERCENTAGE>";
xml_node << "\n\t</COVERAGE-RESULTS>";
if (!called_apis.empty()) {
xml_node << "\n\t<LIST-OF-CALLED-APIs>\n";
for (auto const& hip_api: called_apis) {
for (auto const& hip_api : called_apis) {
xml_node << hip_api.getBasicStatsXML();
}
xml_node << "\t</LIST-OF-CALLED-APIs>";
@@ -117,7 +118,7 @@ std::string HipAPIGroup::getBasicStatsXML() const {
if (!not_called_apis.empty()) {
xml_node << "\n\t<LIST-OF-NOT-CALLED-APIs>\n";
for (auto const& hip_api: not_called_apis) {
for (auto const& hip_api : not_called_apis) {
xml_node << hip_api.getBasicStatsXML();
}
xml_node << "\t</LIST-OF-NOT-CALLED-APIs>";
@@ -125,7 +126,7 @@ std::string HipAPIGroup::getBasicStatsXML() const {
if (!deprecated_apis.empty()) {
xml_node << "\n\t<DEPRECATED-APIs>\n";
for (auto const& hip_api: deprecated_apis) {
for (auto const& hip_api : deprecated_apis) {
xml_node << hip_api.getBasicStatsXML();
}
xml_node << "\t</DEPRECATED-APIs>";
@@ -135,8 +136,7 @@ std::string HipAPIGroup::getBasicStatsXML() const {
return xml_node.str();
}
std::string HipAPIGroup::getBasicStatsHTML() const
{
std::string HipAPIGroup::getBasicStatsHTML() const {
std::stringstream html_object;
std::string two_tabs{"\n\t\t"};
std::string three_tabs{"\n\t\t\t"};
@@ -158,29 +158,42 @@ std::string HipAPIGroup::getBasicStatsHTML() const
color_bar = "resources/emerald.png";
}
if (isDeprecated()) {
font_class = "coverDeprecated";
}
html_object << two_tabs << "<tr>";
html_object << three_tabs << "<td class=\"coverFile\"><a href=\"testModules/" << group_name << ".html\">" << group_name << "</a></td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << total_number_of_apis << "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << number_of_api_calls << "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << number_of_test_cases << "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << called_apis.size() << "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << not_called_apis.size() << "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << deprecated_apis.size() << "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << std::fixed << std::setprecision(2) << percentage_of_called_apis << "%</td>";
html_object << three_tabs << "<td class=\"coverFile\"><a href=\"testModules/" << group_name
<< ".html\">" << group_name << "</a></td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << total_number_of_apis
<< "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << number_of_api_calls
<< "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << number_of_test_cases
<< "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << called_apis.size()
<< "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << not_called_apis.size()
<< "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << deprecated_apis.size()
<< "</td>";
html_object << three_tabs << "<td class=\"" << font_class << "\">" << std::fixed
<< std::setprecision(2) << percentage_of_called_apis << "%</td>";
html_object << three_tabs << "<td class=\"coverBar\" align=\"center\">";
html_object << four_tabs << "<table border=0 cellspacing=0 cellpadding=1>";
html_object << five_tabs << "<tr><td class=\"coverBarOutline\"><img src=\"";
html_object << color_bar << "\" width=" << percentage_of_called_apis<< " height=10 alt=\"" << percentage_of_called_apis << "%\">";
html_object << "<img src=\"resources/snow.png\" width=" << 100.f - percentage_of_called_apis << " height=10 alt=\"" << percentage_of_called_apis << "\"></td></tr></table>";
html_object << color_bar << "\" width=" << percentage_of_called_apis << " height=10 alt=\""
<< percentage_of_called_apis << "%\">";
html_object << "<img src=\"resources/snow.png\" width=" << 100.f - percentage_of_called_apis
<< " height=10 alt=\"" << percentage_of_called_apis << "\"></td></tr></table>";
html_object << four_tabs << "</td>";
html_object << three_tabs << "</tr>";
return html_object.str();
}
std::string HipAPIGroup::createHTMLReport() const
{
std::string HipAPIGroup::createHTMLReport() const {
std::stringstream html_report;
std::string one_tab{"\n\t"};
std::string two_tabs{"\n\t\t"};
@@ -190,14 +203,22 @@ std::string HipAPIGroup::createHTMLReport() const
std::string six_tabs{"\n\t\t\t\t\t\t"};
html_report << "<html lang=\"en\">";
html_report << "<head>" << one_tab << "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">";
html_report << "<head>" << one_tab
<< "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">";
html_report << one_tab << "<title>" << group_name << " Coverage report</title>";
html_report << one_tab << "<link rel=\"stylesheet\" type=\"text/css\" href=\"../resources/coverage.css\">" << one_tab<< "</head>";
html_report << one_tab << "<body>" << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
html_report << two_tabs << "<tr><td class=\"title\">" << group_name << " Coverage report</td></tr>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>\n";
html_report << two_tabs << "<tr>" << three_tabs << "<td width=\"100%\">" << four_tabs << "<table cellpading=1 border=0 width=\"100%\"";
html_report << one_tab
<< "<link rel=\"stylesheet\" type=\"text/css\" href=\"../resources/coverage.css\">"
<< one_tab << "</head>";
html_report << one_tab << "<body>" << one_tab
<< "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
html_report << two_tabs << "<tr><td class=\"title\">" << group_name
<< " Coverage report</td></tr>";
html_report << two_tabs
<< "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 "
"height=3></td></tr>\n";
html_report << two_tabs << "<tr>" << three_tabs << "<td width=\"100%\">" << four_tabs
<< "<table cellpading=1 border=0 width=\"100%\"";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td width=\"70%\"></td>";
html_report << six_tabs << "<td width=\"10%\" class=\"headerCovTableHead\">Value</td>";
@@ -206,37 +227,44 @@ std::string HipAPIGroup::createHTMLReport() const
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">Total number of detected HIP APIs:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << total_number_of_apis << "</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << total_number_of_apis
<< "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">HIP API calls within test source files:</td>";
html_report << six_tabs
<< "<td class=\"headerItem\">HIP API calls within test source files:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << number_of_api_calls << "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">Total number of test cases:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << number_of_test_cases << "</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << number_of_test_cases
<< "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">HIP APIs that are called at least once:</td>";
html_report << six_tabs
<< "<td class=\"headerItem\">HIP APIs that are called at least once:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << called_apis.size() << "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">HIP APIs that are not called at all:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << not_called_apis.size() << "</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << not_called_apis.size()
<< "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">HIP APIs that are marked as deprecated:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << deprecated_apis.size() << "</td>";
html_report << six_tabs
<< "<td class=\"headerItem\">HIP APIs that are marked as deprecated:</td>";
html_report << six_tabs << "<td class=\"headerCovTableEntry\">" << deprecated_apis.size()
<< "</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
@@ -251,17 +279,23 @@ std::string HipAPIGroup::createHTMLReport() const
}
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"headerItem\">Test coverage by implemented tests for the HIP APIs:</td>";
html_report << six_tabs << "<td class=\"" << font_class << "\">" << std::fixed << std::setprecision(2) << percentage_of_called_apis << "%</td>";
html_report
<< six_tabs
<< "<td class=\"headerItem\">Test coverage by implemented tests for the HIP APIs:</td>";
html_report << six_tabs << "<td class=\"" << font_class << "\">" << std::fixed
<< std::setprecision(2) << percentage_of_called_apis << "%</td>";
html_report << six_tabs << "<td></td>";
html_report << five_tabs << "</tr>";
html_report << five_tabs << "<tr><td><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
html_report << five_tabs
<< "<tr><td><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
html_report << four_tabs << "</table>";
html_report << three_tabs << "</td>";
html_report << two_tabs << "</tr>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>\n";
html_report << two_tabs
<< "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 "
"height=3></td></tr>\n";
html_report << one_tab << "</table>";
// Add info about Test module APIs.
@@ -279,9 +313,10 @@ std::string HipAPIGroup::createHTMLReport() const
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"tableHead\">Called APIs</td>";
html_report << five_tabs << "</tr>";
for (auto const& hip_api: called_apis) {
for (auto const& hip_api : called_apis) {
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"coverFile\"><a href=\"../testAPIs/" << hip_api.getName() << ".html\">" << hip_api.getName() << "</a></td>";
html_report << six_tabs << "<td class=\"coverFile\"><a href=\"../testAPIs/" << hip_api.getName()
<< ".html\">" << hip_api.getName() << "</a></td>";
html_report << five_tabs << "</tr>";
}
@@ -293,9 +328,10 @@ std::string HipAPIGroup::createHTMLReport() const
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"tableHead\">Not called APIs</td>";
html_report << five_tabs << "</tr>";
for (auto const& hip_api: not_called_apis) {
for (auto const& hip_api : not_called_apis) {
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"coverFile\"><a href=\"../testAPIs/" << hip_api.getName() << ".html\">" << hip_api.getName() << "</a></td>";
html_report << six_tabs << "<td class=\"coverFile\"><a href=\"../testAPIs/" << hip_api.getName()
<< ".html\">" << hip_api.getName() << "</a></td>";
html_report << five_tabs << "</tr>";
}
html_report << four_tabs << "</table>";
@@ -306,9 +342,10 @@ std::string HipAPIGroup::createHTMLReport() const
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"tableHead\">Deprecated APIs</td>";
html_report << five_tabs << "</tr>";
for (auto const& hip_api: deprecated_apis) {
for (auto const& hip_api : deprecated_apis) {
html_report << five_tabs << "<tr>";
html_report << six_tabs << "<td class=\"coverFile\"><a href=\"../testAPIs/" << hip_api.getName() << ".html\">" << hip_api.getName() << "</a></td>";
html_report << six_tabs << "<td class=\"coverFile\"><a href=\"../testAPIs/" << hip_api.getName()
<< ".html\">" << hip_api.getName() << "</a></td>";
html_report << five_tabs << "</tr>";
}
html_report << four_tabs << "</table>";
@@ -321,7 +358,9 @@ std::string HipAPIGroup::createHTMLReport() const
html_report << one_tab << "<br>";
html_report << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
html_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
html_report
<< two_tabs
<< "<tr><td class=\"ruler\"><img src=\"../resources/glass.png\" width=3 height=3></td></tr>";
time_t now{time(nullptr)};
std::string date{asctime(gmtime(&now))};
+3 -2
Просмотреть файл
@@ -21,10 +21,9 @@ THE SOFTWARE.
*/
#include "hipAPI.h"
#include <algorithm>
#include <iomanip>
class HipAPIGroup{
class HipAPIGroup {
friend bool operator==(const HipAPIGroup& l_hip_api_group, const HipAPIGroup& r_hip_api_group);
public:
@@ -40,6 +39,8 @@ class HipAPIGroup{
std::string getBasicStatsXML() const;
std::string getBasicStatsHTML() const;
std::string createHTMLReport() const;
bool isDeprecated() const;
private:
std::string group_name;
int total_number_of_apis;
+24 -11
Просмотреть файл
@@ -22,10 +22,11 @@ THE SOFTWARE.
#include "reportGenerators.h"
int main(int argc, char** argv)
{
int main(int argc, char** argv) {
if (argc != 2) {
std::cout << "Please provide the path to the cloned HIP/include/ directory as an argument! Only one argument supported." << std::endl;
std::cout << "Please provide the path to the cloned HIP/include/ directory as an argument! "
"Only one argument supported."
<< std::endl;
std::cout << "\tExample: ./generateHipAPICoverage /workspace/user1/HIP/include/" << std::endl;
return -1;
}
@@ -34,33 +35,44 @@ int main(int argc, char** argv)
Relative paths to all needed files, as it is expected that the application
is called from the HIP/tests/catch/coverage directory.
*/
std::string hip_api_header_file{findAbsolutePathOfFile(hip_include_path + "/hip/hip_runtime_api.h")};
std::string hip_api_header_file{
findAbsolutePathOfFile(hip_include_path + "/hip/hip_runtime_api.h")};
std::string hip_rtc_header_file{findAbsolutePathOfFile(hip_include_path + "/hip/hiprtc.h")};
std::string tests_root_directory{findAbsolutePathOfFile("../../catch")};
std::string device_api_file{"device_api_list.txt"};
std::vector<std::string> api_group_names;
// Extract all HIP API declarations from the HIP API header file.
std::vector<HipAPI> hip_apis{extractHipAPIs(hip_api_header_file, api_group_names, false)};
std::cout << "Number of detected HIP APIs from " << hip_api_header_file << ": " << hip_apis.size() << std::endl;
std::cout << "Number of detected HIP APIs from " << hip_api_header_file << ": " << hip_apis.size()
<< std::endl;
std::vector<HipAPI> hip_rtc_apis{extractHipAPIs(hip_rtc_header_file, api_group_names, true)};
std::cout << "Number of detected HIP APIs from " << hip_rtc_header_file << ": " << hip_rtc_apis.size() << std::endl;
std::cout << "Number of detected HIP APIs from " << hip_rtc_header_file << ": "
<< hip_rtc_apis.size() << std::endl;
hip_apis.insert(hip_apis.end(), hip_rtc_apis.begin(), hip_rtc_apis.end());
std::vector<HipAPI> device_apis{extractDeviceAPIs(device_api_file, api_group_names)};
std::cout << "Number of detected device APIs from " << device_api_file << ": "
<< device_apis.size() << std::endl;
hip_apis.insert(hip_apis.end(), device_apis.begin(), device_apis.end());
// Extract all test module .cc files that shall be used for API searching.
std::cout << "Searching for HIP API calls in source files within " << tests_root_directory << "." << std::endl;
std::cout << "Searching for HIP API calls in source files within " << tests_root_directory << "."
<< std::endl;
std::vector<std::string> test_module_files{extractTestModuleFiles(tests_root_directory)};
// Search for each HIP API in the extracted test .cc files.
for(HipAPI& hip_api: hip_apis) {
for (HipAPI& hip_api : hip_apis) {
searchForAPI(hip_api, test_module_files);
}
std::vector<HipAPIGroup> hip_api_groups;
for (auto const& api_group_name: api_group_names) {
for (auto const& api_group_name : api_group_names) {
HipAPIGroup hip_api_group{api_group_name, hip_apis};
// Avoid having duplicated groups.
if (std::find(hip_api_groups.begin(), hip_api_groups.end(), hip_api_group) == hip_api_groups.end()) {
if (std::find(hip_api_groups.begin(), hip_api_groups.end(), hip_api_group) ==
hip_api_groups.end()) {
hip_api_groups.push_back(hip_api_group);
}
}
@@ -68,7 +80,8 @@ int main(int argc, char** argv)
std::cout << "Generating XML report files." << std::endl;
generateXMLReportFiles(hip_apis, hip_api_groups);
std::cout << "Generating HTML report files." << std::endl;
generateHTMLReportFiles(hip_apis, hip_api_groups, tests_root_directory, hip_api_header_file, hip_rtc_header_file);
generateHTMLReportFiles(hip_apis, hip_api_groups, tests_root_directory, hip_api_header_file,
hip_rtc_header_file);
return 0;
}
+183 -78
Просмотреть файл
@@ -22,38 +22,43 @@ THE SOFTWARE.
#include "reportGenerators.h"
BasicAPIStats::BasicAPIStats(std::vector<HipAPIGroup>& hip_api_groups):
number_of_called_apis{0}, number_of_not_called_apis{0},
number_of_deprecated_apis{0}, total_number_of_api_calls{0},
total_number_of_test_cases{0}
{
for (auto const& hip_api_group: hip_api_groups) {
BasicAPIStats::BasicAPIStats(std::vector<HipAPIGroup>& hip_api_groups)
: number_of_called_apis{0},
number_of_not_called_apis{0},
number_of_deprecated_apis{0},
total_number_of_api_calls{0},
total_number_of_test_cases{0} {
for (auto const& hip_api_group : hip_api_groups) {
number_of_called_apis += hip_api_group.getNumberOfCalledAPIs();
number_of_not_called_apis += hip_api_group.getNumberOfNotCalledAPIs();
number_of_deprecated_apis += hip_api_group.getNumberOfDeprecatedAPIs();
total_number_of_api_calls += hip_api_group.getTotalNumberOfCalls();
total_number_of_test_cases += hip_api_group.getTotalNumberOfTestCases();
}
total_number_of_apis = number_of_called_apis + number_of_not_called_apis + number_of_deprecated_apis;
tests_coverage_percentage = 100.f * number_of_called_apis / (number_of_called_apis + number_of_not_called_apis);
total_number_of_apis =
number_of_called_apis + number_of_not_called_apis + number_of_deprecated_apis;
tests_coverage_percentage =
100.f * number_of_called_apis / (number_of_called_apis + number_of_not_called_apis);
}
float BasicAPIStats::getLowCoverageLimit() const {
return 40.f;
}
float BasicAPIStats::getLowCoverageLimit() const { return 40.f; }
float BasicAPIStats::getMediumCoverageLimit() const {
return 80.f;
}
float BasicAPIStats::getMediumCoverageLimit() const { return 80.f; }
void generateXMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGroup>& hip_api_groups) {
void generateXMLReportFiles(std::vector<HipAPI>& hip_apis,
std::vector<HipAPIGroup>& hip_api_groups) {
BasicAPIStats basic_stats{hip_api_groups};
std::cout << "Total number of HIP API calls: " << basic_stats.total_number_of_api_calls << std::endl;
std::cout << "Number of the HIP APIs that are called at least once: " << basic_stats.number_of_called_apis << std::endl;
std::cout << "Number of the HIP APIs that are not called at all: " << basic_stats.number_of_not_called_apis << std::endl;
std::cout << "Number of the HIP APIs that are marked as deprecated: " << basic_stats.number_of_deprecated_apis << std::endl;
std::cout << "Test coverage by implemented tests, for the HIP APIs that are not marked as deprecated: ";
std::cout << "Total number of HIP API calls: " << basic_stats.total_number_of_api_calls
<< std::endl;
std::cout << "Number of the HIP APIs that are called at least once: "
<< basic_stats.number_of_called_apis << std::endl;
std::cout << "Number of the HIP APIs that are not called at all: "
<< basic_stats.number_of_not_called_apis << std::endl;
std::cout << "Number of the HIP APIs that are marked as deprecated: "
<< basic_stats.number_of_deprecated_apis << std::endl;
std::cout
<< "Test coverage by implemented tests, for the HIP APIs that are not marked as deprecated: ";
std::cout << basic_stats.tests_coverage_percentage << "%" << std::endl;
/*
@@ -71,36 +76,51 @@ void generateXMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGro
coverage_report << "<COVERAGE-RESULTS>\n";
coverage_report << "\t<TOTAL-NUMBER-OF-APIs>\n\t\t<DESCRIPTION>Total number of detected HIP APIs.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << hip_apis.size() << "</NUMBER>\n\t</TOTAL-NUMBER-OF-APIs>\n";
coverage_report << "\t<TOTAL-NUMBER-OF-APIs>\n\t\t<DESCRIPTION>Total number of detected HIP "
"APIs.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << hip_apis.size()
<< "</NUMBER>\n\t</TOTAL-NUMBER-OF-APIs>\n";
coverage_report << "\t<TOTAL-NUMBER-OF-API-CALLS>\n\t\t<DESCRIPTION>Total number of HIP API calls within test source files.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << basic_stats.total_number_of_api_calls << "</NUMBER>\n\t</TOTAL-NUMBER-OF-API-CALLS>\n";
coverage_report << "\t<TOTAL-NUMBER-OF-API-CALLS>\n\t\t<DESCRIPTION>Total number of HIP API "
"calls within test source files.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << basic_stats.total_number_of_api_calls
<< "</NUMBER>\n\t</TOTAL-NUMBER-OF-API-CALLS>\n";
coverage_report << "\t<CALLED-APIs>\n\t\t<DESCRIPTION>Number of the HIP APIs that are called at least once.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << basic_stats.number_of_called_apis << "</NUMBER>\n\t</CALLED-APIs>\n";
coverage_report << "\t<CALLED-APIs>\n\t\t<DESCRIPTION>Number of the HIP APIs that are called at "
"least once.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << basic_stats.number_of_called_apis
<< "</NUMBER>\n\t</CALLED-APIs>\n";
coverage_report << "\t<NOT-CALLED-APIs>\n\t\t<DESCRIPTION>Number of the HIP APIs that are not called at all.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << basic_stats.number_of_not_called_apis << "</NUMBER>\n\t</NOT-CALLED-APIs>\n";
coverage_report << "\t<NOT-CALLED-APIs>\n\t\t<DESCRIPTION>Number of the HIP APIs that are not "
"called at all.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << basic_stats.number_of_not_called_apis
<< "</NUMBER>\n\t</NOT-CALLED-APIs>\n";
coverage_report << "\t<DEPRECATED-APIs>\n\t\t<DESCRIPTION>Number of the HIP APIs that are marked as deprecated.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << basic_stats.number_of_deprecated_apis << "</NUMBER>\n\t</DEPRECATED-APIs>\n";
coverage_report << "\t<DEPRECATED-APIs>\n\t\t<DESCRIPTION>Number of the HIP APIs that are marked "
"as deprecated.</DESCRIPTION>";
coverage_report << "\n\t\t<NUMBER>" << basic_stats.number_of_deprecated_apis
<< "</NUMBER>\n\t</DEPRECATED-APIs>\n";
coverage_report << "\t<COVERAGE-PERCENTAGE>\n\t\t<DESCRIPTION>Test coverage by implemented tests for the HIP APIs that are not marked as deprecated.</DESCRIPTION>";
coverage_report << "\n\t\t<VALUE>" << basic_stats.tests_coverage_percentage << "%</VALUE>\n\t</COVERAGE-PERCENTAGE>";
coverage_report << "\t<COVERAGE-PERCENTAGE>\n\t\t<DESCRIPTION>Test coverage by implemented tests "
"for the HIP APIs that are not marked as deprecated.</DESCRIPTION>";
coverage_report << "\n\t\t<VALUE>" << basic_stats.tests_coverage_percentage
<< "%</VALUE>\n\t</COVERAGE-PERCENTAGE>";
coverage_report << "\n</COVERAGE-RESULTS>";
for (auto const& hip_api_group: hip_api_groups) {
coverage_report << hip_api_group.getBasicStatsHTML();
for (auto const& hip_api_group : hip_api_groups) {
coverage_report << hip_api_group.getBasicStatsHTML();
}
coverage_report.close();
std::cout << "Generated XML report file " << findAbsolutePathOfFile(report_file_name) << std::endl;
std::cout << "Generated XML report file " << findAbsolutePathOfFile(report_file_name)
<< std::endl;
}
void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGroup>& hip_api_groups,
std::string tests_root_directory, std::string hipApiHeaderFile, std::string hip_rtc_header_file) {
void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis,
std::vector<HipAPIGroup>& hip_api_groups,
std::string tests_root_directory, std::string hipApiHeaderFile,
std::string hip_rtc_header_file) {
BasicAPIStats basic_stats{hip_api_groups};
std::fstream coverage_report;
@@ -130,17 +150,26 @@ void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGr
source, as it is much more clear.
*/
coverage_report << "<html lang=\"en\">";
coverage_report << "<head>" << one_tab << "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">";
coverage_report << "<head>" << one_tab
<< "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">";
coverage_report << one_tab << "<title>HIP API Coverage report</title>";
coverage_report << one_tab << "<link rel=\"stylesheet\" type=\"text/css\" href=\"resources/coverage.css\">" << one_tab << "</head>";
coverage_report << one_tab << "<body>" << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
coverage_report << one_tab
<< "<link rel=\"stylesheet\" type=\"text/css\" href=\"resources/coverage.css\">"
<< one_tab << "</head>";
coverage_report << one_tab << "<body>" << one_tab
<< "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
coverage_report << two_tabs << "<tr><td class=\"title\">HIP API Coverage report</td></tr>";
coverage_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"resources/glass.png\" width=3 height=3></td></tr>\n";
coverage_report << two_tabs << "<tr>" << three_tabs << "<td width=\"100%\">" << four_tabs << "<table cellpading=1 border=0 width=\"100%\"";
coverage_report
<< two_tabs
<< "<tr><td class=\"ruler\"><img src=\"resources/glass.png\" width=3 height=3></td></tr>\n";
coverage_report << two_tabs << "<tr>" << three_tabs << "<td width=\"100%\">" << four_tabs
<< "<table cellpading=1 border=0 width=\"100%\"";
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td width=\"20%\" class=\"headerItem\">Catch2 tests location:</td>";
coverage_report << six_tabs << "<td width=\"30%\" class=\"headerValue\">" << tests_root_directory << "</td>";
coverage_report << six_tabs
<< "<td width=\"20%\" class=\"headerItem\">Catch2 tests location:</td>";
coverage_report << six_tabs << "<td width=\"30%\" class=\"headerValue\">" << tests_root_directory
<< "</td>";
coverage_report << six_tabs << "<td width=\"20%\"></td>";
coverage_report << six_tabs << "<td width=\"10%\" class=\"headerCovTableHead\">Value</td>";
coverage_report << six_tabs << "<td width=\"20%\"></td>";
@@ -150,15 +179,18 @@ void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGr
coverage_report << six_tabs << "<td class=\"headerItem\">Source files included:</td>";
coverage_report << six_tabs << "<td class=\"headerValue\">" << hipApiHeaderFile << "</td>";
coverage_report << six_tabs << "<td class=\"headerItem\">Total number of detected HIP APIs:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.total_number_of_apis << "</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">"
<< basic_stats.total_number_of_apis << "</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td class=\"headerValue\">" << hip_rtc_header_file << "</td>";
coverage_report << six_tabs << "<td class=\"headerItem\">HIP API calls within test source files:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.total_number_of_api_calls << "</td>";
coverage_report << six_tabs
<< "<td class=\"headerItem\">HIP API calls within test source files:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">"
<< basic_stats.total_number_of_api_calls << "</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
@@ -166,31 +198,38 @@ void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGr
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td class=\"headerItem\">Total number of test cases:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.total_number_of_test_cases << "</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">"
<< basic_stats.total_number_of_test_cases << "</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td class=\"headerItem\">HIP APIs that are called at least once:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.number_of_called_apis << "</td>";
coverage_report << six_tabs
<< "<td class=\"headerItem\">HIP APIs that are called at least once:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">"
<< basic_stats.number_of_called_apis << "</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td class=\"headerItem\">HIP APIs that are not called at all:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.number_of_not_called_apis << "</td>";
coverage_report << six_tabs
<< "<td class=\"headerItem\">HIP APIs that are not called at all:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">"
<< basic_stats.number_of_not_called_apis << "</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td class=\"headerItem\">HIP APIs that are marked as deprecated:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.number_of_deprecated_apis << "</td>";
coverage_report << six_tabs
<< "<td class=\"headerItem\">HIP APIs that are marked as deprecated:</td>";
coverage_report << six_tabs << "<td class=\"headerCovTableEntry\">"
<< basic_stats.number_of_deprecated_apis << "</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
@@ -198,29 +237,32 @@ void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGr
std::string font_class;
if (basic_stats.tests_coverage_percentage < basic_stats.getLowCoverageLimit()) {
font_class = "headerCovTableEntryLo";
}
else if (basic_stats.tests_coverage_percentage < basic_stats.getMediumCoverageLimit()) {
} else if (basic_stats.tests_coverage_percentage < basic_stats.getMediumCoverageLimit()) {
font_class = "headerCovTableEntryMed";
}
else {
} else {
font_class = "headerCovTableEntryHi";
}
coverage_report << five_tabs << "<tr>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << six_tabs << "<td class=\"headerItem\">Test coverage by implemented tests for the HIP APIs:</td>";
coverage_report << six_tabs << "<td class=\""<< font_class << "\">" <<
std::fixed << std::setprecision(2) << basic_stats.tests_coverage_percentage << "%</td>";
coverage_report
<< six_tabs
<< "<td class=\"headerItem\">Test coverage by implemented tests for the HIP APIs:</td>";
coverage_report << six_tabs << "<td class=\"" << font_class << "\">" << std::fixed
<< std::setprecision(2) << basic_stats.tests_coverage_percentage << "%</td>";
coverage_report << six_tabs << "<td></td>";
coverage_report << five_tabs << "</tr>";
coverage_report << five_tabs << "<tr><td><img src=\"resources/glass.png\" width=3 height=3></td></tr>";
coverage_report << five_tabs
<< "<tr><td><img src=\"resources/glass.png\" width=3 height=3></td></tr>";
coverage_report << four_tabs << "</table>";
coverage_report << three_tabs << "</td>";
coverage_report << two_tabs << "</tr>";
coverage_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"resources/glass.png\" width=3 height=3></td></tr>\n";
coverage_report
<< two_tabs
<< "<tr><td class=\"ruler\"><img src=\"resources/glass.png\" width=3 height=3></td></tr>\n";
coverage_report << one_tab << "</table>";
// Add info about HIP API Groups.
@@ -254,11 +296,17 @@ void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGr
Create an HTML page for each API Group for more detailed information, as they are
used as hyperlinks from the main HTML page.
*/
for (auto const& hip_api_group: hip_api_groups) {
for (auto const& hip_api_group : hip_api_groups) {
if (hip_api_group.getTotalNumberOfAPIs() == 0) {
std::cout << "[SKIP_FROM_COV] Couldn't detect any valid HIP API within module "
<< hip_api_group.getName() << " hence skipping its HTML generation" << std::endl;
continue;
}
coverage_report << hip_api_group.getBasicStatsHTML();
std::fstream coverage_module_report;
std::string report_module_file_name{test_modules_directory + "/" + hip_api_group.getName() + ".html"};
std::string report_module_file_name{test_modules_directory + "/" + hip_api_group.getName() +
".html"};
coverage_module_report.open(report_module_file_name, std::ios::out);
coverage_module_report << hip_api_group.createHTMLReport();
coverage_module_report.close();
@@ -266,14 +314,20 @@ void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGr
coverage_report << two_tabs << "<tr>";
coverage_report << three_tabs << "<td></td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.total_number_of_apis << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.total_number_of_api_calls << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.total_number_of_test_cases << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.number_of_called_apis << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.number_of_not_called_apis << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << basic_stats.number_of_deprecated_apis << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" <<
std::fixed << std::setprecision(2) << basic_stats.tests_coverage_percentage << "%</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">"
<< basic_stats.total_number_of_apis << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">"
<< basic_stats.total_number_of_api_calls << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">"
<< basic_stats.total_number_of_test_cases << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">"
<< basic_stats.number_of_called_apis << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">"
<< basic_stats.number_of_not_called_apis << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">"
<< basic_stats.number_of_deprecated_apis << "</td>";
coverage_report << three_tabs << "<td class=\"headerCovTableEntry\">" << std::fixed
<< std::setprecision(2) << basic_stats.tests_coverage_percentage << "%</td>";
coverage_report << three_tabs << "<td></td>";
coverage_report << two_tabs << "</tr>";
@@ -282,7 +336,57 @@ void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGr
coverage_report << one_tab << "<br>";
coverage_report << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
coverage_report << two_tabs << "<tr><td class=\"ruler\"><img src=\"resources/glass.png\" width=3 height=3></td></tr>";
coverage_report
<< two_tabs
<< "<tr><td class=\"ruler\"><img src=\"resources/glass.png\" width=3 height=3></td></tr>";
coverage_report << one_tab << "</table>";
coverage_report << one_tab << "<br>";
coverage_report << one_tab << "<center>";
coverage_report << one_tab << "<table width=\"30%\" cellpadding=1 cellspacing=1 border=0>";
coverage_report << two_tabs << "<tr>";
coverage_report << three_tabs << "<td width=\"3%\"></td>";
coverage_report << three_tabs << "<td width=\"97%\"></td>";
coverage_report << two_tabs << "</tr>";
coverage_report << two_tabs << "<tr>";
coverage_report << three_tabs << "<td class=\"tableHead\" colspan=2>Color legend</td>";
coverage_report << two_tabs << "</tr>";
coverage_report << two_tabs << "<tr>";
coverage_report << three_tabs << "<td class=\"coverDeprecated\"></td>";
coverage_report << three_tabs << "<td class=\"coverFile\">Module is deprecated</td>";
coverage_report << two_tabs << "</tr>";
coverage_report << two_tabs << "<tr>";
coverage_report << three_tabs << "<td class=\"coverNumLo\"></td>";
coverage_report
<< three_tabs
<< "<td class=\"coverFile\">Percentage of called APIs within a module is less than 40%</td>";
coverage_report << two_tabs << "</tr>";
coverage_report << two_tabs << "<tr>";
coverage_report << three_tabs << "<td class=\"coverNumMed\"></td>";
coverage_report << three_tabs
<< "<td class=\"coverFile\">Percentage of called APIs within a module is between "
"40% and 80%</td>";
coverage_report << two_tabs << "</tr>";
coverage_report << two_tabs << "<tr>";
coverage_report << three_tabs << "<td class=\"coverNumHi\"></td>";
coverage_report << three_tabs
<< "<td class=\"coverFile\">Percentage of called APIs within a module is larger "
"than 80%</td>";
coverage_report << two_tabs << "</tr>";
coverage_report << one_tab << "</table>";
coverage_report << one_tab << "</center>";
coverage_report << one_tab << "<br>";
coverage_report << one_tab << "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
coverage_report
<< two_tabs
<< "<tr><td class=\"ruler\"><img src=\"resources/glass.png\" width=3 height=3></td></tr>";
time_t now{time(nullptr)};
std::string date{asctime(gmtime(&now))};
@@ -295,7 +399,7 @@ void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGr
coverage_report.close();
// Create HTML report for each API, as they are used as hyperlinks from Groups HTML.
for (auto const& hip_api: hip_apis) {
for (auto const& hip_api : hip_apis) {
std::fstream coverage_api_report;
std::string report_api_file_name{test_apis_directory + "/" + hip_api.getName() + ".html"};
coverage_api_report.open(report_api_file_name, std::ios::out);
@@ -303,5 +407,6 @@ void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGr
coverage_api_report.close();
}
std::cout << "Generated HTML report file " << findAbsolutePathOfFile(report_file_name) << std::endl;
std::cout << "Generated HTML report file " << findAbsolutePathOfFile(report_file_name)
<< std::endl;
}
+6 -3
Просмотреть файл
@@ -36,6 +36,9 @@ class BasicAPIStats {
float getMediumCoverageLimit() const;
};
void generateXMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGroup>& hip_api_groups);
void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis, std::vector<HipAPIGroup>& hip_api_groups,
std::string tests_root_directory, std::string hipApiHeaderFile, std::string hip_rtc_header_file);
void generateXMLReportFiles(std::vector<HipAPI>& hip_apis,
std::vector<HipAPIGroup>& hip_api_groups);
void generateHTMLReportFiles(std::vector<HipAPI>& hip_apis,
std::vector<HipAPIGroup>& hip_api_groups,
std::string tests_root_directory, std::string hipApiHeaderFile,
std::string hip_rtc_header_file);