From 1a4276bfedfa1eb1d533e919eeaa569a7fbba6d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mirza=20Halil=C4=8Devi=C4=87?= <109971222+mirza-halilcevic@users.noreply.github.com> Date: Wed, 28 Jun 2023 06:04:52 +0200 Subject: [PATCH 01/32] EXSWHTEC-191 - Implement additional tests for Host Graph Node APIs (#9) - Tidy up hipGraphAddHostNode tests - Tidy up hipGraphHostNodeGetParams tests - Tidy up hipGraphHostNodeSetParams tests - Tidy up hipGraphExecHostNodeSetParams tests. - Disable failing test sections on AMD. [ROCm/hip-tests commit: 9f5bb4219ac7c07b6b97da78dd34d7b4804344d0] --- .../catch/unit/graph/hipGraphAddHostNode.cc | 208 ++++++------- .../graph/hipGraphExecHostNodeSetParams.cc | 284 +++++++++--------- .../unit/graph/hipGraphHostNodeGetParams.cc | 166 +++++----- .../unit/graph/hipGraphHostNodeSetParams.cc | 126 ++++---- 4 files changed, 365 insertions(+), 419 deletions(-) diff --git a/projects/hip-tests/catch/unit/graph/hipGraphAddHostNode.cc b/projects/hip-tests/catch/unit/graph/hipGraphAddHostNode.cc index 9da6e3b223..971ac187cb 100644 --- a/projects/hip-tests/catch/unit/graph/hipGraphAddHostNode.cc +++ b/projects/hip-tests/catch/unit/graph/hipGraphAddHostNode.cc @@ -6,23 +6,25 @@ 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 + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY 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 +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 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 +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. */ /** -Testcase Scenarios of hipGraphAddHostNode API: +Test Case Scenarios of hipGraphAddHostNode API: Functional: 1. Creates graph, Adds HostNode which updates the variable and validates the result -2. Create graph, Add Graphnodes and clones the graph. Add Hostnode to the cloned graph +2. Create graph, Add Graph nodes and clones the graph. Add Host node to the cloned graph and validate the result 3. Creates graph which performs the square of number in the kernel function and the result is validated in the callback function of hipGraphAddHostNode API @@ -35,22 +37,22 @@ Negative: 4) Pass hipHostNodeParams::hipHostFn_t as nullptr and verify api doesn't crash, returns error code. */ -#include #include +#include #define SIZE 1024 -static int *B_h; -static int *D_h; +static int* B_h; +static int* D_h; -static void callbackfunc(void *A_h) { - int *A = reinterpret_cast(A_h); +static void callbackfunc(void* A_h) { + int* A = reinterpret_cast(A_h); for (int i = 0; i < SIZE; i++) { A[i] = i; } } -static void __global__ vector_square(int *B_d, int *D_d) { +static void __global__ vector_square(int* B_d, int* D_d) { for (int i = 0; i < SIZE; i++) { D_d[i] = B_d[i] * B_d[i]; } @@ -60,7 +62,7 @@ static void vectorsquare_callback(void* ptr) { // of type void (*)(void*). This test is designed to // work with global variables, hence the workaround to // print this *ptr value to avoid type mismatch errors. - int *A = reinterpret_cast(ptr); + int* A = reinterpret_cast(ptr); for (int i = 0; i < SIZE; i++) { if (D_h[i] != B_h[i] * B_h[i]) { @@ -70,8 +72,9 @@ static void vectorsquare_callback(void* ptr) { } } } + /* -This testcase verifies the negative scenarios of +This test case verifies the negative scenarios of hipGraphAddHostNode API */ TEST_CASE("Unit_hipGraphAddHostNode_Negative") { @@ -79,101 +82,96 @@ TEST_CASE("Unit_hipGraphAddHostNode_Negative") { hipGraph_t graph; int *A_d{nullptr}, *C_d{nullptr}; int *A_h{nullptr}, *C_h{nullptr}; - HipTest::initArrays(&A_d, nullptr, &C_d, - &A_h, nullptr, &C_h, N, false); + HipTest::initArrays(&A_d, nullptr, &C_d, &A_h, nullptr, &C_h, N, false); HIP_CHECK(hipGraphCreate(&graph, 0)); hipGraphNode_t hostNode; hipHostNodeParams hostParams = {0, 0}; + std::vector dependencies; hostParams.fn = callbackfunc; hostParams.userData = A_h; SECTION("Passing nullptr to graph node") { - REQUIRE(hipGraphAddHostNode(nullptr, graph, - nullptr, - 0, &hostParams) == hipErrorInvalidValue); + HIP_CHECK_ERROR(hipGraphAddHostNode(nullptr, graph, nullptr, 0, &hostParams), + hipErrorInvalidValue); } SECTION("Passing nullptr to graph") { - REQUIRE(hipGraphAddHostNode(&hostNode, nullptr, - nullptr, - 0, &hostParams) == hipErrorInvalidValue); + HIP_CHECK_ERROR(hipGraphAddHostNode(&hostNode, nullptr, nullptr, 0, &hostParams), + hipErrorInvalidValue); } -#if HT_NVIDIA - SECTION("Passing nullptr to host params") { - REQUIRE(hipGraphAddHostNode(&hostNode, graph, - nullptr, - 0, nullptr) == hipErrorInvalidValue); + SECTION("Pass invalid numDependencies") { + HIP_CHECK_ERROR(hipGraphAddHostNode(&hostNode, graph, nullptr, 11, &hostParams), + hipErrorInvalidValue); + } + + SECTION("Pass invalid numDependencies and valid list for dependencies") { + HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, nullptr, 0, &hostParams)); + dependencies.push_back(hostNode); + HIP_CHECK_ERROR(hipGraphAddHostNode(&hostNode, graph, dependencies.data(), + dependencies.size() + 1, &hostParams), + hipErrorInvalidValue); + } + + SECTION("Passing nullptr to host params") { + HIP_CHECK_ERROR(hipGraphAddHostNode(&hostNode, graph, nullptr, 0, nullptr), + hipErrorInvalidValue); } -#endif SECTION("Passing nullptr to host func") { hostParams.fn = nullptr; - REQUIRE(hipGraphAddHostNode(&hostNode, graph, - nullptr, - 0, &hostParams) == hipErrorInvalidValue); + HIP_CHECK_ERROR(hipGraphAddHostNode(&hostNode, graph, nullptr, 0, &hostParams), + hipErrorInvalidValue); } + HipTest::freeArrays(A_d, nullptr, C_d, A_h, nullptr, C_h, false); HIP_CHECK(hipGraphDestroy(graph)); } + /* -This testcase verifies hipGraphAddHostNode API in cloned graph +This test case verifies hipGraphAddHostNode API in cloned graph Creates graph, Add graph nodes and clone the graph Add HostNode to the cloned graph and validate the result */ -TEST_CASE("Unit_hipGraphAddHostNode_ClonedGraphwithHostNode") { +TEST_CASE("Unit_hipGraphAddHostNode_ClonedGraphWithHostNode") { constexpr size_t N = 1024; constexpr size_t Nbytes = N * sizeof(int); hipGraph_t graph; hipGraphExec_t graphExec; int *A_d{nullptr}, *C_d{nullptr}; int *A_h{nullptr}, *C_h{nullptr}; - HipTest::initArrays(&A_d, nullptr, &C_d, - &A_h, nullptr, &C_h, N, false); + HipTest::initArrays(&A_d, nullptr, &C_d, &A_h, nullptr, &C_h, N, false); HIP_CHECK(hipGraphCreate(&graph, 0)); - hipGraphNode_t memcpyH2D_A, memcpyH2D_C, - memcpyD2H_AC; - hipGraphNode_t cloned_memcpyH2D_A, cloned_memcpyH2D_C, - cloned_memcpyD2H_AC; + hipGraphNode_t memcpyH2D_A, memcpyH2D_C, memcpyD2H_AC; + hipGraphNode_t cloned_memcpyH2D_A, cloned_memcpyH2D_C, cloned_memcpyD2H_AC; hipStream_t streamForGraph; HIP_CHECK(hipStreamCreate(&streamForGraph)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, - 0, A_d, A_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, - 0, C_d, C_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, - 0, A_h, C_d, - Nbytes, hipMemcpyDeviceToHost)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, 0, A_d, A_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, 0, C_d, C_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, 0, A_h, C_d, Nbytes, + hipMemcpyDeviceToHost)); hipGraph_t clonedgraph; HIP_CHECK(hipGraphClone(&clonedgraph, graph)); - HIP_CHECK(hipGraphNodeFindInClone(&cloned_memcpyH2D_A, memcpyH2D_A, - clonedgraph)); - HIP_CHECK(hipGraphNodeFindInClone(&cloned_memcpyH2D_C, memcpyH2D_C, - clonedgraph)); - HIP_CHECK(hipGraphNodeFindInClone(&cloned_memcpyD2H_AC, memcpyD2H_AC, - clonedgraph)); + HIP_CHECK(hipGraphNodeFindInClone(&cloned_memcpyH2D_A, memcpyH2D_A, clonedgraph)); + HIP_CHECK(hipGraphNodeFindInClone(&cloned_memcpyH2D_C, memcpyH2D_C, clonedgraph)); + HIP_CHECK(hipGraphNodeFindInClone(&cloned_memcpyD2H_AC, memcpyD2H_AC, clonedgraph)); hipGraphNode_t hostNode; hipHostNodeParams hostParams = {0, 0}; hostParams.fn = callbackfunc; hostParams.userData = A_h; - HIP_CHECK(hipGraphAddHostNode(&hostNode, clonedgraph, - nullptr, - 0, &hostParams)); + HIP_CHECK(hipGraphAddHostNode(&hostNode, clonedgraph, nullptr, 0, &hostParams)); - HIP_CHECK(hipGraphAddDependencies(clonedgraph, &cloned_memcpyH2D_A, - &cloned_memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(clonedgraph, &cloned_memcpyH2D_C, - &cloned_memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(clonedgraph, &cloned_memcpyD2H_AC, - &hostNode, 1)); + HIP_CHECK(hipGraphAddDependencies(clonedgraph, &cloned_memcpyH2D_A, &cloned_memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(clonedgraph, &cloned_memcpyH2D_C, &cloned_memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(clonedgraph, &cloned_memcpyD2H_AC, &hostNode, 1)); // Instantiate and launch the cloned graph HIP_CHECK(hipGraphInstantiate(&graphExec, clonedgraph, nullptr, nullptr, 0)); @@ -183,7 +181,7 @@ TEST_CASE("Unit_hipGraphAddHostNode_ClonedGraphwithHostNode") { // Verify execution result for (size_t i = 0; i < N; i++) { if (A_h[i] != static_cast(i)) { - INFO("Validation failed i " << i << "C_h[i] "<< C_h[i]); + INFO("Validation failed i " << i << "C_h[i] " << C_h[i]); REQUIRE(false); } } @@ -196,9 +194,9 @@ TEST_CASE("Unit_hipGraphAddHostNode_ClonedGraphwithHostNode") { } /* -This testcase verifies the square of number by +This test case verifies the square of number by creating graph, Add kernel node which does the square -of number and the result is validated byhipGrahAddHostNode API +of number and the result is validated by hipGraphAddHostNode API */ TEST_CASE("Unit_hipGraphAddHostNode_VectorSquare") { constexpr size_t N = 1024; @@ -206,9 +204,9 @@ TEST_CASE("Unit_hipGraphAddHostNode_VectorSquare") { hipGraph_t graph; hipGraphExec_t graphExec; int *A_d{nullptr}, *A_h{nullptr}, *B_d{nullptr}, *D_d{nullptr}; - int *param = reinterpret_cast(sizeof(int));; - HipTest::initArrays(&A_d, &B_d, &D_d, - &A_h, &B_h, &D_h, N, false); + int* param = reinterpret_cast(sizeof(int)); + + HipTest::initArrays(&A_d, &B_d, &D_d, &A_h, &B_h, &D_h, N, false); HIP_CHECK(hipGraphCreate(&graph, 0)); hipGraphNode_t memcpyH2D_B, memcpyH2D_D, memcpyD2H_D, kernel_vecAdd; hipKernelNodeParams kernelNodeParams{}; @@ -219,37 +217,27 @@ TEST_CASE("Unit_hipGraphAddHostNode_VectorSquare") { hostParams.fn = vectorsquare_callback; hostParams.userData = param; - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_B, graph, nullptr, - 0, B_d, B_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_D, graph, nullptr, - 0, D_d, D_h, - Nbytes, hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_B, graph, nullptr, 0, B_d, B_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_D, graph, nullptr, 0, D_d, D_h, Nbytes, + hipMemcpyHostToDevice)); void* kernelArgs2[] = {&B_d, &D_d}; - kernelNodeParams.func = reinterpret_cast(vector_square); + kernelNodeParams.func = reinterpret_cast(vector_square); kernelNodeParams.gridDim = dim3(1); kernelNodeParams.blockDim = dim3(1); kernelNodeParams.sharedMemBytes = 0; kernelNodeParams.kernelParams = reinterpret_cast(kernelArgs2); kernelNodeParams.extra = nullptr; - HIP_CHECK(hipGraphAddKernelNode(&kernel_vecAdd, graph, nullptr, 0, - &kernelNodeParams)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_D, graph, nullptr, - 0, D_h, D_d, - Nbytes, hipMemcpyDeviceToHost)); + HIP_CHECK(hipGraphAddKernelNode(&kernel_vecAdd, graph, nullptr, 0, &kernelNodeParams)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_D, graph, nullptr, 0, D_h, D_d, Nbytes, + hipMemcpyDeviceToHost)); - HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, - nullptr, - 0, &hostParams)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_B, &kernel_vecAdd, - 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_D, &kernel_vecAdd, - 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &kernel_vecAdd, - &memcpyD2H_D, 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_D, - &hostNode, 1)); + HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, nullptr, 0, &hostParams)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_B, &kernel_vecAdd, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_D, &kernel_vecAdd, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &kernel_vecAdd, &memcpyD2H_D, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_D, &hostNode, 1)); // Instantiate and launch the graph HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0)); @@ -261,8 +249,9 @@ TEST_CASE("Unit_hipGraphAddHostNode_VectorSquare") { HIP_CHECK(hipGraphDestroy(graph)); HIP_CHECK(hipStreamDestroy(streamForGraph)); } + /* -This testcase verifies the following scenario +This test case verifies the following scenario Create graph, calls the host function and updates the parameters in the callback function and validates it. @@ -274,36 +263,27 @@ TEST_CASE("Unit_hipGraphAddHostNode_BasicFunc") { hipGraphExec_t graphExec; int *A_d{nullptr}, *C_d{nullptr}; int *A_h{nullptr}, *C_h{nullptr}; - HipTest::initArrays(&A_d, nullptr, &C_d, - &A_h, nullptr, &C_h, N, false); + HipTest::initArrays(&A_d, nullptr, &C_d, &A_h, nullptr, &C_h, N, false); HIP_CHECK(hipGraphCreate(&graph, 0)); hipGraphNode_t memcpyH2D_A, memcpyD2H_AC, memcpyH2D_C; hipStream_t streamForGraph; HIP_CHECK(hipStreamCreate(&streamForGraph)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, - 0, A_d, A_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, - 0, C_d, C_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, - 0, A_h, C_d, - Nbytes, hipMemcpyDeviceToHost)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, 0, A_d, A_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, 0, C_d, C_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, 0, A_h, C_d, Nbytes, + hipMemcpyDeviceToHost)); hipGraphNode_t hostNode; hipHostNodeParams hostParams = {0, 0}; hostParams.fn = callbackfunc; hostParams.userData = A_h; - HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, - nullptr, - 0, &hostParams)); + HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, nullptr, 0, &hostParams)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, - &memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, - &memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_AC, - &hostNode, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_AC, &hostNode, 1)); // Instantiate and launch the graph HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0)); @@ -313,7 +293,7 @@ TEST_CASE("Unit_hipGraphAddHostNode_BasicFunc") { // Verify execution result for (size_t i = 0; i < N; i++) { if (A_h[i] != static_cast(i)) { - INFO("Validation failed i " << i << "A_h[i] "<< A_h[i]); + INFO("Validation failed i " << i << "A_h[i] " << A_h[i]); REQUIRE(false); } } diff --git a/projects/hip-tests/catch/unit/graph/hipGraphExecHostNodeSetParams.cc b/projects/hip-tests/catch/unit/graph/hipGraphExecHostNodeSetParams.cc index 6f07b23269..6341e73e02 100644 --- a/projects/hip-tests/catch/unit/graph/hipGraphExecHostNodeSetParams.cc +++ b/projects/hip-tests/catch/unit/graph/hipGraphExecHostNodeSetParams.cc @@ -6,164 +6,173 @@ 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 + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY 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 +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 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 +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. */ /** -Testcase Scenarios of hipGraphExecHostNodeSetParams API: +Test Case Scenarios of hipGraphExecHostNodeSetParams API: Functional: 1. Creates graph, Adds HostNode, update hostNode params using hipGraphExecHostNodeSetParams API and validates the result -2. Create graph, Add Graphnodes and clones the graph. Add Hostnode to the cloned graph, update +2. Create graph, Add Graph nodes and clones the graph. Add Host node to the cloned graph, update hostNode params using hipGraphExecHostNodeSetParams API and validate the result Negative: -1) Pass hGraphExec as nullptr and verify api doen't crash, returns error code. -2) Pass node as nullptr and verify api doen't crash, returns error code. +1) Pass hGraphExec as nullptr and verify api doesn't crash, returns error code. +2) Pass node as nullptr and verify api doesn't crash, returns error code. 3) Pass pNodeParams as nullptr and verify api doesn't crash, returns error code. 3) Pass hipHostNodeParams::hipHostFn_t as nullptr and verify api doesn't crash, returns error code. -4) Pass unintialized host params and verify api doesn't crash, returns error code. -5) Pass unintialized graph and verify api doesn't crash, returns error code. -6) Pass nullptr to hostfunc and verify api doesn't crash, returns error code. +4) Pass uninitialized host params and verify api doesn't crash, returns error code. +5) Pass uninitialized graph and verify api doesn't crash, returns error code. +6) Pass nullptr to host func and verify api doesn't crash, returns error code. */ -#include #include +#include #define SIZE 1024 -void callbackfunc(void *A_h) { - int *A = reinterpret_cast(A_h); +void callbackfunc(void* A_h) { + int* A = reinterpret_cast(A_h); for (int i = 0; i < SIZE; i++) { - A[i] = i; + A[i] = i; } } -void callbackfunc_setparams(void *B_h) { - int *B = reinterpret_cast(B_h); +void callbackfunc_setparams(void* B_h) { + int* B = reinterpret_cast(B_h); for (int i = 0; i < SIZE; i++) { - B[i] = i * i; + B[i] = i * i; } } /* -This testcase verifies the negative scenarios of +This test case verifies the negative scenarios of hipGraphExecHostNodeSetParams API */ TEST_CASE("Unit_hipGraphExecHostNodeSetParams_Negative") { -constexpr size_t N = 1024; - constexpr size_t Nbytes = N * sizeof(int); - hipGraph_t graph; - hipGraphExec_t graphExec; - int *A_d{nullptr}, *C_d{nullptr}; - int *A_h{nullptr}, *C_h{nullptr}; - HipTest::initArrays(&A_d, nullptr, &C_d, - &A_h, nullptr, &C_h, N, false); - - HIP_CHECK(hipGraphCreate(&graph, 0)); - hipGraphNode_t memcpyH2D_A, memcpyD2H_AC, memcpyH2D_C; - hipStream_t streamForGraph; - HIP_CHECK(hipStreamCreate(&streamForGraph)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, - 0, A_d, A_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, - 0, C_d, C_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, - 0, A_h, C_d, - Nbytes, hipMemcpyDeviceToHost)); - hipGraphNode_t hostNode; - hipHostNodeParams hostParams = {0, 0}; - hostParams.fn = callbackfunc; - hostParams.userData = A_h; - HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, - nullptr, - 0, &hostParams)); - - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, - &memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, - &memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_AC, - &hostNode, 1)); - - hipHostNodeParams sethostParams = {0, 0}; - sethostParams.fn = callbackfunc_setparams; - sethostParams.userData = C_h; - - // Instantiate and launch the graph - HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0)); -#if HT_NVIDIA - SECTION("Passing nullptr to graphExec") { - REQUIRE(hipGraphExecHostNodeSetParams(nullptr, hostNode, &sethostParams) - == hipErrorInvalidValue); - } - - SECTION("Passing nullptr to hostParams") { - REQUIRE(hipGraphExecHostNodeSetParams(graphExec, hostNode, nullptr) - == hipErrorInvalidValue); - } -#endif - SECTION("Passing nullptr to graph") { - REQUIRE(hipGraphExecHostNodeSetParams(graphExec, nullptr, &sethostParams) - == hipErrorInvalidValue); - } - - SECTION("Passing nullptr to host func") { - sethostParams.fn = nullptr; - REQUIRE(hipGraphExecHostNodeSetParams(graphExec, hostNode, &sethostParams) - == hipErrorInvalidValue); - } - - - SECTION("Passing unintialized hostParams") { - hipHostNodeParams unintParams = {0, 0}; - REQUIRE(hipGraphExecHostNodeSetParams(graphExec, hostNode, &unintParams) - == hipErrorInvalidValue); - } - HIP_CHECK(hipGraphDestroy(graph)); -} -/* -This testcase verifies hipGraphExecHostNodeSetParams API in cloned graph -Creates graph, Add graph nodes and clone the graph -Add HostNode to the cloned graph,update the host params using -hipGraphExecHostNodeSetParams API and validates the result -*/ -TEST_CASE("Unit_hipGraphExecHostNodeSetParams_ClonedGraphwithHostNode") { constexpr size_t N = 1024; constexpr size_t Nbytes = N * sizeof(int); hipGraph_t graph; hipGraphExec_t graphExec; int *A_d{nullptr}, *C_d{nullptr}; int *A_h{nullptr}, *C_h{nullptr}; - HipTest::initArrays(&A_d, nullptr, &C_d, - &A_h, nullptr, &C_h, N, false); + HipTest::initArrays(&A_d, nullptr, &C_d, &A_h, nullptr, &C_h, N, false); HIP_CHECK(hipGraphCreate(&graph, 0)); - hipGraphNode_t memcpyH2D_A, memcpyH2D_C, - memcpyD2H_AC; + hipGraphNode_t memcpyH2D_A, memcpyD2H_AC, memcpyH2D_C; hipStream_t streamForGraph; HIP_CHECK(hipStreamCreate(&streamForGraph)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, - 0, A_d, A_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, - 0, C_d, C_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, - 0, A_h, C_d, - Nbytes, hipMemcpyDeviceToHost)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, 0, A_d, A_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, 0, C_d, C_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, 0, A_h, C_d, Nbytes, + hipMemcpyDeviceToHost)); + + hipGraphNode_t hostNode; + hipHostNodeParams hostParams = {0, 0}; + hostParams.fn = callbackfunc; + hostParams.userData = A_h; + HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, nullptr, 0, &hostParams)); + + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_AC, &hostNode, 1)); + + hipHostNodeParams sethostParams = {0, 0}; + sethostParams.fn = callbackfunc_setparams; + sethostParams.userData = C_h; + + hipGraphNode_t empty_node; + HIP_CHECK(hipGraphAddEmptyNode(&empty_node, graph, &hostNode, 1)); + + // Instantiate and launch the graph + HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0)); + + SECTION("Passing nullptr to graphExec") { + HIP_CHECK_ERROR(hipGraphExecHostNodeSetParams(nullptr, hostNode, &sethostParams), + hipErrorInvalidValue); + } + + SECTION("Passing nullptr to hostParams") { + HIP_CHECK_ERROR(hipGraphExecHostNodeSetParams(graphExec, hostNode, nullptr), + hipErrorInvalidValue); + } + + SECTION("Passing nullptr to graph") { + HIP_CHECK_ERROR(hipGraphExecHostNodeSetParams(graphExec, nullptr, &sethostParams), + hipErrorInvalidValue); + } + + SECTION("Passing nullptr to host func") { + sethostParams.fn = nullptr; + HIP_CHECK_ERROR(hipGraphExecHostNodeSetParams(graphExec, hostNode, &sethostParams), + hipErrorInvalidValue); + } + + SECTION("Passing uninitialized hostParams") { + hipHostNodeParams unintParams = {0, 0}; + HIP_CHECK_ERROR(hipGraphExecHostNodeSetParams(graphExec, hostNode, &unintParams), + hipErrorInvalidValue); + } + +#if HT_NVIDIA // segfaults on AMD + SECTION("node is not a host node") { + HIP_CHECK_ERROR(hipGraphExecHostNodeSetParams(graphExec, empty_node, &sethostParams), + hipErrorInvalidValue); + } +#endif + + SECTION("node is not instantiated") { + HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, nullptr, 0, &hostParams)); + HIP_CHECK_ERROR(hipGraphExecHostNodeSetParams(graphExec, hostNode, &sethostParams), + hipErrorInvalidValue); + } + + HipTest::freeArrays(A_d, nullptr, C_d, A_h, nullptr, C_h, false); + HIP_CHECK(hipGraphExecDestroy(graphExec)); + HIP_CHECK(hipGraphDestroy(graph)); + HIP_CHECK(hipStreamDestroy(streamForGraph)); +} + +/* +This test case verifies hipGraphExecHostNodeSetParams API in cloned graph +Creates graph, Add graph nodes and clone the graph +Add HostNode to the cloned graph,update the host params using +hipGraphExecHostNodeSetParams API and validates the result +*/ +TEST_CASE("Unit_hipGraphExecHostNodeSetParams_ClonedGraphWithHostNode") { + constexpr size_t N = 1024; + constexpr size_t Nbytes = N * sizeof(int); + hipGraph_t graph; + hipGraphExec_t graphExec; + int *A_d{nullptr}, *C_d{nullptr}; + int *A_h{nullptr}, *C_h{nullptr}; + HipTest::initArrays(&A_d, nullptr, &C_d, &A_h, nullptr, &C_h, N, false); + + HIP_CHECK(hipGraphCreate(&graph, 0)); + hipGraphNode_t memcpyH2D_A, memcpyH2D_C, memcpyD2H_AC; + hipStream_t streamForGraph; + HIP_CHECK(hipStreamCreate(&streamForGraph)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, 0, A_d, A_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, 0, C_d, C_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, 0, A_h, C_d, Nbytes, + hipMemcpyDeviceToHost)); hipGraph_t clonedgraph; HIP_CHECK(hipGraphClone(&clonedgraph, graph)); @@ -172,20 +181,15 @@ TEST_CASE("Unit_hipGraphExecHostNodeSetParams_ClonedGraphwithHostNode") { hipHostNodeParams hostParams = {0, 0}; hostParams.fn = callbackfunc; hostParams.userData = A_h; - HIP_CHECK(hipGraphAddHostNode(&hostNode, clonedgraph, - nullptr, - 0, &hostParams)); + HIP_CHECK(hipGraphAddHostNode(&hostNode, clonedgraph, nullptr, 0, &hostParams)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, - &memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, - &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, &memcpyD2H_AC, 1)); hipHostNodeParams sethostParams = {0, 0}; sethostParams.fn = callbackfunc_setparams; sethostParams.userData = C_h; - // Instantiate and launch the cloned graph HIP_CHECK(hipGraphInstantiate(&graphExec, clonedgraph, nullptr, nullptr, 0)); HIP_CHECK(hipGraphExecHostNodeSetParams(graphExec, hostNode, &sethostParams)); @@ -195,7 +199,7 @@ TEST_CASE("Unit_hipGraphExecHostNodeSetParams_ClonedGraphwithHostNode") { // Verify execution result for (size_t i = 0; i < N; i++) { if (C_h[i] != static_cast(i * i)) { - INFO("Validation failed i " << i << "C_h[i] "<< C_h[i]); + INFO("Validation failed i " << i << "C_h[i] " << C_h[i]); REQUIRE(false); } } @@ -207,7 +211,7 @@ TEST_CASE("Unit_hipGraphExecHostNodeSetParams_ClonedGraphwithHostNode") { } /* -This testcase verifies the following scenario +This test case verifies the following scenario Create graph, Adds host node to the graph, updates the host params using hipGraphExecHostNodeSetParams API and validates the result @@ -219,36 +223,28 @@ TEST_CASE("Unit_hipGraphExecHostNodeSetParams_BasicFunc") { hipGraphExec_t graphExec; int *A_d{nullptr}, *C_d{nullptr}; int *A_h{nullptr}, *C_h{nullptr}; - HipTest::initArrays(&A_d, nullptr, &C_d, - &A_h, nullptr, &C_h, N, false); + HipTest::initArrays(&A_d, nullptr, &C_d, &A_h, nullptr, &C_h, N, false); HIP_CHECK(hipGraphCreate(&graph, 0)); hipGraphNode_t memcpyH2D_A, memcpyD2H_AC, memcpyH2D_C; hipStream_t streamForGraph; HIP_CHECK(hipStreamCreate(&streamForGraph)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, - 0, A_d, A_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, - 0, C_d, C_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, - 0, A_h, C_d, - Nbytes, hipMemcpyDeviceToHost)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, 0, A_d, A_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, 0, C_d, C_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, 0, A_h, C_d, Nbytes, + hipMemcpyDeviceToHost)); + hipGraphNode_t hostNode; hipHostNodeParams hostParams = {0, 0}; hostParams.fn = callbackfunc; hostParams.userData = A_h; - HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, - nullptr, - 0, &hostParams)); + HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, nullptr, 0, &hostParams)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, - &memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, - &memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_AC, - &hostNode, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_AC, &hostNode, 1)); hipHostNodeParams sethostParams = {0, 0}; sethostParams.fn = callbackfunc_setparams; @@ -263,8 +259,8 @@ TEST_CASE("Unit_hipGraphExecHostNodeSetParams_BasicFunc") { // Verify execution result for (size_t i = 0; i < N; i++) { - if (C_h[i] != static_cast(i * i)) { - INFO("Validation failed i " << i << "C_h[i] "<< C_h[i]); + if (C_h[i] != static_cast(i * i)) { + INFO("Validation failed i " << i << "C_h[i] " << C_h[i]); REQUIRE(false); } } diff --git a/projects/hip-tests/catch/unit/graph/hipGraphHostNodeGetParams.cc b/projects/hip-tests/catch/unit/graph/hipGraphHostNodeGetParams.cc index a1c769ea47..ffb04cc174 100644 --- a/projects/hip-tests/catch/unit/graph/hipGraphHostNodeGetParams.cc +++ b/projects/hip-tests/catch/unit/graph/hipGraphHostNodeGetParams.cc @@ -6,55 +6,57 @@ 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 + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY 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 +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 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 +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. */ /** -Testcase Scenarios of hipGraphHostNodeGetParams API: +Test Case Scenarios of hipGraphHostNodeGetParams API: Functional Scenarios: -1) Create a graph, add Host node to graph with desired node params. Verify api fetches the node params - which were mentioned while adding the host node. -2) Set host node params with hipGraphHostNodeSetParams, now get the params and verify both are same. -3) Create graph, Add Graphnodes and clones the graph. Add Hostnode to the cloned graph, update - hostNode params using hipGraphHostNodeSetParams API now get the params and verify both are same +1) Create a graph, add Host node to graph with desired node params. Verify api fetches the node +params which were mentioned while adding the host node. 2) Set host node params with +hipGraphHostNodeSetParams, now get the params and verify both are same. 3) Create graph, Add Graph +nodes and clones the graph. Add Host node to the cloned graph, update hostNode params using +hipGraphHostNodeSetParams API now get the params and verify both are same Negative Scenarios: 1) Pass pGraphNode as nullptr and verify api doesn’t crash, returns error code. 2) Pass pNodeParams as nullptr and verify api doesn’t crash, returns error code. -3) Pass unintialized graph node +3) Pass uninitialized graph node */ -#include #include +#include #define SIZE 1024 -static void callbackfunc(void *A_h) { - int *A = reinterpret_cast(A_h); +static void callbackfunc(void* A_h) { + int* A = reinterpret_cast(A_h); for (int i = 0; i < SIZE; i++) { A[i] = i; } } -static void callbackfunc_setparams(void *B_h) { - int *B = reinterpret_cast(B_h); +static void callbackfunc_setparams(void* B_h) { + int* B = reinterpret_cast(B_h); for (int i = 0; i < SIZE; i++) { - B[i] = i * i; + B[i] = i * i; } } /* -This testcase verifies the negative scenarios of +This test case verifies the negative scenarios of hipGraphHostNodeGetParams API */ TEST_CASE("Unit_hipGraphHostNodeGetParams_Negative") { @@ -62,8 +64,7 @@ TEST_CASE("Unit_hipGraphHostNodeGetParams_Negative") { hipGraph_t graph; int *A_d{nullptr}, *C_d{nullptr}; int *A_h{nullptr}, *C_h{nullptr}; - HipTest::initArrays(&A_d, nullptr, &C_d, - &A_h, nullptr, &C_h, N, false); + HipTest::initArrays(&A_d, nullptr, &C_d, &A_h, nullptr, &C_h, N, false); HIP_CHECK(hipGraphCreate(&graph, 0)); @@ -71,63 +72,57 @@ TEST_CASE("Unit_hipGraphHostNodeGetParams_Negative") { hipHostNodeParams hostParams = {0, 0}; hostParams.fn = callbackfunc; hostParams.userData = A_h; - HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, - nullptr, - 0, &hostParams)); + HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, nullptr, 0, &hostParams)); hipHostNodeParams GethostParams; SECTION("Passing nullptr to graph node") { - REQUIRE(hipGraphHostNodeGetParams(nullptr, &GethostParams) - == hipErrorInvalidValue); + HIP_CHECK_ERROR(hipGraphHostNodeGetParams(nullptr, &GethostParams), hipErrorInvalidValue); } SECTION("Passing nullptr to hostParams") { - REQUIRE(hipGraphHostNodeGetParams(hostNode, nullptr) - == hipErrorInvalidValue); + HIP_CHECK_ERROR(hipGraphHostNodeGetParams(hostNode, nullptr), hipErrorInvalidValue); } - SECTION("Passing unintialized graphNode") { - hipGraphNode_t unint_graphnode{nullptr}; - REQUIRE(hipGraphHostNodeGetParams(unint_graphnode, &GethostParams) - == hipErrorInvalidValue); +#if HT_NVIDIA // segfaults on AMD + SECTION("node is not a host node") { + hipGraphNode_t empty_node; + HIP_CHECK(hipGraphAddEmptyNode(&empty_node, graph, nullptr, 0)); + HIP_CHECK_ERROR(hipGraphHostNodeGetParams(empty_node, &GethostParams), hipErrorInvalidValue); } +#endif + + HipTest::freeArrays(A_d, nullptr, C_d, A_h, nullptr, C_h, false); HIP_CHECK(hipGraphDestroy(graph)); } + /* -This testcase verifies hipGraphHostNodeGetParams API in cloned graph +This test case verifies hipGraphHostNodeGetParams API in cloned graph Creates graph, Add graph nodes and clone the graph Add HostNode to the cloned graph, update hostNode using hipGraphHostNodeSetParams, then get the host node params using hipGraphHostNodeGetParams API and compare it. */ -TEST_CASE("Unit_hipGraphHostNodeGetParams_ClonedGraphwithHostNode") { +TEST_CASE("Unit_hipGraphHostNodeGetParams_ClonedGraphWithHostNode") { constexpr size_t N = 1024; constexpr size_t Nbytes = N * sizeof(int); hipGraph_t graph; hipGraphExec_t graphExec; int *A_d{nullptr}, *C_d{nullptr}; int *A_h{nullptr}, *C_h{nullptr}; - HipTest::initArrays(&A_d, nullptr, &C_d, - &A_h, nullptr, &C_h, N, false); + HipTest::initArrays(&A_d, nullptr, &C_d, &A_h, nullptr, &C_h, N, false); HIP_CHECK(hipGraphCreate(&graph, 0)); - hipGraphNode_t memcpyH2D_A, memcpyH2D_C, - memcpyD2H_AC; + hipGraphNode_t memcpyH2D_A, memcpyH2D_C, memcpyD2H_AC; hipStream_t streamForGraph; HIP_CHECK(hipStreamCreate(&streamForGraph)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, - 0, A_d, A_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, - 0, C_d, C_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, - 0, A_h, C_d, - Nbytes, hipMemcpyDeviceToHost)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, - &memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, - &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, 0, A_d, A_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, 0, C_d, C_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, 0, A_h, C_d, Nbytes, + hipMemcpyDeviceToHost)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, &memcpyD2H_AC, 1)); hipGraph_t clonedgraph; HIP_CHECK(hipGraphClone(&clonedgraph, graph)); @@ -136,17 +131,16 @@ TEST_CASE("Unit_hipGraphHostNodeGetParams_ClonedGraphwithHostNode") { hipHostNodeParams hostParams = {0, 0}; hostParams.fn = callbackfunc; hostParams.userData = A_h; - HIP_CHECK(hipGraphAddHostNode(&hostNode, clonedgraph, - nullptr, - 0, &hostParams)); + HIP_CHECK(hipGraphAddHostNode(&hostNode, clonedgraph, nullptr, 0, &hostParams)); + hipHostNodeParams sethostParams = {0, 0}; sethostParams.fn = callbackfunc_setparams; sethostParams.userData = C_h; HIP_CHECK(hipGraphHostNodeSetParams(hostNode, &sethostParams)); hipHostNodeParams gethostParams; HIP_CHECK(hipGraphHostNodeGetParams(hostNode, &gethostParams)); - REQUIRE(memcmp(&sethostParams, &gethostParams, sizeof(hipHostNodeParams)) - == 0); + REQUIRE(memcmp(&sethostParams, &gethostParams, sizeof(hipHostNodeParams)) == 0); + // Instantiate and launch the cloned graph HIP_CHECK(hipGraphInstantiate(&graphExec, clonedgraph, nullptr, nullptr, 0)); HIP_CHECK(hipGraphLaunch(graphExec, streamForGraph)); @@ -155,10 +149,11 @@ TEST_CASE("Unit_hipGraphHostNodeGetParams_ClonedGraphwithHostNode") { // Verify execution result for (size_t i = 0; i < N; i++) { if (C_h[i] != static_cast(i * i)) { - INFO("Validation failed i " << i << "C_h[i] "<< C_h[i]); + INFO("Validation failed i " << i << "C_h[i] " << C_h[i]); REQUIRE(false); } } + HIP_CHECK(hipGraphExecDestroy(graphExec)); HIP_CHECK(hipGraphDestroy(graph)); HIP_CHECK(hipGraphDestroy(clonedgraph)); @@ -167,7 +162,7 @@ TEST_CASE("Unit_hipGraphHostNodeGetParams_ClonedGraphwithHostNode") { } /* -This testcase verifies the following scenarios +This test case verifies the following scenarios Create graph, Adds host node to the graph, updates it with hipGraphHostNodeSetParams and gets the host node params using hipGraphHostNodeGetParams API and validates @@ -180,36 +175,28 @@ void hipGraphHostNodeGetParams_func(bool setparams) { hipGraphExec_t graphExec; int *A_d{nullptr}, *C_d{nullptr}; int *A_h{nullptr}, *C_h{nullptr}; - HipTest::initArrays(&A_d, nullptr, &C_d, - &A_h, nullptr, &C_h, N, false); + HipTest::initArrays(&A_d, nullptr, &C_d, &A_h, nullptr, &C_h, N, false); HIP_CHECK(hipGraphCreate(&graph, 0)); hipGraphNode_t memcpyH2D_A, memcpyD2H_AC, memcpyH2D_C; hipStream_t streamForGraph; HIP_CHECK(hipStreamCreate(&streamForGraph)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, - 0, A_d, A_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, - 0, C_d, C_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, - 0, A_h, C_d, - Nbytes, hipMemcpyDeviceToHost)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, 0, A_d, A_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, 0, C_d, C_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, 0, A_h, C_d, Nbytes, + hipMemcpyDeviceToHost)); + hipGraphNode_t hostNode; hipHostNodeParams hostParams = {0, 0}; hostParams.fn = callbackfunc; hostParams.userData = A_h; - HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, - nullptr, - 0, &hostParams)); + HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, nullptr, 0, &hostParams)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, - &memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, - &memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_AC, - &hostNode, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_A, &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_AC, &hostNode, 1)); if (setparams) { hipHostNodeParams sethostParams = {0, 0}; @@ -219,32 +206,30 @@ void hipGraphHostNodeGetParams_func(bool setparams) { hipHostNodeParams gethostParams; HIP_CHECK(hipGraphHostNodeGetParams(hostNode, &gethostParams)); - REQUIRE(memcmp(&sethostParams, &gethostParams, sizeof(hipHostNodeParams)) - == 0); + REQUIRE(memcmp(&sethostParams, &gethostParams, sizeof(hipHostNodeParams)) == 0); } else { hipHostNodeParams gethostParams; HIP_CHECK(hipGraphHostNodeGetParams(hostNode, &gethostParams)); - REQUIRE(memcmp(&hostParams, &gethostParams, sizeof(hipHostNodeParams)) - == 0); + REQUIRE(memcmp(&hostParams, &gethostParams, sizeof(hipHostNodeParams)) == 0); } + // Instantiate and launch the graph HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0)); HIP_CHECK(hipGraphLaunch(graphExec, streamForGraph)); HIP_CHECK(hipStreamSynchronize(streamForGraph)); // Verify execution result - if (setparams) { for (size_t i = 0; i < N; i++) { if (C_h[i] != static_cast(i * i)) { - INFO("Validation failed i " << i << "C_h[i] "<< C_h[i]); + INFO("Validation failed i " << i << "C_h[i] " << C_h[i]); REQUIRE(false); } } } else { for (size_t i = 0; i < N; i++) { if (A_h[i] != static_cast(i)) { - INFO("Validation failed i " << i << "C_h[i] "<< C_h[i]); + INFO("Validation failed i " << i << "C_h[i] " << C_h[i]); REQUIRE(false); } } @@ -255,21 +240,18 @@ void hipGraphHostNodeGetParams_func(bool setparams) { HIP_CHECK(hipGraphDestroy(graph)); HIP_CHECK(hipStreamDestroy(streamForGraph)); } + /* -This testcase verifies hipGraphHostNodeGetParams API by +This test case verifies hipGraphHostNodeGetParams API by adding host node to graph and gets the host params and validates it */ -TEST_CASE("Unit_hipGraphHostNodeGetParams_BasicFunc") { - hipGraphHostNodeGetParams_func(false); -} +TEST_CASE("Unit_hipGraphHostNodeGetParams_BasicFunc") { hipGraphHostNodeGetParams_func(false); } /* -This testcase verifies hipGraphHostNodeGetParams API by +This test case verifies hipGraphHostNodeGetParams API by adding host node to graph, updates host node params using hipGraphHostNodeSetParams and gets the host params validates it */ -TEST_CASE("Unit_hipGraphHostNodeGetParams_SetParams") { - hipGraphHostNodeGetParams_func(true); -} +TEST_CASE("Unit_hipGraphHostNodeGetParams_SetParams") { hipGraphHostNodeGetParams_func(true); } diff --git a/projects/hip-tests/catch/unit/graph/hipGraphHostNodeSetParams.cc b/projects/hip-tests/catch/unit/graph/hipGraphHostNodeSetParams.cc index a2899198cd..d9b275b375 100644 --- a/projects/hip-tests/catch/unit/graph/hipGraphHostNodeSetParams.cc +++ b/projects/hip-tests/catch/unit/graph/hipGraphHostNodeSetParams.cc @@ -6,24 +6,26 @@ 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 + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY 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 +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 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 +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. */ /** -Testcase Scenarios of hipGraphHostNodeSetParams API: +Test Case Scenarios of hipGraphHostNodeSetParams API: Functional: 1. Creates graph, Adds HostNode, update hostNode params using hipGraphHostNodeSetParams API and validates the result -2. Create graph, Add Graphnodes and clones the graph. Add Hostnode to the cloned graph, update +2. Create graph, Add Graph nodes and clones the graph. Add Host node to the cloned graph, update hostNode params using hipGraphHostNodeSetParams API and validate the result Negative: @@ -31,30 +33,30 @@ Negative: 1) Pass pGraphNode as nullptr and verify api doesn’t crash, returns error code. 2) Pass pNodeParams as nullptr and verify api doesn’t crash, returns error code. 3) Pass hipHostNodeParams::hipHostFn_t as nullptr and verify api doesn't crash, returns error code. -4) Pass unintialized host params +4) Pass uninitialized host params */ -#include #include +#include #define SIZE 1024 -static void callbackfunc(void *A_h) { - int *A = reinterpret_cast(A_h); +static void callbackfunc(void* A_h) { + int* A = reinterpret_cast(A_h); for (int i = 0; i < SIZE; i++) { - A[i] = i; + A[i] = i; } } -static void callbackfunc_setparams(void *B_h) { - int *B = reinterpret_cast(B_h); +static void callbackfunc_setparams(void* B_h) { + int* B = reinterpret_cast(B_h); for (int i = 0; i < SIZE; i++) { - B[i] = i * i; + B[i] = i * i; } } /* -This testcase verifies the negative scenarios of +This test case verifies the negative scenarios of hipGraphHostNodeSetParams API */ TEST_CASE("Unit_hipGraphHostNodeSetParams_Negative") { @@ -62,8 +64,7 @@ TEST_CASE("Unit_hipGraphHostNodeSetParams_Negative") { hipGraph_t graph; int *A_d{nullptr}, *C_d{nullptr}; int *A_h{nullptr}, *C_h{nullptr}; - HipTest::initArrays(&A_d, nullptr, &C_d, - &A_h, nullptr, &C_h, N, false); + HipTest::initArrays(&A_d, nullptr, &C_d, &A_h, nullptr, &C_h, N, false); HIP_CHECK(hipGraphCreate(&graph, 0)); @@ -71,65 +72,63 @@ TEST_CASE("Unit_hipGraphHostNodeSetParams_Negative") { hipHostNodeParams hostParams; hostParams.fn = callbackfunc; hostParams.userData = A_h; - HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, - nullptr, - 0, &hostParams)); -#if HT_NVIDIA + HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, nullptr, 0, &hostParams)); + SECTION("Passing nullptr to graph node") { - REQUIRE(hipGraphHostNodeSetParams(nullptr, &hostParams) - == hipErrorInvalidValue); + HIP_CHECK_ERROR(hipGraphHostNodeSetParams(nullptr, &hostParams), hipErrorInvalidValue); } SECTION("Passing nullptr to hostParams") { - REQUIRE(hipGraphHostNodeSetParams(hostNode, nullptr) - == hipErrorInvalidValue); + HIP_CHECK_ERROR(hipGraphHostNodeSetParams(hostNode, nullptr), hipErrorInvalidValue); } -#endif SECTION("Passing nullptr to host func") { hostParams.fn = nullptr; - REQUIRE(hipGraphHostNodeSetParams(hostNode, &hostParams) - == hipErrorInvalidValue); + HIP_CHECK_ERROR(hipGraphHostNodeSetParams(hostNode, &hostParams), hipErrorInvalidValue); } - - SECTION("Passing unintialized hostParams") { + SECTION("Passing uninitialized hostParams") { hipHostNodeParams unintParams = {0, 0}; - REQUIRE(hipGraphHostNodeSetParams(hostNode, &unintParams) - == hipErrorInvalidValue); + HIP_CHECK_ERROR(hipGraphHostNodeSetParams(hostNode, &unintParams), hipErrorInvalidValue); } + +#if HT_NVIDIA // segfaults on AMD + SECTION("node is not a host node") { + hipGraphNode_t empty_node; + HIP_CHECK(hipGraphAddEmptyNode(&empty_node, graph, nullptr, 0)); + HIP_CHECK_ERROR(hipGraphHostNodeSetParams(empty_node, &hostParams), hipErrorInvalidValue); + } +#endif + + HipTest::freeArrays(A_d, nullptr, C_d, A_h, nullptr, C_h, false); HIP_CHECK(hipGraphDestroy(graph)); } + /* -This testcase verifies hipGraphHostNodeSetParams API in cloned graph +This test case verifies hipGraphHostNodeSetParams API in cloned graph Creates graph, Add graph nodes and clone the graph Add HostNode to the cloned graph,update the host params using hipGraphHostNodeSetParams API and validates the result */ -TEST_CASE("Unit_hipGraphHostNodeSetParams_ClonedGraphwithHostNode") { +TEST_CASE("Unit_hipGraphHostNodeSetParams_ClonedGraphWithHostNode") { constexpr size_t N = 1024; constexpr size_t Nbytes = N * sizeof(int); hipGraph_t graph; hipGraphExec_t graphExec; int *A_d{nullptr}, *C_d{nullptr}; int *A_h{nullptr}, *C_h{nullptr}; - HipTest::initArrays(&A_d, nullptr, &C_d, - &A_h, nullptr, &C_h, N, false); + HipTest::initArrays(&A_d, nullptr, &C_d, &A_h, nullptr, &C_h, N, false); HIP_CHECK(hipGraphCreate(&graph, 0)); - hipGraphNode_t memcpyH2D_C, - memcpyD2H_AC; + hipGraphNode_t memcpyH2D_C, memcpyD2H_AC; hipStream_t streamForGraph; HIP_CHECK(hipStreamCreate(&streamForGraph)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, - 0, C_d, C_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, - 0, A_h, C_d, - Nbytes, hipMemcpyDeviceToHost)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, 0, C_d, C_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, 0, A_h, C_d, Nbytes, + hipMemcpyDeviceToHost)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, - &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, &memcpyD2H_AC, 1)); hipGraph_t clonedgraph; HIP_CHECK(hipGraphClone(&clonedgraph, graph)); @@ -138,17 +137,13 @@ TEST_CASE("Unit_hipGraphHostNodeSetParams_ClonedGraphwithHostNode") { hipHostNodeParams hostParams; hostParams.fn = callbackfunc; hostParams.userData = A_h; - HIP_CHECK(hipGraphAddHostNode(&hostNode, clonedgraph, - nullptr, - 0, &hostParams)); - + HIP_CHECK(hipGraphAddHostNode(&hostNode, clonedgraph, nullptr, 0, &hostParams)); hipHostNodeParams sethostParams; sethostParams.fn = callbackfunc_setparams; sethostParams.userData = C_h; HIP_CHECK(hipGraphHostNodeSetParams(hostNode, &sethostParams)); - // Instantiate and launch the cloned graph HIP_CHECK(hipGraphInstantiate(&graphExec, clonedgraph, nullptr, nullptr, 0)); HIP_CHECK(hipGraphLaunch(graphExec, streamForGraph)); @@ -157,7 +152,7 @@ TEST_CASE("Unit_hipGraphHostNodeSetParams_ClonedGraphwithHostNode") { // Verify execution result for (size_t i = 0; i < N; i++) { if (C_h[i] != static_cast(i * i)) { - INFO("Validation failed i " << i << "C_h[i] "<< C_h[i]); + INFO("Validation failed i " << i << "C_h[i] " << C_h[i]); REQUIRE(false); } } @@ -169,7 +164,7 @@ TEST_CASE("Unit_hipGraphHostNodeSetParams_ClonedGraphwithHostNode") { } /* -This testcase verifies the following scenario +This test case verifies the following scenario Create graph, Adds host node to the graph, updates the host params using hipGraphHostNodeSetParams API and validates the result @@ -181,31 +176,24 @@ TEST_CASE("Unit_hipGraphHostNodeSetParams_BasicFunc") { hipGraphExec_t graphExec; int *A_d{nullptr}, *C_d{nullptr}; int *A_h{nullptr}, *C_h{nullptr}; - HipTest::initArrays(&A_d, nullptr, &C_d, - &A_h, nullptr, &C_h, N, false); + HipTest::initArrays(&A_d, nullptr, &C_d, &A_h, nullptr, &C_h, N, false); HIP_CHECK(hipGraphCreate(&graph, 0)); hipGraphNode_t memcpyD2H_AC, memcpyH2D_C; hipStream_t streamForGraph; HIP_CHECK(hipStreamCreate(&streamForGraph)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, - 0, C_d, C_h, - Nbytes, hipMemcpyHostToDevice)); - HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, - 0, A_h, C_d, - Nbytes, hipMemcpyDeviceToHost)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_C, graph, nullptr, 0, C_d, C_h, Nbytes, + hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_AC, graph, nullptr, 0, A_h, C_d, Nbytes, + hipMemcpyDeviceToHost)); hipGraphNode_t hostNode; hipHostNodeParams hostParams; hostParams.fn = callbackfunc; hostParams.userData = A_h; - HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, - nullptr, - 0, &hostParams)); + HIP_CHECK(hipGraphAddHostNode(&hostNode, graph, nullptr, 0, &hostParams)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, - &memcpyD2H_AC, 1)); - HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_AC, - &hostNode, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyH2D_C, &memcpyD2H_AC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_AC, &hostNode, 1)); hipHostNodeParams sethostParams; sethostParams.fn = callbackfunc_setparams; @@ -220,7 +208,7 @@ TEST_CASE("Unit_hipGraphHostNodeSetParams_BasicFunc") { // Verify execution result for (size_t i = 0; i < N; i++) { if (C_h[i] != static_cast(i * i)) { - INFO("Validation failed i " << i << "C_h[i] "<< C_h[i]); + INFO("Validation failed i " << i << "C_h[i] " << C_h[i]); REQUIRE(false); } } From a8f65237ebd51fce0a50769809274239c65e9157 Mon Sep 17 00:00:00 2001 From: milos-mozetic <118800401+milos-mozetic@users.noreply.github.com> Date: Wed, 28 Jun 2023 06:14:00 +0200 Subject: [PATCH 02/32] EXSWHTEC-224 - Test cases ID clean up and documentation for Device Management (#70) - Test cases ID clean up and documentation for Device Management - Adjust doxygen comments to fix bugs - Adjust defgroup comments for test modules [ROCm/hip-tests commit: d0295c4295c8af0019b9b948ae79bbaa5c8a1e68] --- .../catch/include/hip_test_defgroups.hh | 9 +- .../catch/multiproc/hipIpcEventHandle.cc | 98 +++++++++--- .../catch/multiproc/hipIpcMemAccessTest.cc | 64 +++++++- .../catch/unit/device/hipChooseDevice.cc | 38 ++++- .../unit/device/hipDeviceGetDefaultMemPool.cc | 36 +++++ .../catch/unit/device/hipDeviceGetLimit.cc | 49 ++++-- .../catch/unit/device/hipDeviceReset.cc | 37 +++++ .../unit/device/hipDeviceSetGetCacheConfig.cc | 98 +++++++++++- .../unit/device/hipDeviceSetGetMemPool.cc | 107 +++++++++++++ .../device/hipDeviceSetGetSharedMemConfig.cc | 95 +++++++++++ .../catch/unit/device/hipDeviceSetLimit.cc | 32 ++-- .../catch/unit/device/hipDeviceSynchronize.cc | 52 +++++- .../device/hipExtGetLinkTypeAndHopCount.cc | 56 ++++++- .../unit/device/hipGetDeviceAttribute.cc | 71 ++++++++- .../catch/unit/device/hipGetDeviceCount.cc | 49 +++++- .../unit/device/hipGetDeviceProperties.cc | 54 ++++++- .../catch/unit/device/hipGetSetDeviceFlags.cc | 150 ++++++++++++++---- .../catch/unit/device/hipIpcCloseMemHandle.cc | 38 +++++ .../catch/unit/device/hipIpcGetMemHandle.cc | 64 ++++++++ .../catch/unit/device/hipIpcOpenMemHandle.cc | 39 +++++ .../catch/unit/device/hipSetGetDevice.cc | 89 ++++++++++- .../unit/graph/hipGraphKernelNodeSetParams.cc | 4 +- .../catch/unit/graph/hipUserObjectCreate.cc | 6 +- 23 files changed, 1195 insertions(+), 140 deletions(-) diff --git a/projects/hip-tests/catch/include/hip_test_defgroups.hh b/projects/hip-tests/catch/include/hip_test_defgroups.hh index 4fa9facedb..360bfe1282 100644 --- a/projects/hip-tests/catch/include/hip_test_defgroups.hh +++ b/projects/hip-tests/catch/include/hip_test_defgroups.hh @@ -32,7 +32,14 @@ THE SOFTWARE. /** * @defgroup GraphTest Graph Management * @{ - * This section describes the graph management types & functions of HIP runtime API. + * This section describes tests for the graph management types & functions of HIP runtime API. + * @} + */ + +/** + * @defgroup DeviceTest Device Management + * @{ + * This section describes tests for device management functions of HIP runtime API. * @} */ diff --git a/projects/hip-tests/catch/multiproc/hipIpcEventHandle.cc b/projects/hip-tests/catch/multiproc/hipIpcEventHandle.cc index 440b00f598..1e16aaf7cb 100644 --- a/projects/hip-tests/catch/multiproc/hipIpcEventHandle.cc +++ b/projects/hip-tests/catch/multiproc/hipIpcEventHandle.cc @@ -17,23 +17,6 @@ OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/** - -Testcase Scenarios ------------------- -Functional: -1) Validate usecase of Event handle along with memory handle across multiple -processes with complex scenario. - -Negative/Argument Validation: -1) Get event handle with eventHandle(nullptr). -2) Get event handle with event(nullptr). -3) Get event handle with invalid event object. -4) Get event handle for event allocated without Interprocess flag. -5) Open event handle with event(nullptr). -6) Open event handle with eventHandle as invalid. -*/ - #include #include @@ -42,6 +25,14 @@ Negative/Argument Validation: #include #include +/** + * @addtogroup hipIpcGetEventHandle hipIpcGetEventHandle + * @{ + * @ingroup DeviceTest + * `hipIpcGetEventHandle(hipIpcEventHandle_t* handle, hipEvent_t event)` - + * Gets an opaque interprocess handle for an event. + * This opaque handle may be copied into other processes and opened with hipIpcOpenEventHandle. + */ #define BUF_SIZE 4096 #define MAX_DEVICES 16 @@ -65,7 +56,7 @@ typedef struct ipcBarrier { bool allExit; } ipcBarrier_t; -/** +/* Get device count and list down devices with P2P access with Device 0. */ @@ -118,7 +109,7 @@ static ipcBarrier_t *g_Barrier{}; static bool g_procSense; static int g_processCnt; -/** +/* Calling process waits for other processes to signal/complete. */ void processBarrier() { @@ -147,7 +138,7 @@ __global__ void computeKernel(int *dst, int *src, int num) { dst[idx] = src[idx] / num; } -/** +/* * 1) Process 0 allocates buffer in GPU0 memory and exports the memory handle. * 2) Other processes opens memory handle of GPU0 memory, performs computation * and records event. @@ -235,8 +226,19 @@ void runMultiProcKernel(ipcEventInfo_t *shmEventInfo, int index) { } /** - Functional test demonstrating IPC event usage along with IPC memory handle -*/ + * Test Description + * ------------------------ + * - Validate use case of event handle along with memory handle + * across multiple processes with complex scenario. + * - Utilizes synchronization of processes and events. + * - Lauches kernels and validates computation results. + * Test source + * ------------------------ + * - unit/multiproc/hipIpcEventHandle.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipIpcEventHandle_Functional") { ipcDevices_t *shmDevices; ipcEventInfo_t *shmEventInfo; @@ -300,8 +302,38 @@ TEST_CASE("Unit_hipIpcEventHandle_Functional") { } /** - Performs API Parameter validation. -*/ + * Test Description + * ------------------------ + * - Validates handling of invalid arguments for + * [hipIpcGetEventHandle](@ref hipIpcGetEventHandle): + * -# When pointer to the event handle is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When pointer to the event is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When both pointers are `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When event is not valid + * - Expected output: return `hipErrorInvalidValue` + * -# When event is created without interprocess flag + * - Expected output: return `hipErrorInvalidResourceHandle` or `hipErrorInvalidConfiguration` + * -# When event is created without flags + * - Expected output: return `hipErrorInvalidResourceHandle` + * - Validates handling of invalid arguments for + * [hipIpcOpenEventHandle](@ref hipIpcOpenEventHandle) + * -# When pointer to the event is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When pointer to the event handle is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When attemted to open handle in the process that created it + * - Expected output: return `hipErrorInvalidContext` + * Test source + * ------------------------ + * - unit/multiproc/hipIpcEventHandle.cc + * Test requirements + * ------------------------ + * - Host specific (LINUX) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipIpcEventHandle_ParameterValidation") { hipEvent_t event; hipIpcEventHandle_t eventHandle; @@ -381,4 +413,22 @@ TEST_CASE("Unit_hipIpcEventHandle_ParameterValidation") { #endif } +/** + * End doxygen group hipIpcGetEventHandle. + * @} + */ + +/** + * @addtogroup hipIpcOpenEventHandle hipIpcOpenEventHandle + * @{ + * @ingroup DeviceTest + * `hipIpcOpenEventHandle(hipEvent_t* event, hipIpcEventHandle_t handle)` - + * Opens an interprocess event handles. + * Opens an interprocess event handle exported from another process with hipIpcGetEventHandle. + * ________________________ + * Test cases from other modules: + * - @ref Unit_hipIpcEventHandle_Functional + * - @ref Unit_hipIpcEventHandle_ParameterValidation + */ + #endif diff --git a/projects/hip-tests/catch/multiproc/hipIpcMemAccessTest.cc b/projects/hip-tests/catch/multiproc/hipIpcMemAccessTest.cc index fee23c1ef4..8750bc4306 100644 --- a/projects/hip-tests/catch/multiproc/hipIpcMemAccessTest.cc +++ b/projects/hip-tests/catch/multiproc/hipIpcMemAccessTest.cc @@ -17,12 +17,6 @@ OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - 1)Testcase verifies the hipIpcMemAccess APIs by creating memory handle -in parent process and access it in child process. - 2)Test case performs Parameter validation of hipIpcMemAccess APIs. -*/ - #include #include @@ -34,6 +28,14 @@ in parent process and access it in child process. #include #include +/** + * @addtogroup hipIpcOpenMemHandle hipIpcOpenMemHandle + * @{ + * @ingroup DeviceTest + * `hipIpcOpenMemHandle(void** devPtr, hipIpcMemHandle_t handle, unsigned int flags)` - + * Opens an interprocess memory handle exported from another process + * and returns a device pointer usable in the local process. + */ #define NUM_ELMTS 1024 #define NUM_THREADS 10 @@ -58,6 +60,23 @@ typedef struct mem_handle { // and check for data consistencies and close the hipIpcCloseMemHandle // release the parent and wait for parent to release itself(child) +/** + * Test Description + * ------------------------ + * - Verifies that getting and opening mem handle works correctly + * in specific scenarion, and handles the case when the same device + * is used in both processes. + * - Creates memory from the parent process for each device. + * - Spawns child process and waits for it to finish. + * - Child process gets the handle and check data consistencies. + * Test source + * ------------------------ + * - unit/multiproc/hipIpcMemAccessTest.cc + * Test requirements + * ------------------------ + * - Host specific (LINUX) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipIpcMemAccess_Semaphores") { hip_ipc_t *shrd_mem = NULL; pid_t pid; @@ -161,6 +180,39 @@ TEST_CASE("Unit_hipIpcMemAccess_Semaphores") { REQUIRE(shrd_mem->IfTestPassed == true); } +/** + * Test Description + * ------------------------ + * - Validates handling of valid and invalid arguments for + * [hipIpcGetMemHandle](@ref hipIpcGetMemHandle): + * -# When memory handle pointer is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When device pointer is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When both pointers are `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When both pointers are valid + * - Expected output: return `hipSuccess` + * - Validates handling of valid and invalid arguments for + * [hipIpcOpenMemHandle](@ref hipIpcOpenMemHandle): + * -# When device pointer is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When memory handle pointer uninitialized + * - Expected output: return `hipErrorInvalidValue` or `hipErrorInvalidDevicePointer` + * -# When memory handle has random flags + * - Expected output: return `hipErrorInvalidValue` + * - Validates handling of valid and invalid arguments for + * [hipIpcCloseMemHandle](@ref hipIpcCloseMemHandle): + * -# When device pointer is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/multiproc/hipIpcMemAccessTest.cc + * Test requirements + * ------------------------ + * - Host specific (LINUX) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipIpcMemAccess_ParameterValidation") { hipIpcMemHandle_t MemHandle; hipIpcMemHandle_t MemHandleUninit; diff --git a/projects/hip-tests/catch/unit/device/hipChooseDevice.cc b/projects/hip-tests/catch/unit/device/hipChooseDevice.cc index 0cbcc68a4a..d27cddc424 100644 --- a/projects/hip-tests/catch/unit/device/hipChooseDevice.cc +++ b/projects/hip-tests/catch/unit/device/hipChooseDevice.cc @@ -23,8 +23,23 @@ THE SOFTWARE. #include /** - * hipChooseDevice tests - * Scenario: Validates dev id value. + * @addtogroup hipChooseDevice hipChooseDevice + * @{ + * @ingroup DeviceTest + * `hipChooseDevice(int* device, const hipDeviceProp_t* prop)` - + * Device which matches `hipDeviceProp_t` is returned. + */ + +/** + * Test Description + * ------------------------ + * - Validate chosen device against gotten device properties. + * Test source + * ------------------------ + * - unit/device/hipChooseDevice.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipChooseDevice_ValidateDevId") { hipDeviceProp_t prop; @@ -36,21 +51,30 @@ TEST_CASE("Unit_hipChooseDevice_ValidateDevId") { REQUIRE_FALSE(dev < 0); REQUIRE_FALSE(dev >= numDevices); } + /** - * hipChooseDevice tests - * Scenario1: Validates if dev = nullptr returns error code - * Scenario2: Validates if prop = nullptr returns error code + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When pointer to the device is `nullptr` + * - Expected output: do not return `hipSuccess` + * -# When pointer to the properties is `nullptr` + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/device/hipChooseDevice.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipChooseDevice_NegTst") { hipDeviceProp_t prop; int dev = -1; - // Scenario1 SECTION("dev is nullptr") { REQUIRE_FALSE(hipSuccess == hipChooseDevice(nullptr, &prop)); } - // Scenario2 SECTION("prop is nullptr") { REQUIRE_FALSE(hipSuccess == hipChooseDevice(&dev, nullptr)); } diff --git a/projects/hip-tests/catch/unit/device/hipDeviceGetDefaultMemPool.cc b/projects/hip-tests/catch/unit/device/hipDeviceGetDefaultMemPool.cc index 822c2ab81c..12d620d6ce 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceGetDefaultMemPool.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceGetDefaultMemPool.cc @@ -23,6 +23,25 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipDeviceGetDefaultMemPool hipDeviceGetDefaultMemPool + * @{ + * @ingroup DeviceTest + * `hipDeviceGetDefaultMemPool(hipMemPool_t* mem_pool, int device)` - + * Returns the default memory pool of the specified device + */ + +/** + * Test Description + * ------------------------ + * - Check that MemPool can be fetched and is not `nullptr`. + * Test source + * ------------------------ + * - unit/device/hipDeviceGetDefaultMemPool.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetDefaultMemPool_Positive_Basic") { const int device = GENERATE(range(0, HipTest::getDeviceCount())); @@ -39,6 +58,23 @@ TEST_CASE("Unit_hipDeviceGetDefaultMemPool_Positive_Basic") { REQUIRE(mem_pool != nullptr); } +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the MemPool is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When device ID is equal to -1 + * - Expected output: return 'hipErrorInvalidDevice' + * -# When device ID is out of bounds + * - Expected output: return 'hipErrorInvalidDevice' + * Test source + * ------------------------ + * - unit/device/hipDeviceGetDefaultMemPool.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetDefaultMemPool_Negative_Parameters") { hipMemPool_t mem_pool; diff --git a/projects/hip-tests/catch/unit/device/hipDeviceGetLimit.cc b/projects/hip-tests/catch/unit/device/hipDeviceGetLimit.cc index cf3de67cdc..24c9b143e0 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceGetLimit.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceGetLimit.cc @@ -17,34 +17,59 @@ OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Conformance test for checking functionality of - * hipError_t hipDeviceGetLimit(size_t* pValue, enum hipLimit_t limit); - */ -#include /** - * hipDeviceGetLimit tests - * Scenario1: Validates if pValue = nullptr returns hip error code. - * Scenario2: Validates if *pValue > 0 is returned for limit = hipLimitMallocHeapSize. - * Scenario3: Validates if error code is returned for limit = Invalid Flag = 0xff. + * @addtogroup hipDeviceGetLimit hipDeviceGetLimit + * @{ + * @ingroup DeviceTest + * `hipDeviceGetLimit(size_t* pValue, enum hipLimit_t limit)` - + * Get Resource limits of current device. + */ + +#include + +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the limit value is `nullptr` + * - Expected output: do not return `hipSuccess` + * -# When limit enum is out of bounds + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/device/hipDeviceGetLimit.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceGetLimit_NegTst") { size_t Value = 0; - // Scenario1 + SECTION("NULL check") { REQUIRE_FALSE(hipDeviceGetLimit(nullptr, hipLimitMallocHeapSize) == hipSuccess); } - // Scenario3 + SECTION("Invalid Input Flag") { REQUIRE_FALSE(hipDeviceGetLimit(&Value, static_cast(0xff)) == hipSuccess); } } +/** + * Test Description + * ------------------------ + * - Validate that returned limit value for Malloc Heap size is valid. + * Test source + * ------------------------ + * - unit/device/hipDeviceGetLimit.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetLimit_CheckValidityOfOutputVal") { size_t Value = 0; - // Scenario2 + REQUIRE(hipDeviceGetLimit(&Value, hipLimitMallocHeapSize) == hipSuccess); REQUIRE_FALSE(Value <= 0); diff --git a/projects/hip-tests/catch/unit/device/hipDeviceReset.cc b/projects/hip-tests/catch/unit/device/hipDeviceReset.cc index ad9e6fe0c1..b65155db6f 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceReset.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceReset.cc @@ -22,6 +22,30 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipDeviceReset hipDeviceReset + * @{ + * @ingroup DeviceTest + * `hipDeviceReset(void)` - + * The state of current device is discarded and updated to a fresh state. + * + * Calling this function deletes all streams created, memory allocated, kernels running, events + * created. Make sure that no other thread is using the device or streams, memory, kernels, events + * associated with the current device. + */ + +/** + * Test Description + * ------------------------ + * - Validates that device reset frees allocated memory and + * reverts modified flags and configs to its default values. + * Test source + * ------------------------ + * - unit/device/hipDeviceReset.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceReset_Positive_Basic") { const auto device = GENERATE(range(0, HipTest::getDeviceCount())); HIP_CHECK(hipSetDevice(device)); @@ -74,6 +98,19 @@ TEST_CASE("Unit_hipDeviceReset_Positive_Basic") { } } +/** + * Test Description + * ------------------------ + * - Resets device from another thread + * - Validates that device reset frees allocated memory from the main + * thread, and reverts modified flags and configs to its default values. + * Test source + * ------------------------ + * - unit/device/hipDeviceReset.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceReset_Positive_Threaded") { HIP_CHECK(hipSetDevice(0)); INFO("Current device is: " << 0); diff --git a/projects/hip-tests/catch/unit/device/hipDeviceSetGetCacheConfig.cc b/projects/hip-tests/catch/unit/device/hipDeviceSetGetCacheConfig.cc index dc82a85fc3..5034bf9d46 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceSetGetCacheConfig.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceSetGetCacheConfig.cc @@ -24,13 +24,31 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipDeviceSetCacheConfig hipDeviceSetCacheConfig + * @{ + * @ingroup DeviceTest + * `hipDeviceSetCacheConfig(hipFuncCache_t cacheConfig)` - + * Set L1/Shared cache partition. + */ + namespace { constexpr std::array kCacheConfigs{ hipFuncCachePreferNone, hipFuncCachePreferShared, hipFuncCachePreferL1, hipFuncCachePreferEqual}; } // anonymous namespace - +/** + * Test Description + * ------------------------ + * - Check that `hipSuccess` is returned for all enumerators of `hipFuncCache_t` + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetCacheConfig.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceSetCacheConfig_Positive_Basic") { const auto device = GENERATE(range(0, HipTest::getDeviceCount())); HIP_CHECK(hipSetDevice(device)); @@ -41,6 +59,21 @@ TEST_CASE("Unit_hipDeviceSetCacheConfig_Positive_Basic") { HIP_CHECK(hipDeviceSetCacheConfig(cache_config)); } +/** + * Test Description + * ------------------------ + * - Handle invalid cache config (-1): + * -# When platform is AMD + * - Expected output: return `hipErrorNotSupported` + * -# When platform is NVIDIA + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetCacheConfig.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceSetCacheConfig_Negative_Parameters") { #if HT_AMD HIP_CHECK_ERROR(hipDeviceSetCacheConfig(static_cast(-1)), hipSuccess); @@ -49,6 +82,31 @@ TEST_CASE("Unit_hipDeviceSetCacheConfig_Negative_Parameters") { #endif } +/** + * End doxygen group hipDeviceSetCacheConfig. + * @} + */ + +/** + * @addtogroup hipDeviceGetCacheConfig hipDeviceGetCacheConfig + * @{ + * @ingroup DeviceTest + * `hipDeviceGetCacheConfig(hipFuncCache_t* cacheConfig)` - + * Get Cache configuration for a specific Device. + */ + +/** + * Test Description + * ------------------------ + * - Check that default cache config is returned if set + * has not been called previously. + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetCacheConfig.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetCacheConfig_Positive_Default") { const auto device = GENERATE(range(0, HipTest::getDeviceCount())); HIP_CHECK(hipSetDevice(device)); @@ -59,6 +117,19 @@ TEST_CASE("Unit_hipDeviceGetCacheConfig_Positive_Default") { REQUIRE(cache_config == hipFuncCachePreferNone); } +/** + * Test Description + * ------------------------ + * - Check that the returned cache configuration is equal to + * the one that is set previously. + * - Verify for multiple devices. + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetCacheConfig.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetCacheConfig_Positive_Basic") { const auto device = GENERATE(range(0, HipTest::getDeviceCount())); HIP_CHECK(hipSetDevice(device)); @@ -74,6 +145,18 @@ TEST_CASE("Unit_hipDeviceGetCacheConfig_Positive_Basic") { REQUIRE(returned_cache_config == cache_config); } +/** + * Test Description + * ------------------------ + * - Check that the returned cache configuration from the main thread + * is equal to the one that is set previously from different thread. + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetCacheConfig.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetCacheConfig_Positive_Threaded") { class HipDeviceSetGetCacheConfigTest : public ThreadedZigZagTest { public: @@ -99,6 +182,19 @@ TEST_CASE("Unit_hipDeviceGetCacheConfig_Positive_Threaded") { test.run(); } +/** + * Test Description + * ------------------------ + * - Verify handling of invalid arguments: + * -# When cache config is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetCacheConfig.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_HipDeviceGetCacheConfig_Negative_Parameters") { HIP_CHECK_ERROR(hipDeviceGetCacheConfig(nullptr), hipErrorInvalidValue); } diff --git a/projects/hip-tests/catch/unit/device/hipDeviceSetGetMemPool.cc b/projects/hip-tests/catch/unit/device/hipDeviceSetGetMemPool.cc index 089c8003ac..83329146ca 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceSetGetMemPool.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceSetGetMemPool.cc @@ -24,6 +24,16 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipDeviceSetMemPool hipDeviceSetMemPool + * @{ + * @ingroup DeviceTest + * `hipDeviceSetMemPool(int device, hipMemPool_t mem_pool)` - + * Sets the current memory pool of a device. + * + * The memory pool must be local to the specified device. + */ + static inline bool CheckMemPoolSupport(const int device) { int mem_pool_support = 0; HIP_CHECK( @@ -50,6 +60,18 @@ static inline hipMemPool_t CreateMemPool(const int device) { return mem_pool; } +/** + * Test Description + * ------------------------ + * - Validate behaviour when the valid MemPool is used, for multiple devices. + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetMemPool.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceSetMemPool_Positive_Basic") { const int device = GENERATE(range(0, HipTest::getDeviceCount())); @@ -63,6 +85,24 @@ TEST_CASE("Unit_hipDeviceSetMemPool_Positive_Basic") { HIP_CHECK(hipMemPoolDestroy(mem_pool)); } +/** + * Test Description + * ------------------------ + * - Validate handling of invalid arguments: + * -# When pointer to MemPool is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When device ID is equal to -1 + * - Expected output: return `hipErrorInvalidValue` + * -# When device ID is out of bounds + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetMemPool.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceSetMemPool_Negative_Parameters") { hipMemPool_t mem_pool; HIP_CHECK(hipDeviceGetDefaultMemPool(&mem_pool, 0)); @@ -80,6 +120,31 @@ TEST_CASE("Unit_hipDeviceSetMemPool_Negative_Parameters") { } } +/** + * End doxygen group hipDeviceSetMemPool. + * @} + */ + +/** + * @addtogroup hipDeviceGetMemPool hipDeviceGetMemPool + * @{ + * @ingroup DeviceTest + * `hipDeviceGetMemPool(hipMemPool_t* mem_pool, int device)` - + * Gets the current memory pool for the specified device + */ + +/** + * Test Description + * ------------------------ + * - Checks that returned MemPool is the default MemPool. + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetMemPool.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetMemPool_Positive_Default") { const int device = GENERATE(range(0, HipTest::getDeviceCount())); @@ -96,6 +161,18 @@ TEST_CASE("Unit_hipDeviceGetMemPool_Positive_Default") { REQUIRE(mem_pool == default_mem_pool); } +/** + * Test Description + * ------------------------ + * - Checks that returned MemPool is equal to the mempool that is set. + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetMemPool.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetMemPool_Positive_Basic") { const int device = GENERATE(range(0, HipTest::getDeviceCount())); @@ -114,6 +191,18 @@ TEST_CASE("Unit_hipDeviceGetMemPool_Positive_Basic") { HIP_CHECK(hipMemPoolDestroy(mem_pool)); } +/** + * Test Description + * ------------------------ + * - Checks that returned MemPool is equal to the mempool that is set from a different thread. + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetMemPool.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetMemPool_Positive_Threaded") { class HipDeviceGetMemPoolTest : public ThreadedZigZagTest { public: @@ -141,6 +230,24 @@ TEST_CASE("Unit_hipDeviceGetMemPool_Positive_Threaded") { test.run(); } +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the MemPool is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When device ID is equal to -1 + * - Expected output: return `hipErrorInvalidValue` + * -# When device ID is out of bounds + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetMemPool.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetMemPool_Negative_Parameters") { hipMemPool_t mem_pool; diff --git a/projects/hip-tests/catch/unit/device/hipDeviceSetGetSharedMemConfig.cc b/projects/hip-tests/catch/unit/device/hipDeviceSetGetSharedMemConfig.cc index 9a1230a7c8..ca8df7458c 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceSetGetSharedMemConfig.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceSetGetSharedMemConfig.cc @@ -24,11 +24,30 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipDeviceSetSharedMemConfig hipDeviceSetSharedMemConfig + * @{ + * @ingroup DeviceTest + * `hipDeviceSetSharedMemConfig(hipSharedMemConfig config)` - + * The bank width of shared memory on current device is set. + */ + namespace { constexpr std::array kMemConfigs{ hipSharedMemBankSizeDefault, hipSharedMemBankSizeFourByte, hipSharedMemBankSizeEightByte}; } // anonymous namespace +/** + * Test Description + * ------------------------ + * - Checks that all shared memory configs can be set. + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetSharedMemConfig.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceSetSharedMemConfig_Positive_Basic") { const auto device = GENERATE(range(0, HipTest::getDeviceCount())); const auto mem_config = GENERATE(from_range(std::begin(kMemConfigs), std::end(kMemConfigs))); @@ -38,11 +57,49 @@ TEST_CASE("Unit_hipDeviceSetSharedMemConfig_Positive_Basic") { HIP_CHECK(hipDeviceSetSharedMemConfig(mem_config)); } +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When shared memory config has ordinal enum number -1: + * - AMD expected output: return `hipErrorNotSupported` + * - NVIDIA expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetSharedMemConfig.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceSetSharedMemConfig_Negative_Parameters") { HIP_CHECK_ERROR(hipDeviceSetSharedMemConfig(static_cast(-1)), hipErrorInvalidValue); } +/** + * End doxygen group hipDeviceSetSharedMemConfig. + * @} + */ + +/** + * @addtogroup hipDeviceGetSharedMemConfig hipDeviceGetSharedMemConfig + * @{ + * @ingroup DeviceTest + * `hipDeviceGetSharedMemConfig(hipSharedMemConfig* pConfig)` - + * Returns bank width of shared memory for current device. + */ + +/** + * Test Description + * ------------------------ + * - Checks that the returned shared memory configuration is the default one. + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetSharedMemConfig.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetSharedMemConfig_Positive_Default") { const auto device = GENERATE(range(0, HipTest::getDeviceCount())); HIP_CHECK(hipSetDevice(device)); @@ -53,6 +110,18 @@ TEST_CASE("Unit_hipDeviceGetSharedMemConfig_Positive_Default") { REQUIRE(mem_config == hipSharedMemBankSizeFourByte); } +/** + * Test Description + * ------------------------ + * - Checks that the returned shared memory configuration is equal + * to the one that is set previously. + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetSharedMemConfig.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetSharedMemConfig_Positive_Basic") { const auto device = GENERATE(range(0, HipTest::getDeviceCount())); const auto mem_config = GENERATE(from_range(std::begin(kMemConfigs), std::end(kMemConfigs))); @@ -74,6 +143,19 @@ TEST_CASE("Unit_hipDeviceGetSharedMemConfig_Positive_Basic") { } } +/** + * Test Description + * ------------------------ + * - Checks that the returned shared memory configuration from + * the main thread is equal to the one that is set in a separate + * thread previously. + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetSharedMemConfig.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetSharedMemConfig_Positive_Threaded") { class HipDeviceGetSharedMemConfigTest : public ThreadedZigZagTest { @@ -107,6 +189,19 @@ TEST_CASE("Unit_hipDeviceGetSharedMemConfig_Positive_Threaded") { test.run(); } +/** + * Test Description + * ------------------------ + * - Verifies handling of invalid arguments: + * -# When pointer to the output shared memory configuration is `nullptr`: + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/device/hipDeviceSetGetSharedMemConfig.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetSharedMemConfig_Negative_Parameters") { HIP_CHECK_ERROR(hipDeviceGetSharedMemConfig(nullptr), hipErrorInvalidValue); } diff --git a/projects/hip-tests/catch/unit/device/hipDeviceSetLimit.cc b/projects/hip-tests/catch/unit/device/hipDeviceSetLimit.cc index 0007a942e7..4760f22756 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceSetLimit.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceSetLimit.cc @@ -17,12 +17,16 @@ OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Conformance test for checking functionality of - * hipError_t hipDeviceSetLimit ( enum hipLimit_t limit, size_t value ); - */ #include +/** + * @addtogroup hipDeviceSetLimit hipDeviceSetLimit + * @{ + * @ingroup DeviceTest + * `hipDeviceSetLimit(enum hipLimit_t limit, size_t value)` - + * Set Resource limits of current device. + */ + // Currently the HIGHER_VALUE is fixed to 16 KB based on currently // set maximum value for hipLimitStackSize. In future, this value // might need to change to avoid test case failure. In the same way @@ -51,17 +55,15 @@ static bool testSetLimitFunc(hipLimit_t limit_to_test) { } /** - * hipDeviceSetLimit tests => - * - * Scenario1: Single device Set-Get test for hipLimitStackSize flag. - * - * Scenario2: Single device Set-Get test for hipLimitPrintfFifoSize flag. - * - * Scenario3: Single device Set-Get test for hipLimitMallocHeapSize flag. - * - * Scenario4: Multidevice Set-Get test for all the flags - * - * Scenario5: Negative Scenario - Invalid flag value + * Test Description + * ------------------------ + * - Sets different values for the resource limits. + * Test source + * ------------------------ + * - unit/device/hipDeviceSetLimit.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceSetLimit_SetGet") { size_t value = 0; diff --git a/projects/hip-tests/catch/unit/device/hipDeviceSynchronize.cc b/projects/hip-tests/catch/unit/device/hipDeviceSynchronize.cc index 4dd3ed0dff..b94ddc39a9 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceSynchronize.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceSynchronize.cc @@ -20,14 +20,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Test for checking the functionality of - * hipError_t hipDeviceSynchronize(); - */ - - #include +/** + * @addtogroup hipDeviceSynchronize hipDeviceSynchronize + * @{ + * @ingroup DeviceTest + * `hipDeviceSynchronize(void)` - + * Waits on all active streams on current device. + * When this command is invoked, the host thread gets blocked until all the commands associated + * with streams associated with the device. HIP does not support multiple blocking modes (yet!). + */ + #define _SIZE sizeof(int) * 1024 * 1024 #define NUM_STREAMS 2 #define NUM_ITERS 1 << 30 @@ -44,6 +48,18 @@ static __global__ void Iter(int* Ad, int num) { } } +/** + * Test Description + * ------------------------ + * - Performs synchronization when no work is enqueued on stream, + * utilizing multiple devices. + * Test source + * ------------------------ + * - unit/device/hipDeviceSynchronize.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceSynchronize_Positive_Empty_Streams") { const auto device = GENERATE(range(0, HipTest::getDeviceCount())); HIP_CHECK(hipSetDevice(device)); @@ -55,6 +71,18 @@ TEST_CASE("Unit_hipDeviceSynchronize_Positive_Empty_Streams") { HIP_CHECK(hipStreamDestroy(stream)); } +/** + * Test Description + * ------------------------ + * - Performs synchronization between large kernel execution + * and asynchronous copying of the array, on default(null) stream. + * Test source + * ------------------------ + * - unit/device/hipDeviceSynchronize.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceSynchronize_Positive_Nullstream") { const auto device = GENERATE(range(0, HipTest::getDeviceCount())); HIP_CHECK(hipSetDevice(device)); @@ -78,6 +106,18 @@ TEST_CASE("Unit_hipDeviceSynchronize_Positive_Nullstream") { REQUIRE(1 << 30 == A_h[0] - 1); } +/** + * Test Description + * ------------------------ + * - Performs synchronization between large kernel execution + * and asynchronous copying of the array, on multiple streams. + * Test source + * ------------------------ + * - unit/device/hipDeviceSynchronize.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceSynchronize_Functional") { int* A[NUM_STREAMS]; int* Ad[NUM_STREAMS]; diff --git a/projects/hip-tests/catch/unit/device/hipExtGetLinkTypeAndHopCount.cc b/projects/hip-tests/catch/unit/device/hipExtGetLinkTypeAndHopCount.cc index 7911b133ec..8c10e5976f 100644 --- a/projects/hip-tests/catch/unit/device/hipExtGetLinkTypeAndHopCount.cc +++ b/projects/hip-tests/catch/unit/device/hipExtGetLinkTypeAndHopCount.cc @@ -23,7 +23,28 @@ THE SOFTWARE. #include #include -#if __linux__ && HT_AMD +/** + * @addtogroup hipExtGetLinkTypeAndHopCount hipExtGetLinkTypeAndHopCount + * @{ + * @ingroup DeviceTest + * `hipExtGetLinkTypeAndHopCount(int device1, int device2, uint32_t* linktype, uint32_t* hopcount)` - + * Returns the link type and hop count between two devices. + */ + +#if __linux__ +#if HT_AMD +/** + * Test Description + * ------------------------ + * - Check commutativity of devices for every device combination. + * Test source + * ------------------------ + * - unit/device/hipExtGetLinkTypeAndHopCount.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipExtGetLinkTypeAndHopCount_Positive_Basic") { const auto device1 = GENERATE(range(0, HipTest::getDeviceCount())); const auto device2 = GENERATE(range(0, HipTest::getDeviceCount())); @@ -44,6 +65,38 @@ TEST_CASE("Unit_hipExtGetLinkTypeAndHopCount_Positive_Basic") { REQUIRE(link_type1 == link_type2); } +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When creating the link between the same device + * - Expected output: return `hipErrorInvalidValue` + * -# When device ordinance for the first device is out of bounds + * - Expected output: return `hipErrorInvalidDevice` + * -# When device ordinance for the second device is out of bounds + * - Expected output: return `hipErrorInvalidDevice` + * -# When device ordinance for both devices is out of bounds + * - Expected output: return `hipErrorInvalidDevice` + * -# When device ordinance for the first device is < 0 + * - Expected output: return `hipErrorInvalidValue` + * -# When device ordinance for the second device is < 0 + * - Expected output: return `hipErrorInvalidValue` + * -# When device ordinance for both devices is < 0 + * - Expected output: return `hipErrorInvalidValue` + * -# When pointer to the link type is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When pointer to the hop count is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When both pointers are `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/device/hipExtGetLinkTypeAndHopCount.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipExtGetLinkTypeAndHopCount_Negative_Parameters") { uint32_t link_type, hop_count; SECTION("same device") { @@ -98,3 +151,4 @@ TEST_CASE("Unit_hipExtGetLinkTypeAndHopCount_Negative_Parameters") { } } #endif +#endif diff --git a/projects/hip-tests/catch/unit/device/hipGetDeviceAttribute.cc b/projects/hip-tests/catch/unit/device/hipGetDeviceAttribute.cc index 208f997e2b..780a1877a4 100644 --- a/projects/hip-tests/catch/unit/device/hipGetDeviceAttribute.cc +++ b/projects/hip-tests/catch/unit/device/hipGetDeviceAttribute.cc @@ -16,7 +16,6 @@ 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. */ -// Test the device info API extensions for HIP #include #ifdef __linux__ @@ -28,6 +27,14 @@ THE SOFTWARE. #include +/** + * @addtogroup hipDeviceGetAttribute hipDeviceGetAttribute + * @{ + * @ingroup DeviceTest + * `hipDeviceGetAttribute(int* pi, hipDeviceAttribute_t attr, int deviceId)` - + * Query for a specific device attribute. + */ + static hipError_t test_hipDeviceGetAttribute(int deviceId, hipDeviceAttribute_t attr, int expectedValue = -1) { @@ -64,6 +71,18 @@ static hipError_t test_hipDeviceGetHdpAddress(int deviceId, return hipSuccess; } +/** + * Test Description + * ------------------------ + * - Validate various device attributes against device properties. + * - Matching attribute and property value shall be equal. + * Test source + * ------------------------ + * - unit/device/hipGetDeviceAttribute.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetDeviceAttribute_CheckAttrValues") { int deviceId; HIP_CHECK(hipGetDevice(&deviceId)); @@ -235,7 +254,7 @@ TEST_CASE("Unit_hipGetDeviceAttribute_CheckAttrValues") { hipDeviceAttributeUnifiedAddressing, 1/*true*/)); } -/** +/* * Validate the hipDeviceAttributeFineGrainSupport property in AMD. */ #ifdef __linux__ @@ -264,7 +283,19 @@ static bool isRocmPathSet() { return false; } -// This is AMD specific property test +/** + * Test Description + * ------------------------ + * - Validate fine grain support attribute against + * known values for different AMD architectures + * Test source + * ------------------------ + * - unit/device/hipGetDeviceAttribute.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetDeviceAttribute_CheckFineGrainSupport") { int deviceId; int deviceCount = 0; @@ -326,12 +357,25 @@ TEST_CASE("Unit_hipGetDeviceAttribute_CheckFineGrainSupport") { } #endif #endif + /** - * Validates negative scenarios for hipDeviceGetAttribute - * scenario1: pi = nullptr - * scenario2: device = -1 (Invalid Device) - * scenario3: device = Non Existing Device - * scenario4: attr = Invalid Attribute + * Test Description + * ------------------------ + * - Validates negative scenarios: + * -# When pointer to value is `nullptr` + * - Expected output: do not return `hipSuccess` + * -# When device ID is `-1` + * - Expected output: do not return `hipSuccess` + * -# When device ID is out of bounds + * - Expected output: do not return `hipSuccess` + * -# When attribute is invalid (-1) + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/device/hipGetDeviceAttribute.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceGetAttribute_NegTst") { int deviceCount = 0; @@ -526,6 +570,17 @@ template void printAttributes(const AttributeToStringMap& attribut std::flush(std::cout); } +/** + * Test Description + * ------------------------ + * - Print out all device attributes in agreed upon format. + * Test source + * ------------------------ + * - unit/device/hipGetDeviceAttribute.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Print_Out_Attributes") { const auto device = GENERATE(range(0, HipTest::getDeviceCount())); hipDeviceProp_t properties; diff --git a/projects/hip-tests/catch/unit/device/hipGetDeviceCount.cc b/projects/hip-tests/catch/unit/device/hipGetDeviceCount.cc index 387afc5ff6..d0d77a5e06 100644 --- a/projects/hip-tests/catch/unit/device/hipGetDeviceCount.cc +++ b/projects/hip-tests/catch/unit/device/hipGetDeviceCount.cc @@ -20,23 +20,45 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Conformance test for checking functionality of - * hipError_t hipGetDeviceCount(int* count); - */ - #include #include /** - * hipGetDeviceCount tests - * Scenario: Validates if &numDevices = nullptr returns error code. + * @addtogroup hipGetDeviceCount hipGetDeviceCount + * @{ + * @ingroup DeviceTest + * `hipGetDeviceCount(int* count)` - + * Return number of compute-capable devices. + */ + +/** + * Test Description + * ------------------------ + * - Passes invalid pointer as output parameter for device count - `nullptr` + * Test source + * ------------------------ + * - unit/device/hipGetDeviceCount.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipGetDeviceCount_NegTst") { - // Scenario1 REQUIRE_FALSE(hipGetDeviceCount(nullptr) == hipSuccess); } +/** + * Test Description + * ------------------------ + * - Validates correct functionality when the device visibility + * environment variables are set. Uses unit/device/hipDeviceCount_exe.cc + * to set visibility. + * Test source + * ------------------------ + * - unit/device/hipGetDeviceCount.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetDeviceCount_HideDevices") { int deviceCount = HipTest::getDeviceCount(); if (deviceCount < 2) { @@ -59,6 +81,17 @@ TEST_CASE("Unit_hipGetDeviceCount_HideDevices") { } } +/** + * Test Description + * ------------------------ + * - Prints device count to the standard output. + * Test source + * ------------------------ + * - unit/device/hipGetDeviceCount.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Print_Out_Device_Count") { std::cout << "Device Count: " << HipTest::getDeviceCount() << std::endl; } \ No newline at end of file diff --git a/projects/hip-tests/catch/unit/device/hipGetDeviceProperties.cc b/projects/hip-tests/catch/unit/device/hipGetDeviceProperties.cc index ae8d7db439..05a56dccb0 100644 --- a/projects/hip-tests/catch/unit/device/hipGetDeviceProperties.cc +++ b/projects/hip-tests/catch/unit/device/hipGetDeviceProperties.cc @@ -22,6 +22,13 @@ THE SOFTWARE. #include +/** + * @addtogroup hipGetDeviceProperties hipGetDeviceProperties + * @{ + * @ingroup DeviceTest + * `hipGetDeviceProperties(hipDeviceProp_t* prop, int deviceId)` - + * Returns device properties. + */ #define NUM_OF_ARCHPROP 17 #define HIP_ARCH_HAS_GLOBAL_INT32_ATOMICS_IDX 0 @@ -66,7 +73,7 @@ __global__ void mykernel(int *archProp_d) { getArchValuesFromDevice(archProp_d); } -/** +/* * Internal Functions */ static void validateDeviceMacro(int *archProp_h, hipDeviceProp_t *prop) { @@ -121,7 +128,7 @@ static void validateDeviceMacro(int *archProp_h, hipDeviceProp_t *prop) { CHECK_FALSE(prop->arch.hasDynamicParallelism != archProp_h[HIP_ARCH_HAS_DYNAMIC_PARALLEL_IDX]); } -/** +/* * Validates value of __HIP_ARCH_* with deviceProp.arch.has* as follows * __HIP_ARCH_HAS_GLOBAL_INT32_ATOMICS__ == hasGlobalInt32Atomics * __HIP_ARCH_HAS_GLOBAL_FLOAT_ATOMIC_EXCH__ == hasGlobalFloatAtomicExch @@ -142,6 +149,18 @@ static void validateDeviceMacro(int *archProp_h, hipDeviceProp_t *prop) { * __HIP_ARCH_HAS_DYNAMIC_PARALLEL__ == hasDynamicParallelism */ #if HT_AMD +/** + * Test Description + * ------------------------ + * - Compare some device properties against properties derived from device code. + * Test source + * ------------------------ + * - unit/device/hipGetDeviceProperties.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetDeviceProperties_ArchPropertiesTst") { int *archProp_h, *archProp_d; archProp_h = new int[NUM_OF_ARCHPROP]; @@ -174,11 +193,23 @@ TEST_CASE("Unit_hipGetDeviceProperties_ArchPropertiesTst") { delete[] archProp_h; } #endif + /** - * Validates negative scenarios for hipGetDeviceProperties - * scenario1: props = nullptr - * scenario2: device = -1 (Invalid Device) - * scenario3: device = Non Existing Device + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the properties is `nullptr` + * - Expected output: do not return `hipSuccess` + * -# When the device ID is equal to -1 + * - Expected output: do not return `hipSuccess` + * -# When the device ID is out of bounds + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/device/hipGetDeviceProperties.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipGetDeviceProperties_NegTst") { hipDeviceProp_t prop; @@ -201,6 +232,17 @@ TEST_CASE("Unit_hipGetDeviceProperties_NegTst") { } } +/** + * Test Description + * ------------------------ + * - Print out all properties in agreed upon format. + * Test source + * ------------------------ + * - unit/device/hipGetDeviceProperties.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Print_Out_Properties") { constexpr int w = 42; const auto device = GENERATE(range(0, HipTest::getDeviceCount())); diff --git a/projects/hip-tests/catch/unit/device/hipGetSetDeviceFlags.cc b/projects/hip-tests/catch/unit/device/hipGetSetDeviceFlags.cc index c661f4e7ba..68f20ea3e5 100644 --- a/projects/hip-tests/catch/unit/device/hipGetSetDeviceFlags.cc +++ b/projects/hip-tests/catch/unit/device/hipGetSetDeviceFlags.cc @@ -22,42 +22,32 @@ THE SOFTWARE. #include #include #include + /** - * Conformance test for checking functionality of - * hipError_t hipGetDeviceFlags(unsigned int* flags); - * hipError_t hipSetDeviceFlags(unsigned flags); - * - * - * hipGetDeviceFlags and hipSetDeviceFlags tests. - * Scenario1: Validates if hipGetDeviceFlags returns hipErrorInvalidValue for flags = nullptr. - * Scenario2: Validates if hipSetDeviceFlags returns hipErrorInvalidValue for invalid flags. - * Scenario3: Validates if flags returned by hipGetDeviceFlags are valid. - * Scenario4: Validates that flags set with hipSetDeviceFlags can be retrieved with - * hipGetDeviceFlags. - * Scenario5: Validates that flags set with hipSetDeviceFlags can be retrieved on a seperate thread - * with hipGetDeviceFlags. + * @addtogroup hipGetDeviceFlags hipGetDeviceFlags + * @{ + * @ingroup DeviceTest + * `hipGetDeviceFlags(unsigned int* flags)` - + * Gets the flags set for current device. + */ + +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the flag is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/device/hipGetSetDeviceFlags.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipGetSetDeviceFlags_NullptrFlag") { - // Scenario1 HIP_CHECK_ERROR(hipGetDeviceFlags(nullptr), hipErrorInvalidValue); } -TEST_CASE("Unit_hipGetSetDeviceFlags_InvalidFlag") { -#if HT_AMD - HipTest::HIP_SKIP_TEST("EXSWCPHIPT-115"); - return; -#endif - // Scenario2 - const unsigned int invalidFlag = GENERATE(0b011, // schedule flags should not overlap - 0b101, // schedule flags should not overlap - 0b110, // schedule flags should not overlap - 0b111, // schedule flags should not overlap - 0b100000, // out of bounds - 0xFFFF); - CAPTURE(invalidFlag); - HIP_CHECK_ERROR(hipSetDeviceFlags(invalidFlag), hipErrorInvalidValue); -} - std::array getValidFlags() { constexpr std::array scheduleFlags{hipDeviceScheduleAuto, hipDeviceScheduleSpin, hipDeviceScheduleYield, @@ -78,9 +68,19 @@ std::array getValidFlags() { return validFlags; } - +/** + * Test Description + * ------------------------ + * - Check returned flags against Cartesian product of all + * possible valid flag combinations. + * Test source + * ------------------------ + * - unit/device/hipGetSetDeviceFlags.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetSetDeviceFlags_ValidFlag") { - // Scenario3 auto validFlags = getValidFlags(); unsigned int flag = 0; @@ -88,8 +88,20 @@ TEST_CASE("Unit_hipGetSetDeviceFlags_ValidFlag") { REQUIRE(std::find(std::begin(validFlags), std::end(validFlags), flag) != std::end(validFlags)); } +/** + * Test Description + * ------------------------ + * - Validate that returned flags are equal to the ones that have + * been previously set. + * - Perform validation for all connected devices and all flag combinations. + * Test source + * ------------------------ + * - unit/device/hipGetSetDeviceFlags.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetSetDeviceFlags_SetThenGet") { - // Scenario4 auto validFlags = getValidFlags(); auto devNo = GENERATE(range(0, HipTest::getDeviceCount())); @@ -108,8 +120,19 @@ TEST_CASE("Unit_hipGetSetDeviceFlags_SetThenGet") { REQUIRE((flag & hipDeviceScheduleMask) == getFlag); } +/** + * Test Description + * ------------------------ + * - Validate that the returned flags from the main thread are + * equal to the flags that are set from another thread. + * Test source + * ------------------------ + * - unit/device/hipGetSetDeviceFlags.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetSetDeviceFlags_Threaded") { - // Scenario5 auto validFlags = getValidFlags(); auto devNo = GENERATE(range(0, HipTest::getDeviceCount())); @@ -146,6 +169,19 @@ TEST_CASE("Unit_hipGetSetDeviceFlags_Threaded") { HIP_CHECK_THREAD_FINALIZE(); } +/** + * Test Description + * ------------------------ + * - Create context with flags and validate that valid + * flags are returned. + * - Perform validation for all connected devices and all flag combinations. + * Test source + * ------------------------ + * - unit/device/hipGetSetDeviceFlags.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetDeviceFlags_Positive_Context") { auto validFlags = getValidFlags(); const unsigned int flags = @@ -163,4 +199,50 @@ TEST_CASE("Unit_hipGetDeviceFlags_Positive_Context") { HIP_CHECK(hipCtxPopCurrent(&ctx)); HIP_CHECK(hipCtxDestroy(ctx)); +} + +/** + * End doxygen group hipGetDeviceFlags. + * @} + */ + +/** + * @addtogroup hipSetDeviceFlags hipSetDeviceFlags + * @{ + * @ingroup DeviceTest + * `hipSetDeviceFlags(unsigned flags)` - + * The current device behavior is changed according the flags passed. + * ________________________ + * Test cases from other modules: + * - @ref Unit_hipGetSetDeviceFlags_SetThenGet + * - @ref Unit_hipGetSetDeviceFlags_Threaded + */ + +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When flag combinations are invalid + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/device/hipGetSetDeviceFlags.cc + * Test requirements + * ------------------------ + * - Platform specific (NVIDIA) + * - HIP_VERSION >= 5.2 + */ +TEST_CASE("Unit_hipGetSetDeviceFlags_InvalidFlag") { +#if HT_AMD + HipTest::HIP_SKIP_TEST("EXSWCPHIPT-115"); + return; +#endif + const unsigned int invalidFlag = GENERATE(0b011, // schedule flags should not overlap + 0b101, // schedule flags should not overlap + 0b110, // schedule flags should not overlap + 0b111, // schedule flags should not overlap + 0b100000, // out of bounds + 0xFFFF); + CAPTURE(invalidFlag); + HIP_CHECK_ERROR(hipSetDeviceFlags(invalidFlag), hipErrorInvalidValue); } \ No newline at end of file diff --git a/projects/hip-tests/catch/unit/device/hipIpcCloseMemHandle.cc b/projects/hip-tests/catch/unit/device/hipIpcCloseMemHandle.cc index 138ef15e5d..eb81c3f93f 100644 --- a/projects/hip-tests/catch/unit/device/hipIpcCloseMemHandle.cc +++ b/projects/hip-tests/catch/unit/device/hipIpcCloseMemHandle.cc @@ -27,6 +27,32 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipIpcCloseMemHandle hipIpcCloseMemHandle + * @{ + * @ingroup DeviceTest + * `hipIpcCloseMemHandle(void* devPtr)` - + * Close memory mapped with hipIpcOpenMemHandle. + * Unmaps memory returned by hipIpcOpenMemHandle. + * ________________________ + * Test cases from other modules: + * - @ref Unit_hipIpcMemAccess_Semaphores + * - @ref Unit_hipIpcMemAccess_ParameterValidation + */ + +/** + * Test Description + * ------------------------ + * - Checks that memory stays mapped if reference count doesn't reach zero. + * - Checks that memory stays mapped if handle is closed in second process. + * Test source + * ------------------------ + * - unit/device/hipIpcCloseMemHandle.cc + * Test requirements + * ------------------------ + * - Host specific (LINUX) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipIpcCloseMemHandle_Positive_Reference_Counting") { int fd[2]; REQUIRE(pipe(fd) == 0); @@ -80,6 +106,18 @@ TEST_CASE("Unit_hipIpcCloseMemHandle_Positive_Reference_Counting") { } } +/** + * Test Description + * ------------------------ + * - Closes the memory handle from the process that has created it. + * Test source + * ------------------------ + * - unit/device/hipIpcCloseMemHandle.cc + * Test requirements + * ------------------------ + * - Host specific (LINUX) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipIpcCloseMemHandle_Negative_Close_In_Originating_Process") { void* ptr; hipIpcMemHandle_t handle; diff --git a/projects/hip-tests/catch/unit/device/hipIpcGetMemHandle.cc b/projects/hip-tests/catch/unit/device/hipIpcGetMemHandle.cc index 76d2c92ffc..72d34fe117 100644 --- a/projects/hip-tests/catch/unit/device/hipIpcGetMemHandle.cc +++ b/projects/hip-tests/catch/unit/device/hipIpcGetMemHandle.cc @@ -25,6 +25,29 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipIpcGetMemHandle hipIpcGetMemHandle + * @{ + * @ingroup DeviceTest + * `hipIpcGetMemHandle(hipIpcMemHandle_t* handle, void* devPtr)` - + * Gets an interprocess memory handle for an existing device memory allocation. + * ________________________ + * Test cases from other modules: + * - @ref Unit_hipIpcMemAccess_ParameterValidation + */ + +/** + * Test Description + * ------------------------ + * - Check that unique handles are returned in consecutive calls. + * Test source + * ------------------------ + * - unit/device/hipIpcGetMemHandle.cc + * Test requirements + * ------------------------ + * - Host specific (LINUX) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipIpcGetMemHandle_Positive_Unique_Handles_Separate_Allocations") { void *ptr1, *ptr2; hipIpcMemHandle_t handle1, handle2; @@ -39,6 +62,19 @@ TEST_CASE("Unit_hipIpcGetMemHandle_Positive_Unique_Handles_Separate_Allocations" HIP_CHECK(hipFree(ptr2)); } +/** + * Test Description + * ------------------------ + * - Check that unique handles are returned for the same address, + * but separate allocations. + * Test source + * ------------------------ + * - unit/device/hipIpcGetMemHandle.cc + * Test requirements + * ------------------------ + * - Host specific (LINUX) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipIpcGetMemHandle_Positive_Unique_Handles_Reused_Memory") { void *ptr1 = nullptr, *ptr2 = nullptr; hipIpcMemHandle_t handle1, handle2; @@ -54,6 +90,20 @@ TEST_CASE("Unit_hipIpcGetMemHandle_Positive_Unique_Handles_Reused_Memory") { HIP_CHECK(hipFree(ptr2)); } +/** + * Test Description + * ------------------------ + * - Test if previously freed memory will generate an invalid handle: + * -# When memory is freed before getting handle + * - Expected output: return `hipErrorInvalidValue + * Test source + * ------------------------ + * - unit/device/hipIpcGetMemHandle.cc + * Test requirements + * ------------------------ + * - Host specific (LINUX) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipIpcGetMemHandle_Negative_Handle_For_Freed_Memory") { void* ptr; hipIpcMemHandle_t handle; @@ -62,6 +112,20 @@ TEST_CASE("Unit_hipIpcGetMemHandle_Negative_Handle_For_Freed_Memory") { HIP_CHECK_ERROR(hipIpcGetMemHandle(&handle, ptr), hipErrorInvalidValue); } +/** + * Test Description + * ------------------------ + * - Test if out of bounds pointer will generate an error: + * -# When the memory pointer is too large + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/device/hipIpcGetMemHandle.cc + * Test requirements + * ------------------------ + * - Host specific (LINUX) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipIpcGetMemHandle_Negative_Out_Of_Bound_Pointer") { int* ptr; constexpr size_t n = 1024; diff --git a/projects/hip-tests/catch/unit/device/hipIpcOpenMemHandle.cc b/projects/hip-tests/catch/unit/device/hipIpcOpenMemHandle.cc index 4edc7cd616..46329b32c8 100644 --- a/projects/hip-tests/catch/unit/device/hipIpcOpenMemHandle.cc +++ b/projects/hip-tests/catch/unit/device/hipIpcOpenMemHandle.cc @@ -28,6 +28,30 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipIpcOpenMemHandle hipIpcOpenMemHandle + * @{ + * @ingroup DeviceTest + * `hipIpcOpenMemHandle(void** devPtr, hipIpcMemHandle_t handle, unsigned int flags)` - + * Opens an interprocess memory handle exported from another process + * and returns a device pointer usable in the local process. + */ + +/** + * Test Description + * ------------------------ + * - Handle the attempt to open memory handle in the same process + * that has created it. + * -# When the process is the same + * - Expected output: return `hipErrorInvalidContext` + * Test source + * ------------------------ + * - unit/device/hipIpcOpenMemHandle.cc + * Test requirements + * ------------------------ + * - Host specific (LINUX) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipIpcOpenMemHandle_Negative_Open_In_Creating_Process") { hipDeviceptr_t ptr1, ptr2; hipIpcMemHandle_t handle; @@ -39,6 +63,21 @@ TEST_CASE("Unit_hipIpcOpenMemHandle_Negative_Open_In_Creating_Process") { HIP_CHECK(hipFree(reinterpret_cast(ptr1))); } +/** + * Test Description + * ------------------------ + * - Checks that opening the same memory handle from a different context + * returns error + * -# When different context + * - Expected output: return `hipErrorInvalidResourceHandle` + * Test source + * ------------------------ + * - unit/device/hipIpcOpenMemHandle.cc + * Test requirements + * ------------------------ + * - Host specific (LINUX) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipIpcOpenMemHandle_Negative_Open_In_Two_Contexts_Same_Device") { int fd[2]; REQUIRE(pipe(fd) == 0); diff --git a/projects/hip-tests/catch/unit/device/hipSetGetDevice.cc b/projects/hip-tests/catch/unit/device/hipSetGetDevice.cc index 62df5f5ac8..6b2f53f6b7 100644 --- a/projects/hip-tests/catch/unit/device/hipSetGetDevice.cc +++ b/projects/hip-tests/catch/unit/device/hipSetGetDevice.cc @@ -19,16 +19,31 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Verifies functionality of hipSetDevice/hipGetDevice api. - * -- Basic Test to set and get valid device numbers. - */ - #include #include #include +/** + * @addtogroup hipSetDevice hipSetDevice + * @{ + * @ingroup DeviceTest + * `hipSetDevice(int deviceId)` - + * Set default device to be used for subsequent hip API calls from this thread. + */ + +/** + * Test Description + * ------------------------ + * - Performs multiple set/get device operations and verifies + * that the device that is set is the one that is gotten. + * Test source + * ------------------------ + * - unit/device/hipSetGetDevice.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipSetDevice_BasicSetGet") { int numDevices = 0; int device{}; @@ -46,6 +61,18 @@ TEST_CASE("Unit_hipSetDevice_BasicSetGet") { } } +/** + * Test Description + * ------------------------ + * - Performs set/get operations for each detected + * device from multiple threads. + * Test source + * ------------------------ + * - unit/device/hipSetGetDevice.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetSetDevice_MultiThreaded") { auto maxThreads = std::thread::hardware_concurrency(); auto deviceCount = HipTest::getDeviceCount(); @@ -87,6 +114,18 @@ TEST_CASE("Unit_hipGetSetDevice_MultiThreaded") { HIP_CHECK_THREAD_FINALIZE(); } +/** + * Test Description + * ------------------------ + * - Performs set/get device for separate devices on two + * threads and validates device ordinance via memory allocation. + * Test source + * ------------------------ + * - unit/device/hipSetGetDevice.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipSetGetDevice_Positive_Threaded_Basic") { class HipSetGetDeviceThreadedTest : public ThreadedZigZagTest { public: @@ -125,6 +164,23 @@ TEST_CASE("Unit_hipSetGetDevice_Positive_Threaded_Basic") { test.run(); } +/** + * Test Description + * ------------------------ + * - Validates that get/set device APIs can handle invalid parameters + * -# Get device when device is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# Set device with ordinal number `-1` + * - Expected output: return `hipErrorInvalidDevice` + * -# Set device to the ID which is out of bounds + * - Expected output: return `hipErrorInvalidDevice` + * Test source + * ------------------------ + * - unit/device/hipSetGetDevice.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipSetGetDevice_Negative") { SECTION("Get Device - nullptr") { HIP_CHECK_ERROR(hipGetDevice(nullptr), hipErrorInvalidValue); } @@ -135,6 +191,29 @@ TEST_CASE("Unit_hipSetGetDevice_Negative") { } } +/** + * End doxygen group hipSetDevice. + * @} + */ + +/** + * @addtogroup hipGetDevice hipGetDevice + * @{ + * @ingroup DeviceTest + * `hipGetDevice(int* deviceId)` - + * Return the default device id for the calling host thread. + * ________________________ + * Test cases from other modules: + * - @ref Unit_hipSetDevice_BasicSetGet + * - @ref Unit_hipGetSetDevice_MultiThreaded + * - @ref Unit_hipSetGetDevice_Negative + */ + +/** + * End doxygen group hipGetDevice. + * @} + */ + TEST_CASE("Unit_hipDeviceGet_Negative") { // TODO enable after EXSWCPHIPT-104 is fixed #if HT_NVIDIA diff --git a/projects/hip-tests/catch/unit/graph/hipGraphKernelNodeSetParams.cc b/projects/hip-tests/catch/unit/graph/hipGraphKernelNodeSetParams.cc index 0685b81a76..eb561c05e3 100644 --- a/projects/hip-tests/catch/unit/graph/hipGraphKernelNodeSetParams.cc +++ b/projects/hip-tests/catch/unit/graph/hipGraphKernelNodeSetParams.cc @@ -171,9 +171,7 @@ static __global__ void ker_vec_sub(int* A, int* B) { A[i] = A[i] - B[i]; } -/** - Internal class for creating nested graphs. - */ +// Internal class for creating nested graphs. class GraphKernelNodeGetSetParam { const int N = 1024; size_t Nbytes; diff --git a/projects/hip-tests/catch/unit/graph/hipUserObjectCreate.cc b/projects/hip-tests/catch/unit/graph/hipUserObjectCreate.cc index 6e086aae22..2a22e62d9f 100644 --- a/projects/hip-tests/catch/unit/graph/hipUserObjectCreate.cc +++ b/projects/hip-tests/catch/unit/graph/hipUserObjectCreate.cc @@ -23,8 +23,8 @@ THE SOFTWARE. #include "user_object_common.hh" -/** - * Functional Test for API - hipUserObjectCreate +/* + Functional Test for API - hipUserObjectCreate 1) Call hipUserObjectCreate once and release it by calling hipUserObjectRelease 2) Call hipUserObjectCreate refCount as X and release it by calling hipUserObjectRelease with same refCount. @@ -33,7 +33,7 @@ THE SOFTWARE. 4) Call hipUserObjectCreate with refCount as X, retain it by calling hipUserObjectRetain with count as Y and release it by calling hipUserObjectRelease with count as X+Y. - */ +*/ /* 1) Call hipUserObjectCreate once and release it by calling hipUserObjectRelease */ From b2829b49decbfd7ff1621271d5482143ac0e936b Mon Sep 17 00:00:00 2001 From: milos-mozetic <118800401+milos-mozetic@users.noreply.github.com> Date: Wed, 28 Jun 2023 06:15:15 +0200 Subject: [PATCH 03/32] EXSWHTEC-224 - Test cases ID clean up and documentation for Event Management (#71) - Test cases ID clean up and documentation for Event Management [ROCm/hip-tests commit: 3969e4a32095d9e9d24217136e6f31e4fd4067e8] --- .../catch/include/hip_test_defgroups.hh | 7 + .../catch/unit/event/Unit_hipEvent.cc | 20 ++- .../unit/event/Unit_hipEventElapsedTime.cc | 93 +++++++++-- .../catch/unit/event/Unit_hipEventIpc.cc | 16 ++ .../unit/event/Unit_hipEventMGpuMThreads.cc | 39 +++++ .../catch/unit/event/Unit_hipEventQuery.cc | 22 +++ .../catch/unit/event/Unit_hipEventRecord.cc | 48 +++++- .../unit/event/Unit_hipEvent_Negative.cc | 156 ++++++++++++++++-- .../catch/unit/event/hipEventCreate.cc | 23 ++- .../unit/event/hipEventCreateWithFlags.cc | 23 ++- .../catch/unit/event/hipEventDestroy.cc | 56 ++++++- .../catch/unit/event/hipEventSynchronize.cc | 42 ++++- 12 files changed, 491 insertions(+), 54 deletions(-) diff --git a/projects/hip-tests/catch/include/hip_test_defgroups.hh b/projects/hip-tests/catch/include/hip_test_defgroups.hh index 360bfe1282..97e9bea8ab 100644 --- a/projects/hip-tests/catch/include/hip_test_defgroups.hh +++ b/projects/hip-tests/catch/include/hip_test_defgroups.hh @@ -43,6 +43,13 @@ THE SOFTWARE. * @} */ +/** + * @defgroup EventTest Event Management + * @{ + * This section describes tests for the event management functions of HIP runtime API. + * @} + */ + /** * @defgroup ShflTest warp shuffle function Management * @{ diff --git a/projects/hip-tests/catch/unit/event/Unit_hipEvent.cc b/projects/hip-tests/catch/unit/event/Unit_hipEvent.cc index 6654c58d5b..24c8856006 100644 --- a/projects/hip-tests/catch/unit/event/Unit_hipEvent.cc +++ b/projects/hip-tests/catch/unit/event/Unit_hipEvent.cc @@ -26,6 +26,12 @@ THE SOFTWARE. #include +/** + * @addtogroup hipEventRecord hipEventRecord + * @{ + * @ingroup EventTest + */ + int tests = -1; enum SyncMode { syncNone, @@ -183,7 +189,19 @@ void runTests(int64_t numElements) { HIP_CHECK(hipHostFree(C_h)); } - +/** + * Test Description + * ------------------------ + * - Complex test case used to create a lot of events. + * - Each event is enqueued to the stream. + * - Kernels are launched and synchronized. + * Test source + * ------------------------ + * - unit/event/Unit_hipEvent.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEvent") { runTests(10000000); } diff --git a/projects/hip-tests/catch/unit/event/Unit_hipEventElapsedTime.cc b/projects/hip-tests/catch/unit/event/Unit_hipEventElapsedTime.cc index 1b5f6e22e9..7149c8cbea 100644 --- a/projects/hip-tests/catch/unit/event/Unit_hipEventElapsedTime.cc +++ b/projects/hip-tests/catch/unit/event/Unit_hipEventElapsedTime.cc @@ -19,21 +19,43 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipEventElapsedTime_NullCheck - Test unsuccessful hipEventElapsedTime when either event passed as nullptr -Unit_hipEventElapsedTime_DisableTiming - Test unsuccessful hipEventElapsedTime when events are created with hipEventDisableTiming flag -Unit_hipEventElapsedTime_DifferentDevices - Test unsuccessful hipEventElapsedTime when events are recorded on different devices -Unit_hipEventElapsedTime_NotReady_Negative - Test unsuccessful hipEventElapsedTime when an event has not been completed -Unit_hipEventElapsedTime - Test time elapsed between two recorded events with hipEventElapsedTime api -*/ #include - #include - #include +/** + * @addtogroup hipEventElapsedTime hipEventElapsedTime + * @{ + * @ingroup EventTest + * `hipEventElapsedTime(float* ms, hipEvent_t start, hipEvent_t stop)` - + * Return the elapsed time between two events. + * ________________________ + * Test cases from other modules: + * - @ref Unit_hipEvent + * - @ref Unit_hipEventIpc + * - @ref Unit_hipEventMGpuMThreads_1 + * - @ref Unit_hipEventMGpuMThreads_2 + * - @ref Unit_hipEventMGpuMThreads_3 + */ + +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output parameter for time is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When first event is `nullptr` + * - Expected output: return `hipErrorInvalidHandle` + * -# When second event is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/event/Unit_hipEventElapsedTime.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventElapsedTime_NullCheck") { hipEvent_t start = nullptr, end = nullptr; float tms = 1.0f; @@ -45,6 +67,19 @@ TEST_CASE("Unit_hipEventElapsedTime_NullCheck") { #endif } +/** + * Test Description + * ------------------------ + * - Calculates elapsed time when events are created with disable timing flag + * -# When flag is set to disable timing + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/event/Unit_hipEventElapsedTime.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventElapsedTime_DisableTiming") { float timeElapsed = 1.0f; hipEvent_t start, stop; @@ -55,6 +90,19 @@ TEST_CASE("Unit_hipEventElapsedTime_DisableTiming") { HIP_CHECK(hipEventDestroy(stop)); } +/** + * Test Description + * ------------------------ + * - Calculates elapsed time when events are recorded on different devices + * -# When start and stop events are recorded on different devices + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/event/Unit_hipEventElapsedTime.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventElapsedTime_DifferentDevices") { int devCount = 0; HIP_CHECK(hipGetDeviceCount(&devCount)); @@ -86,6 +134,20 @@ TEST_CASE("Unit_hipEventElapsedTime_DifferentDevices") { #if HT_AMD /* Disabled because frequency based wait is timing out on nvidia platforms */ +/** + * Test Description + * ------------------------ + * - Calculates elapsed time when an event has not been completed. + * -# When the stop event has not finished yet + * - Expected output: return `hipErrorNotReady` + * Test source + * ------------------------ + * - unit/event/Unit_hipEventElapsedTime.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventElapsedTime_NotReady_Negative") { hipEvent_t start; HIP_CHECK(hipEventCreate(&start)); @@ -112,6 +174,17 @@ TEST_CASE("Unit_hipEventElapsedTime_NotReady_Negative") { } #endif // HT_AMD +/** + * Test Description + * ------------------------ + * - Calculates elapsed time between two successfully created and recorded events. + * Test source + * ------------------------ + * - unit/event/Unit_hipEventElapsedTime.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventElapsedTime") { hipEvent_t start; HIP_CHECK(hipEventCreate(&start)); diff --git a/projects/hip-tests/catch/unit/event/Unit_hipEventIpc.cc b/projects/hip-tests/catch/unit/event/Unit_hipEventIpc.cc index 1081327f8c..a4f71d568a 100644 --- a/projects/hip-tests/catch/unit/event/Unit_hipEventIpc.cc +++ b/projects/hip-tests/catch/unit/event/Unit_hipEventIpc.cc @@ -27,7 +27,23 @@ THE SOFTWARE. #include +/** + * @addtogroup hipEventCreateWithFlags hipEventCreateWithFlags + * @{ + * @ingroup EventTest + */ +/** + * Test Description + * ------------------------ + * - Validate Event Management APIs when working with multiple processes. + * Test source + * ------------------------ + * - unit/event/Unit_hipEventIpc.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventIpc") { size_t N = 4 * 1024 * 1024; unsigned threadsPerBlock = 256; diff --git a/projects/hip-tests/catch/unit/event/Unit_hipEventMGpuMThreads.cc b/projects/hip-tests/catch/unit/event/Unit_hipEventMGpuMThreads.cc index a6d849065b..346d8c05ec 100644 --- a/projects/hip-tests/catch/unit/event/Unit_hipEventMGpuMThreads.cc +++ b/projects/hip-tests/catch/unit/event/Unit_hipEventMGpuMThreads.cc @@ -22,6 +22,12 @@ #include #include +/** + * @addtogroup hipEventCreate hipEventCreate + * @{ + * @ingroup EventTest + */ + int64_t timeNanos() { using namespace std::chrono; static auto t0 = steady_clock::now(); @@ -187,10 +193,32 @@ void testEventMGpuMThreads(int nThreads = 1) { delete []threads; } +/** + * Test Description + * ------------------------ + * - Validate Event Management APIs when working with one thread. + * Test source + * ------------------------ + * - unit/event/Unit_hipEventMGpuMThreads.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventMGpuMThreads_1") { testEventMGpuMThreads(1); } +/** + * Test Description + * ------------------------ + * - Validate Event Management APIs when working with at least two threads. + * Test source + * ------------------------ + * - unit/event/Unit_hipEventMGpuMThreads.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventMGpuMThreads_2") { int numDevices = 0; HIP_CHECK(hipGetDeviceCount(&numDevices)); @@ -201,6 +229,17 @@ TEST_CASE("Unit_hipEventMGpuMThreads_2") { } } +/** + * Test Description + * ------------------------ + * - Validate Event Management APIs when working with at least three threads. + * Test source + * ------------------------ + * - unit/event/Unit_hipEventMGpuMThreads.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventMGpuMThreads_3") { int numDevices = 0; HIP_CHECK(hipGetDeviceCount(&numDevices)); diff --git a/projects/hip-tests/catch/unit/event/Unit_hipEventQuery.cc b/projects/hip-tests/catch/unit/event/Unit_hipEventQuery.cc index 47d8995c18..726a57ca53 100644 --- a/projects/hip-tests/catch/unit/event/Unit_hipEventQuery.cc +++ b/projects/hip-tests/catch/unit/event/Unit_hipEventQuery.cc @@ -19,6 +19,17 @@ THE SOFTWARE. #include +/** + * @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 @@ -48,6 +59,17 @@ __global__ void waitKernel_gfx11(int clockRate, int seconds) { #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)); diff --git a/projects/hip-tests/catch/unit/event/Unit_hipEventRecord.cc b/projects/hip-tests/catch/unit/event/Unit_hipEventRecord.cc index 70e5a684ec..7dd8c582b9 100644 --- a/projects/hip-tests/catch/unit/event/Unit_hipEventRecord.cc +++ b/projects/hip-tests/catch/unit/event/Unit_hipEventRecord.cc @@ -19,12 +19,6 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipEventRecord- Test hipEventRecord serialization behavior -Unit_hipEventRecord_Negative - Test unsuccessful hipEventRecord when event is passed as nullptr - - Test unsuccessful hipEventRecord when event is created/recorded on different devices -*/ #include @@ -32,6 +26,33 @@ Unit_hipEventRecord_Negative - Test unsuccessful hipEventRecord when event is pa #include #include +/** + * @addtogroup hipEventRecord hipEventRecord + * @{ + * @ingroup EventTest + * `hipEventRecord(hipEvent_t event, hipStream_t stream = NULL)` - + * Record an event in the specified stream. + * ________________________ + * Test cases from other modules: + * - @ref Unit_hipEventIpc + * - @ref Unit_hipEventMGpuMThreads_1 + * - @ref Unit_hipEventMGpuMThreads_2 + * - @ref Unit_hipEventMGpuMThreads_3 + */ + +/** + * Test Description + * ------------------------ + * - Creates regular events and events with flags. + * - Enqueues them to the streams and checks if events + * can be successfully used for synchronization. + * Test source + * ------------------------ + * - unit/event/Unit_hipEventRecord.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventRecord") { constexpr size_t N = 1024; constexpr int iterations = 1; @@ -117,6 +138,21 @@ TEST_CASE("Unit_hipEventRecord") { TestContext::get().cleanContext(); } +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When event is `nullptr` + * - Expected output: return `hipErrorInvalidResourceHandle` + * -# When event is created on one device but recorded on the other one + * - Expected output: return `hipErrorInvalidHandle` + * Test source + * ------------------------ + * - unit/event/Unit_hipEventRecord.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventRecord_Negative") { SECTION("Nullptr event") { HIP_CHECK_ERROR(hipEventRecord(nullptr, nullptr), hipErrorInvalidResourceHandle); diff --git a/projects/hip-tests/catch/unit/event/Unit_hipEvent_Negative.cc b/projects/hip-tests/catch/unit/event/Unit_hipEvent_Negative.cc index 6dd0b44363..14c173ceb7 100644 --- a/projects/hip-tests/catch/unit/event/Unit_hipEvent_Negative.cc +++ b/projects/hip-tests/catch/unit/event/Unit_hipEvent_Negative.cc @@ -31,31 +31,71 @@ Unit_hipEventCreate_IncompatibleFlags - Test unsuccessful event creation when in #include +/** + * @addtogroup hipEventCreate hipEventCreate + * @{ + * @ingroup EventTest + */ + +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the event is `nullptr` + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/event/Unit_hipEvent_Negative.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventCreate_NullCheck") { auto res = hipEventCreate(nullptr); REQUIRE(res != hipSuccess); } +/** + * End doxygen group hipEventCreate. + * @} + */ +/** + * @addtogroup hipEventCreateWithFlags hipEventCreateWithFlags + * @{ + * @ingroup EventTest + */ + +/** + * Test Description + * ------------------------ + * - Validates handling of `nullptr` arguments: + * -# When output pointer to the event is `nullptr` + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/event/Unit_hipEvent_Negative.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventCreateWithFlags_NullCheck") { auto res = hipEventCreateWithFlags(nullptr, 0); REQUIRE(res != hipSuccess); } -TEST_CASE("Unit_hipEventSynchronize_NullCheck") { - auto res = hipEventSynchronize(nullptr); - REQUIRE(res != hipSuccess); -} - -TEST_CASE("Unit_hipEventQuery_NullCheck") { - auto res = hipEventQuery(nullptr); - REQUIRE(res != hipSuccess); -} - -TEST_CASE("Unit_hipEventDestroy_NullCheck") { - auto res = hipEventDestroy(nullptr); - REQUIRE(res != hipSuccess); -} - +/** + * Test Description + * ------------------------ + * - Validates handling of incompatible flags: + * -# When the flags are not supported on the device + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/event/Unit_hipEvent_Negative.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventCreate_IncompatibleFlags") { hipEvent_t event; HIP_CHECK_ERROR(hipEventCreateWithFlags(&event, hipEventInterprocess), hipErrorInvalidValue); @@ -79,4 +119,88 @@ TEST_CASE("Unit_hipEventCreate_IncompatibleFlags") { unsigned invalidFlag{0x08000000}; HIP_CHECK_ERROR(hipEventCreateWithFlags(&event, invalidFlag), hipErrorInvalidValue); -} \ No newline at end of file +} +/** + * End doxygen group hipEventCreateWithFlags. + * @} + */ + +/** + * @addtogroup hipEventSynchronize hipEventSynchronize + * @{ + * @ingroup EventTest + */ + +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When event is `nullptr` + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/event/Unit_hipEvent_Negative.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ +TEST_CASE("Unit_hipEventSynchronize_NullCheck") { + auto res = hipEventSynchronize(nullptr); + REQUIRE(res != hipSuccess); +} +/** + * End doxygen group hipEventSynchronize. + * @} + */ + +/** + * @addtogroup hipEventQuery hipEventQuery + * @{ + * @ingroup EventTest + */ + +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When event is `nullptr` + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/event/Unit_hipEvent_Negative.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ +TEST_CASE("Unit_hipEventQuery_NullCheck") { + auto res = hipEventQuery(nullptr); + REQUIRE(res != hipSuccess); +} +/** + * End doxygen group hipEventQuery. + * @} + */ + +/** + * @addtogroup hipEventDestroy hipEventDestroy + * @{ + * @ingroup EventTest + */ + +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When event is `nullptr` + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/event/Unit_hipEvent_Negative.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ +TEST_CASE("Unit_hipEventDestroy_NullCheck") { + auto res = hipEventDestroy(nullptr); + REQUIRE(res != hipSuccess); +} diff --git a/projects/hip-tests/catch/unit/event/hipEventCreate.cc b/projects/hip-tests/catch/unit/event/hipEventCreate.cc index 30cad62c77..c4d355f533 100644 --- a/projects/hip-tests/catch/unit/event/hipEventCreate.cc +++ b/projects/hip-tests/catch/unit/event/hipEventCreate.cc @@ -19,13 +19,28 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipEventCreate_Positive - Test simple event creation with hipEventCreate api -*/ #include +/** + * @addtogroup hipEventCreate hipEventCreate + * @{ + * @ingroup EventTest + * `hipEventCreate(hipEvent_t* event)` - + * Create an event. + */ + +/** + * Test Description + * ------------------------ + * - Successfully creates and event for each device. + * Test source + * ------------------------ + * - unit/event/hipEventCreate.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventCreate_Positive") { int id = GENERATE(range(0, HipTest::getDeviceCount())); HIP_CHECK(hipSetDevice(id)); diff --git a/projects/hip-tests/catch/unit/event/hipEventCreateWithFlags.cc b/projects/hip-tests/catch/unit/event/hipEventCreateWithFlags.cc index 7f31c8e347..c758e12a55 100644 --- a/projects/hip-tests/catch/unit/event/hipEventCreateWithFlags.cc +++ b/projects/hip-tests/catch/unit/event/hipEventCreateWithFlags.cc @@ -19,13 +19,28 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipEventCreateWithFlags_Positive - Test simple event creation with hipEventCreateWithFlags api for each flag -*/ #include +/** + * @addtogroup hipEventCreateWithFlags hipEventCreateWithFlags + * @{ + * @ingroup EventTest + * `hipEventCreateWithFlags(hipEvent_t* event, unsigned flags)` - + * Create an event with the specified flags to control event behaviour. + */ + +/** + * Test Description + * ------------------------ + * - Successfully create an event with all defined device flags. + * Test source + * ------------------------ + * - unit/event/hipEventCreateWithFlags.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventCreateWithFlags_Positive") { #if HT_AMD diff --git a/projects/hip-tests/catch/unit/event/hipEventDestroy.cc b/projects/hip-tests/catch/unit/event/hipEventDestroy.cc index 8965d5227a..d62921f01b 100644 --- a/projects/hip-tests/catch/unit/event/hipEventDestroy.cc +++ b/projects/hip-tests/catch/unit/event/hipEventDestroy.cc @@ -26,12 +26,23 @@ THE SOFTWARE. #include #include "hip/hip_runtime_api.h" +/** + * @addtogroup hipEventDestroy hipEventDestroy + * @{ + * @ingroup EventTest + * `hipEventDestroy(hipEvent_t event)` - + * Destroy the specified event. + * ________________________ + * Test cases from other modules: + * - @ref Unit_hipEventIpc + */ + #if HT_AMD /* Disabled because frequency based wait is timing out on nvidia platforms */ static constexpr size_t vectorSize{1024}; -/** - * @brief Launches vectorAdd kernel with a delay +/* + * Launches vectorAdd kernel with a delay */ static inline void launchVectorAdd(float*& A_h, float*& B_h, float*& C_h, std::chrono::milliseconds delay, hipStream_t stream = nullptr) { @@ -46,10 +57,17 @@ static inline void launchVectorAdd(float*& A_h, float*& B_h, float*& C_h, HipTest::vectorADD<<<1, 1, 0, stream>>>(A_d, B_d, C_d, vectorSize); } - /** - * @brief Check that destroying an event before the kernel has finished running causes no errors. - * + * Test Description + * ------------------------ + * - Destroys the event before launched kernel has finished running. + * Test source + * ------------------------ + * - unit/event/hipEventDestroy.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipEventDestroy_Unfinished") { hipEvent_t event; @@ -69,8 +87,16 @@ TEST_CASE("Unit_hipEventDestroy_Unfinished") { } /** - * @brief Check that destroying an event enqueued to a stream causes no errors. - * + * Test Description + * ------------------------ + * - Destroys the event that is enqueued into a stream. + * Test source + * ------------------------ + * - unit/event/hipEventDestroy.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipEventDestroy_WithWaitingStream") { hipEvent_t event; @@ -94,6 +120,22 @@ TEST_CASE("Unit_hipEventDestroy_WithWaitingStream") { HipTest::freeArraysForHost(A_h, B_h, C_h, true); } +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the event is `nullptr` + * - Expected output: return `hipErrorInvalidResourceHandle` + * -# When event is destroyed twice + * - Expected output: return `hipErrorContextIsDestroyed` + * Test source + * ------------------------ + * - unit/event/hipEventDestroy.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventDestroy_Negative") { SECTION("Invalid Event") { hipEvent_t event{nullptr}; diff --git a/projects/hip-tests/catch/unit/event/hipEventSynchronize.cc b/projects/hip-tests/catch/unit/event/hipEventSynchronize.cc index dc70323b15..76373eea31 100644 --- a/projects/hip-tests/catch/unit/event/hipEventSynchronize.cc +++ b/projects/hip-tests/catch/unit/event/hipEventSynchronize.cc @@ -19,17 +19,25 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipEventSynchronize_Default_Positive- Test synchronization of an event that is completed after a simple kernel launch (on null/created stream) -Unit_hipEventSynchronize_NoEventRecord_Positive - Test synchronization of an event that has not been recorded -*/ #include - #include #include +/** + * @addtogroup hipEventSynchronize hipEventSynchronize + * @{ + * @ingroup EventTest + * `hipEventSynchronize(hipEvent_t event)` - + * Wait for an event to complete. + * ________________________ + * Test cases from other modules: + * - @ref Unit_hipEventIpc + * - @ref Unit_hipEventMGpuMThreads_1 + * - @ref Unit_hipEventMGpuMThreads_2 + * - @ref Unit_hipEventMGpuMThreads_3 + */ + void testSynchronize(hipStream_t stream) { constexpr size_t N = 1024; @@ -70,6 +78,17 @@ void testSynchronize(hipStream_t stream) { HipTest::freeArrays(A_d, B_d, C_d, A_h, B_h, C_h, false); } +/** + * Test Description + * ------------------------ + * - Synchronization of an event that is completed after a simple kernel launch (on null/created stream). + * Test source + * ------------------------ + * - unit/event/hipEventSynchronize.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventSynchronize_Default_Positive") { hipStream_t stream{nullptr}; @@ -84,6 +103,17 @@ TEST_CASE("Unit_hipEventSynchronize_Default_Positive") { } } +/** + * Test Description + * ------------------------ + * - Synchronization of an event that has not been recorded. + * Test source + * ------------------------ + * - unit/event/hipEventSynchronize.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipEventSynchronize_NoEventRecord_Positive") { constexpr size_t N = 1024; From 86a80099b544354f023ac260347124ff12ff1bab Mon Sep 17 00:00:00 2001 From: milos-mozetic <118800401+milos-mozetic@users.noreply.github.com> Date: Wed, 28 Jun 2023 06:15:53 +0200 Subject: [PATCH 04/32] EXSWHTEC-224 - Test cases ID clean up and documentation for Error Handling (#72) - Test cases ID clean up and documentation for Error Handling [ROCm/hip-tests commit: 93751460f745688f2f04ee6c6d83802c341fd349] --- .../catch/include/hip_test_defgroups.hh | 7 ++++ .../unit/errorHandling/hipGetErrorName.cc | 34 +++++++++++++++++++ .../unit/errorHandling/hipGetErrorString.cc | 33 ++++++++++++++++++ .../unit/errorHandling/hipGetLastError.cc | 33 ++++++++++++++++++ .../unit/errorHandling/hipPeekAtLastError.cc | 33 ++++++++++++++++++ 5 files changed, 140 insertions(+) diff --git a/projects/hip-tests/catch/include/hip_test_defgroups.hh b/projects/hip-tests/catch/include/hip_test_defgroups.hh index 97e9bea8ab..b0e57cd791 100644 --- a/projects/hip-tests/catch/include/hip_test_defgroups.hh +++ b/projects/hip-tests/catch/include/hip_test_defgroups.hh @@ -50,6 +50,13 @@ THE SOFTWARE. * @} */ +/** + * @defgroup ErrorTest Error Handling + * @{ + * This section describes tests for the error handling functions of HIP runtime API. + * @} + */ + /** * @defgroup ShflTest warp shuffle function Management * @{ diff --git a/projects/hip-tests/catch/unit/errorHandling/hipGetErrorName.cc b/projects/hip-tests/catch/unit/errorHandling/hipGetErrorName.cc index f8c7f624be..a498e62387 100644 --- a/projects/hip-tests/catch/unit/errorHandling/hipGetErrorName.cc +++ b/projects/hip-tests/catch/unit/errorHandling/hipGetErrorName.cc @@ -25,6 +25,26 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipGetErrorName hipGetErrorName + * @{ + * @ingroup ErrorTest + * `hipGetErrorName(hipError_t hip_error)` - + * Return hip error as text string form. + */ + +/** + * Test Description + * ------------------------ + * - Validate that a non-empty string is returned for each supported + * device error enumeration. + * Test source + * ------------------------ + * - unit/errorHandling/hipGetErrorName.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetErrorName_Positive_Basic") { const char* error_string = nullptr; const auto enumerator = @@ -36,6 +56,20 @@ TEST_CASE("Unit_hipGetErrorName_Positive_Basic") { REQUIRE(strlen(error_string) > 0); } +/** + * Test Description + * ------------------------ + * - Validate handling of invalid arguments: + * -# When error enumerator is invalid (-1) + * - AMD expected output: return "hipErrorUnknown" + * - NVIDIA expected output: return "cudaErrorUnknown" + * Test source + * ------------------------ + * - unit/errorHandling/hipGetErrorName.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetErrorName_Negative_Parameters") { const char* error_string = hipGetErrorName(static_cast(-1)); REQUIRE(error_string != nullptr); diff --git a/projects/hip-tests/catch/unit/errorHandling/hipGetErrorString.cc b/projects/hip-tests/catch/unit/errorHandling/hipGetErrorString.cc index fe3f5523c2..e38f0dc54e 100644 --- a/projects/hip-tests/catch/unit/errorHandling/hipGetErrorString.cc +++ b/projects/hip-tests/catch/unit/errorHandling/hipGetErrorString.cc @@ -24,6 +24,26 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipGetErrorString hipGetErrorString + * @{ + * @ingroup ErrorTest + * `hipGetErrorString(hipError_t hipError)` - + * Return handy text string message to explain the error which occurred. + */ + +/** + * Test Description + * ------------------------ + * - Validate that a non-empty string is returned for each supported + * device error enumeration. + * Test source + * ------------------------ + * - unit/errorHandling/hipGetErrorString.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetErrorString_Positive_Basic") { const char* error_string = nullptr; const auto enumerator = @@ -35,6 +55,19 @@ TEST_CASE("Unit_hipGetErrorString_Positive_Basic") { REQUIRE(strlen(error_string) > 0); } +/** + * Test Description + * ------------------------ + * - Validate handling of invalid arguments: + * -# When error enumerator is invalid (-1) + * - Expected output: do not return `nullptr` + * Test source + * ------------------------ + * - unit/errorHandling/hipGetErrorString.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetErrorString_Negative_Parameters") { const char* error_string = hipGetErrorString(static_cast(-1)); REQUIRE(error_string != nullptr); diff --git a/projects/hip-tests/catch/unit/errorHandling/hipGetLastError.cc b/projects/hip-tests/catch/unit/errorHandling/hipGetLastError.cc index f2b8f1cfd3..6d39b8bf33 100644 --- a/projects/hip-tests/catch/unit/errorHandling/hipGetLastError.cc +++ b/projects/hip-tests/catch/unit/errorHandling/hipGetLastError.cc @@ -24,6 +24,27 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipGetLastError hipGetLastError + * @{ + * @ingroup ErrorTest + * `hipGetLastError(void)` - + * Return last error returned by any HIP runtime API call and resets the stored error code to + * `hipSuccess`. + */ + +/** + * Test Description + * ------------------------ + * - Validate that `hipErrorInvalidValue` is returned after invalid `hipMalloc` call. + * - Validate that `hipSuccess` is returned afterwards. + * Test source + * ------------------------ + * - unit/errorHandling/hipGetLastError.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetLastError_Positive_Basic") { HIP_CHECK(hipGetLastError()); HIP_CHECK_ERROR(hipMalloc(nullptr, 1), hipErrorInvalidValue); @@ -31,6 +52,18 @@ TEST_CASE("Unit_hipGetLastError_Positive_Basic") { HIP_CHECK(hipGetLastError()); } +/** + * Test Description + * ------------------------ + * - Validate that appropriate error is returned when working with multiple threads. + * - Cause error on purpose within one of the threads. + * Test source + * ------------------------ + * - unit/errorHandling/hipGetLastError.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipGetLastError_Positive_Threaded") { class HipGetLastErrorThreadedTest : public ThreadedZigZagTest { public: diff --git a/projects/hip-tests/catch/unit/errorHandling/hipPeekAtLastError.cc b/projects/hip-tests/catch/unit/errorHandling/hipPeekAtLastError.cc index ce7c605719..ae22a3067a 100644 --- a/projects/hip-tests/catch/unit/errorHandling/hipPeekAtLastError.cc +++ b/projects/hip-tests/catch/unit/errorHandling/hipPeekAtLastError.cc @@ -24,6 +24,26 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipPeekAtLastError hipPeekAtLastError + * @{ + * @ingroup ErrorTest + * `hipPeekAtLastError(void)` - + * Return last error returned by any HIP runtime API call. + */ + +/** + * Test Description + * ------------------------ + * - Validate that `hipErrorInvalidValue` is returned after invalid `hipMalloc` call. + * - Validate that `hipSuccess` is returned again for getting the last error. + * Test source + * ------------------------ + * - unit/errorHandling/hipPeekAtLastError.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipPeekAtLastError_Positive_Basic") { HIP_CHECK(hipPeekAtLastError()); HIP_CHECK_ERROR(hipMalloc(nullptr, 1), hipErrorInvalidValue); @@ -32,6 +52,19 @@ TEST_CASE("Unit_hipPeekAtLastError_Positive_Basic") { HIP_CHECK(hipPeekAtLastError()); } +/** + * Test Description + * ------------------------ + * - Validate that appropriate error is returned when working with multiple threads. + * - Validate that appropriate error is returned for getting the last erro when working with multiple threads. + * - Cause error on purpose within one of the threads. + * Test source + * ------------------------ + * - unit/errorHandling/hipPeekAtLastError.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipPeekAtLastError_Positive_Threaded") { class HipPeekAtLastErrorTest : public ThreadedZigZagTest { public: From a2ead92795291f951c7a0d3efc86c9e87d769974 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Wed, 28 Jun 2023 09:46:12 +0530 Subject: [PATCH 05/32] SWDEV-366314 - Test for hip_bfloat16 using hiprtc (#77) Change-Id: I919b1386c4812c160f39c8cffa4ac3403c959d99 [ROCm/hip-tests commit: 6a1564a4b294b3949b4f80724a269368fb302a38] --- .../hip-tests/catch/unit/rtc/CMakeLists.txt | 1 + .../catch/unit/rtc/hipRtcBfloat16.cc | 109 ++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 projects/hip-tests/catch/unit/rtc/hipRtcBfloat16.cc diff --git a/projects/hip-tests/catch/unit/rtc/CMakeLists.txt b/projects/hip-tests/catch/unit/rtc/CMakeLists.txt index 42d5ec5d9a..a1aea77c78 100644 --- a/projects/hip-tests/catch/unit/rtc/CMakeLists.txt +++ b/projects/hip-tests/catch/unit/rtc/CMakeLists.txt @@ -9,6 +9,7 @@ set(TEST_SRC # AMD only tests set(AMD_TEST_SRC customOptions.cc + hipRtcBfloat16.cc linker.cc ) diff --git a/projects/hip-tests/catch/unit/rtc/hipRtcBfloat16.cc b/projects/hip-tests/catch/unit/rtc/hipRtcBfloat16.cc new file mode 100644 index 0000000000..9f4404c288 --- /dev/null +++ b/projects/hip-tests/catch/unit/rtc/hipRtcBfloat16.cc @@ -0,0 +1,109 @@ +/* +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. +*/ + +// This test verifies the accuracy of hip_bfloat16 and its usage with hiprtc + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const char* kernelname = "test_hip_bfloat16"; + +static constexpr auto code{ + R"( +extern "C" +__global__ +void test_hip_bfloat16(float* f, bool* result) +{ + float &f_a = *f; + hip_bfloat16 bf_a(f_a); + float f_c = float(bf_a); + // float relative error should be less than 1/(2^7) since bfloat16 + // has 7 bits mantissa. + if (fabs(f_c - f_a) / f_a <= 1.0 / 128) { + *result = true; + } else { + *result = false; + } +} +)"}; + +TEST_CASE("Unit_hiprtc_test_hip_bfloat16") { + using namespace std; + hiprtcProgram prog; + HIPRTC_CHECK(hiprtcCreateProgram(&prog, code, "code.cu", 0, nullptr, nullptr)); + hipDeviceProp_t props; + int device = 0; + HIP_CHECK(hipGetDeviceProperties(&props, device)); +#ifdef __HIP_PLATFORM_AMD__ + std::string sarg = std::string("--gpu-architecture=") + props.gcnArchName; +#else + std::string sarg = std::string("--gpu-architecture=compute_") + + std::to_string(props.major) + std::to_string(props.minor); +#endif + vector opts; + opts.push_back(sarg.c_str()); + hiprtcResult compileResult{hiprtcCompileProgram(prog, opts.size(), opts.data())}; + size_t logSize; + HIPRTC_CHECK(hiprtcGetProgramLogSize(prog, &logSize)); + if (logSize) { + string log(logSize, '\0'); + HIPRTC_CHECK(hiprtcGetProgramLog(prog, &log[0])); + std::cout << log << '\n'; + } + REQUIRE(compileResult == HIPRTC_SUCCESS); + size_t codeSize; + HIPRTC_CHECK(hiprtcGetCodeSize(prog, &codeSize)); + vector codec(codeSize); + HIPRTC_CHECK(hiprtcGetCode(prog, codec.data())); + HIPRTC_CHECK(hiprtcDestroyProgram(&prog)); + float h_a = 10.0f; + float* f_a; + bool *d_result; + HIP_CHECK(hipMalloc(&f_a, sizeof(float))); + HIP_CHECK(hipMalloc(&d_result, sizeof(bool))); + HIP_CHECK(hipMemcpy(f_a, &h_a, sizeof(float), hipMemcpyHostToDevice)); + hipModule_t module; + hipFunction_t function; + HIP_CHECK(hipModuleLoadData(&module, codec.data())); + HIP_CHECK(hipModuleGetFunction(&function, module, kernelname)); + struct { + float *a_; + bool *b_; + } args{f_a, d_result}; + auto sizeofargs = sizeof(args); + void* config[] = {HIP_LAUNCH_PARAM_BUFFER_POINTER, &args, HIP_LAUNCH_PARAM_BUFFER_SIZE, + &sizeofargs, HIP_LAUNCH_PARAM_END}; + HIP_CHECK(hipModuleLaunchKernel(function, 1, 1, 1, 1, 1, 1, 0, nullptr, nullptr, config)); + HIP_CHECK(hipDeviceSynchronize()); + bool h_result; + HIP_CHECK(hipMemcpyDtoH(&h_result, reinterpret_cast(d_result), sizeof(bool))); + HIP_CHECK(hipFree(d_result)); + HIP_CHECK(hipModuleUnload(module)); + // Result returned is true if the hip_bfloat16 accuracy is as expected + REQUIRE(h_result == true); +} From 16eee59975dd64f1ce8f2b28bc8c1e09495dcea7 Mon Sep 17 00:00:00 2001 From: milos-mozetic <118800401+milos-mozetic@users.noreply.github.com> Date: Wed, 28 Jun 2023 06:17:04 +0200 Subject: [PATCH 06/32] EXSWHTEC-224 - Test cases ID clean up and documentation for Device Memory Access (#88) - Test cases ID clean up and documentation for Device Memory Access - Added group for deprecated Context Management [ROCm/hip-tests commit: 15c91808ccb7cd9352007203506642e50f1f3fa3] --- .../config/config_amd_linux_MI2xx.json | 22 ++--- .../catch/include/hip_test_defgroups.hh | 16 ++++ .../unit/device/hipDeviceCanAccessPeer.cc | 47 +++++++--- .../hipDeviceEnableDisablePeerAccess.cc | 85 ++++++++++++++++--- .../unit/memory/hipMemGetAddressRange.cc | 45 ++++++++-- .../catch/unit/memory/hipMemcpyPeer.cc | 82 +++++++++++++++--- .../catch/unit/memory/hipMemcpyPeerAsync.cc | 84 +++++++++++++++--- 7 files changed, 324 insertions(+), 57 deletions(-) diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_MI2xx.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_MI2xx.json index ee1afd5acc..a7f158e9b4 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_MI2xx.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_MI2xx.json @@ -9,17 +9,17 @@ "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" ] } diff --git a/projects/hip-tests/catch/include/hip_test_defgroups.hh b/projects/hip-tests/catch/include/hip_test_defgroups.hh index b0e57cd791..d7ff394a8b 100644 --- a/projects/hip-tests/catch/include/hip_test_defgroups.hh +++ b/projects/hip-tests/catch/include/hip_test_defgroups.hh @@ -57,6 +57,14 @@ THE SOFTWARE. * @} */ +/** + * @defgroup PeerToPeerTest PeerToPeer Device Memory Access + * @{ + * This section describes tests for the PeerToPeer device memory access functions of HIP runtime API. + * @warning PeerToPeer support is experimental. + * @} + */ + /** * @defgroup ShflTest warp shuffle function Management * @{ @@ -64,6 +72,14 @@ THE SOFTWARE. * @} */ +/** + * @defgroup ContextTest Context Management + * @{ + * This section describes tests for the context management functions of HIP runtime API. + * @warning All Context Management APIs are **deprecated** and shall not be implemented. + * @} + */ + /** * @defgroup StreamTest Stream Management * @{ diff --git a/projects/hip-tests/catch/unit/device/hipDeviceCanAccessPeer.cc b/projects/hip-tests/catch/unit/device/hipDeviceCanAccessPeer.cc index 5945d51224..78d2ac5ca5 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceCanAccessPeer.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceCanAccessPeer.cc @@ -23,16 +23,26 @@ THE SOFTWARE. #include #include -/* - Positive tests: - - for each peer check other peer access - - Negative tests: - - canAccessPeer pointer is nullptr - - deviceId is invalid - - peerDeviceId is invalid -*/ +/** + * @addtogroup hipDeviceCanAccessPeer hipDeviceCanAccessPeer + * @{ + * @ingroup PeerToPeerTest + * `hipDeviceCanAccessPeer(int* canAccessPeer, int deviceId, int peerDeviceId)` - + * Determine if a device can access a peer's memory. + */ +/** + * Test Description + * ------------------------ + * - Verifies that each available device can access memory from all other devices. + * Test source + * ------------------------ + * - unit/device/hipDeviceCanAccessPeer.cc + * Test requirements + * ------------------------ + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceCanAccessPeer_positive") { int canAccessPeer = 0; int deviceCount = HipTest::getGeviceCount(); @@ -54,7 +64,24 @@ TEST_CASE("Unit_hipDeviceCanAccessPeer_positive") { } } - +/** + * Test Description + * ------------------------ + * - Verifies handling of invalid arguments: + * -# When output pointer to the peer result is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When device ID is invalid (-1 or out of bounds) + * - Expected output: return `hipErrorInvalidDevice` + * -# When peer device ID is invalid (-1 or out of bounds) + * - Expected output: return `hipErrorInvalidDevice` + * Test source + * ------------------------ + * - unit/device/hipDeviceCanAccessPeer.cc + * Test requirements + * ------------------------ + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceCanAccessPeer_negative") { int canAccessPeer = 0; int deviceCount = HipTest::getGeviceCount(); diff --git a/projects/hip-tests/catch/unit/device/hipDeviceEnableDisablePeerAccess.cc b/projects/hip-tests/catch/unit/device/hipDeviceEnableDisablePeerAccess.cc index d6cd24853d..bf85cbe0e8 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceEnableDisablePeerAccess.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceEnableDisablePeerAccess.cc @@ -23,16 +23,29 @@ THE SOFTWARE. #include #include -/* - Positive tests: - - for each peer change and check other peer access +/** + * @addtogroup hipDeviceEnablePeerAccess hipDeviceEnablePeerAccess + * @{ + * @ingroup PeerToPeerTest + * `hipDeviceEnablePeerAccess(int peerDeviceId, unsigned int flags)` - + * Enable direct access from current device's virtual address space to memory allocations + * physically located on a peer device. + */ - Negative tests: - - peerDeviceId is invalid - - flag value is invalid - - peer access is enabled/disabled twice - - peer access is disabled before being enabled -*/ +/** + * Test Description + * ------------------------ + * - Enables peer access for each GPU pair. + * - Disables peer access for each GPU pair. + * Test source + * ------------------------ + * - unit/device/hipDeviceEnableDisablePeerAccess.cc + * Test requirements + * ------------------------ + * - PeerToPeer supported + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceEnableDisablePeerAccess_positive") { int canAccessPeer = 0; int deviceCount = HipTest::getGeviceCount(); @@ -56,7 +69,24 @@ TEST_CASE("Unit_hipDeviceEnableDisablePeerAccess_positive") { } } - +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When peer device ID is invalid (-1 or out of bounds) + * - Expected output: return `hipErrorInvalidDevice` + * -# When flag is invalid (-1) + * - Expected output: return `hipErrorInvalidValue` + * -# When peer access has already been enabled + * - Expected output: return `hipErrorPeerAccessAleadyEnabled` + * Test source + * ------------------------ + * - unit/device/hipDeviceEnableDisablePeerAccess.cc + * Test requirements + * ------------------------ + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceEnablePeerAccess_negative") { int deviceCount = HipTest::getGeviceCount(); if (deviceCount < 2) { @@ -86,6 +116,41 @@ TEST_CASE("Unit_hipDeviceEnablePeerAccess_negative") { } } +/** + * End doxygen group hipDeviceEnablePeerAccess. + * @} + */ + +/** + * @addtogroup hipDeviceDisablePeerAccess hipDeviceDisablePeerAccess + * @{ + * @ingroup PeerToPeerTest + * hipDeviceDisablePeerAccess(int peerDeviceId)` - + * Disable direct access from current device's virtual address space + * to memory allocations physically located on a peer device. + * ________________________ + * Test cases from other modules: + * - @ref Unit_hipDeviceEnableDisablePeerAccess_positive + */ + +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When peer device ID is invalid (-1 or out of bounds) + * - Expected output: return `hipErrorInvalidDevice` + * -# When peer access is not enabled + * - Expected output: return `hipErrorPeerAccessNotEnabled` + * -# When peer access is already disabled + * - Expected output: return `hipErrorPeerAccessNotEnabled` + * Test source + * ------------------------ + * - unit/device/hipDeviceEnableDisablePeerAccess.cc + * Test requirements + * ------------------------ + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceDisablePeerAccess_negative") { int deviceCount = HipTest::getGeviceCount(); if (deviceCount < 2) { diff --git a/projects/hip-tests/catch/unit/memory/hipMemGetAddressRange.cc b/projects/hip-tests/catch/unit/memory/hipMemGetAddressRange.cc index d63433c696..c6237bbd11 100644 --- a/projects/hip-tests/catch/unit/memory/hipMemGetAddressRange.cc +++ b/projects/hip-tests/catch/unit/memory/hipMemGetAddressRange.cc @@ -16,17 +16,35 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipMemGetAddressRange_Positive - Test hipMemGetAddressRange api for various memory allocation -types and offsets Unit_hipMemGetAddressRange_Negative - Test unsuccessful execution of -hipMemGetAddressRange api when parameters are invalid -*/ + #include #include #include #include +/** + * @addtogroup hipMemGetAddressRange hipMemGetAddressRange + * @{ + * @ingroup PeerToPeerTest + * `hipMemGetAddressRange(hipDeviceptr_t* pbase, size_t* psize, hipDeviceptr_t dptr)` - + * Get information on memory allocations. + */ + +/** + * Test Description + * ------------------------ + * - Allocate memory and check if base and size match allocated memory values. + * - Check for various offset values from base memory address: + * - Host address range + * - Device address range + * - Pitch address range + * Test source + * ------------------------ + * - unit/memory/hipMemGetAddressRange.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipMemGetAddressRange_Positive") { hipDeviceptr_t base_ptr; size_t mem_size = 0; @@ -67,6 +85,21 @@ TEST_CASE("Unit_hipMemGetAddressRange_Positive") { } } +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When device handle is not valid + * - Expected output: return `hipErrorNotFound` + * -# When offset is greated than allocated size + * - Expected output: return `hipErrorNotFound` + * Test source + * ------------------------ + * - unit/memory/hipMemGetAddressRange.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipMemGetAddressRange_Negative") { hipDeviceptr_t base_ptr; size_t mem_size = 0; diff --git a/projects/hip-tests/catch/unit/memory/hipMemcpyPeer.cc b/projects/hip-tests/catch/unit/memory/hipMemcpyPeer.cc index 8c91281cf6..95698b63df 100644 --- a/projects/hip-tests/catch/unit/memory/hipMemcpyPeer.cc +++ b/projects/hip-tests/catch/unit/memory/hipMemcpyPeer.cc @@ -16,21 +16,35 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipMemcpyPeer_Positive_Default - Test basic P2P memcpy between two devices -with hipMemcpyPeer api Unit_hipMemcpyPeer_Positive_Synchronization_Behavior - -Test synchronization behavior for hipMemcpyPeer api -Unit_hipMemcpyPeer_Positive_ZeroSize - Test that no data is copied when -sizeBytes is set to 0 Unit_hipMemcpyPeer_Negative_Parameters - Test unsuccessful -execution of hipMemcpyPeer api when parameters are invalid -*/ + #include #include #include #include +/** + * @addtogroup hipMemcpyPeer hipMemcpyPeer + * @{ + * @ingroup PeerToPeerTest + * `hipMemcpyPeer(void* dst, int dstDeviceId, const void* src, + * int srcDeviceId, size_t sizeBytes)` - + * Copies memory from one device to memory on another device. + */ +/** + * Test Description + * ------------------------ + * - Performs basic peer to peer memcpy functionality between each pair of devices. + * - Launches computation kernel. + * Test source + * ------------------------ + * - unit/memory/hipMemcpyPeer.cc + * Test requirements + * ------------------------ + * - Peer access supported + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipMemcpyPeer_Positive_Default") { const auto device_count = HipTest::getDeviceCount(); if (device_count < 2) { @@ -77,6 +91,19 @@ TEST_CASE("Unit_hipMemcpyPeer_Positive_Default") { } } +/** + * Test Description + * ------------------------ + * - Checks synchronization behavior for peer memcpy. + * Test source + * ------------------------ + * - unit/memory/hipMemcpyPeer.cc + * Test requirements + * ------------------------ + * - Peer access supported + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipMemcpyPeer_Positive_Synchronization_Behavior") { HIP_CHECK(hipDeviceSynchronize()); @@ -111,6 +138,19 @@ TEST_CASE("Unit_hipMemcpyPeer_Positive_Synchronization_Behavior") { } } +/** + * Test Description + * ------------------------ + * - Checks that no data is copied if size is set to 0. + * Test source + * ------------------------ + * - unit/memory/hipMemcpyPeer.cc + * Test requirements + * ------------------------ + * - Peer access supported + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipMemcpyPeer_Positive_ZeroSize") { const auto device_count = HipTest::getDeviceCount(); if (device_count < 2) { @@ -151,7 +191,6 @@ TEST_CASE("Unit_hipMemcpyPeer_Positive_ZeroSize") { constexpr int set_value_h = 21; std::fill_n(result.host_ptr(), element_count, set_value_h); - HIP_CHECK(hipMemcpyPeer(dst_alloc.ptr(), dst_device, src_alloc.ptr(), src_device, 0)); HIP_CHECK( @@ -165,6 +204,29 @@ TEST_CASE("Unit_hipMemcpyPeer_Positive_ZeroSize") { } } +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output destination pointer is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When source pointer is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When copying more than allocated + * - Expected output: return `hipErrorInvalidValue` + * -# When destination device ID is not valid (out of bounds) + * - Expected output: return `hipErrorInvalidDevice` + * -# When source device ID is not valid (out of bounds) + * - Expected output: return `hipErrorInvalidDevice` + * Test source + * ------------------------ + * - unit/memory/hipMemcpyPeer.cc + * Test requirements + * ------------------------ + * - Peer access supported + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipMemcpyPeer_Negative_Parameters") { const auto device_count = HipTest::getDeviceCount(); if (device_count < 2) { diff --git a/projects/hip-tests/catch/unit/memory/hipMemcpyPeerAsync.cc b/projects/hip-tests/catch/unit/memory/hipMemcpyPeerAsync.cc index a84ade3329..d86da680d2 100644 --- a/projects/hip-tests/catch/unit/memory/hipMemcpyPeerAsync.cc +++ b/projects/hip-tests/catch/unit/memory/hipMemcpyPeerAsync.cc @@ -16,22 +16,35 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipMemcpyPeerAsync_Positive_Default - Test basic P2P async memcpy between -two devices with hipMemcpyPeerAsync api -Unit_hipMemcpyPeerAsync_Positive_Synchronization_Behavior - Test synchronization -behavior for hipMemcpyPeerAsync api Unit_hipMemcpyPeerAsync_Positive_ZeroSize - -Test that no data is copied when sizeBytes is set to 0 -Unit_hipMemcpyPeerAsync_Negative_Parameters - Test unsuccessful execution of -hipMemcpyPeerAsync api when parameters are invalid -*/ + #include #include #include #include +/** + * @addtogroup hipMemcpyPeerAsync hipMemcpyPeerAsync + * @{ + * @ingroup PeerToPeerTest + * `hipMemcpyPeerAsync(void* dst, int dstDeviceId, const void* src, + * int srcDevice, size_t sizeBytes, hipStream_t stream __dparm(0))` - + * Copies memory from one device to memory on another device. + */ +/** + * Test Description + * ------------------------ + * - Performs basic peer to peer async memcpy functionality between each pair of devices. + * - Launches computation kernel. + * Test source + * ------------------------ + * - unit/memory/hipMemcpyPeerAsync.cc + * Test requirements + * ------------------------ + * - Peer access supported + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipMemcpyPeerAsync_Positive_Default") { const auto device_count = HipTest::getDeviceCount(); if (device_count < 2) { @@ -86,6 +99,19 @@ TEST_CASE("Unit_hipMemcpyPeerAsync_Positive_Default") { } } +/** + * Test Description + * ------------------------ + * - Checks synchronization behavior for peer async memcpy. + * Test source + * ------------------------ + * - unit/memory/hipMemcpyPeerAsync.cc + * Test requirements + * ------------------------ + * - Peer access supported + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipMemcpyPeerAsync_Positive_Synchronization_Behavior") { HIP_CHECK(hipDeviceSynchronize()); @@ -124,6 +150,19 @@ TEST_CASE("Unit_hipMemcpyPeerAsync_Positive_Synchronization_Behavior") { } } +/** + * Test Description + * ------------------------ + * - Checks that no data is copied if size is set to 0. + * Test source + * ------------------------ + * - unit/memory/hipMemcpyPeerAsync.cc + * Test requirements + * ------------------------ + * - Peer access supported + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipMemcpyPeerAsync_Positive_ZeroSize") { const auto device_count = HipTest::getDeviceCount(); if (device_count < 2) { @@ -184,6 +223,31 @@ TEST_CASE("Unit_hipMemcpyPeerAsync_Positive_ZeroSize") { } } +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output destination pointer is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When source pointer is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When copying more than allocated + * - Expected output: return `hipErrorInvalidValue` + * -# When destination device ID is not valid (out of bounds) + * - Expected output: return `hipErrorInvalidDevice` + * -# When source device ID is not valid (out of bounds) + * - Expected output: return `hipErrorInvalidDevice` + * -# When stream is not valid + * - Expected output: return `hipErrorContextIsDestroyed` + * Test source + * ------------------------ + * - unit/memory/hipMemcpyPeerAsync.cc + * Test requirements + * ------------------------ + * - Peer access supported + * - Multi-device + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipMemcpyPeerAsync_Negative_Parameters") { const auto device_count = HipTest::getDeviceCount(); if (device_count < 2) { From be8a0d7d2c95ab02418e00fcd01e0f4fe8f5965a Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Wed, 28 Jun 2023 12:47:48 +0530 Subject: [PATCH 07/32] SWDEV-389689 - Rework oversubscription test to use threads instead of process. Also consider system memory when oversubscribing (#317) Change-Id: If063552e9e2815f07e944259237310f6fef37ad5 [ROCm/hip-tests commit: 329a350ec0b585800ff2792d2334a138b6a4277e] --- .../config/config_amd_linux_common.json | 1 - .../catch/include/hip_test_process.hh | 14 +- .../catch/stress/memory/CMakeLists.txt | 7 + .../stress/memory/hipHmmOvrSubscriptionTst.cc | 114 +++++++++ .../memory/hipMemPrftchAsyncStressTst.cc | 2 +- .../catch/stress/memory/hold_memory.cc | 45 ++++ .../catch/unit/memory/CMakeLists.txt | 7 - .../unit/memory/hipHmmOvrSubscriptionTst.cc | 221 ------------------ 8 files changed, 180 insertions(+), 231 deletions(-) create mode 100644 projects/hip-tests/catch/stress/memory/hipHmmOvrSubscriptionTst.cc create mode 100644 projects/hip-tests/catch/stress/memory/hold_memory.cc delete mode 100644 projects/hip-tests/catch/unit/memory/hipHmmOvrSubscriptionTst.cc diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json index 8c580cc95f..9dc8bbb073 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json @@ -55,7 +55,6 @@ "Disabling test tracked SWDEV-391718", "Unit_hipMemRangeGetAttribute_TstCountParam", "Fails in Stress test SWDEV-398971", - "Unit_HMM_OverSubscriptionTst", "SWDEV-398975 Seg faults in stress test", "Unit_hipMemcpyWithStream_MultiThread", "SWDEV-398977 fails in stress tests", diff --git a/projects/hip-tests/catch/include/hip_test_process.hh b/projects/hip-tests/catch/include/hip_test_process.hh index 2113dc85e1..e65be29d7e 100644 --- a/projects/hip-tests/catch/include/hip_test_process.hh +++ b/projects/hip-tests/catch/include/hip_test_process.hh @@ -31,6 +31,8 @@ THE SOFTWARE. #include #include #include +#include +#include namespace hip { /* @@ -46,6 +48,7 @@ class SpawnProc { std::string exeName; std::string resultStr; std::string tmpFileName; + std::future ret_from_run; bool captureOutput; std::string getRandomString(size_t len = 6) { @@ -68,7 +71,7 @@ class SpawnProc { exeName = dir.string(); // On Windows, fs::exists returns false without extension. if (TestContext::get().isWindows()) { - if(fs::path(exeName).extension().empty()) { + if (fs::path(exeName).extension().empty()) { exeName += ".exe"; } } @@ -112,6 +115,15 @@ class SpawnProc { #endif } + void run_async(std::string commandLineArgs = "") { + ret_from_run = std::async(std::launch::async, &hip::SpawnProc::run, this, commandLineArgs); + } + + int wait() { + ret_from_run.wait(); + return ret_from_run.get(); + } + std::string getOutput() { return resultStr; } }; } // namespace hip diff --git a/projects/hip-tests/catch/stress/memory/CMakeLists.txt b/projects/hip-tests/catch/stress/memory/CMakeLists.txt index a455dea73d..502eb9b42f 100644 --- a/projects/hip-tests/catch/stress/memory/CMakeLists.txt +++ b/projects/hip-tests/catch/stress/memory/CMakeLists.txt @@ -7,6 +7,13 @@ set(TEST_SRC hipHostMallocStress.cc ) +if(UNIX) + set(TEST_SRC ${TEST_SRC} + hipHmmOvrSubscriptionTst.cc) + add_executable(hold_memory EXCLUDE_FROM_ALL hold_memory.cc) + add_dependencies(stress_test hold_memory) +endif() + hip_add_exe_to_target(NAME memory_stress TEST_SRC ${TEST_SRC} TEST_TARGET_NAME stress_test) diff --git a/projects/hip-tests/catch/stress/memory/hipHmmOvrSubscriptionTst.cc b/projects/hip-tests/catch/stress/memory/hipHmmOvrSubscriptionTst.cc new file mode 100644 index 0000000000..6c7abf210f --- /dev/null +++ b/projects/hip-tests/catch/stress/memory/hipHmmOvrSubscriptionTst.cc @@ -0,0 +1,114 @@ +/* +Copyright (c) 2021-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. +*/ + +/* Test Case Description: This test case tests the working of OverSubscription + feature which is part of HMM.*/ + +#include +#include +#include + +__global__ void floatx2(float* ptr, size_t size) { + auto i = blockIdx.x * blockDim.x + threadIdx.x; + if (i < size) { + ptr[i] *= 2; + } +} + +TEST_CASE("Stress_HMM_OverSubscriptionTst") { + int hmm = 0; + HIP_CHECK(hipDeviceGetAttribute(&hmm, hipDeviceAttributeManagedMemory, 0)); + + bool shouldRun = []() -> bool { +#if HT_AMD // For AMD this gcn arch needs to have xnack+ + int device = 0; + hipDeviceProp_t props{}; + HIP_CHECK(hipGetDevice(&device)); + HIP_CHECK(hipGetDeviceProperties(&props, device)); + std::string arch(props.gcnArchName); + return arch.find("xnack+") != std::string::npos; +#else // For CUDA this depends on SM and attribute check should be fine + return true; +#endif + }(); + + if (hmm == 1 && shouldRun) { + hip::SpawnProc proc("hold_memory", true); + proc.run_async(); + size_t freeMem, totalMem; + HIP_CHECK(hipMemGetInfo(&freeMem, &totalMem)); + + constexpr float oversub_factor = 1.2f; + auto system_ram = HipTest::getMemoryAmount(); // In MB + + // Take in account of system memory + size_t max_memory = std::min(freeMem / (1024 * 1024), system_ram); + + size_t max_mem_used = (max_memory * oversub_factor) / 1024; // GB + + auto OneGBTest = []() { + constexpr size_t oneGB = 1024 * 1024 * 1024; + + hipStream_t stream; + HIP_CHECK_THREAD(hipStreamCreate(&stream)); + + float* data; + constexpr size_t alloc_elem = oneGB / sizeof(float); + HIP_CHECK_THREAD(hipMallocManaged(&data, oneGB, hipMemAttachGlobal)); + + constexpr float init_val = 1.1f; + + std::for_each(data, data + alloc_elem, [](float& a) { a = init_val; }); + + // basic sanity - first and last val are same + REQUIRE_THREAD(data[0] == init_val); + REQUIRE_THREAD(data[alloc_elem - 1] == init_val); + + // Page migrated to GPU + floatx2<<<(alloc_elem / 256) + 1, 256, 0, stream>>>(data, alloc_elem); + + HIP_CHECK_THREAD(hipStreamSynchronize(stream)); + + // Back to host + REQUIRE_THREAD( + std::all_of(data, data + alloc_elem, [](float a) { return a == (2.0f * init_val); })); + + HIP_CHECK_THREAD(hipFree(data)); + HIP_CHECK_THREAD(hipStreamDestroy(stream)); + }; + + std::vector thread_pool; + thread_pool.reserve(max_mem_used); + + for (size_t i = 0; i < max_mem_used; i++) { + thread_pool.emplace_back(std::thread(OneGBTest)); + } + + std::for_each(thread_pool.begin(), thread_pool.end(), + [](std::thread& thread) { thread.join(); }); + + HIP_CHECK_THREAD_FINALIZE(); + REQUIRE(proc.wait() == 0); + } else { + HipTest::HIP_SKIP_TEST("Tests only supposed to run on xnack+ devices"); + } +} diff --git a/projects/hip-tests/catch/stress/memory/hipMemPrftchAsyncStressTst.cc b/projects/hip-tests/catch/stress/memory/hipMemPrftchAsyncStressTst.cc index a551721b40..0e6acd5c7b 100644 --- a/projects/hip-tests/catch/stress/memory/hipMemPrftchAsyncStressTst.cc +++ b/projects/hip-tests/catch/stress/memory/hipMemPrftchAsyncStressTst.cc @@ -66,7 +66,7 @@ static void ReleaseResource(int *Hmm, hipStream_t *strm) { /* The following test allocates a managed memory and prefetch it in one-to-all and all-to-one fahsion followed by kernel launch within available devices*/ -TEST_CASE("Unit_hipMemPrefetchAsyncOneToAll") { +TEST_CASE("Stress_hipMemPrefetchAsyncOneToAll") { int MangdMem = HmmAttrPrint(); if (MangdMem == 1) { int *Hmm1 = nullptr, NumDevs, MemSz = (4096 * 4); diff --git a/projects/hip-tests/catch/stress/memory/hold_memory.cc b/projects/hip-tests/catch/stress/memory/hold_memory.cc new file mode 100644 index 0000000000..023782facd --- /dev/null +++ b/projects/hip-tests/catch/stress/memory/hold_memory.cc @@ -0,0 +1,45 @@ +/* + 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 +#include +#include +#include + +#define HIP_CHECK(call) \ + { \ + auto res_ = (call); \ + if (res_ != hipSuccess) { \ + std::cout << "Failed in: " << #call << std::endl; \ + return -1; \ + } \ + } + +int main() { + size_t freeMem = 0, totalMem = 0; + HIP_CHECK(hipMemGetInfo(&freeMem, &totalMem)); + + void* ptr; + HIP_CHECK(hipMalloc(&ptr, 0.4 * totalMem)); // hold 40% of total gpu memory + std::cout << "Sleeping..." << std::endl; + std::this_thread::sleep_for( + std::chrono::seconds(4)); // sleep for few seconds till test complete + std::cout << "Waking up..." << std::endl; + HIP_CHECK(hipFree(ptr)); +} \ No newline at end of file diff --git a/projects/hip-tests/catch/unit/memory/CMakeLists.txt b/projects/hip-tests/catch/unit/memory/CMakeLists.txt index dfecc3471f..f910089201 100644 --- a/projects/hip-tests/catch/unit/memory/CMakeLists.txt +++ b/projects/hip-tests/catch/unit/memory/CMakeLists.txt @@ -120,13 +120,6 @@ else() set(TEST_SRC ${TEST_SRC} hipGetSymbolSizeAddress.cc) endif() -# skipped due to os related code in tests need to work on them when all the -# tests are enabled -if(UNIX) - set(TEST_SRC ${TEST_SRC} hipHmmOvrSubscriptionTst.cc - hipMemoryAllocateCoherent.cc) -endif() - hip_add_exe_to_target(NAME MemoryTest TEST_SRC ${TEST_SRC} TEST_TARGET_NAME build_tests COMMON_SHARED_SRC ${COMMON_SHARED_SRC}) diff --git a/projects/hip-tests/catch/unit/memory/hipHmmOvrSubscriptionTst.cc b/projects/hip-tests/catch/unit/memory/hipHmmOvrSubscriptionTst.cc deleted file mode 100644 index 22fd5eb4b6..0000000000 --- a/projects/hip-tests/catch/unit/memory/hipHmmOvrSubscriptionTst.cc +++ /dev/null @@ -1,221 +0,0 @@ -/* -Copyright (c) 2021-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. -*/ - -/* Test Case Description: This test case tests the working of OverSubscription - feature which is part of HMM.*/ - -#include -#ifdef __linux__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif -#include - -#define INIT_VAL 2.5 -#define NUM_ELMS 268435456 // 268435456 * 4 = 1GB -#define ITERATIONS 10 -#define ONE_GB 1024 * 1024 * 1024 - -static void GetTotGpuMem(int *TotMem); -static void DisplayHmmFlgs(int *Signal); -// Kernel function -__global__ void Square(int n, float *x) { - int index = blockIdx.x * blockDim.x + threadIdx.x; - int stride = blockDim.x * gridDim.x; - for (int i = index; i < n; i += stride) { - x[i] = x[i] + 10; - } -} - -static void OneGBMemTest(int dev) { - int DataMismatch = 0; - float *HmmAG = nullptr; - hipStream_t strm; - HIP_CHECK(hipStreamCreate(&strm)); - // Testing hipMemAttachGlobal Flag - HIP_CHECK(hipMallocManaged(&HmmAG, NUM_ELMS * sizeof(float), - hipMemAttachGlobal)); - - // Initializing HmmAG memory - for (int i = 0; i < NUM_ELMS; i++) { - HmmAG[i] = INIT_VAL; - } - - int blockSize = 256; - int numBlocks = (NUM_ELMS + blockSize - 1) / blockSize; - dim3 dimGrid(numBlocks, 1, 1); - dim3 dimBlock(blockSize, 1, 1); - HIP_CHECK(hipSetDevice(dev)); - for (int i = 0; i < ITERATIONS; ++i) { - Square<<>>(NUM_ELMS, HmmAG); - } - HIP_CHECK(hipStreamSynchronize(strm)); - for (int j = 0; j < NUM_ELMS; ++j) { - if (HmmAG[j] != (INIT_VAL + ITERATIONS * 10)) { - DataMismatch++; - break; - } - } - if (DataMismatch != 0) { - WARN("Data Mismatch observed when kernel launched on device: " << dev); - REQUIRE(false); - } - HIP_CHECK(hipFree(HmmAG)); - HIP_CHECK(hipStreamDestroy(strm)); -} - -static void GetTotGpuMem(int *TotMem) { - size_t FreeMem, TotGpuMem; - HIP_CHECK(hipMemGetInfo(&FreeMem, &TotGpuMem)); - TotMem[0] = (TotGpuMem/(ONE_GB)); - TotMem[1] = 1; -} - -static void DisplayHmmFlgs(int *Signal) { - int managed = 0; - WARN("The following are the attribute values related to HMM for" - " device 0:\n"); - HIP_CHECK(hipDeviceGetAttribute(&managed, - hipDeviceAttributeDirectManagedMemAccessFromHost, 0)); - WARN("hipDeviceAttributeDirectManagedMemAccessFromHost: " << managed); - HIP_CHECK(hipDeviceGetAttribute(&managed, - hipDeviceAttributeConcurrentManagedAccess, 0)); - WARN("hipDeviceAttributeConcurrentManagedAccess: " << managed); - HIP_CHECK(hipDeviceGetAttribute(&managed, - hipDeviceAttributePageableMemoryAccess, 0)); - WARN("hipDeviceAttributePageableMemoryAccess: " << managed); - HIP_CHECK(hipDeviceGetAttribute(&managed, - hipDeviceAttributePageableMemoryAccessUsesHostPageTables, 0)); - WARN("hipDeviceAttributePageableMemoryAccessUsesHostPageTables:" - << managed); - - HIP_CHECK(hipDeviceGetAttribute(&managed, hipDeviceAttributeManagedMemory, - 0)); - WARN("hipDeviceAttributeManagedMemory: " << managed); - - // Checking for Vega20 or MI100 - hipDeviceProp_t prop; - HIP_CHECK(hipGetDeviceProperties(&prop, 0)); - char *p = NULL; - p = strstr(prop.gcnArchName, "gfx906"); - if (p) { - WARN("This system has MI60 gpu hence OverSubscription test will be"); - WARN(" skipped"); - Signal[2] = 1; - } - p = strstr(prop.gcnArchName, "gfx908"); - if (p) { - WARN("This system has MI100 gpu hence OverSubscription test will be"); - WARN(" skipped"); - Signal[2] = 1; - } - Signal[1] = managed; - Signal[0] = 1; -} - -TEST_CASE("Unit_HMM_OverSubscriptionTst") { - hipDeviceProp_t prop; - HIP_CHECK(hipGetDeviceProperties(&prop, 0)); - char *p = nullptr; - p = strstr(prop.gcnArchName, "xnack+"); - if (p == nullptr) { - INFO("Skipped due current device is non xnack device."); - return; - } - int HmmEnabled = 0; - // The following Shared Mem is to get Max GPU Mem - // The size requested is for three ints - // 1) To get Max GPU Mem in GB - // 2) To Signal parent that req. info is available to consume - // 3) To know if MI60 or MI100 gpu are there in the system - key_t key = ftok("shmTotMem", 66); - int shmid = shmget(key, (3 * sizeof(int)), 0666|IPC_CREAT); - int *TotGpuMem = reinterpret_cast(shmat(shmid, NULL, 0)); - TotGpuMem[0] = 0; TotGpuMem[1] = 0; - // The following function DisplayHmmFlgs() displays the flag values related - // to HMM and also sends us ManagedMemory attribute value - if (fork() == 0) { - DisplayHmmFlgs(TotGpuMem); - exit(1); - } - while (TotGpuMem[0] == 0) { - sleep(2); - } - // The following if block will skip test if either of MI60 or MI100 is found - if (TotGpuMem[2] == 1) { - SUCCEED("Test is skipped!!"); - REQUIRE(true); - } else { - HmmEnabled = TotGpuMem[1]; - - // Re-setting the shared memory values for further usage - TotGpuMem[0] = 0; - TotGpuMem[1] = 0; - - std::list PidLst; - // The following function gets the MaxGpu memory in GBs and also launches - // OverSubscription test - if (HmmEnabled) { - if ((setenv("HSA_XNACK", "1", 1)) != 0) { - WARN("Unable to turn on HSA_XNACK, hence terminating the Test case!"); - REQUIRE(false); - } - if (fork() == 0) { - GetTotGpuMem(TotGpuMem); - } - while (TotGpuMem[1] == 0) { - sleep(2); - } - int NumGB = TotGpuMem[0], TotalThreads = (NumGB + 10); - WARN("Launching " << TotalThreads); - WARN(" processes to test OverSubscription."); - pid_t pid; - for (int k = 0; k < TotalThreads; ++k) { - pid = fork(); - PidLst.push_back(pid); - if (pid == 0) { - OneGBMemTest(0); - exit(10); - } - } - } else { - SUCCEED("GPU 0 doesn't support hipDeviceAttributeManagedMemory " - "attribute. Hence skipping the testing with Pass result.\n"); - } - int status; - for (pid_t pd : PidLst) { - waitpid(pd, &status, 0); - if (!(WIFEXITED(status))) { - REQUIRE(false); - } - } - } - shmdt(TotGpuMem); - shmctl(shmid, IPC_RMID, NULL); -} From a8a0863e43401a138f1c4dcbaf0eb1b8ce462bad Mon Sep 17 00:00:00 2001 From: nives-vukovic <110852104+nives-vukovic@users.noreply.github.com> Date: Wed, 28 Jun 2023 09:19:28 +0200 Subject: [PATCH 08/32] EXSWHTEC-106 - Reimplement tests for hipOccupancyMaxActiveBlocksPerMultiprocessor and hipOccupancyMaxPotentialBlockSize APIs (#46) - Reimplement tests for hipOccupancyMaxActiveBlocksPerMultiprocessor and hipOccupancyMaxPotentialBlockSize APIs - Add helper file occupancy_common.hh with parameterized templates - Expand all positive and negative tests to use the templates - Change section disable macros - Disable AMD specific test due to defect - Disable negative test using json file - Fix disabled files [ROCm/hip-tests commit: dd9b9b027f2bfea7fe68e4700eadcd4f633f960b] --- .../config/config_amd_linux_common.json | 1 + .../config/config_amd_windows_common.json | 1 + .../catch/unit/occupancy/CMakeLists.txt | 2 + ...cupancyMaxActiveBlocksPerMultiprocessor.cc | 143 +++++++++++------- ...ncyMaxActiveBlocksPerMultiprocessor_old.cc | 91 +++++++++++ .../hipOccupancyMaxPotentialBlockSize.cc | 111 ++++++++------ .../hipOccupancyMaxPotentialBlockSize_old.cc | 80 ++++++++++ .../catch/unit/occupancy/occupancy_common.hh | 72 +++++++++ 8 files changed, 396 insertions(+), 105 deletions(-) create mode 100644 projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxActiveBlocksPerMultiprocessor_old.cc create mode 100644 projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxPotentialBlockSize_old.cc create mode 100644 projects/hip-tests/catch/unit/occupancy/occupancy_common.hh diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json index 9dc8bbb073..23d61f3ca6 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json @@ -13,6 +13,7 @@ "Unit_hipInit_Negative", "Unit_hipDeviceReset_Positive_Basic", "Unit_hipDeviceReset_Positive_Threaded", + "Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Negative_Parameters", "Unit_hipGraphMemcpyNodeSetParamsToSymbol_Positive_Basic", "Unit_hipGraphMemcpyNodeSetParamsFromSymbol_Positive_Basic", "Unit_hipKernelNameRef_Negative_Parameters", diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_windows_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_windows_common.json index c6dcda0c92..c88dfdfe7c 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_windows_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_windows_common.json @@ -95,6 +95,7 @@ "Unit_hipStreamSynchronize_NullStreamAndStreamPerThread", "Note: intermittent Seg fault failure ", "Unit_hipGraphAddEventRecordNode_Functional_WithoutFlags", + "Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Negative_Parameters", "Unit_hipGraphMemcpyNodeSetParamsToSymbol_Positive_Basic", "Unit_hipGraphExecMemcpyNodeSetParamsToSymbol_Positive_Basic", "Unit_hipGraphMemcpyNodeSetParamsFromSymbol_Positive_Basic", diff --git a/projects/hip-tests/catch/unit/occupancy/CMakeLists.txt b/projects/hip-tests/catch/unit/occupancy/CMakeLists.txt index eceb8626ca..2ad7eb5a6d 100644 --- a/projects/hip-tests/catch/unit/occupancy/CMakeLists.txt +++ b/projects/hip-tests/catch/unit/occupancy/CMakeLists.txt @@ -1,7 +1,9 @@ # Common Tests - Test independent of all platforms set(TEST_SRC hipOccupancyMaxActiveBlocksPerMultiprocessor.cc + hipOccupancyMaxActiveBlocksPerMultiprocessor_old.cc hipOccupancyMaxPotentialBlockSize.cc + hipOccupancyMaxPotentialBlockSize_old.cc hipOccupancyMaxPotentialBlockSizeVariableSMemWithFlags.cc ) diff --git a/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxActiveBlocksPerMultiprocessor.cc b/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxActiveBlocksPerMultiprocessor.cc index e6fdb3ba04..6199f45c38 100644 --- a/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxActiveBlocksPerMultiprocessor.cc +++ b/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxActiveBlocksPerMultiprocessor.cc @@ -1,5 +1,5 @@ /* -Copyright (c) 2021 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 @@ -16,76 +16,103 @@ 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 +/* +Testcase Scenarios : +Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Positive_RangeValidation - Test correct execution +of hipOccupancyMaxActiveBlocksPerMultiprocessor for diffrent parameter values +Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Positive_TemplateInvocation - Test correct +execution of hipOccupancyMaxActiveBlocksPerMultiprocessor template for diffrent parameter values +Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Negative_Parameters - Test unsuccessful execution +of hipOccupancyMaxActiveBlocksPerMultiprocessor api when parameters are invalid +*/ +#include "occupancy_common.hh" -static __global__ void f1(float *a) { *a = 1.0; } +static __global__ void f1(float* a) { *a = 1.0; } -template -static __global__ void f2(T *a) { *a = 1; } +template static __global__ void f2(T* a) { *a = 1; } -/** - * Defines - */ -#define OccupancyDisableCachingOverride 0x01 - -TEST_CASE("Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Negative") { - hipError_t ret; - int numBlock = 0, blockSize = 0; - int gridSize = 0, defBlkSize = 32; - - // Get potential blocksize - HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, f1, 0, 0)); - - // Validate each argument - ret = hipOccupancyMaxActiveBlocksPerMultiprocessor(NULL, f1, blockSize, 0); - REQUIRE(ret != hipSuccess); - - ret = hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlock, NULL, blockSize, 0); - REQUIRE(ret != hipSuccess); - - ret = hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlock, f1, 0, 0); - REQUIRE(ret != hipSuccess); - - ret = hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlock, f1, 0, - std::numeric_limits::max()); - REQUIRE(ret != hipSuccess); - - ret = hipOccupancyMaxActiveBlocksPerMultiprocessorWithFlags(&numBlock, f1, - defBlkSize, 0, OccupancyDisableCachingOverride); - REQUIRE(ret == hipSuccess); -} - -TEST_CASE("Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_rangeValidation") { - hipDeviceProp_t devProp; - int numBlock = 0, blockSize = 0; +TEST_CASE("Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Negative_Parameters") { + int numBlocks = 0; + int blockSize = 0; int gridSize = 0; // Get potential blocksize HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, f1, 0, 0)); + // Common negative tests + MaxActiveBlocksPerMultiprocessorNegative( + [](int* numBlocks, int blockSize, size_t dynSharedMemPerBlk) { + return hipOccupancyMaxActiveBlocksPerMultiprocessor(numBlocks, f1, blockSize, + dynSharedMemPerBlk); + }, + blockSize); + + SECTION("Kernel function is NULL") { + HIP_CHECK_ERROR(hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlocks, NULL, blockSize, 0), + hipErrorInvalidDeviceFunction); + } +} + +TEST_CASE("Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Positive_RangeValidation") { + hipDeviceProp_t devProp; + int blockSize = 0; + int gridSize = 0; + HIP_CHECK(hipGetDeviceProperties(&devProp, 0)); - HIP_CHECK(hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlock, f1, blockSize, 0)); + SECTION("dynSharedMemPerBlk = 0") { + // Get potential blocksize + HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, f1, 0, 0)); - // Check if numBlocks and blockSize are within limits - REQUIRE(numBlock > 0); - REQUIRE((numBlock * blockSize) <= devProp.maxThreadsPerMultiProcessor); + MaxActiveBlocksPerMultiprocessor( + [blockSize](int* numBlocks) { + return hipOccupancyMaxActiveBlocksPerMultiprocessor(numBlocks, f1, blockSize, 0); + }, + blockSize, devProp.maxThreadsPerMultiProcessor); + } + SECTION("dynSharedMemPerBlk = sharedMemPerBlock") { + // Get potential blocksize + HIP_CHECK( + hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, f1, devProp.sharedMemPerBlock, 0)); - // Validate numBlock after passing dynSharedMemPerBlk - HIP_CHECK(hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlock, f1, blockSize, - devProp.sharedMemPerBlock)); - - // Check if numBlocks and blockSize are within limits - REQUIRE(numBlock > 0); - REQUIRE((numBlock * blockSize) <= devProp.maxThreadsPerMultiProcessor); + MaxActiveBlocksPerMultiprocessor( + [blockSize, devProp](int* numBlocks) { + return hipOccupancyMaxActiveBlocksPerMultiprocessor(numBlocks, f1, blockSize, + devProp.sharedMemPerBlock); + }, + blockSize, devProp.maxThreadsPerMultiProcessor); + } } -TEST_CASE("Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_templateInvocation") { - int blockSize = 32; - int numBlock = 0; +TEST_CASE("Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Positive_TemplateInvocation") { + hipDeviceProp_t devProp; + int blockSize = 0; + int gridSize = 0; - HIP_CHECK(hipOccupancyMaxActiveBlocksPerMultiprocessor - (&numBlock, f2, blockSize, 0)); - REQUIRE(numBlock > 0); + HIP_CHECK(hipGetDeviceProperties(&devProp, 0)); + + SECTION("dynSharedMemPerBlk = 0") { + // Get potential blocksize + HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, f2, 0, 0)); + + MaxActiveBlocksPerMultiprocessor( + [blockSize](int* numBlocks) { + return hipOccupancyMaxActiveBlocksPerMultiprocessor(numBlocks, f2, + blockSize, 0); + }, + blockSize, devProp.maxThreadsPerMultiProcessor); + } + + SECTION("dynSharedMemPerBlk = sharedMemPerBlock") { + // Get potential blocksize + HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, f2, + devProp.sharedMemPerBlock, 0)); + + MaxActiveBlocksPerMultiprocessor( + [blockSize, devProp](int* numBlocks) { + return hipOccupancyMaxActiveBlocksPerMultiprocessor( + numBlocks, f2, blockSize, devProp.sharedMemPerBlock); + }, + blockSize, devProp.maxThreadsPerMultiProcessor); + } } - diff --git a/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxActiveBlocksPerMultiprocessor_old.cc b/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxActiveBlocksPerMultiprocessor_old.cc new file mode 100644 index 0000000000..e6fdb3ba04 --- /dev/null +++ b/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxActiveBlocksPerMultiprocessor_old.cc @@ -0,0 +1,91 @@ +/* +Copyright (c) 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 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 + +static __global__ void f1(float *a) { *a = 1.0; } + +template +static __global__ void f2(T *a) { *a = 1; } + +/** + * Defines + */ +#define OccupancyDisableCachingOverride 0x01 + +TEST_CASE("Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Negative") { + hipError_t ret; + int numBlock = 0, blockSize = 0; + int gridSize = 0, defBlkSize = 32; + + // Get potential blocksize + HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, f1, 0, 0)); + + // Validate each argument + ret = hipOccupancyMaxActiveBlocksPerMultiprocessor(NULL, f1, blockSize, 0); + REQUIRE(ret != hipSuccess); + + ret = hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlock, NULL, blockSize, 0); + REQUIRE(ret != hipSuccess); + + ret = hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlock, f1, 0, 0); + REQUIRE(ret != hipSuccess); + + ret = hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlock, f1, 0, + std::numeric_limits::max()); + REQUIRE(ret != hipSuccess); + + ret = hipOccupancyMaxActiveBlocksPerMultiprocessorWithFlags(&numBlock, f1, + defBlkSize, 0, OccupancyDisableCachingOverride); + REQUIRE(ret == hipSuccess); +} + +TEST_CASE("Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_rangeValidation") { + hipDeviceProp_t devProp; + int numBlock = 0, blockSize = 0; + int gridSize = 0; + + // Get potential blocksize + HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, f1, 0, 0)); + + HIP_CHECK(hipGetDeviceProperties(&devProp, 0)); + + HIP_CHECK(hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlock, f1, blockSize, 0)); + + // Check if numBlocks and blockSize are within limits + REQUIRE(numBlock > 0); + REQUIRE((numBlock * blockSize) <= devProp.maxThreadsPerMultiProcessor); + + // Validate numBlock after passing dynSharedMemPerBlk + HIP_CHECK(hipOccupancyMaxActiveBlocksPerMultiprocessor(&numBlock, f1, blockSize, + devProp.sharedMemPerBlock)); + + // Check if numBlocks and blockSize are within limits + REQUIRE(numBlock > 0); + REQUIRE((numBlock * blockSize) <= devProp.maxThreadsPerMultiProcessor); +} + +TEST_CASE("Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_templateInvocation") { + int blockSize = 32; + int numBlock = 0; + + HIP_CHECK(hipOccupancyMaxActiveBlocksPerMultiprocessor + (&numBlock, f2, blockSize, 0)); + REQUIRE(numBlock > 0); +} + diff --git a/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxPotentialBlockSize.cc b/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxPotentialBlockSize.cc index e31988a55b..0fc60cedfa 100644 --- a/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxPotentialBlockSize.cc +++ b/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxPotentialBlockSize.cc @@ -1,5 +1,5 @@ /* -Copyright (c) 2021 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 @@ -16,65 +16,82 @@ 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 +/* +Testcase Scenarios : +Unit_hipOccupancyMaxPotentialBlockSize_Positive_RangeValidation - Test correct execution of +hipOccupancyMaxPotentialBlockSize for diffrent parameter values +Unit_hipOccupancyMaxPotentialBlockSize_Positive_TemplateInvocation - Test correct execution of +hipOccupancyMaxPotentialBlockSize template for diffrent parameter values +Unit_hipOccupancyMaxPotentialBlockSize_Negative_Parameters - Test unsuccessful execution of +hipOccupancyMaxPotentialBlockSize api when parameters are invalid +*/ +#include "occupancy_common.hh" -static __global__ void f1(float *a) { *a = 1.0; } +static __global__ void f1(float* a) { *a = 1.0; } -template -static __global__ void f2(T *a) { *a = 1; } +template static __global__ void f2(T* a) { *a = 1; } -TEST_CASE("Unit_hipOccupancyMaxPotentialBlockSize_Negative") { - hipError_t ret; - int blockSize = 0; - int gridSize = 0; +TEST_CASE("Unit_hipOccupancyMaxPotentialBlockSize_Negative_Parameters") { + // Common negative tests + MaxPotentialBlockSizeNegative([](int* gridSize, int* blockSize) { + return hipOccupancyMaxPotentialBlockSize(gridSize, blockSize, f1, 0, 0); + }); - // Validate each argument - ret = hipOccupancyMaxPotentialBlockSize(NULL, &blockSize, f1, 0, 0); - REQUIRE(ret != hipSuccess); - - ret = hipOccupancyMaxPotentialBlockSize(&gridSize, NULL, f1, 0, 0); - REQUIRE(ret != hipSuccess); - -#ifndef __HIP_PLATFORM_NVIDIA__ - // nvcc doesnt support kernelfunc(NULL) for api - ret = hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, NULL, 0, 0); - REQUIRE(ret != hipSuccess); +#if HT_AMD +#if 0 // EXSWHTEC-219 + SECTION("Kernel function is NULL") { + int blockSize = 0; + int gridSize = 0; + // nvcc doesnt support kernelfunc(NULL) for api + HIP_CHECK_ERROR(hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, NULL, 0, 0), + hipErrorInvalidDeviceFunction); + } +#endif #endif } -TEST_CASE("Unit_hipOccupancyMaxPotentialBlockSize_rangeValidation") { +TEST_CASE("Unit_hipOccupancyMaxPotentialBlockSize_Positive_RangeValidation") { hipDeviceProp_t devProp; - int blockSize = 0; - int gridSize = 0; - - // Get potential blocksize - HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, f1, 0, 0)); HIP_CHECK(hipGetDeviceProperties(&devProp, 0)); - // Check if blockSize doen't exceed maxThreadsPerBlock - REQUIRE(gridSize > 0); REQUIRE(blockSize > 0); - REQUIRE(blockSize <= devProp.maxThreadsPerBlock); - - // Pass dynSharedMemPerBlk, blockSizeLimit and check out param - blockSize = 0; - gridSize = 0; - - HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, f1, - devProp.sharedMemPerBlock, devProp.maxThreadsPerBlock)); - - // Check if blockSize doen't exceed maxThreadsPerBlock - REQUIRE(gridSize > 0); REQUIRE(blockSize > 0); - REQUIRE(blockSize <= devProp.maxThreadsPerBlock); + SECTION("dynSharedMemPerBlk = 0, blockSizeLimit = 0") { + MaxPotentialBlockSize( + [](int* gridSize, int* blockSize) { + return hipOccupancyMaxPotentialBlockSize(gridSize, blockSize, f1, 0, 0); + }, + devProp.maxThreadsPerBlock); + } + SECTION("dynSharedMemPerBlk = sharedMemPerBlock, blockSizeLimit = maxThreadsPerBlock") { + MaxPotentialBlockSize( + [devProp](int* gridSize, int* blockSize) { + return hipOccupancyMaxPotentialBlockSize( + gridSize, blockSize, f1, devProp.sharedMemPerBlock, devProp.maxThreadsPerBlock); + }, + devProp.maxThreadsPerBlock); + } } -TEST_CASE("Unit_hipOccupancyMaxPotentialBlockSize_templateInvocation") { - int gridSize = 0, blockSize = 0; +TEST_CASE("Unit_hipOccupancyMaxPotentialBlockSize_Positive_TemplateInvocation") { + hipDeviceProp_t devProp; - HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, - &blockSize, f2, 0, 0)); - REQUIRE(gridSize > 0); - REQUIRE(blockSize > 0); + HIP_CHECK(hipGetDeviceProperties(&devProp, 0)); + + SECTION("dynSharedMemPerBlk = 0, blockSizeLimit = 0") { + MaxPotentialBlockSize( + [](int* gridSize, int* blockSize) { + return hipOccupancyMaxPotentialBlockSize(gridSize, blockSize, f2, 0, 0); + }, + devProp.maxThreadsPerBlock); + } + + SECTION("dynSharedMemPerBlk = sharedMemPerBlock, blockSizeLimit = maxThreadsPerBlock") { + MaxPotentialBlockSize( + [devProp](int* gridSize, int* blockSize) { + return hipOccupancyMaxPotentialBlockSize( + gridSize, blockSize, f2, devProp.sharedMemPerBlock, devProp.maxThreadsPerBlock); + }, + devProp.maxThreadsPerBlock); + } } - diff --git a/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxPotentialBlockSize_old.cc b/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxPotentialBlockSize_old.cc new file mode 100644 index 0000000000..e31988a55b --- /dev/null +++ b/projects/hip-tests/catch/unit/occupancy/hipOccupancyMaxPotentialBlockSize_old.cc @@ -0,0 +1,80 @@ +/* +Copyright (c) 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 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 + +static __global__ void f1(float *a) { *a = 1.0; } + +template +static __global__ void f2(T *a) { *a = 1; } + +TEST_CASE("Unit_hipOccupancyMaxPotentialBlockSize_Negative") { + hipError_t ret; + int blockSize = 0; + int gridSize = 0; + + // Validate each argument + ret = hipOccupancyMaxPotentialBlockSize(NULL, &blockSize, f1, 0, 0); + REQUIRE(ret != hipSuccess); + + ret = hipOccupancyMaxPotentialBlockSize(&gridSize, NULL, f1, 0, 0); + REQUIRE(ret != hipSuccess); + +#ifndef __HIP_PLATFORM_NVIDIA__ + // nvcc doesnt support kernelfunc(NULL) for api + ret = hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, NULL, 0, 0); + REQUIRE(ret != hipSuccess); +#endif +} + +TEST_CASE("Unit_hipOccupancyMaxPotentialBlockSize_rangeValidation") { + hipDeviceProp_t devProp; + int blockSize = 0; + int gridSize = 0; + + // Get potential blocksize + HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, f1, 0, 0)); + + HIP_CHECK(hipGetDeviceProperties(&devProp, 0)); + + // Check if blockSize doen't exceed maxThreadsPerBlock + REQUIRE(gridSize > 0); REQUIRE(blockSize > 0); + REQUIRE(blockSize <= devProp.maxThreadsPerBlock); + + // Pass dynSharedMemPerBlk, blockSizeLimit and check out param + blockSize = 0; + gridSize = 0; + + HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, &blockSize, f1, + devProp.sharedMemPerBlock, devProp.maxThreadsPerBlock)); + + // Check if blockSize doen't exceed maxThreadsPerBlock + REQUIRE(gridSize > 0); REQUIRE(blockSize > 0); + REQUIRE(blockSize <= devProp.maxThreadsPerBlock); + +} + +TEST_CASE("Unit_hipOccupancyMaxPotentialBlockSize_templateInvocation") { + int gridSize = 0, blockSize = 0; + + HIP_CHECK(hipOccupancyMaxPotentialBlockSize(&gridSize, + &blockSize, f2, 0, 0)); + REQUIRE(gridSize > 0); + REQUIRE(blockSize > 0); +} + diff --git a/projects/hip-tests/catch/unit/occupancy/occupancy_common.hh b/projects/hip-tests/catch/unit/occupancy/occupancy_common.hh new file mode 100644 index 0000000000..d03caad35b --- /dev/null +++ b/projects/hip-tests/catch/unit/occupancy/occupancy_common.hh @@ -0,0 +1,72 @@ +/* +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 + +#include + +template void MaxPotentialBlockSize(F func, int maxThreadsPerBlock) { + int gridSize = 0; + int blockSize = 0; + + // Get potential blocksize + HIP_CHECK(func(&gridSize, &blockSize)); + + // Check if blockSize doesn't exceed maxThreadsPerBlock + REQUIRE(gridSize > 0); + REQUIRE(blockSize > 0); + REQUIRE(blockSize <= maxThreadsPerBlock); + REQUIRE(gridSize * blockSize < static_cast(std::pow(2, 32))); +} + +template void MaxPotentialBlockSizeNegative(F func) { + int blockSize = 0; + int gridSize = 0; + + // Validate common arguments + SECTION("gridSize is nullptr") { + HIP_CHECK_ERROR(func(nullptr, &blockSize), hipErrorInvalidValue); + } + SECTION("blockSize is nullptr") { + HIP_CHECK_ERROR(func(&gridSize, nullptr), hipErrorInvalidValue); + } +} + +template +void MaxActiveBlocksPerMultiprocessor(F func, int blockSize, int maxThreadsPerMultiProcessor) { + int numBlocks = 0; + + // Validate maximum active block pre multiprocessor + HIP_CHECK(func(&numBlocks)); + + // Check if numBlocks and blockSize are within limits + REQUIRE(numBlocks > 0); + REQUIRE((numBlocks * blockSize) <= maxThreadsPerMultiProcessor); +} + +template void MaxActiveBlocksPerMultiprocessorNegative(F func, int blockSize) { + int numBlocks = 0; + + // Validate common arguments + SECTION("numBlocks is nullptr") { + HIP_CHECK_ERROR(func(nullptr, blockSize, 0), hipErrorInvalidValue); + } + SECTION("Block size is 0") { + HIP_CHECK_ERROR(func(&numBlocks, 0, 0), hipErrorInvalidValue); + } +} From 498662a131ca83dbc54978ae57aba16a8a1d006d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mirza=20Halil=C4=8Devi=C4=87?= <109971222+mirza-halilcevic@users.noreply.github.com> Date: Wed, 28 Jun 2023 09:20:42 +0200 Subject: [PATCH 09/32] EXSWHTEC-98 - Implement tests for hipMemcpy3D APIs (#55) - Implement tests for hipMemcpy3D APIs - Implement basic behavior checks in all copy directions - Implement synchronization behavior checks for expected behavior based on cuda docs - Implement positive tests for zero sized width and/or height copies, where no copy is expected to happen - Implement negative parameter tests - Implement all of the above for hipMemcpy3D and hipMemcpy3DAsync. - Disable failing tests on AMD. - Fix copyright disclaimer. [ROCm/hip-tests commit: 113a36c0eb67a5c127cba836df6f25872d665bb5] --- .../catch/include/memcpy1d_tests_common.hh | 1 + .../catch/include/memcpy3d_tests_common.hh | 585 +++++++++++ .../catch/unit/memory/CMakeLists.txt | 2 + .../catch/unit/memory/hipMemcpy3D.cc | 775 ++++----------- .../catch/unit/memory/hipMemcpy3DAsync.cc | 918 ++++-------------- .../catch/unit/memory/hipMemcpy3DAsync_old.cc | 755 ++++++++++++++ .../catch/unit/memory/hipMemcpy3D_old.cc | 627 ++++++++++++ 7 files changed, 2363 insertions(+), 1300 deletions(-) create mode 100644 projects/hip-tests/catch/include/memcpy3d_tests_common.hh create mode 100644 projects/hip-tests/catch/unit/memory/hipMemcpy3DAsync_old.cc create mode 100644 projects/hip-tests/catch/unit/memory/hipMemcpy3D_old.cc diff --git a/projects/hip-tests/catch/include/memcpy1d_tests_common.hh b/projects/hip-tests/catch/include/memcpy1d_tests_common.hh index 37d48a95c2..c14e6db444 100644 --- a/projects/hip-tests/catch/include/memcpy1d_tests_common.hh +++ b/projects/hip-tests/catch/include/memcpy1d_tests_common.hh @@ -1,5 +1,6 @@ /* 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 diff --git a/projects/hip-tests/catch/include/memcpy3d_tests_common.hh b/projects/hip-tests/catch/include/memcpy3d_tests_common.hh new file mode 100644 index 0000000000..eff00712ce --- /dev/null +++ b/projects/hip-tests/catch/include/memcpy3d_tests_common.hh @@ -0,0 +1,585 @@ +/* +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 + +#include + +#include +#include +#include +#include + +using PtrVariant = std::variant; + +static hipMemcpyKind ReverseMemcpyDirection(const hipMemcpyKind direction) { + switch (direction) { + case hipMemcpyHostToDevice: + return hipMemcpyDeviceToHost; + case hipMemcpyDeviceToHost: + return hipMemcpyHostToDevice; + default: + return direction; + } +}; + +static hipMemcpy3DParms GetMemcpy3DParms(PtrVariant dst_ptr, hipPos dst_pos, PtrVariant src_ptr, + hipPos src_pos, hipExtent extent, hipMemcpyKind kind) { + hipMemcpy3DParms parms = {0}; + if (std::holds_alternative(dst_ptr)) { + parms.dstArray = std::get(dst_ptr); + } else { + parms.dstPtr = std::get(dst_ptr); + } + parms.dstPos = dst_pos; + if (std::holds_alternative(src_ptr)) { + parms.srcArray = std::get(src_ptr); + } else { + parms.srcPtr = std::get(src_ptr); + } + parms.srcPos = src_pos; + parms.extent = extent; + parms.kind = kind; + + return parms; +} + +static bool operator==(const hipPitchedPtr& lhs, const hipPitchedPtr& rhs) { + // not checking for xsize currently as hipGraphMemcpyNodeGetParams returns incorrect value + return lhs.ptr == rhs.ptr && lhs.pitch == rhs.pitch && lhs.ysize == rhs.ysize; +} + +static bool operator==(const hipPos& lhs, const hipPos& rhs) { + return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z; +} + +static bool operator==(const hipExtent& lhs, const hipExtent& rhs) { + return lhs.width == rhs.width && lhs.height == rhs.height && lhs.depth == rhs.depth; +} + +static bool operator==(const hipMemcpy3DParms& lhs, const hipMemcpy3DParms& rhs) { + return lhs.dstArray == rhs.dstArray && lhs.dstPtr == rhs.dstPtr && lhs.dstPos == rhs.dstPos && + lhs.srcArray == rhs.srcArray && lhs.srcPtr == rhs.srcPtr && lhs.srcPos == rhs.srcPos && + lhs.extent == rhs.extent && lhs.kind == rhs.kind; +} + +template +hipError_t Memcpy3DWrapper(PtrVariant dst_ptr, hipPos dst_pos, PtrVariant src_ptr, hipPos src_pos, + hipExtent extent, hipMemcpyKind kind, hipStream_t stream = nullptr) { + auto parms = GetMemcpy3DParms(dst_ptr, dst_pos, src_ptr, src_pos, extent, kind); + + if constexpr (graph) { + hipGraph_t g = nullptr; + HIP_CHECK(hipGraphCreate(&g, 0)); + hipGraphNode_t node = nullptr; + + if constexpr (set_params) { + auto reversed_parms = GetMemcpy3DParms(src_ptr, src_pos, dst_ptr, dst_pos, extent, + ReverseMemcpyDirection(kind)); + HIP_CHECK(hipGraphAddMemcpyNode(&node, g, nullptr, 0, &reversed_parms)); + HIP_CHECK(hipGraphMemcpyNodeSetParams(node, &parms)); + } else { + HIP_CHECK(hipGraphAddMemcpyNode(&node, g, nullptr, 0, &parms)); + } + + hipMemcpy3DParms retrieved_params = {0}; + HIP_CHECK(hipGraphMemcpyNodeGetParams(node, &retrieved_params)); + REQUIRE(parms == retrieved_params); + + hipGraphExec_t graph_exec = nullptr; + HIP_CHECK(hipGraphInstantiate(&graph_exec, g, nullptr, nullptr, 0)); + HIP_CHECK(hipGraphLaunch(graph_exec, hipStreamPerThread)); + HIP_CHECK(hipStreamSynchronize(hipStreamPerThread)); + + HIP_CHECK(hipGraphExecDestroy(graph_exec)); + HIP_CHECK(hipGraphDestroy(g)); + + return hipSuccess; + } + + if constexpr (async) { + return hipMemcpy3DAsync(&parms, stream); + } else { + return hipMemcpy3D(&parms); + } +} + +template +void Memcpy3DDeviceToHostShell(F memcpy_func, const hipStream_t kernel_stream = nullptr) { + const auto kind = GENERATE(hipMemcpyDeviceToHost, hipMemcpyDefault); + + constexpr hipExtent extent{127 * sizeof(int), 128, 8}; + + LinearAllocGuard3D device_alloc(extent); + + const size_t host_pitch = GENERATE_REF(device_alloc.width(), device_alloc.width() + 64); + LinearAllocGuard host_alloc(LinearAllocs::hipHostMalloc, + host_pitch * device_alloc.height() * device_alloc.depth()); + + const dim3 threads_per_block(32, 32); + const dim3 blocks(device_alloc.width_logical() / threads_per_block.x + 1, + device_alloc.height() / threads_per_block.y + 1, device_alloc.depth()); + Iota<<>>(device_alloc.ptr(), device_alloc.pitch(), + device_alloc.width_logical(), device_alloc.height(), + device_alloc.depth()); + HIP_CHECK(hipGetLastError()); + + HIP_CHECK(memcpy_func( + make_hipPitchedPtr(host_alloc.ptr(), host_pitch, device_alloc.width(), device_alloc.height()), + make_hipPos(0, 0, 0), device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), device_alloc.extent(), + kind, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + const auto f = [extent](size_t x, size_t y, size_t z) { + constexpr auto width_logical = extent.width / sizeof(int); + return z * width_logical * extent.height + y * width_logical + x; + }; + PitchedMemoryVerify(host_alloc.ptr(), host_pitch, device_alloc.width_logical(), + device_alloc.height(), device_alloc.depth(), f); +} + +template +void Memcpy3DDeviceToDeviceShell(F memcpy_func, const hipStream_t kernel_stream = nullptr) { + const auto kind = GENERATE(hipMemcpyDeviceToDevice, hipMemcpyDefault); + + constexpr hipExtent extent{127 * sizeof(int), 128, 8}; + + const auto device_count = HipTest::getDeviceCount(); + const auto src_device = GENERATE_COPY(range(0, device_count)); + const auto dst_device = GENERATE_COPY(range(0, device_count)); + const size_t src_cols_mult = GENERATE(1, 2); + + INFO("Src device: " << src_device << ", Dst device: " << dst_device); + + HIP_CHECK(hipSetDevice(src_device)); + if constexpr (enable_peer_access) { + if (src_device == dst_device) { + return; + } + int can_access_peer = 0; + HIP_CHECK(hipDeviceCanAccessPeer(&can_access_peer, src_device, dst_device)); + if (!can_access_peer) { + INFO("Peer access cannot be enabled between devices " << src_device << " " << dst_device); + REQUIRE(can_access_peer); + } + HIP_CHECK(hipDeviceEnablePeerAccess(dst_device, 0)); + } + + LinearAllocGuard3D src_alloc(extent); + HIP_CHECK(hipSetDevice(src_device)); + LinearAllocGuard3D dst_alloc(extent); + HIP_CHECK(hipSetDevice(src_device)); + LinearAllocGuard host_alloc(LinearAllocs::hipHostMalloc, + dst_alloc.width() * dst_alloc.height() * dst_alloc.depth()); + + const dim3 threads_per_block(32, 32); + const dim3 blocks(dst_alloc.width_logical() / threads_per_block.x + 1, + dst_alloc.height() / threads_per_block.y + 1, dst_alloc.depth()); + // Using dst_alloc width and height to set only the elements that will be copied over to + // dst_alloc + Iota<<>>(src_alloc.ptr(), src_alloc.pitch(), dst_alloc.width_logical(), + dst_alloc.height(), dst_alloc.depth()); + HIP_CHECK(hipGetLastError()); + + HIP_CHECK(memcpy_func(dst_alloc.pitched_ptr(), make_hipPos(0, 0, 0), src_alloc.pitched_ptr(), + make_hipPos(0, 0, 0), dst_alloc.extent(), kind, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + HIP_CHECK(Memcpy3DWrapper(make_hipPitchedPtr(host_alloc.ptr(), dst_alloc.width(), + dst_alloc.width(), dst_alloc.height()), + make_hipPos(0, 0, 0), dst_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + dst_alloc.extent(), hipMemcpyDeviceToHost)); + + const auto f = [extent](size_t x, size_t y, size_t z) { + constexpr auto width_logical = extent.width / sizeof(int); + return z * width_logical * extent.height + y * width_logical + x; + }; + PitchedMemoryVerify(host_alloc.ptr(), dst_alloc.width(), dst_alloc.width_logical(), + dst_alloc.height(), dst_alloc.depth(), f); +} + +template +void Memcpy3DHostToDeviceShell(F memcpy_func, const hipStream_t kernel_stream = nullptr) { + const auto kind = GENERATE(hipMemcpyHostToDevice, hipMemcpyDefault); + + constexpr hipExtent extent{127 * sizeof(int), 128, 8}; + + LinearAllocGuard3D device_alloc(extent); + + const size_t host_pitch = GENERATE_REF(device_alloc.pitch(), 2 * device_alloc.pitch()); + + LinearAllocGuard src_host_alloc(LinearAllocs::hipHostMalloc, + host_pitch * device_alloc.height() * device_alloc.depth()); + LinearAllocGuard dst_host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.width() * device_alloc.height() * device_alloc.depth()); + + const auto f = [extent](size_t x, size_t y, size_t z) { + constexpr auto width_logical = extent.width / sizeof(int); + return z * width_logical * extent.height + y * width_logical + x; + }; + PitchedMemorySet(src_host_alloc.ptr(), host_pitch, device_alloc.width_logical(), + device_alloc.height(), device_alloc.depth(), f); + + std::fill_n(dst_host_alloc.ptr(), + device_alloc.width_logical() * device_alloc.height() * device_alloc.depth(), 0); + + HIP_CHECK(memcpy_func(device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + make_hipPitchedPtr(src_host_alloc.ptr(), host_pitch, device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), device_alloc.extent(), kind, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + HIP_CHECK(Memcpy3DWrapper(make_hipPitchedPtr(dst_host_alloc.ptr(), device_alloc.width(), + device_alloc.width(), device_alloc.height()), + make_hipPos(0, 0, 0), device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + device_alloc.extent(), hipMemcpyDeviceToHost)); + + PitchedMemoryVerify(dst_host_alloc.ptr(), device_alloc.width(), device_alloc.width_logical(), + device_alloc.height(), device_alloc.depth(), f); +} + +template +void Memcpy3DHostToHostShell(F memcpy_func, const hipStream_t kernel_stream = nullptr) { + const auto kind = GENERATE(hipMemcpyHostToHost, hipMemcpyDefault); + + constexpr hipExtent extent{127 * sizeof(int), 128, 8}; + + const size_t padding = GENERATE_COPY(0, 64); + const size_t src_pitch = extent.width + padding; + + LinearAllocGuard src_host(LinearAllocs::hipHostMalloc, + src_pitch * extent.height * extent.depth); + LinearAllocGuard dst_host(LinearAllocs::hipHostMalloc, + extent.width * extent.height * extent.depth); + + const auto f = [extent](size_t x, size_t y, size_t z) { + constexpr auto width_logical = extent.width / sizeof(int); + return z * width_logical * extent.height + y * width_logical + x; + }; + PitchedMemorySet(src_host.ptr(), src_pitch, extent.width / sizeof(int), extent.height, + extent.depth, f); + + HIP_CHECK( + memcpy_func(make_hipPitchedPtr(dst_host.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), + make_hipPitchedPtr(src_host.ptr(), src_pitch, extent.width, extent.height), + make_hipPos(0, 0, 0), extent, kind, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + PitchedMemoryVerify(dst_host.ptr(), extent.width, extent.width / sizeof(int), extent.height, + extent.depth, f); +} + +template +void Memcpy3DArrayHostShell(F memcpy_func, const hipStream_t kernel_stream = nullptr) { + constexpr hipExtent extent{127, 128, 8}; + + LinearAllocGuard src_host(LinearAllocs::hipHostMalloc, + extent.width * sizeof(int) * extent.height * extent.depth); + LinearAllocGuard dst_host(LinearAllocs::hipHostMalloc, + extent.width * sizeof(int) * extent.height * extent.depth); + + ArrayAllocGuard src_array(extent); + ArrayAllocGuard dst_array(extent); + + const auto f = [extent](size_t x, size_t y, size_t z) { + return z * extent.width * extent.height + y * extent.width + x; + }; + PitchedMemorySet(src_host.ptr(), extent.width * sizeof(int), extent.width, extent.height, + extent.depth, f); + + // Host -> Array + HIP_CHECK(memcpy_func(src_array.ptr(), make_hipPos(0, 0, 0), + make_hipPitchedPtr(src_host.ptr(), extent.width * sizeof(int), + extent.width * sizeof(int), extent.height), + make_hipPos(0, 0, 0), extent, hipMemcpyHostToDevice, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + // Array -> Array + HIP_CHECK(memcpy_func(dst_array.ptr(), make_hipPos(0, 0, 0), src_array.ptr(), + make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + // Array -> Host + HIP_CHECK(memcpy_func(make_hipPitchedPtr(dst_host.ptr(), extent.width * sizeof(int), + extent.width * sizeof(int), extent.height), + make_hipPos(0, 0, 0), dst_array.ptr(), make_hipPos(0, 0, 0), extent, + hipMemcpyDeviceToHost, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + PitchedMemoryVerify(dst_host.ptr(), extent.width * sizeof(int), extent.width, extent.height, + extent.depth, f); +} + +template +void Memcpy3DArrayDeviceShell(F memcpy_func, const hipStream_t kernel_stream = nullptr) { + constexpr hipExtent extent{127, 128, 8}; + + LinearAllocGuard host_alloc(LinearAllocs::hipHostMalloc, + extent.width * sizeof(int) * extent.height * extent.depth); + + ArrayAllocGuard src_array(extent); + ArrayAllocGuard dst_array(extent); + + LinearAllocGuard3D src_device(extent.width, extent.height, extent.depth); + LinearAllocGuard3D dst_device(extent.width, extent.height, extent.depth); + + const dim3 threads_per_block(32, 32); + const dim3 blocks(src_device.width_logical() / threads_per_block.x + 1, + src_device.height() / threads_per_block.y + 1, src_device.depth()); + Iota<<>>(src_device.ptr(), src_device.pitch(), + src_device.width_logical(), src_device.height(), + src_device.depth()); + HIP_CHECK(hipGetLastError()); + + // Device -> Array + HIP_CHECK(memcpy_func(src_array.ptr(), make_hipPos(0, 0, 0), src_device.pitched_ptr(), + make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + // Array -> Array + HIP_CHECK(memcpy_func(dst_array.ptr(), make_hipPos(0, 0, 0), src_array.ptr(), + make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + // Array -> Device + HIP_CHECK(memcpy_func(dst_device.pitched_ptr(), make_hipPos(0, 0, 0), dst_array.ptr(), + make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + // Device -> Host + HIP_CHECK(memcpy_func(make_hipPitchedPtr(host_alloc.ptr(), extent.width * sizeof(int), + extent.width * sizeof(int), extent.height), + make_hipPos(0, 0, 0), dst_device.pitched_ptr(), make_hipPos(0, 0, 0), + dst_device.extent(), hipMemcpyDeviceToHost, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + const auto f = [extent](size_t x, size_t y, size_t z) { + return z * extent.width * extent.height + y * extent.width + x; + }; + PitchedMemoryVerify(host_alloc.ptr(), extent.width * sizeof(int), extent.width, extent.height, + extent.depth, f); +} + +template +void Memcpy3DHtoDSyncBehavior(F memcpy_func, const bool should_sync, + const hipStream_t kernel_stream = nullptr) { + using LA = LinearAllocs; + const auto host_alloc_type = GENERATE(LA::malloc, LA::hipHostMalloc); + LinearAllocGuard3D device_alloc(make_hipExtent(32 * sizeof(int), 32, 8)); + LinearAllocGuard host_alloc( + host_alloc_type, device_alloc.width() * device_alloc.height() * device_alloc.depth()); + MemcpySyncBehaviorCheck( + std::bind(memcpy_func, device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + make_hipPitchedPtr(host_alloc.ptr(), device_alloc.width(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), device_alloc.extent(), hipMemcpyHostToDevice, kernel_stream), + should_sync, kernel_stream); +} + +template +void Memcpy3DDtoHPageableSyncBehavior(F memcpy_func, const bool should_sync, + const hipStream_t kernel_stream = nullptr) { + LinearAllocGuard3D device_alloc(make_hipExtent(32 * sizeof(int), 32, 8)); + LinearAllocGuard host_alloc( + LinearAllocs::malloc, device_alloc.width() * device_alloc.height() * device_alloc.depth()); + MemcpySyncBehaviorCheck( + std::bind(memcpy_func, + make_hipPitchedPtr(host_alloc.ptr(), device_alloc.width(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + device_alloc.extent(), hipMemcpyDeviceToHost, kernel_stream), + should_sync, kernel_stream); +} + +template +void Memcpy3DDtoHPinnedSyncBehavior(F memcpy_func, const bool should_sync, + const hipStream_t kernel_stream = nullptr) { + LinearAllocGuard3D device_alloc(make_hipExtent(32 * sizeof(int), 32, 8)); + LinearAllocGuard host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.width() * device_alloc.height() * device_alloc.depth()); + MemcpySyncBehaviorCheck( + std::bind(memcpy_func, + make_hipPitchedPtr(host_alloc.ptr(), device_alloc.width(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + device_alloc.extent(), hipMemcpyDeviceToHost, kernel_stream), + should_sync, kernel_stream); +} + +template +void Memcpy3DDtoDSyncBehavior(F memcpy_func, const bool should_sync, + const hipStream_t kernel_stream = nullptr) { + LinearAllocGuard3D src_alloc(make_hipExtent(32 * sizeof(int), 32, 8)); + LinearAllocGuard3D dst_alloc(make_hipExtent(32 * sizeof(int), 32, 8)); + MemcpySyncBehaviorCheck( + std::bind(memcpy_func, dst_alloc.pitched_ptr(), make_hipPos(0, 0, 0), src_alloc.pitched_ptr(), + make_hipPos(0, 0, 0), dst_alloc.extent(), hipMemcpyDeviceToDevice, kernel_stream), + should_sync, kernel_stream); +} + +template +void Memcpy3DHtoHSyncBehavior(F memcpy_func, const bool should_sync, + const hipStream_t kernel_stream = nullptr) { + using LA = LinearAllocs; + const auto src_alloc_type = GENERATE(LA::malloc, LA::hipHostMalloc); + const auto dst_alloc_type = GENERATE(LA::malloc, LA::hipHostMalloc); + + LinearAllocGuard src_alloc(src_alloc_type, 32 * sizeof(int) * 32 * 8); + LinearAllocGuard dst_alloc(dst_alloc_type, 32 * sizeof(int) * 32 * 8); + MemcpySyncBehaviorCheck( + std::bind(memcpy_func, + make_hipPitchedPtr(dst_alloc.ptr(), 32 * sizeof(int), 32 * sizeof(int), 32), + make_hipPos(0, 0, 0), + make_hipPitchedPtr(src_alloc.ptr(), 32 * sizeof(int), 32 * sizeof(int), 32), + make_hipPos(0, 0, 0), make_hipExtent(32 * sizeof(int), 32, 8), hipMemcpyHostToHost, + kernel_stream), + should_sync, kernel_stream); +} + +template +void Memcpy3DZeroWidthHeightDepth(F memcpy_func, const hipStream_t stream = nullptr) { + constexpr hipExtent extent{127 * sizeof(int), 128, 8}; + + const auto [width_mult, height_mult, depth_mult] = + GENERATE(std::make_tuple(0, 1, 1), std::make_tuple(1, 0, 1), std::make_tuple(1, 1, 0)); + + SECTION("Device to Host") { + LinearAllocGuard3D device_alloc(extent); + LinearAllocGuard host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.width() * device_alloc.height() * device_alloc.depth()); + std::fill_n(host_alloc.ptr(), + device_alloc.width_logical() * device_alloc.height() * device_alloc.depth(), 42); + HIP_CHECK(hipMemset3D(device_alloc.pitched_ptr(), 1, device_alloc.extent())); + HIP_CHECK(memcpy_func( + make_hipPitchedPtr(host_alloc.ptr(), device_alloc.width(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + make_hipExtent(device_alloc.width() * width_mult, device_alloc.height() * height_mult, + device_alloc.depth() * depth_mult), + hipMemcpyDeviceToHost, stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(stream)); + } + ArrayFindIfNot(host_alloc.ptr(), static_cast(42), + device_alloc.width_logical() * device_alloc.height() * device_alloc.depth()); + } + + SECTION("Device to Device") { + LinearAllocGuard3D src_alloc(extent); + LinearAllocGuard3D dst_alloc(extent); + LinearAllocGuard host_alloc( + LinearAllocs::hipHostMalloc, dst_alloc.width() * dst_alloc.height() * dst_alloc.depth()); + HIP_CHECK(hipMemset3D(src_alloc.pitched_ptr(), 1, src_alloc.extent())); + HIP_CHECK(hipMemset3D(dst_alloc.pitched_ptr(), 42, dst_alloc.extent())); + HIP_CHECK( + memcpy_func(dst_alloc.pitched_ptr(), make_hipPos(0, 0, 0), src_alloc.pitched_ptr(), + make_hipPos(0, 0, 0), + make_hipExtent(dst_alloc.width() * width_mult, dst_alloc.height() * height_mult, + dst_alloc.depth() * depth_mult), + hipMemcpyDeviceToDevice, stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(stream)); + } + HIP_CHECK(Memcpy3DWrapper(make_hipPitchedPtr(host_alloc.ptr(), dst_alloc.width(), + dst_alloc.width(), dst_alloc.height()), + make_hipPos(0, 0, 0), dst_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + dst_alloc.extent(), hipMemcpyDeviceToHost)); + ArrayFindIfNot(host_alloc.ptr(), static_cast(42), + dst_alloc.width_logical() * dst_alloc.height()); + } + + SECTION("Host to Device") { + LinearAllocGuard3D device_alloc(extent); + LinearAllocGuard src_host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.width() * device_alloc.height() * device_alloc.depth()); + LinearAllocGuard dst_host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.width() * device_alloc.height() * device_alloc.depth()); + std::fill_n(src_host_alloc.ptr(), + device_alloc.width_logical() * device_alloc.height() * device_alloc.depth(), 1); + HIP_CHECK(hipMemset3D(device_alloc.pitched_ptr(), 42, device_alloc.extent())); + HIP_CHECK(memcpy_func( + device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + make_hipPitchedPtr(src_host_alloc.ptr(), device_alloc.width(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), + make_hipExtent(device_alloc.width() * width_mult, device_alloc.height() * height_mult, + device_alloc.depth() * depth_mult), + hipMemcpyHostToDevice, stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(stream)); + } + HIP_CHECK(Memcpy3DWrapper(make_hipPitchedPtr(dst_host_alloc.ptr(), device_alloc.width(), + device_alloc.width(), device_alloc.height()), + make_hipPos(0, 0, 0), device_alloc.pitched_ptr(), + make_hipPos(0, 0, 0), device_alloc.extent(), hipMemcpyDeviceToHost)); + ArrayFindIfNot(dst_host_alloc.ptr(), static_cast(42), + device_alloc.width_logical() * device_alloc.height()); + } + + SECTION("Host to Host") { + const auto alloc_size = extent.width * extent.height * extent.depth; + LinearAllocGuard src_alloc(LinearAllocs::hipHostMalloc, alloc_size); + LinearAllocGuard dst_alloc(LinearAllocs::hipHostMalloc, alloc_size); + std::fill_n(src_alloc.ptr(), alloc_size, 1); + std::fill_n(dst_alloc.ptr(), alloc_size, 42); + HIP_CHECK( + memcpy_func(make_hipPitchedPtr(dst_alloc.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), + make_hipPitchedPtr(src_alloc.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), + make_hipExtent(extent.width * width_mult, extent.height * height_mult, + extent.depth * depth_mult), + hipMemcpyHostToHost, stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(stream)); + } + ArrayFindIfNot(dst_alloc.ptr(), static_cast(42), alloc_size); + } +} \ No newline at end of file diff --git a/projects/hip-tests/catch/unit/memory/CMakeLists.txt b/projects/hip-tests/catch/unit/memory/CMakeLists.txt index f910089201..585f749fed 100644 --- a/projects/hip-tests/catch/unit/memory/CMakeLists.txt +++ b/projects/hip-tests/catch/unit/memory/CMakeLists.txt @@ -29,7 +29,9 @@ set(TEST_SRC hipMemcpy2DToArrayAsync.cc hipMemcpy2DToArrayAsync_old.cc hipMemcpy3D.cc + hipMemcpy3D_old.cc hipMemcpy3DAsync.cc + hipMemcpy3DAsync_old.cc hipMemcpyParam2D.cc hipMemcpyParam2DAsync.cc hipMemcpy2D.cc diff --git a/projects/hip-tests/catch/unit/memory/hipMemcpy3D.cc b/projects/hip-tests/catch/unit/memory/hipMemcpy3D.cc index 4af0883639..90638fc59a 100644 --- a/projects/hip-tests/catch/unit/memory/hipMemcpy3D.cc +++ b/projects/hip-tests/catch/unit/memory/hipMemcpy3D.cc @@ -1,13 +1,16 @@ /* -Copyright (c) 2021 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,611 +20,209 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * This testfile verifies the following scenarios of hipMemcpy3D API - * - * 1. Verifying hipMemcpy3D API for H2D,D2D and D2H scenarios for - different datatypes and sizes. - * 2. Verifying Negative Scenarios - * 3. Verifying Extent validation scenarios by passing 0 - * 4. Verifying hipMemcpy3D API by allocating Memory in - * one GPU and trigger hipMemcpy3D from peer GPU - * - */ +#include +#include #include -#include +#include +#include +#include -static constexpr auto width{10}; -static constexpr auto height{10}; -static constexpr auto depth{10}; +TEST_CASE("Unit_hipMemcpy3D_Positive_Basic") { + constexpr bool async = false; -template -class Memcpy3D { - int width, height, depth; - unsigned int size; - hipArray *arr, *arr1; - hipChannelFormatKind formatKind; - hipMemcpy3DParms myparms; - T* hData; - public: - Memcpy3D(int l_width, int l_height, int l_depth, - hipChannelFormatKind l_format); - void simple_Memcpy3D(); - void Extent_Validation(); - void NegativeTests(); - void AllocateMemory(); - void DeAllocateMemory(); - void SetDefaultData(); - void D2D_DeviceMem_OnDiffDevice(); - void D2H_H2D_DeviceMem_OnDiffDevice(); -}; + SECTION("Device to Host") { Memcpy3DDeviceToHostShell(Memcpy3DWrapper<>); } -/* - * This API sets the default values of hipMemcpy3DParms structure - */ -template -void Memcpy3D::SetDefaultData() { - myparms.srcPos = make_hipPos(0, 0, 0); - myparms.dstPos = make_hipPos(0, 0, 0); - myparms.extent = make_hipExtent(width , height, depth); -} - -/* - * Constructor initalized width,depth and height - */ -template -Memcpy3D::Memcpy3D(int l_width, int l_height, int l_depth, - hipChannelFormatKind l_format) { - width = l_width; - height = l_height; - depth = l_depth; - formatKind = l_format; -} - -/* - * Allocating Memory and initalizing data for both - * device and host variables - */ -template -void Memcpy3D::AllocateMemory() { - size = width * height * depth * sizeof(T); - hData = reinterpret_cast(malloc(size)); - memset(hData, 0, size); - for (int i = 0; i < depth; i++) { - for (int j = 0; j < height; j++) { - for (int k = 0; k < width; k++) { - hData[i*width*height + j*width +k] = i*width*height + j*width + k; - } + SECTION("Device to Device") { + SECTION("Peer access disabled") { + Memcpy3DDeviceToDeviceShell(Memcpy3DWrapper<>); } + SECTION("Peer access enabled") { Memcpy3DDeviceToDeviceShell(Memcpy3DWrapper<>); } } - hipChannelFormatDesc channelDesc = hipCreateChannelDesc(sizeof(T)*8, - 0, 0, 0, formatKind); - HIP_CHECK(hipMalloc3DArray(&arr, &channelDesc, make_hipExtent(width, height, - depth), hipArrayDefault)); - HIP_CHECK(hipMalloc3DArray(&arr1, &channelDesc, make_hipExtent(width, height, - depth), hipArrayDefault)); + + SECTION("Host to Device") { Memcpy3DHostToDeviceShell(Memcpy3DWrapper<>); } + + SECTION("Host to Host") { Memcpy3DHostToHostShell(Memcpy3DWrapper<>); } } -/* - * DeAllocates the Memory of device and host variables - */ -template -void Memcpy3D::DeAllocateMemory() { - HIP_CHECK(hipFreeArray(arr)); - HIP_CHECK(hipFreeArray(arr1)); - free(hData); +TEST_CASE("Unit_hipMemcpy3D_Positive_Synchronization_Behavior") { + HIP_CHECK(hipDeviceSynchronize()); + + SECTION("Host to Device") { Memcpy3DHtoDSyncBehavior(Memcpy3DWrapper<>, true); } + + SECTION("Device to Pageable Host") { Memcpy3DDtoHPageableSyncBehavior(Memcpy3DWrapper<>, true); } + + SECTION("Device to Pinned Host") { Memcpy3DDtoHPinnedSyncBehavior(Memcpy3DWrapper<>, true); } + + SECTION("Device to Device") { +#if HT_NVIDIA + Memcpy3DDtoDSyncBehavior(Memcpy3DWrapper<>, false); +#else + Memcpy3DDtoDSyncBehavior(Memcpy3DWrapper<>, true); +#endif + } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-232 + SECTION("Host to Host") { Memcpy3DHtoHSyncBehavior(Memcpy3DWrapper<>, true); } +#endif } -/* - * This API verifies both H2D & D2H functionalities of hipMemcpy3D API - * by allocating memory in one GPU and calling the hipMemcpy3D API - * from another GPU. - * H2D case: - * Input : "hData" is initialized with the respective offset value - * Output: Destination array "arr" variable. - * - * D2H case: - * Input: "arr" array variable from the above output - * Output: "hOutputData" variable data is copied from "arr" variable - * - * Validating the result by comparing "hData" and "hOutputData" variables - */ -template -void Memcpy3D::D2H_H2D_DeviceMem_OnDiffDevice() { - HIP_CHECK(hipSetDevice(0)); - int peerAccess = 0; - HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 1, 0)); - if (peerAccess) { - AllocateMemory(); - // Memory is allocated on device 0 and Memcpy3DAsync triggered from device 1 - HIP_CHECK(hipSetDevice(1)); - - // H2D Scenario - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.dstArray = arr; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyHostToDevice; -#else - myparms.kind = hipMemcpyHostToDevice; -#endif - REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); - HIP_CHECK(hipDeviceSynchronize()); - - // Device to host - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - T *hOutputData = reinterpret_cast(malloc(size)); - memset(hOutputData, 0, size); - SetDefaultData(); - myparms.dstPtr = make_hipPitchedPtr(hOutputData, - width * sizeof(T), - width, height); - myparms.srcArray = arr; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToHost; -#else - myparms.kind = hipMemcpyDeviceToHost; -#endif - REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); - HIP_CHECK(hipDeviceSynchronize()); - - // Validating the result - HipTest::checkArray(hData, hOutputData, width, height, depth); - free(hOutputData); - DeAllocateMemory(); - } else { - SUCCEED("Skipped the test as there is no peer access\n"); - } -} -/* - * This API verifies both D2D functionalities of hipMemcpy3D API - * by allocating memory in one GPU and calling the hipMemcpy3D API - * from another GPU. - * - * D2D case: - * Input : "arr" variable is initialized with the "hData" variable in GPU-0 - * Output: "arr2" variable in GPU-0 - * - * hipMemcpy3D API is triggered from GPU-1 - * The "arr2" variable is then copied to "hOutputData" for validating - * the result - * - * Validating the result by comparing "hData" and "hOutputData" variables - */ -template -void Memcpy3D::D2D_DeviceMem_OnDiffDevice() { - HIP_CHECK(hipSetDevice(0)); - int peerAccess = 0; - HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); - if (peerAccess) { - AllocateMemory(); - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - - // Host to device copy - myparms.srcPtr = make_hipPitchedPtr(hData, - width * sizeof(T), - width, height); - myparms.dstArray = arr; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyHostToDevice; -#else - myparms.kind = hipMemcpyHostToDevice; -#endif - REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); - hipArray *arr2; - hipChannelFormatDesc channelDesc1 = hipCreateChannelDesc(sizeof(T)*8, - 0, 0, 0, formatKind); - HIP_CHECK(hipMalloc3DArray(&arr2, &channelDesc1, - make_hipExtent(width, height, - depth), hipArrayDefault)); - - // Allocating Mem on GPU device 0 and trigger hipMemcpy3D from GPU 1 - HIP_CHECK(hipSetDevice(1)); - - // D2D Scenario - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - myparms.srcArray = arr; - myparms.dstArray = arr2; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); - HIP_CHECK(hipDeviceSynchronize()); - - // For validating the D2D copy copying it again to hOutputData and - // verifying it with iniital data hData - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - T *hOutputData = reinterpret_cast(malloc(size)); - memset(hOutputData, 0, size); - SetDefaultData(); - - // Device to host - myparms.dstPtr = make_hipPitchedPtr(hOutputData, - width * sizeof(T), - width, height); - myparms.srcArray = arr2; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToHost; -#else - myparms.kind = hipMemcpyDeviceToHost; -#endif - REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); - HIP_CHECK(hipDeviceSynchronize()); - HipTest::checkArray(hData, hOutputData, width, height, depth); - - // DeAllocating Memory - free(hOutputData); - DeAllocateMemory(); - } else { - SUCCEED("Skipped the test as there is no peer access\n"); - } -} -/* - * This API verifies all the negative scenarios of hipMemcpy3D API - */ -template -void Memcpy3D::NegativeTests() { - HIP_CHECK(hipSetDevice(0)); - AllocateMemory(); - - // Initialization of data - memset(&myparms, 0, sizeof(myparms)); - myparms.srcPos = make_hipPos(0, 0, 0); - myparms.dstPos = make_hipPos(0, 0, 0); - myparms.extent = make_hipExtent(width , height, depth); -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyHostToDevice; -#else - myparms.kind = hipMemcpyHostToDevice; -#endif - - SECTION("Nullptr to destination array") { - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.dstArray = nullptr; - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Nullptr to source array") { - myparms.srcArray = nullptr; - myparms.dstPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing both Source ptr and array") { - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.srcArray = arr; - myparms.dstArray = arr1; - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing both destination ptr and array") { - myparms.dstPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.dstArray = arr; - myparms.srcArray = arr1; - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing Max value to extent") { - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.dstArray = arr; - myparms.extent = make_hipExtent(std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::max()); - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing Source pitchedPtr as nullptr") { - myparms.srcPtr = make_hipPitchedPtr(nullptr, width * sizeof(T), - width, height); - myparms.dstArray = arr; - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing Dst pitchedPtr as nullptr") { - myparms.dstPtr = make_hipPitchedPtr(nullptr, width * sizeof(T), - width, height); - myparms.srcArray = arr; - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing width > max width size in extent") { - myparms.extent = make_hipExtent(width+1 , height, depth); - myparms.dstArray = arr; - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing hgt > max width size in extent") { - myparms.extent = make_hipExtent(width , height+1, depth); - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.dstArray = arr; - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing depth > max width size in extent") { - myparms.extent = make_hipExtent(width , height, depth+1); - myparms.dstArray = arr; - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing dst width pos > max allocated width") { - myparms.dstPos = make_hipPos(width+1, 0, 0); - myparms.dstArray = arr; - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing dst height pos > max allocated hgt") { - myparms.dstPos = make_hipPos(0, height+1, 0); - myparms.dstArray = arr; - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing dst depth pos > max allocated depth") { - myparms.dstPos = make_hipPos(0, 0, depth+1); - myparms.dstArray = arr; - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing src width pos > max allocated width") { - myparms.srcPos = make_hipPos(width+1, 0, 0); - myparms.srcArray = arr; - myparms.dstArray = arr1; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing src height pos > max allocated hgt") { - myparms.srcPos = make_hipPos(0, height+1, 0); - myparms.srcArray = arr; - myparms.dstArray = arr1; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing src height pos > max allocated hgt") { - myparms.srcPos = make_hipPos(0, 0, depth+1); - myparms.srcArray = arr; - myparms.dstArray = arr1; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing src array size > dst array size") { - // Passing src array size greater than destination array size - hipArray *arr2; - hipChannelFormatDesc channelDesc1 = hipCreateChannelDesc(sizeof(T)*8, - 0, 0, 0, formatKind); - HIP_CHECK(hipMalloc3DArray(&arr2, &channelDesc1, - make_hipExtent(3, 3 - , 3), hipArrayDefault)); - myparms.srcArray = arr; - myparms.dstArray = arr2; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); - } - - // DeAllocation of memory - DeAllocateMemory(); +TEST_CASE("Unit_hipMemcpy3D_Positive_Parameters") { + constexpr bool async = false; + Memcpy3DZeroWidthHeightDepth(Memcpy3DWrapper); } -/* - * This API verifies the Extent validation Scenarios - */ -template -void Memcpy3D::Extent_Validation() { - HIP_CHECK(hipSetDevice(0)); - AllocateMemory(); - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - myparms.srcPos = make_hipPos(0, 0, 0); - myparms.dstPos = make_hipPos(0, 0, 0); - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.dstArray = arr; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyHostToDevice; -#else - myparms.kind = hipMemcpyHostToDevice; +TEST_CASE("Unit_hipMemcpy3D_Positive_Array") { + constexpr bool async = false; + SECTION("Array from/to Host") { Memcpy3DArrayHostShell(Memcpy3DWrapper); } +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-238 + SECTION("Array from/to Device") { Memcpy3DArrayDeviceShell(Memcpy3DWrapper); } #endif - SECTION("Passing Extent as 0") { - myparms.extent = make_hipExtent(0 , 0, 0); - REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); - } - SECTION("Passing Width 0 in Extent") { - myparms.extent = make_hipExtent(0 , height, depth); - REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); - } - SECTION("Passing Height 0 in Extent") { - myparms.extent = make_hipExtent(width , 0, depth); - REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); - } - SECTION("Passing Depth 0 in Extent") { - myparms.extent = make_hipExtent(width , height, 0); - REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); - } - SECTION("Passing Depth 0 in Extent") { - REQUIRE(hipMemcpy3D(nullptr) != hipSuccess); - } - DeAllocateMemory(); } -/* - * This API verifies H2H-D2D-D2H functionalities of hipMemcpy3D API - * - * Input : "arr" variable is initialized with the "hData" variable in GPU-0 - * Output: "arr1" variable in GPU-0 - * - * The "arr1" variable is then copied to "hOutputData" for validating - * the result - * - * Validating the result by comparing "hData" and "hOutputData" variables - */ +TEST_CASE("Unit_hipMemcpy3D_Negative_Parameters") { + constexpr hipExtent extent{128 * sizeof(int), 128, 8}; -template -void Memcpy3D::simple_Memcpy3D() { - HIP_CHECK(hipSetDevice(0)); - AllocateMemory(); - - // Host to Device - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.dstArray = arr; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyHostToDevice; -#else - myparms.kind = hipMemcpyHostToDevice; -#endif - REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); - - // Array to Array - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - myparms.srcArray = arr; - myparms.dstArray = arr1; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); - T *hOutputData = reinterpret_cast(malloc(size)); - memset(hOutputData, 0, size); - - // Device to host - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - myparms.dstPtr = make_hipPitchedPtr(hOutputData, - width * sizeof(T), width, height); - myparms.srcArray = arr1; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToHost; -#else - myparms.kind = hipMemcpyDeviceToHost; -#endif - REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); - - // Validating the result - HipTest::checkArray(hData, hOutputData, width, height, depth); - - // DeAllocating the Memory - free(hOutputData); - DeAllocateMemory(); -} -/* - This testcase performs hipMemcpy3D API validation for - different datatypes and different sizes -*/ -TEMPLATE_TEST_CASE("Unit_hipMemcpy3D_Basic", "[hipMemcpy3D]", - int, unsigned int, float) { - int device = -1; - HIP_CHECK(hipGetDevice(&device)); - hipDeviceProp_t prop; - HIP_CHECK(hipGetDeviceProperties(&prop,device)); - auto i = GENERATE_COPY(10, 100, 1024, prop.maxTexture3D[0]); - auto j = GENERATE(10, 100); - int numDevices = 0; - HIP_CHECK(hipGetDeviceCount(&numDevices)); - if (numDevices > 1) { - if (std::is_same::value) { - Memcpy3D memcpy3d_obj(i, j, j, hipChannelFormatKindFloat); - memcpy3d_obj.simple_Memcpy3D(); - } else if (std::is_same::value) { - Memcpy3D memcpy3d_obj(i, j, j, hipChannelFormatKindUnsigned); - memcpy3d_obj.simple_Memcpy3D(); - } else if (std::is_same::value) { - Memcpy3D memcpy3d_obj(i, j, j, hipChannelFormatKindSigned); - memcpy3d_obj.simple_Memcpy3D(); - } - } else { - SUCCEED("skipping the testcases as numDevices < 2"); - } -} - -/* -This testcase performs the extent validation scenarios of -hipMemcpy3D API -*/ -TEST_CASE("Unit_hipMemcpy3D_ExtentValidation") { - Memcpy3D memcpy3d(width, height, depth, - hipChannelFormatKindSigned); - memcpy3d.Extent_Validation(); -} - -/* -This testcase performs the negative scenarios of -hipMemcpy3D API -*/ -TEST_CASE("Unit_hipMemcpy3D_multiDevice-Negative") { - int numDevices = 0; - HIP_CHECK(hipGetDeviceCount(&numDevices)); - if (numDevices > 1) { - Memcpy3D memcpy3d(width, height, depth, - hipChannelFormatKindSigned); - memcpy3d.NegativeTests(); - } else { - SUCCEED("skipping the testcases as numDevices < 2"); - } -} - -/* -This testcase performs the D2H,H2D and D2D on peer -GPU device -*/ -TEST_CASE("Unit_hipMemcpy3D_multiDevice-OnPeerDevice") { - int numDevices = 0; - HIP_CHECK(hipGetDeviceCount(&numDevices)); - if (numDevices > 1) { - SECTION("D2H & H2D On DiffDevice") { - Memcpy3D memcpy3d_d2h_obj(width, height, depth, - hipChannelFormatKindFloat); - memcpy3d_d2h_obj.D2H_H2D_DeviceMem_OnDiffDevice(); + constexpr auto NegativeTests = [](hipPitchedPtr dst_ptr, hipPos dst_pos, hipPitchedPtr src_ptr, + hipPos src_pos, hipExtent extent, hipMemcpyKind kind) { + SECTION("dst_ptr.ptr == nullptr") { + hipPitchedPtr invalid_ptr = dst_ptr; + invalid_ptr.ptr = nullptr; + HIP_CHECK_ERROR(Memcpy3DWrapper(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); } - SECTION("D2D On DiffDevice") { - Memcpy3D memcpy3d_d2d_obj(width, height, depth, - hipChannelFormatKindFloat); - memcpy3d_d2d_obj.D2D_DeviceMem_OnDiffDevice(); + SECTION("src_ptr.ptr == nullptr") { + hipPitchedPtr invalid_ptr = src_ptr; + invalid_ptr.ptr = nullptr; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind), + hipErrorInvalidValue); } - } else { - SUCCEED("skipping the testcases as numDevices < 2"); + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-239 + SECTION("dst_ptr.pitch < width") { + hipPitchedPtr invalid_ptr = dst_ptr; + invalid_ptr.pitch = extent.width - 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidPitchValue); + } + + SECTION("src_ptr.pitch < width") { + hipPitchedPtr invalid_ptr = src_ptr; + invalid_ptr.pitch = extent.width - 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind), + hipErrorInvalidPitchValue); + } +#endif + + SECTION("dst_ptr.pitch > max pitch") { + int attr = 0; + HIP_CHECK(hipDeviceGetAttribute(&attr, hipDeviceAttributeMaxPitch, 0)); + hipPitchedPtr invalid_ptr = dst_ptr; + invalid_ptr.pitch = attr; + HIP_CHECK_ERROR(Memcpy3DWrapper(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("src_ptr.pitch > max pitch") { + int attr = 0; + HIP_CHECK(hipDeviceGetAttribute(&attr, hipDeviceAttributeMaxPitch, 0)); + hipPitchedPtr invalid_ptr = src_ptr; + invalid_ptr.pitch = attr; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-237 + SECTION("extent.width + dst_pos.x > dst_ptr.pitch") { + hipPos invalid_pos = dst_pos; + invalid_pos.x = dst_ptr.pitch - extent.width + 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("extent.width + src_pos.x > src_ptr.pitch") { + hipPos invalid_pos = src_pos; + invalid_pos.x = src_ptr.pitch - extent.width + 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("dst_pos.y out of bounds") { + hipPos invalid_pos = dst_pos; + invalid_pos.y = 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("src_pos.y out of bounds") { + hipPos invalid_pos = src_pos; + invalid_pos.y = 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("dst_pos.z out of bounds") { + hipPos invalid_pos = dst_pos; + invalid_pos.z = 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("src_pos.z out of bounds") { + hipPos invalid_pos = src_pos; + invalid_pos.z = 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind), + hipErrorInvalidValue); + } +#endif + +#if HT_NVIDIA // Disable on AMD due to defect - EXSWHTEC-234 + SECTION("Invalid MemcpyKind") { + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, src_ptr, src_pos, extent, + static_cast(-1)), + hipErrorInvalidMemcpyDirection); + } +#endif + }; + + SECTION("Host to Device") { + LinearAllocGuard3D device_alloc(extent); + LinearAllocGuard host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.pitch() * device_alloc.height() * device_alloc.depth()); + NegativeTests(device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + make_hipPitchedPtr(host_alloc.ptr(), device_alloc.pitch(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), extent, hipMemcpyHostToDevice); + } + + SECTION("Device to Host") { + LinearAllocGuard3D device_alloc(extent); + LinearAllocGuard host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.pitch() * device_alloc.height() * device_alloc.depth()); + NegativeTests(make_hipPitchedPtr(host_alloc.ptr(), device_alloc.pitch(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), extent, + hipMemcpyDeviceToHost); + } + + SECTION("Host to Host") { + LinearAllocGuard src_alloc(LinearAllocs::hipHostMalloc, + extent.width * extent.height * extent.depth); + LinearAllocGuard dst_alloc(LinearAllocs::hipHostMalloc, + extent.width * extent.height * extent.depth); + NegativeTests(make_hipPitchedPtr(dst_alloc.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), + make_hipPitchedPtr(src_alloc.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), extent, hipMemcpyHostToHost); + } + + SECTION("Device to Device") { + LinearAllocGuard3D src_alloc(extent); + LinearAllocGuard3D dst_alloc(extent); + NegativeTests(dst_alloc.pitched_ptr(), make_hipPos(0, 0, 0), src_alloc.pitched_ptr(), + make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice); } } diff --git a/projects/hip-tests/catch/unit/memory/hipMemcpy3DAsync.cc b/projects/hip-tests/catch/unit/memory/hipMemcpy3DAsync.cc index 451da3e4fc..99b74fe13f 100644 --- a/projects/hip-tests/catch/unit/memory/hipMemcpy3DAsync.cc +++ b/projects/hip-tests/catch/unit/memory/hipMemcpy3DAsync.cc @@ -1,13 +1,16 @@ /* -Copyright (c) 2021 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,739 +20,228 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * This testfile verifies the following Scenarios of hipMemcpy3DAsync API - - * 1. Verifying hipMemcpy3DAsync API for H2D,D2D and D2H scenarios - * 2. Verifying Negative Scenarios - * 3. Verifying Extent validation scenarios by passing 0 - * 4. Verifying hipMemcpy3DAsync API by allocating Memory in - * one GPU and trigger hipMemcpy3D from peer GPU - * 5. D2D where src and dst memory on GPU-0 and stream on GPU-1 -*/ +#include +#include #include -#include +#include +#include +#include -static constexpr auto width{10}; -static constexpr auto height{10}; -static constexpr auto depth{10}; +TEST_CASE("Unit_hipMemcpy3DAsync_Positive_Basic") { + constexpr bool async = true; -template -class Memcpy3DAsync { - int width, height, depth; - unsigned int size; - hipArray *arr, *arr1; - hipChannelFormatKind formatKind; - hipMemcpy3DParms myparms; - T* hData; - hipStream_t stream; - public: - Memcpy3DAsync(int l_width, int l_height, int l_depth, - hipChannelFormatKind l_format); - void simple_Memcpy3DAsync(); - void Extent_Validation(); - void NegativeTests(); - void AllocateMemory(); - void DeAllocateMemory(); - void SetDefaultData(); - void D2D_SameDeviceMem_StreamDiffDevice(); - void D2D_DeviceMem_OnDiffDevice(); - void D2H_H2D_DeviceMem_OnDiffDevice(); -}; + const auto stream_type = GENERATE(Streams::nullstream, Streams::perThread, Streams::created); + const StreamGuard stream_guard(stream_type); + const hipStream_t stream = stream_guard.stream(); -/* - * This API sets the default values of hipMemcpy3DParms structure - */ -template -void Memcpy3DAsync::SetDefaultData() { - myparms.srcPos = make_hipPos(0, 0, 0); - myparms.dstPos = make_hipPos(0, 0, 0); - myparms.extent = make_hipExtent(width , height, depth); -} + SECTION("Device to Host") { Memcpy3DDeviceToHostShell(Memcpy3DWrapper, stream); } -/* - * Constructor initalized width,depth and height - */ -template -Memcpy3DAsync::Memcpy3DAsync(int l_width, int l_height, int l_depth, - hipChannelFormatKind l_format) { - width = l_width; - height = l_height; - depth = l_depth; - formatKind = l_format; -} - -/* - * Allocating Memory and initalizing data for both - * device and host variables - */ -template -void Memcpy3DAsync::AllocateMemory() { - size = width * height * depth * sizeof(T); - hData = reinterpret_cast(malloc(size)); - memset(hData, 0, size); - for (int i = 0; i < depth; i++) { - for (int j = 0; j < height; j++) { - for (int k = 0; k < width; k++) { - hData[i*width*height + j*width +k] = i*width*height + j*width + k; - } + SECTION("Device to Device") { + SECTION("Peer access disabled") { + Memcpy3DDeviceToDeviceShell(Memcpy3DWrapper, stream); + } + SECTION("Peer access enabled") { + Memcpy3DDeviceToDeviceShell(Memcpy3DWrapper, stream); } } - hipChannelFormatDesc channelDesc = hipCreateChannelDesc(sizeof(T)*8, - 0, 0, 0, formatKind); - HIP_CHECK(hipMalloc3DArray(&arr, &channelDesc, make_hipExtent(width, height, - depth), hipArrayDefault)); - HIP_CHECK(hipMalloc3DArray(&arr1, &channelDesc, make_hipExtent(width, height, - depth), hipArrayDefault)); + + SECTION("Host to Device") { Memcpy3DHostToDeviceShell(Memcpy3DWrapper, stream); } + + SECTION("Host to Host") { Memcpy3DHostToHostShell(Memcpy3DWrapper, stream); } } -/* - * DeAllocates the Memory of device and host variables - */ -template -void Memcpy3DAsync::DeAllocateMemory() { - HIP_CHECK(hipFreeArray(arr)); - HIP_CHECK(hipFreeArray(arr1)); - free(hData); - HIP_CHECK(hipStreamDestroy(stream)); +TEST_CASE("Unit_hipMemcpy3DAsync_Positive_Synchronization_Behavior") { + constexpr bool async = true; + + HIP_CHECK(hipDeviceSynchronize()); + + SECTION("Host to Device") { Memcpy3DHtoDSyncBehavior(Memcpy3DWrapper, false); } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-233 + SECTION("Device to Pageable Host") { + Memcpy3DDtoHPageableSyncBehavior(Memcpy3DWrapper, true); + } +#endif + + SECTION("Device to Pinned Host") { + Memcpy3DDtoHPinnedSyncBehavior(Memcpy3DWrapper, false); + } + + SECTION("Device to Device") { Memcpy3DDtoDSyncBehavior(Memcpy3DWrapper, false); } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-233 + SECTION("Host to Host") { Memcpy3DHtoHSyncBehavior(Memcpy3DWrapper, true); } +#endif } -/* - * This API verifies both H2D & D2H functionalities of hipMemcpy3DAsync API - * by allocating memory in one GPU and calling the hipMemcpy3DAsync API - * from another GPU. - * H2D case: - * Input : "hData" is initialized with the respective offset value - * Output: Destination array "arr" variable. - * - * D2H case: - * Input: "arr" array variable from the above output - * Output: "hOutputData" variable data is copied from "arr" variable - * - * Validating the result by comparing "hData" and "hOutputData" variables - */ -template -void Memcpy3DAsync::D2H_H2D_DeviceMem_OnDiffDevice() { - HIP_CHECK(hipSetDevice(0)); - int peerAccess = 0; - HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 1, 0)); - if (peerAccess) { - AllocateMemory(); - - // Memory is allocated on device 0 and Memcpy3DAsyncAsync - // triggered from device 1 - HIP_CHECK(hipSetDevice(1)); - HIP_CHECK(hipStreamCreate(&stream)); - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - - // Host to Device - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.dstArray = arr; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyHostToDevice; -#else - myparms.kind = hipMemcpyHostToDevice; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - HIP_CHECK(hipStreamSynchronize(stream)); - - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - T *hOutputData = reinterpret_cast(malloc(size)); - memset(hOutputData, 0, size); - SetDefaultData(); - - // Device to host - myparms.dstPtr = make_hipPitchedPtr(hOutputData, - width * sizeof(T), - width, height); - myparms.srcArray = arr; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToHost; -#else - myparms.kind = hipMemcpyDeviceToHost; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - HIP_CHECK(hipStreamSynchronize(stream)); - - // Validating the result - HipTest::checkArray(hData, hOutputData, width, height, depth); - free(hOutputData); - - // DeAllocating the Memory - DeAllocateMemory(); - } else { - SUCCEED("Skipped the test as there is no peer access"); - } +TEST_CASE("Unit_hipMemcpy3DAsync_Positive_Parameters") { + constexpr bool async = true; + Memcpy3DZeroWidthHeightDepth(Memcpy3DWrapper); } -/* - * This API verifies both D2D functionalities of hipMemcpy3DAsync API - * by allocating memory in one GPU and calling the hipMemcpy3DAsync API - * from another GPU. - * - * D2D case: - * Input : "arr" variable is initialized with the "hData" variable in GPU-0 - * Output: "arr2" variable in GPU-0 - * - * hipMemcpy3DAsync API is triggered from GPU-1 - * The "arr2" variable is then copied to "hOutputData" for validating - * the result - * - * Validating the result by comparing "hData" and "hOutputData" variables - */ -template -void Memcpy3DAsync::D2D_DeviceMem_OnDiffDevice() { - HIP_CHECK(hipSetDevice(0)); - int peerAccess = 0; - HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); - if (peerAccess) { - // Allocating Memory and setting default data - AllocateMemory(); - hipStream_t stream1; - HIP_CHECK(hipStreamCreate(&stream1)); - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - - // Host to Device Scenario - myparms.srcPtr = make_hipPitchedPtr(hData, - width * sizeof(T), - width, height); - myparms.dstArray = arr; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyHostToDevice; -#else - myparms.kind = hipMemcpyHostToDevice; +TEST_CASE("Unit_hipMemcpy3DAsync_Positive_Array") { + constexpr bool async = true; + SECTION("Array from/to Host") { Memcpy3DArrayHostShell(Memcpy3DWrapper); } +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-238 + SECTION("Array from/to Device") { Memcpy3DArrayDeviceShell(Memcpy3DWrapper); } #endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream1) == hipSuccess); - HIP_CHECK(hipStreamSynchronize(stream1)); - - // Allocating Mem on GPU device 0 and trigger hipMemcpy3DAsync from GPU 1 - HIP_CHECK(hipSetDevice(1)); - HIP_CHECK(hipStreamCreate(&stream)); - hipArray *arr2; - hipChannelFormatDesc channelDesc1 = hipCreateChannelDesc(sizeof(T)*8, - 0, 0, 0, formatKind); - HIP_CHECK(hipMalloc3DArray(&arr2, &channelDesc1, - make_hipExtent(width, height, - depth), hipArrayDefault)); - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - - // Device to Device - myparms.srcArray = arr; - myparms.dstArray = arr2; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - HIP_CHECK(hipStreamSynchronize(stream)); - - // For validating the D2D copy copying it again to hOutputData and - // verifying it with iniital data hData - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - T *hOutputData = reinterpret_cast(malloc(size)); - memset(hOutputData, 0, size); - SetDefaultData(); - - // Device to host - myparms.dstPtr = make_hipPitchedPtr(hOutputData, - width * sizeof(T), - width, height); - myparms.srcArray = arr2; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToHost; -#else - myparms.kind = hipMemcpyDeviceToHost; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream)== hipSuccess); - HIP_CHECK(hipStreamSynchronize(stream)); - - // Validating the result - HipTest::checkArray(hData, hOutputData, width, height, depth); - - // Deleting the memory - free(hOutputData); - DeAllocateMemory(); - } else { - SUCCEED("Skipped the test as there is no peer access"); - } } -/* - * This API verifies all the negative scenarios of hipMemcpy3D API -*/ -template -void Memcpy3DAsync::NegativeTests() { - HIP_CHECK(hipSetDevice(0)); - AllocateMemory(); - HIP_CHECK(hipStreamCreate(&stream)); +TEST_CASE("Unit_hipMemcpy3DAsync_Negative_Parameters") { + constexpr bool async = true; + constexpr hipExtent extent{128 * sizeof(int), 128, 8}; - // Initialization of data - memset(&myparms, 0, sizeof(myparms)); - myparms.srcPos = make_hipPos(0, 0, 0); - myparms.dstPos = make_hipPos(0, 0, 0); - myparms.extent = make_hipExtent(width , height, depth); -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyHostToDevice; -#else - myparms.kind = hipMemcpyHostToDevice; -#endif - - SECTION("Nullptr to destination array") { - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.dstArray = nullptr; - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Nullptr to source array") { - myparms.srcArray = nullptr; - myparms.dstPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing both Source ptr and array") { - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.srcArray = arr; - myparms.dstArray = arr1; - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing both destination ptr and array") { - myparms.dstPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.dstArray = arr; - myparms.srcArray = arr1; - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing Max value to extent") { - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.dstArray = arr; - myparms.extent = make_hipExtent(std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::max()); - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing Source pitchedPtr as nullptr") { - myparms.srcPtr = make_hipPitchedPtr(nullptr, width * sizeof(T), - width, height); - myparms.dstArray = arr; - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing Dst pitchedPtr as nullptr") { - myparms.dstPtr = make_hipPitchedPtr(nullptr, width * sizeof(T), - width, height); - myparms.srcArray = arr; - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing width > max width size in extent") { - myparms.extent = make_hipExtent(width+1 , height, depth); - myparms.dstArray = arr; - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing hgt > max width size in extent") { - myparms.extent = make_hipExtent(width , height+1, depth); - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - myparms.dstArray = arr; - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing depth > max width size in extent") { - myparms.extent = make_hipExtent(width , height, depth+1); - myparms.dstArray = arr; - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing dst width pos > max allocated width") { - myparms.dstPos = make_hipPos(width+1, 0, 0); - myparms.dstArray = arr; - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing dst height pos > max allocated hgt") { - myparms.dstPos = make_hipPos(0, height+1, 0); - myparms.dstArray = arr; - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing dst depth pos > max allocated depth") { - myparms.dstPos = make_hipPos(0, 0, depth+1); - myparms.dstArray = arr; - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), - width, height); - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing src width pos > max allocated width") { - myparms.srcPos = make_hipPos(width+1, 0, 0); - myparms.srcArray = arr; - myparms.dstArray = arr1; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing src height pos > max allocated hgt") { - myparms.srcPos = make_hipPos(0, height+1, 0); - myparms.srcArray = arr; - myparms.dstArray = arr1; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing src height pos > max allocated hgt") { - myparms.srcPos = make_hipPos(0, 0, depth+1); - myparms.srcArray = arr; - myparms.dstArray = arr1; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing src array size > dst array size") { - hipArray *arr2; - hipChannelFormatDesc channelDesc1 = hipCreateChannelDesc(sizeof(T)*8, - 0, 0, 0, formatKind); - HIP_CHECK(hipMalloc3DArray(&arr2, &channelDesc1, - make_hipExtent(3, 3 - , 3), hipArrayDefault)); - myparms.srcArray = arr; - myparms.dstArray = arr2; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing nullptr to hipMemcpy3DAsync") { - REQUIRE(hipMemcpy3DAsync(nullptr, stream) != hipSuccess); - } - // DeAllocating of memory - DeAllocateMemory(); -} - -/* - * This API verifies both D2D functionalities of hipMemcpy3DAsync API - * by allocating memory in one GPU and calling the hipMemcpy3DAsync API - * from another GPU. - * - * D2D case: - * Input : "arr" variable is initialized with the "hData" variable in GPU-0 - * Output: "arr1" variable in GPU-0 - * - * Stream on GPU-1 - * The "arr2" variable is then copied to "hOutputData" for validating - * the result - * - * Validating the result by comparing "hData" and "hOutputData" variables - */ -template -void Memcpy3DAsync::D2D_SameDeviceMem_StreamDiffDevice() { - HIP_CHECK(hipSetDevice(0)); - // Allocating the Memory - int peerAccess = 0; - HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); - if (peerAccess) { - AllocateMemory(); - HIP_CHECK(hipSetDevice(1)); - HIP_CHECK(hipStreamCreate(&stream)); - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - - // Host to Device - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), width, height); - myparms.dstArray = arr; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyHostToDevice; -#else - myparms.kind = hipMemcpyHostToDevice; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - HIP_CHECK(hipStreamSynchronize(stream)); - - // Array to Array - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - myparms.srcArray = arr; - myparms.dstArray = arr1; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - HIP_CHECK(hipStreamSynchronize(stream)); - T *hOutputData = reinterpret_cast(malloc(size)); - memset(hOutputData, 0, size); - - // Device to host - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - myparms.dstPtr = make_hipPitchedPtr(hOutputData, - width * sizeof(T), width, height); - myparms.srcArray = arr1; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToHost; -#else - myparms.kind = hipMemcpyDeviceToHost; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - HIP_CHECK(hipStreamSynchronize(stream)); - - // Validating the result - HipTest::checkArray(hData, hOutputData, width, height, depth); - - // Deallocating the memory - free(hOutputData); - DeAllocateMemory(); - } else { - SUCCEED("Skipped the test as there is no peer access"); - } -} - -/* - * This API verifies the Extent validation Scenarios - */ -template -void Memcpy3DAsync::Extent_Validation() { - HIP_CHECK(hipSetDevice(0)); - AllocateMemory(); - HIP_CHECK(hipStreamCreate(&stream)); - // Passing extent as 0 - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - myparms.srcPos = make_hipPos(0, 0, 0); - myparms.dstPos = make_hipPos(0, 0, 0); - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), width, height); - myparms.dstArray = arr; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyHostToDevice; -#else - myparms.kind = hipMemcpyHostToDevice; -#endif - SECTION("Passing Extent as 0") { - myparms.extent = make_hipExtent(0 , 0, 0); - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - } - SECTION("Passing Width 0 in Extent") { - myparms.extent = make_hipExtent(0 , height, depth); - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - } - SECTION("Passing Height 0 in Extent") { - myparms.extent = make_hipExtent(width , 0, depth); - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - } - SECTION("Passing Depth 0 in Extent") { - myparms.extent = make_hipExtent(width , height, 0); - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - } - DeAllocateMemory(); -} - -/* - * This API verifies H2H-D2D-D2H functionalities of hipMemcpy3DAsync API - * - * Input : "arr" variable is initialized with the "hData" variable in GPU-0 - * Output: "arr1" variable in GPU-0 - * - * The "arr1" variable is then copied to "hOutputData" for validating - * the result - * - * Validating the result by comparing "hData" and "hOutputData" variables - */ -template -void Memcpy3DAsync::simple_Memcpy3DAsync() { - HIP_CHECK(hipSetDevice(0)); - - // Allocating the Memory - AllocateMemory(); - HIP_CHECK(hipStreamCreate(&stream)); - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - - // Host to Device - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), width, height); - myparms.dstArray = arr; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyHostToDevice; -#else - myparms.kind = hipMemcpyHostToDevice; -#endif - SECTION("Calling hipMemcpy3DAsync() using user declared stream obj") { - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - HIP_CHECK(hipStreamSynchronize(stream)); - } - SECTION("Calling hipMemcpy3DAsync() using hipStreamPerThread") { - REQUIRE(hipMemcpy3DAsync(&myparms, hipStreamPerThread) == hipSuccess); - HIP_CHECK(hipStreamSynchronize(hipStreamPerThread)); - } - - // Array to Array - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - myparms.srcArray = arr; - myparms.dstArray = arr1; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToDevice; -#else - myparms.kind = hipMemcpyDeviceToDevice; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - HIP_CHECK(hipStreamSynchronize(stream)); - T *hOutputData = reinterpret_cast(malloc(size)); - memset(hOutputData, 0, size); - - // Device to host - memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); - SetDefaultData(); - myparms.dstPtr = make_hipPitchedPtr(hOutputData, - width * sizeof(T), width, height); - myparms.srcArray = arr1; -#ifdef __HIP_PLATFORM_NVCC__ - myparms.kind = cudaMemcpyDeviceToHost; -#else - myparms.kind = hipMemcpyDeviceToHost; -#endif - REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); - HIP_CHECK(hipStreamSynchronize(stream)); - - // Validating the result - HipTest::checkArray(hData, hOutputData, width, height, depth); - - // DeAllocating the memory - free(hOutputData); - DeAllocateMemory(); -} -/* -This testcase verifies hipMemcpyAsync for different datatypes -and different sizes -*/ -TEMPLATE_TEST_CASE("Unit_hipMemcpy3DAsync_Basic", - "[hipMemcpy3DAsync]", - int, unsigned int, float) { - int numDevices = 0; - HIP_CHECK(hipGetDeviceCount(&numDevices)); - int device = -1; - HIP_CHECK(hipGetDevice(&device)); - hipDeviceProp_t prop; - HIP_CHECK(hipGetDeviceProperties(&prop,device)); - auto i = GENERATE_COPY(10, 100, 1024, prop.maxTexture3D[0]); - auto j = GENERATE(10, 100); - if (numDevices > 1) { - if (std::is_same::value) { - Memcpy3DAsync memcpy3d_obj(i, j, j, - hipChannelFormatKindSigned); - memcpy3d_obj.simple_Memcpy3DAsync(); - } else if (std::is_same::value) { - Memcpy3DAsync memcpy3d_obj(i, j, j, - hipChannelFormatKindUnsigned); - memcpy3d_obj.simple_Memcpy3DAsync(); - } else if (std::is_same::value) { - Memcpy3DAsync memcpy3d_obj(i, j, j, - hipChannelFormatKindFloat); - memcpy3d_obj.simple_Memcpy3DAsync(); - } - } else { - SUCCEED("skipping the testcases as numDevices < 2"); - } -} - -/* -This testcase performs the extent validation scenarios of -hipMemcpy3D API -*/ -TEST_CASE("Unit_hipMemcpy3DAsync_ExtentValidation") { - Memcpy3DAsync memcpy3d(width, height, depth, - hipChannelFormatKindSigned); - memcpy3d.Extent_Validation(); -} - -/* -This testcase performs the negative scenarios of -hipMemcpy3DAsync API -*/ -TEST_CASE("Unit_hipMemcpy3DAsync_multiDevice-Negative") { - int numDevices = 0; - HIP_CHECK(hipGetDeviceCount(&numDevices)); - if (numDevices > 1) { - Memcpy3DAsync memcpy3d(width, height, depth, - hipChannelFormatKindSigned); - memcpy3d.NegativeTests(); - } else { - SUCCEED("skipping the testcases as numDevices < 2"); - } -} - -/* -This testcase performs the D2H,H2D and D2D on peer -GPU device -*/ -TEST_CASE("Unit_hipMemcpy3DAsync_multiDevice-D2D") { - int numDevices = 0; - HIP_CHECK(hipGetDeviceCount(&numDevices)); - if (numDevices > 1) { - SECTION("D2D on different Device") { - Memcpy3DAsync memcpy3d_d2d_obj(width, height, depth, - hipChannelFormatKindFloat); - memcpy3d_d2d_obj.D2D_DeviceMem_OnDiffDevice(); + constexpr auto NegativeTests = [](hipPitchedPtr dst_ptr, hipPos dst_pos, hipPitchedPtr src_ptr, + hipPos src_pos, hipExtent extent, hipMemcpyKind kind) { + SECTION("dst_ptr.ptr == nullptr") { + hipPitchedPtr invalid_ptr = dst_ptr; + invalid_ptr.ptr = nullptr; + HIP_CHECK_ERROR(Memcpy3DWrapper(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); } - SECTION("D2H and H2D on different device") { - Memcpy3DAsync memcpy3d_d2h_obj(width, height, depth, - hipChannelFormatKindFloat); - memcpy3d_d2h_obj.D2H_H2D_DeviceMem_OnDiffDevice(); + SECTION("src_ptr.ptr == nullptr") { + hipPitchedPtr invalid_ptr = src_ptr; + invalid_ptr.ptr = nullptr; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind), + hipErrorInvalidValue); } - } else { - SUCCEED("skipping the testcases as numDevices < 2"); - } -} -/* -This testcase checks hipMemcpy3DAsync API by -allocating memory in one GPU and creating stream -in another GPU -*/ -TEST_CASE("Unit_hipMemcpy3DAsync_multiDevice-DiffStream") { - int numDevices = 0; - HIP_CHECK(hipGetDeviceCount(&numDevices)); - if (numDevices > 1) { - Memcpy3DAsync memcpy3dAsync(width, height, depth, - hipChannelFormatKindFloat); - memcpy3dAsync.D2D_SameDeviceMem_StreamDiffDevice(); - } else { - SUCCEED("skipping the testcases as numDevices < 2"); +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-239 + SECTION("dst_ptr.pitch < width") { + hipPitchedPtr invalid_ptr = dst_ptr; + invalid_ptr.pitch = extent.width - 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidPitchValue); + } + + SECTION("src_ptr.pitch < width") { + hipPitchedPtr invalid_ptr = src_ptr; + invalid_ptr.pitch = extent.width - 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind), + hipErrorInvalidPitchValue); + } +#endif + + SECTION("dst_ptr.pitch > max pitch") { + int attr = 0; + HIP_CHECK(hipDeviceGetAttribute(&attr, hipDeviceAttributeMaxPitch, 0)); + hipPitchedPtr invalid_ptr = dst_ptr; + invalid_ptr.pitch = attr; + HIP_CHECK_ERROR(Memcpy3DWrapper(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("src_ptr.pitch > max pitch") { + int attr = 0; + HIP_CHECK(hipDeviceGetAttribute(&attr, hipDeviceAttributeMaxPitch, 0)); + hipPitchedPtr invalid_ptr = src_ptr; + invalid_ptr.pitch = attr; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-237 + SECTION("extent.width + dst_pos.x > dst_ptr.pitch") { + hipPos invalid_pos = dst_pos; + invalid_pos.x = dst_ptr.pitch - extent.width + 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("extent.width + src_pos.x > src_ptr.pitch") { + hipPos invalid_pos = src_pos; + invalid_pos.x = src_ptr.pitch - extent.width + 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("dst_pos.y out of bounds") { + hipPos invalid_pos = dst_pos; + invalid_pos.y = 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("src_pos.y out of bounds") { + hipPos invalid_pos = src_pos; + invalid_pos.y = 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("dst_pos.z out of bounds") { + hipPos invalid_pos = dst_pos; + invalid_pos.z = 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("src_pos.z out of bounds") { + hipPos invalid_pos = src_pos; + invalid_pos.z = 1; + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind), + hipErrorInvalidValue); + } +#endif + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-234 + SECTION("Invalid MemcpyKind") { + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, src_ptr, src_pos, extent, + static_cast(-1)), + hipErrorInvalidMemcpyDirection); + } +#endif + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-235 + SECTION("Invalid stream") { + StreamGuard stream_guard(Streams::created); + HIP_CHECK(hipStreamDestroy(stream_guard.stream())); + HIP_CHECK_ERROR(Memcpy3DWrapper(dst_ptr, dst_pos, src_ptr, src_pos, extent, kind, + stream_guard.stream()), + hipErrorContextIsDestroyed); + } +#endif + }; + + SECTION("Host to Device") { + LinearAllocGuard3D device_alloc(extent); + LinearAllocGuard host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.pitch() * device_alloc.height() * device_alloc.depth()); + NegativeTests(device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + make_hipPitchedPtr(host_alloc.ptr(), device_alloc.pitch(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), extent, hipMemcpyHostToDevice); + } + + SECTION("Device to Host") { + LinearAllocGuard3D device_alloc(extent); + LinearAllocGuard host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.pitch() * device_alloc.height() * device_alloc.depth()); + NegativeTests(make_hipPitchedPtr(host_alloc.ptr(), device_alloc.pitch(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), extent, + hipMemcpyDeviceToHost); + } + + SECTION("Host to Host") { + LinearAllocGuard src_alloc(LinearAllocs::hipHostMalloc, + extent.width * extent.height * extent.depth); + LinearAllocGuard dst_alloc(LinearAllocs::hipHostMalloc, + extent.width * extent.height * extent.depth); + NegativeTests(make_hipPitchedPtr(dst_alloc.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), + make_hipPitchedPtr(src_alloc.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), extent, hipMemcpyHostToHost); + } + + SECTION("Device to Device") { + LinearAllocGuard3D src_alloc(extent); + LinearAllocGuard3D dst_alloc(extent); + NegativeTests(dst_alloc.pitched_ptr(), make_hipPos(0, 0, 0), src_alloc.pitched_ptr(), + make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice); } } diff --git a/projects/hip-tests/catch/unit/memory/hipMemcpy3DAsync_old.cc b/projects/hip-tests/catch/unit/memory/hipMemcpy3DAsync_old.cc new file mode 100644 index 0000000000..451da3e4fc --- /dev/null +++ b/projects/hip-tests/catch/unit/memory/hipMemcpy3DAsync_old.cc @@ -0,0 +1,755 @@ +/* +Copyright (c) 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 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 testfile verifies the following Scenarios of hipMemcpy3DAsync API + + * 1. Verifying hipMemcpy3DAsync API for H2D,D2D and D2H scenarios + * 2. Verifying Negative Scenarios + * 3. Verifying Extent validation scenarios by passing 0 + * 4. Verifying hipMemcpy3DAsync API by allocating Memory in + * one GPU and trigger hipMemcpy3D from peer GPU + * 5. D2D where src and dst memory on GPU-0 and stream on GPU-1 +*/ + +#include +#include + +static constexpr auto width{10}; +static constexpr auto height{10}; +static constexpr auto depth{10}; + +template +class Memcpy3DAsync { + int width, height, depth; + unsigned int size; + hipArray *arr, *arr1; + hipChannelFormatKind formatKind; + hipMemcpy3DParms myparms; + T* hData; + hipStream_t stream; + public: + Memcpy3DAsync(int l_width, int l_height, int l_depth, + hipChannelFormatKind l_format); + void simple_Memcpy3DAsync(); + void Extent_Validation(); + void NegativeTests(); + void AllocateMemory(); + void DeAllocateMemory(); + void SetDefaultData(); + void D2D_SameDeviceMem_StreamDiffDevice(); + void D2D_DeviceMem_OnDiffDevice(); + void D2H_H2D_DeviceMem_OnDiffDevice(); +}; + +/* + * This API sets the default values of hipMemcpy3DParms structure + */ +template +void Memcpy3DAsync::SetDefaultData() { + myparms.srcPos = make_hipPos(0, 0, 0); + myparms.dstPos = make_hipPos(0, 0, 0); + myparms.extent = make_hipExtent(width , height, depth); +} + +/* + * Constructor initalized width,depth and height + */ +template +Memcpy3DAsync::Memcpy3DAsync(int l_width, int l_height, int l_depth, + hipChannelFormatKind l_format) { + width = l_width; + height = l_height; + depth = l_depth; + formatKind = l_format; +} + +/* + * Allocating Memory and initalizing data for both + * device and host variables + */ +template +void Memcpy3DAsync::AllocateMemory() { + size = width * height * depth * sizeof(T); + hData = reinterpret_cast(malloc(size)); + memset(hData, 0, size); + for (int i = 0; i < depth; i++) { + for (int j = 0; j < height; j++) { + for (int k = 0; k < width; k++) { + hData[i*width*height + j*width +k] = i*width*height + j*width + k; + } + } + } + hipChannelFormatDesc channelDesc = hipCreateChannelDesc(sizeof(T)*8, + 0, 0, 0, formatKind); + HIP_CHECK(hipMalloc3DArray(&arr, &channelDesc, make_hipExtent(width, height, + depth), hipArrayDefault)); + HIP_CHECK(hipMalloc3DArray(&arr1, &channelDesc, make_hipExtent(width, height, + depth), hipArrayDefault)); +} + +/* + * DeAllocates the Memory of device and host variables + */ +template +void Memcpy3DAsync::DeAllocateMemory() { + HIP_CHECK(hipFreeArray(arr)); + HIP_CHECK(hipFreeArray(arr1)); + free(hData); + HIP_CHECK(hipStreamDestroy(stream)); +} + +/* + * This API verifies both H2D & D2H functionalities of hipMemcpy3DAsync API + * by allocating memory in one GPU and calling the hipMemcpy3DAsync API + * from another GPU. + * H2D case: + * Input : "hData" is initialized with the respective offset value + * Output: Destination array "arr" variable. + * + * D2H case: + * Input: "arr" array variable from the above output + * Output: "hOutputData" variable data is copied from "arr" variable + * + * Validating the result by comparing "hData" and "hOutputData" variables + */ +template +void Memcpy3DAsync::D2H_H2D_DeviceMem_OnDiffDevice() { + HIP_CHECK(hipSetDevice(0)); + int peerAccess = 0; + HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 1, 0)); + if (peerAccess) { + AllocateMemory(); + + // Memory is allocated on device 0 and Memcpy3DAsyncAsync + // triggered from device 1 + HIP_CHECK(hipSetDevice(1)); + HIP_CHECK(hipStreamCreate(&stream)); + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + + // Host to Device + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.dstArray = arr; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyHostToDevice; +#else + myparms.kind = hipMemcpyHostToDevice; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + HIP_CHECK(hipStreamSynchronize(stream)); + + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + T *hOutputData = reinterpret_cast(malloc(size)); + memset(hOutputData, 0, size); + SetDefaultData(); + + // Device to host + myparms.dstPtr = make_hipPitchedPtr(hOutputData, + width * sizeof(T), + width, height); + myparms.srcArray = arr; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToHost; +#else + myparms.kind = hipMemcpyDeviceToHost; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + HIP_CHECK(hipStreamSynchronize(stream)); + + // Validating the result + HipTest::checkArray(hData, hOutputData, width, height, depth); + free(hOutputData); + + // DeAllocating the Memory + DeAllocateMemory(); + } else { + SUCCEED("Skipped the test as there is no peer access"); + } +} + +/* + * This API verifies both D2D functionalities of hipMemcpy3DAsync API + * by allocating memory in one GPU and calling the hipMemcpy3DAsync API + * from another GPU. + * + * D2D case: + * Input : "arr" variable is initialized with the "hData" variable in GPU-0 + * Output: "arr2" variable in GPU-0 + * + * hipMemcpy3DAsync API is triggered from GPU-1 + * The "arr2" variable is then copied to "hOutputData" for validating + * the result + * + * Validating the result by comparing "hData" and "hOutputData" variables + */ +template +void Memcpy3DAsync::D2D_DeviceMem_OnDiffDevice() { + HIP_CHECK(hipSetDevice(0)); + int peerAccess = 0; + HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); + if (peerAccess) { + // Allocating Memory and setting default data + AllocateMemory(); + hipStream_t stream1; + HIP_CHECK(hipStreamCreate(&stream1)); + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + + // Host to Device Scenario + myparms.srcPtr = make_hipPitchedPtr(hData, + width * sizeof(T), + width, height); + myparms.dstArray = arr; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyHostToDevice; +#else + myparms.kind = hipMemcpyHostToDevice; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream1) == hipSuccess); + HIP_CHECK(hipStreamSynchronize(stream1)); + + // Allocating Mem on GPU device 0 and trigger hipMemcpy3DAsync from GPU 1 + HIP_CHECK(hipSetDevice(1)); + HIP_CHECK(hipStreamCreate(&stream)); + hipArray *arr2; + hipChannelFormatDesc channelDesc1 = hipCreateChannelDesc(sizeof(T)*8, + 0, 0, 0, formatKind); + HIP_CHECK(hipMalloc3DArray(&arr2, &channelDesc1, + make_hipExtent(width, height, + depth), hipArrayDefault)); + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + + // Device to Device + myparms.srcArray = arr; + myparms.dstArray = arr2; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + HIP_CHECK(hipStreamSynchronize(stream)); + + // For validating the D2D copy copying it again to hOutputData and + // verifying it with iniital data hData + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + T *hOutputData = reinterpret_cast(malloc(size)); + memset(hOutputData, 0, size); + SetDefaultData(); + + // Device to host + myparms.dstPtr = make_hipPitchedPtr(hOutputData, + width * sizeof(T), + width, height); + myparms.srcArray = arr2; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToHost; +#else + myparms.kind = hipMemcpyDeviceToHost; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream)== hipSuccess); + HIP_CHECK(hipStreamSynchronize(stream)); + + // Validating the result + HipTest::checkArray(hData, hOutputData, width, height, depth); + + // Deleting the memory + free(hOutputData); + DeAllocateMemory(); + } else { + SUCCEED("Skipped the test as there is no peer access"); + } +} + +/* + * This API verifies all the negative scenarios of hipMemcpy3D API +*/ +template +void Memcpy3DAsync::NegativeTests() { + HIP_CHECK(hipSetDevice(0)); + AllocateMemory(); + HIP_CHECK(hipStreamCreate(&stream)); + + // Initialization of data + memset(&myparms, 0, sizeof(myparms)); + myparms.srcPos = make_hipPos(0, 0, 0); + myparms.dstPos = make_hipPos(0, 0, 0); + myparms.extent = make_hipExtent(width , height, depth); +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyHostToDevice; +#else + myparms.kind = hipMemcpyHostToDevice; +#endif + + SECTION("Nullptr to destination array") { + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.dstArray = nullptr; + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Nullptr to source array") { + myparms.srcArray = nullptr; + myparms.dstPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing both Source ptr and array") { + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.srcArray = arr; + myparms.dstArray = arr1; + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing both destination ptr and array") { + myparms.dstPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.dstArray = arr; + myparms.srcArray = arr1; + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing Max value to extent") { + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.dstArray = arr; + myparms.extent = make_hipExtent(std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max()); + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing Source pitchedPtr as nullptr") { + myparms.srcPtr = make_hipPitchedPtr(nullptr, width * sizeof(T), + width, height); + myparms.dstArray = arr; + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing Dst pitchedPtr as nullptr") { + myparms.dstPtr = make_hipPitchedPtr(nullptr, width * sizeof(T), + width, height); + myparms.srcArray = arr; + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing width > max width size in extent") { + myparms.extent = make_hipExtent(width+1 , height, depth); + myparms.dstArray = arr; + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing hgt > max width size in extent") { + myparms.extent = make_hipExtent(width , height+1, depth); + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.dstArray = arr; + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing depth > max width size in extent") { + myparms.extent = make_hipExtent(width , height, depth+1); + myparms.dstArray = arr; + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing dst width pos > max allocated width") { + myparms.dstPos = make_hipPos(width+1, 0, 0); + myparms.dstArray = arr; + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing dst height pos > max allocated hgt") { + myparms.dstPos = make_hipPos(0, height+1, 0); + myparms.dstArray = arr; + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing dst depth pos > max allocated depth") { + myparms.dstPos = make_hipPos(0, 0, depth+1); + myparms.dstArray = arr; + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing src width pos > max allocated width") { + myparms.srcPos = make_hipPos(width+1, 0, 0); + myparms.srcArray = arr; + myparms.dstArray = arr1; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing src height pos > max allocated hgt") { + myparms.srcPos = make_hipPos(0, height+1, 0); + myparms.srcArray = arr; + myparms.dstArray = arr1; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing src height pos > max allocated hgt") { + myparms.srcPos = make_hipPos(0, 0, depth+1); + myparms.srcArray = arr; + myparms.dstArray = arr1; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing src array size > dst array size") { + hipArray *arr2; + hipChannelFormatDesc channelDesc1 = hipCreateChannelDesc(sizeof(T)*8, + 0, 0, 0, formatKind); + HIP_CHECK(hipMalloc3DArray(&arr2, &channelDesc1, + make_hipExtent(3, 3 + , 3), hipArrayDefault)); + myparms.srcArray = arr; + myparms.dstArray = arr2; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing nullptr to hipMemcpy3DAsync") { + REQUIRE(hipMemcpy3DAsync(nullptr, stream) != hipSuccess); + } + // DeAllocating of memory + DeAllocateMemory(); +} + +/* + * This API verifies both D2D functionalities of hipMemcpy3DAsync API + * by allocating memory in one GPU and calling the hipMemcpy3DAsync API + * from another GPU. + * + * D2D case: + * Input : "arr" variable is initialized with the "hData" variable in GPU-0 + * Output: "arr1" variable in GPU-0 + * + * Stream on GPU-1 + * The "arr2" variable is then copied to "hOutputData" for validating + * the result + * + * Validating the result by comparing "hData" and "hOutputData" variables + */ +template +void Memcpy3DAsync::D2D_SameDeviceMem_StreamDiffDevice() { + HIP_CHECK(hipSetDevice(0)); + // Allocating the Memory + int peerAccess = 0; + HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); + if (peerAccess) { + AllocateMemory(); + HIP_CHECK(hipSetDevice(1)); + HIP_CHECK(hipStreamCreate(&stream)); + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + + // Host to Device + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), width, height); + myparms.dstArray = arr; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyHostToDevice; +#else + myparms.kind = hipMemcpyHostToDevice; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + HIP_CHECK(hipStreamSynchronize(stream)); + + // Array to Array + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + myparms.srcArray = arr; + myparms.dstArray = arr1; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + HIP_CHECK(hipStreamSynchronize(stream)); + T *hOutputData = reinterpret_cast(malloc(size)); + memset(hOutputData, 0, size); + + // Device to host + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + myparms.dstPtr = make_hipPitchedPtr(hOutputData, + width * sizeof(T), width, height); + myparms.srcArray = arr1; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToHost; +#else + myparms.kind = hipMemcpyDeviceToHost; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + HIP_CHECK(hipStreamSynchronize(stream)); + + // Validating the result + HipTest::checkArray(hData, hOutputData, width, height, depth); + + // Deallocating the memory + free(hOutputData); + DeAllocateMemory(); + } else { + SUCCEED("Skipped the test as there is no peer access"); + } +} + +/* + * This API verifies the Extent validation Scenarios + */ +template +void Memcpy3DAsync::Extent_Validation() { + HIP_CHECK(hipSetDevice(0)); + AllocateMemory(); + HIP_CHECK(hipStreamCreate(&stream)); + // Passing extent as 0 + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + myparms.srcPos = make_hipPos(0, 0, 0); + myparms.dstPos = make_hipPos(0, 0, 0); + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), width, height); + myparms.dstArray = arr; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyHostToDevice; +#else + myparms.kind = hipMemcpyHostToDevice; +#endif + SECTION("Passing Extent as 0") { + myparms.extent = make_hipExtent(0 , 0, 0); + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + } + SECTION("Passing Width 0 in Extent") { + myparms.extent = make_hipExtent(0 , height, depth); + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + } + SECTION("Passing Height 0 in Extent") { + myparms.extent = make_hipExtent(width , 0, depth); + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + } + SECTION("Passing Depth 0 in Extent") { + myparms.extent = make_hipExtent(width , height, 0); + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + } + DeAllocateMemory(); +} + +/* + * This API verifies H2H-D2D-D2H functionalities of hipMemcpy3DAsync API + * + * Input : "arr" variable is initialized with the "hData" variable in GPU-0 + * Output: "arr1" variable in GPU-0 + * + * The "arr1" variable is then copied to "hOutputData" for validating + * the result + * + * Validating the result by comparing "hData" and "hOutputData" variables + */ +template +void Memcpy3DAsync::simple_Memcpy3DAsync() { + HIP_CHECK(hipSetDevice(0)); + + // Allocating the Memory + AllocateMemory(); + HIP_CHECK(hipStreamCreate(&stream)); + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + + // Host to Device + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), width, height); + myparms.dstArray = arr; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyHostToDevice; +#else + myparms.kind = hipMemcpyHostToDevice; +#endif + SECTION("Calling hipMemcpy3DAsync() using user declared stream obj") { + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + HIP_CHECK(hipStreamSynchronize(stream)); + } + SECTION("Calling hipMemcpy3DAsync() using hipStreamPerThread") { + REQUIRE(hipMemcpy3DAsync(&myparms, hipStreamPerThread) == hipSuccess); + HIP_CHECK(hipStreamSynchronize(hipStreamPerThread)); + } + + // Array to Array + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + myparms.srcArray = arr; + myparms.dstArray = arr1; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + HIP_CHECK(hipStreamSynchronize(stream)); + T *hOutputData = reinterpret_cast(malloc(size)); + memset(hOutputData, 0, size); + + // Device to host + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + myparms.dstPtr = make_hipPitchedPtr(hOutputData, + width * sizeof(T), width, height); + myparms.srcArray = arr1; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToHost; +#else + myparms.kind = hipMemcpyDeviceToHost; +#endif + REQUIRE(hipMemcpy3DAsync(&myparms, stream) == hipSuccess); + HIP_CHECK(hipStreamSynchronize(stream)); + + // Validating the result + HipTest::checkArray(hData, hOutputData, width, height, depth); + + // DeAllocating the memory + free(hOutputData); + DeAllocateMemory(); +} +/* +This testcase verifies hipMemcpyAsync for different datatypes +and different sizes +*/ +TEMPLATE_TEST_CASE("Unit_hipMemcpy3DAsync_Basic", + "[hipMemcpy3DAsync]", + int, unsigned int, float) { + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + int device = -1; + HIP_CHECK(hipGetDevice(&device)); + hipDeviceProp_t prop; + HIP_CHECK(hipGetDeviceProperties(&prop,device)); + auto i = GENERATE_COPY(10, 100, 1024, prop.maxTexture3D[0]); + auto j = GENERATE(10, 100); + if (numDevices > 1) { + if (std::is_same::value) { + Memcpy3DAsync memcpy3d_obj(i, j, j, + hipChannelFormatKindSigned); + memcpy3d_obj.simple_Memcpy3DAsync(); + } else if (std::is_same::value) { + Memcpy3DAsync memcpy3d_obj(i, j, j, + hipChannelFormatKindUnsigned); + memcpy3d_obj.simple_Memcpy3DAsync(); + } else if (std::is_same::value) { + Memcpy3DAsync memcpy3d_obj(i, j, j, + hipChannelFormatKindFloat); + memcpy3d_obj.simple_Memcpy3DAsync(); + } + } else { + SUCCEED("skipping the testcases as numDevices < 2"); + } +} + +/* +This testcase performs the extent validation scenarios of +hipMemcpy3D API +*/ +TEST_CASE("Unit_hipMemcpy3DAsync_ExtentValidation") { + Memcpy3DAsync memcpy3d(width, height, depth, + hipChannelFormatKindSigned); + memcpy3d.Extent_Validation(); +} + +/* +This testcase performs the negative scenarios of +hipMemcpy3DAsync API +*/ +TEST_CASE("Unit_hipMemcpy3DAsync_multiDevice-Negative") { + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + if (numDevices > 1) { + Memcpy3DAsync memcpy3d(width, height, depth, + hipChannelFormatKindSigned); + memcpy3d.NegativeTests(); + } else { + SUCCEED("skipping the testcases as numDevices < 2"); + } +} + +/* +This testcase performs the D2H,H2D and D2D on peer +GPU device +*/ +TEST_CASE("Unit_hipMemcpy3DAsync_multiDevice-D2D") { + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + if (numDevices > 1) { + SECTION("D2D on different Device") { + Memcpy3DAsync memcpy3d_d2d_obj(width, height, depth, + hipChannelFormatKindFloat); + memcpy3d_d2d_obj.D2D_DeviceMem_OnDiffDevice(); + } + + SECTION("D2H and H2D on different device") { + Memcpy3DAsync memcpy3d_d2h_obj(width, height, depth, + hipChannelFormatKindFloat); + memcpy3d_d2h_obj.D2H_H2D_DeviceMem_OnDiffDevice(); + } + } else { + SUCCEED("skipping the testcases as numDevices < 2"); + } +} + +/* +This testcase checks hipMemcpy3DAsync API by +allocating memory in one GPU and creating stream +in another GPU +*/ +TEST_CASE("Unit_hipMemcpy3DAsync_multiDevice-DiffStream") { + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + if (numDevices > 1) { + Memcpy3DAsync memcpy3dAsync(width, height, depth, + hipChannelFormatKindFloat); + memcpy3dAsync.D2D_SameDeviceMem_StreamDiffDevice(); + } else { + SUCCEED("skipping the testcases as numDevices < 2"); + } +} diff --git a/projects/hip-tests/catch/unit/memory/hipMemcpy3D_old.cc b/projects/hip-tests/catch/unit/memory/hipMemcpy3D_old.cc new file mode 100644 index 0000000000..4af0883639 --- /dev/null +++ b/projects/hip-tests/catch/unit/memory/hipMemcpy3D_old.cc @@ -0,0 +1,627 @@ +/* +Copyright (c) 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 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 testfile verifies the following scenarios of hipMemcpy3D API + * + * 1. Verifying hipMemcpy3D API for H2D,D2D and D2H scenarios for + different datatypes and sizes. + * 2. Verifying Negative Scenarios + * 3. Verifying Extent validation scenarios by passing 0 + * 4. Verifying hipMemcpy3D API by allocating Memory in + * one GPU and trigger hipMemcpy3D from peer GPU + * + */ + +#include +#include + +static constexpr auto width{10}; +static constexpr auto height{10}; +static constexpr auto depth{10}; + +template +class Memcpy3D { + int width, height, depth; + unsigned int size; + hipArray *arr, *arr1; + hipChannelFormatKind formatKind; + hipMemcpy3DParms myparms; + T* hData; + public: + Memcpy3D(int l_width, int l_height, int l_depth, + hipChannelFormatKind l_format); + void simple_Memcpy3D(); + void Extent_Validation(); + void NegativeTests(); + void AllocateMemory(); + void DeAllocateMemory(); + void SetDefaultData(); + void D2D_DeviceMem_OnDiffDevice(); + void D2H_H2D_DeviceMem_OnDiffDevice(); +}; + +/* + * This API sets the default values of hipMemcpy3DParms structure + */ +template +void Memcpy3D::SetDefaultData() { + myparms.srcPos = make_hipPos(0, 0, 0); + myparms.dstPos = make_hipPos(0, 0, 0); + myparms.extent = make_hipExtent(width , height, depth); +} + +/* + * Constructor initalized width,depth and height + */ +template +Memcpy3D::Memcpy3D(int l_width, int l_height, int l_depth, + hipChannelFormatKind l_format) { + width = l_width; + height = l_height; + depth = l_depth; + formatKind = l_format; +} + +/* + * Allocating Memory and initalizing data for both + * device and host variables + */ +template +void Memcpy3D::AllocateMemory() { + size = width * height * depth * sizeof(T); + hData = reinterpret_cast(malloc(size)); + memset(hData, 0, size); + for (int i = 0; i < depth; i++) { + for (int j = 0; j < height; j++) { + for (int k = 0; k < width; k++) { + hData[i*width*height + j*width +k] = i*width*height + j*width + k; + } + } + } + hipChannelFormatDesc channelDesc = hipCreateChannelDesc(sizeof(T)*8, + 0, 0, 0, formatKind); + HIP_CHECK(hipMalloc3DArray(&arr, &channelDesc, make_hipExtent(width, height, + depth), hipArrayDefault)); + HIP_CHECK(hipMalloc3DArray(&arr1, &channelDesc, make_hipExtent(width, height, + depth), hipArrayDefault)); +} + +/* + * DeAllocates the Memory of device and host variables + */ +template +void Memcpy3D::DeAllocateMemory() { + HIP_CHECK(hipFreeArray(arr)); + HIP_CHECK(hipFreeArray(arr1)); + free(hData); +} + +/* + * This API verifies both H2D & D2H functionalities of hipMemcpy3D API + * by allocating memory in one GPU and calling the hipMemcpy3D API + * from another GPU. + * H2D case: + * Input : "hData" is initialized with the respective offset value + * Output: Destination array "arr" variable. + * + * D2H case: + * Input: "arr" array variable from the above output + * Output: "hOutputData" variable data is copied from "arr" variable + * + * Validating the result by comparing "hData" and "hOutputData" variables + */ +template +void Memcpy3D::D2H_H2D_DeviceMem_OnDiffDevice() { + HIP_CHECK(hipSetDevice(0)); + int peerAccess = 0; + HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 1, 0)); + if (peerAccess) { + AllocateMemory(); + // Memory is allocated on device 0 and Memcpy3DAsync triggered from device 1 + HIP_CHECK(hipSetDevice(1)); + + // H2D Scenario + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.dstArray = arr; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyHostToDevice; +#else + myparms.kind = hipMemcpyHostToDevice; +#endif + REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); + HIP_CHECK(hipDeviceSynchronize()); + + // Device to host + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + T *hOutputData = reinterpret_cast(malloc(size)); + memset(hOutputData, 0, size); + SetDefaultData(); + myparms.dstPtr = make_hipPitchedPtr(hOutputData, + width * sizeof(T), + width, height); + myparms.srcArray = arr; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToHost; +#else + myparms.kind = hipMemcpyDeviceToHost; +#endif + REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); + HIP_CHECK(hipDeviceSynchronize()); + + // Validating the result + HipTest::checkArray(hData, hOutputData, width, height, depth); + free(hOutputData); + DeAllocateMemory(); + } else { + SUCCEED("Skipped the test as there is no peer access\n"); + } +} +/* + * This API verifies both D2D functionalities of hipMemcpy3D API + * by allocating memory in one GPU and calling the hipMemcpy3D API + * from another GPU. + * + * D2D case: + * Input : "arr" variable is initialized with the "hData" variable in GPU-0 + * Output: "arr2" variable in GPU-0 + * + * hipMemcpy3D API is triggered from GPU-1 + * The "arr2" variable is then copied to "hOutputData" for validating + * the result + * + * Validating the result by comparing "hData" and "hOutputData" variables + */ +template +void Memcpy3D::D2D_DeviceMem_OnDiffDevice() { + HIP_CHECK(hipSetDevice(0)); + int peerAccess = 0; + HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); + if (peerAccess) { + AllocateMemory(); + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + + // Host to device copy + myparms.srcPtr = make_hipPitchedPtr(hData, + width * sizeof(T), + width, height); + myparms.dstArray = arr; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyHostToDevice; +#else + myparms.kind = hipMemcpyHostToDevice; +#endif + REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); + hipArray *arr2; + hipChannelFormatDesc channelDesc1 = hipCreateChannelDesc(sizeof(T)*8, + 0, 0, 0, formatKind); + HIP_CHECK(hipMalloc3DArray(&arr2, &channelDesc1, + make_hipExtent(width, height, + depth), hipArrayDefault)); + + // Allocating Mem on GPU device 0 and trigger hipMemcpy3D from GPU 1 + HIP_CHECK(hipSetDevice(1)); + + // D2D Scenario + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + myparms.srcArray = arr; + myparms.dstArray = arr2; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); + HIP_CHECK(hipDeviceSynchronize()); + + // For validating the D2D copy copying it again to hOutputData and + // verifying it with iniital data hData + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + T *hOutputData = reinterpret_cast(malloc(size)); + memset(hOutputData, 0, size); + SetDefaultData(); + + // Device to host + myparms.dstPtr = make_hipPitchedPtr(hOutputData, + width * sizeof(T), + width, height); + myparms.srcArray = arr2; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToHost; +#else + myparms.kind = hipMemcpyDeviceToHost; +#endif + REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); + HIP_CHECK(hipDeviceSynchronize()); + HipTest::checkArray(hData, hOutputData, width, height, depth); + + // DeAllocating Memory + free(hOutputData); + DeAllocateMemory(); + } else { + SUCCEED("Skipped the test as there is no peer access\n"); + } +} +/* + * This API verifies all the negative scenarios of hipMemcpy3D API + */ +template +void Memcpy3D::NegativeTests() { + HIP_CHECK(hipSetDevice(0)); + AllocateMemory(); + + // Initialization of data + memset(&myparms, 0, sizeof(myparms)); + myparms.srcPos = make_hipPos(0, 0, 0); + myparms.dstPos = make_hipPos(0, 0, 0); + myparms.extent = make_hipExtent(width , height, depth); +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyHostToDevice; +#else + myparms.kind = hipMemcpyHostToDevice; +#endif + + SECTION("Nullptr to destination array") { + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.dstArray = nullptr; + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Nullptr to source array") { + myparms.srcArray = nullptr; + myparms.dstPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing both Source ptr and array") { + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.srcArray = arr; + myparms.dstArray = arr1; + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing both destination ptr and array") { + myparms.dstPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.dstArray = arr; + myparms.srcArray = arr1; + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing Max value to extent") { + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.dstArray = arr; + myparms.extent = make_hipExtent(std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max()); + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing Source pitchedPtr as nullptr") { + myparms.srcPtr = make_hipPitchedPtr(nullptr, width * sizeof(T), + width, height); + myparms.dstArray = arr; + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing Dst pitchedPtr as nullptr") { + myparms.dstPtr = make_hipPitchedPtr(nullptr, width * sizeof(T), + width, height); + myparms.srcArray = arr; + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing width > max width size in extent") { + myparms.extent = make_hipExtent(width+1 , height, depth); + myparms.dstArray = arr; + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing hgt > max width size in extent") { + myparms.extent = make_hipExtent(width , height+1, depth); + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.dstArray = arr; + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing depth > max width size in extent") { + myparms.extent = make_hipExtent(width , height, depth+1); + myparms.dstArray = arr; + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing dst width pos > max allocated width") { + myparms.dstPos = make_hipPos(width+1, 0, 0); + myparms.dstArray = arr; + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing dst height pos > max allocated hgt") { + myparms.dstPos = make_hipPos(0, height+1, 0); + myparms.dstArray = arr; + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing dst depth pos > max allocated depth") { + myparms.dstPos = make_hipPos(0, 0, depth+1); + myparms.dstArray = arr; + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing src width pos > max allocated width") { + myparms.srcPos = make_hipPos(width+1, 0, 0); + myparms.srcArray = arr; + myparms.dstArray = arr1; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing src height pos > max allocated hgt") { + myparms.srcPos = make_hipPos(0, height+1, 0); + myparms.srcArray = arr; + myparms.dstArray = arr1; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing src height pos > max allocated hgt") { + myparms.srcPos = make_hipPos(0, 0, depth+1); + myparms.srcArray = arr; + myparms.dstArray = arr1; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing src array size > dst array size") { + // Passing src array size greater than destination array size + hipArray *arr2; + hipChannelFormatDesc channelDesc1 = hipCreateChannelDesc(sizeof(T)*8, + 0, 0, 0, formatKind); + HIP_CHECK(hipMalloc3DArray(&arr2, &channelDesc1, + make_hipExtent(3, 3 + , 3), hipArrayDefault)); + myparms.srcArray = arr; + myparms.dstArray = arr2; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3D(&myparms) != hipSuccess); + } + + // DeAllocation of memory + DeAllocateMemory(); +} + +/* + * This API verifies the Extent validation Scenarios + */ +template +void Memcpy3D::Extent_Validation() { + HIP_CHECK(hipSetDevice(0)); + AllocateMemory(); + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + myparms.srcPos = make_hipPos(0, 0, 0); + myparms.dstPos = make_hipPos(0, 0, 0); + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.dstArray = arr; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyHostToDevice; +#else + myparms.kind = hipMemcpyHostToDevice; +#endif + SECTION("Passing Extent as 0") { + myparms.extent = make_hipExtent(0 , 0, 0); + REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); + } + SECTION("Passing Width 0 in Extent") { + myparms.extent = make_hipExtent(0 , height, depth); + REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); + } + SECTION("Passing Height 0 in Extent") { + myparms.extent = make_hipExtent(width , 0, depth); + REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); + } + SECTION("Passing Depth 0 in Extent") { + myparms.extent = make_hipExtent(width , height, 0); + REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); + } + SECTION("Passing Depth 0 in Extent") { + REQUIRE(hipMemcpy3D(nullptr) != hipSuccess); + } + DeAllocateMemory(); +} + +/* + * This API verifies H2H-D2D-D2H functionalities of hipMemcpy3D API + * + * Input : "arr" variable is initialized with the "hData" variable in GPU-0 + * Output: "arr1" variable in GPU-0 + * + * The "arr1" variable is then copied to "hOutputData" for validating + * the result + * + * Validating the result by comparing "hData" and "hOutputData" variables + */ + +template +void Memcpy3D::simple_Memcpy3D() { + HIP_CHECK(hipSetDevice(0)); + AllocateMemory(); + + // Host to Device + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), + width, height); + myparms.dstArray = arr; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyHostToDevice; +#else + myparms.kind = hipMemcpyHostToDevice; +#endif + REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); + + // Array to Array + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + myparms.srcArray = arr; + myparms.dstArray = arr1; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToDevice; +#else + myparms.kind = hipMemcpyDeviceToDevice; +#endif + REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); + T *hOutputData = reinterpret_cast(malloc(size)); + memset(hOutputData, 0, size); + + // Device to host + memset(&myparms, 0x0, sizeof(hipMemcpy3DParms)); + SetDefaultData(); + myparms.dstPtr = make_hipPitchedPtr(hOutputData, + width * sizeof(T), width, height); + myparms.srcArray = arr1; +#ifdef __HIP_PLATFORM_NVCC__ + myparms.kind = cudaMemcpyDeviceToHost; +#else + myparms.kind = hipMemcpyDeviceToHost; +#endif + REQUIRE(hipMemcpy3D(&myparms) == hipSuccess); + + // Validating the result + HipTest::checkArray(hData, hOutputData, width, height, depth); + + // DeAllocating the Memory + free(hOutputData); + DeAllocateMemory(); +} +/* + This testcase performs hipMemcpy3D API validation for + different datatypes and different sizes +*/ +TEMPLATE_TEST_CASE("Unit_hipMemcpy3D_Basic", "[hipMemcpy3D]", + int, unsigned int, float) { + int device = -1; + HIP_CHECK(hipGetDevice(&device)); + hipDeviceProp_t prop; + HIP_CHECK(hipGetDeviceProperties(&prop,device)); + auto i = GENERATE_COPY(10, 100, 1024, prop.maxTexture3D[0]); + auto j = GENERATE(10, 100); + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + if (numDevices > 1) { + if (std::is_same::value) { + Memcpy3D memcpy3d_obj(i, j, j, hipChannelFormatKindFloat); + memcpy3d_obj.simple_Memcpy3D(); + } else if (std::is_same::value) { + Memcpy3D memcpy3d_obj(i, j, j, hipChannelFormatKindUnsigned); + memcpy3d_obj.simple_Memcpy3D(); + } else if (std::is_same::value) { + Memcpy3D memcpy3d_obj(i, j, j, hipChannelFormatKindSigned); + memcpy3d_obj.simple_Memcpy3D(); + } + } else { + SUCCEED("skipping the testcases as numDevices < 2"); + } +} + +/* +This testcase performs the extent validation scenarios of +hipMemcpy3D API +*/ +TEST_CASE("Unit_hipMemcpy3D_ExtentValidation") { + Memcpy3D memcpy3d(width, height, depth, + hipChannelFormatKindSigned); + memcpy3d.Extent_Validation(); +} + +/* +This testcase performs the negative scenarios of +hipMemcpy3D API +*/ +TEST_CASE("Unit_hipMemcpy3D_multiDevice-Negative") { + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + if (numDevices > 1) { + Memcpy3D memcpy3d(width, height, depth, + hipChannelFormatKindSigned); + memcpy3d.NegativeTests(); + } else { + SUCCEED("skipping the testcases as numDevices < 2"); + } +} + +/* +This testcase performs the D2H,H2D and D2D on peer +GPU device +*/ +TEST_CASE("Unit_hipMemcpy3D_multiDevice-OnPeerDevice") { + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + if (numDevices > 1) { + SECTION("D2H & H2D On DiffDevice") { + Memcpy3D memcpy3d_d2h_obj(width, height, depth, + hipChannelFormatKindFloat); + memcpy3d_d2h_obj.D2H_H2D_DeviceMem_OnDiffDevice(); + } + + SECTION("D2D On DiffDevice") { + Memcpy3D memcpy3d_d2d_obj(width, height, depth, + hipChannelFormatKindFloat); + memcpy3d_d2d_obj.D2D_DeviceMem_OnDiffDevice(); + } + } else { + SUCCEED("skipping the testcases as numDevices < 2"); + } +} From 562a022bbafe0feeffcc57ce86d456dfd460a4bd Mon Sep 17 00:00:00 2001 From: agunashe <86270081+agunashe@users.noreply.github.com> Date: Wed, 28 Jun 2023 00:21:22 -0700 Subject: [PATCH 10/32] SWDEV-327563 - skip Unit_hipMemAdvise_NegtveTsts test on linux (#158) [ROCm/hip-tests commit: 93961c148aa32bc0ac3713260949c3de5d5db66b] --- .../catch/hipTestMain/config/config_amd_linux_common.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json index 23d61f3ca6..9640959961 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json @@ -33,6 +33,8 @@ "Unit_hipStreamGetCaptureInfo_Nullstream_CaptureInfo", "intermittent issue: corrupted double-linked list", "Unit_hipGraphRetainUserObject_Functional_2", + "intermittent issue: failure expected but sucess returned", + "Unit_hipMemAdvise_NegtveTsts", "Note: Following four tests disabled due to defect - EXSWHTEC-203", "Unit_hipGraphAddMemsetNode_Positive_Basic - uint16_t", "Unit_hipGraphAddMemsetNode_Positive_Basic - uint32_t", From 84f4cb0bc199e68fc8fab887537c92075f3d08f0 Mon Sep 17 00:00:00 2001 From: milos-mozetic <118800401+milos-mozetic@users.noreply.github.com> Date: Wed, 28 Jun 2023 12:16:40 +0200 Subject: [PATCH 11/32] EXSWHTEC-224 - Test cases ID clean up and documentation for Initialization&Version (#83) - Test cases ID clean up and documentation for Initialization and Version [ROCm/hip-tests commit: 1af95c5a2a469ba8844c318dfb3cd0bbd16c2e77] --- .../catch/include/hip_test_defgroups.hh | 7 ++ .../catch/multiproc/hipDeviceTotalMemMproc.cc | 23 +++++-- .../unit/device/hipDeviceComputeCapability.cc | 52 ++++++++++----- .../unit/device/hipDeviceGetByPCIBusId.cc | 65 ++++++++++++++++--- .../catch/unit/device/hipDeviceGetName.cc | 60 +++++++++++++---- .../unit/device/hipDeviceGetP2PAttribute.cc | 45 +++++++++++-- .../catch/unit/device/hipDeviceGetPCIBusId.cc | 59 +++++++++++++++-- .../catch/unit/device/hipDeviceGetUuid.cc | 52 +++++++++------ .../catch/unit/device/hipDeviceTotalMem.cc | 57 +++++++++++++--- .../catch/unit/device/hipDriverGetVersion.cc | 39 +++++++++-- .../hip-tests/catch/unit/device/hipInit.cc | 39 +++++++++-- .../catch/unit/device/hipRuntimeGetVersion.cc | 42 +++++++++--- .../catch/unit/device/hipSetGetDevice.cc | 29 +++++++++ 13 files changed, 466 insertions(+), 103 deletions(-) diff --git a/projects/hip-tests/catch/include/hip_test_defgroups.hh b/projects/hip-tests/catch/include/hip_test_defgroups.hh index d7ff394a8b..ce6158a72d 100644 --- a/projects/hip-tests/catch/include/hip_test_defgroups.hh +++ b/projects/hip-tests/catch/include/hip_test_defgroups.hh @@ -65,6 +65,13 @@ THE SOFTWARE. * @} */ +/** + * @defgroup DriverTest Initialization and Version + * @{ + * This section describes tests for the initialization and version functions of HIP runtime API. + * @} + */ + /** * @defgroup ShflTest warp shuffle function Management * @{ diff --git a/projects/hip-tests/catch/multiproc/hipDeviceTotalMemMproc.cc b/projects/hip-tests/catch/multiproc/hipDeviceTotalMemMproc.cc index 03217d0ee4..11ce921e1a 100644 --- a/projects/hip-tests/catch/multiproc/hipDeviceTotalMemMproc.cc +++ b/projects/hip-tests/catch/multiproc/hipDeviceTotalMemMproc.cc @@ -17,16 +17,17 @@ OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/** - * hipDeviceTotalMem tests - * Scenario: Validate behavior of hipDeviceTotalMem for masked devices. - */ - #include #ifdef __linux__ #include #include +/** + * @addtogroup hipDeviceTotalMem hipDeviceTotalMem + * @{ + * @ingroup DriverTest + */ + #define MAX_SIZE 30 #define VISIBLE_DEVICE 0 @@ -141,7 +142,17 @@ static bool getTotalMemoryOfMaskedDevices(int actualNumGPUs) { /** - * Scenario: Validate behavior of hipDeviceTotalMem for masked devices. + * Test Description + * ------------------------ + * - Check that total memory is returned correctly when + * the devices are masked. + * Test source + * ------------------------ + * - unit/multiproc/hipDeviceTotalMemMproc.cc + * Test requirements + * ------------------------ + * - Multi-device test + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceTotalMem_MaskedDevices") { int count = -1; diff --git a/projects/hip-tests/catch/unit/device/hipDeviceComputeCapability.cc b/projects/hip-tests/catch/unit/device/hipDeviceComputeCapability.cc index a44bfeae1b..12dfc245ab 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceComputeCapability.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceComputeCapability.cc @@ -16,25 +16,35 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipDeviceComputeCapability_ValidateVersion - Check if hipDeviceComputeCapability api returns valid Major and Minor versions -Unit_hipDeviceComputeCapability_Negative - Test unsuccessful execution of hipDeviceComputeCapability when nullptr - or invalid device is set as input parameter -*/ -/* - * Conformance test for checking functionality of - * hipError_t hipDeviceComputeCapability(int* major, int* minor, hipDevice_t device); - */ #include /** - * hipDeviceComputeCapability negative tests - * Scenario1: Validates if &major = nullptr returns error code - * Scenario2: Validates if &minor = nullptr returns error code - * Scenario3: Validates if device is -1 - * Scenario4: Validates if device is out of bounds + * @addtogroup hipDeviceComputeCapability hipDeviceComputeCapability + * @{ + * @ingroup DriverTest + * `hipDeviceComputeCapability(int* major, int* minor, hipDevice_t device)` - + * Returns the compute capability of the device. + */ + +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the major number is `nullptr` + * - Expected output: do not return `hipSuccess` + * -# When output pointer to the minor number is `nullptr` + * - Expected output: do not return `hipSuccess` + * -# When device ordinal is negative + * - Expected output: do not return `hipSuccess` + * -# When device ordinal is out of bounds + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/device/hipDeviceComputeCapability.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceComputeCapability_Negative") { int major, minor, numDevices; @@ -71,7 +81,17 @@ TEST_CASE("Unit_hipDeviceComputeCapability_Negative") { } } -// Scenario 5 : Check whether major and minor version value is valid. +/** + * Test Description + * ------------------------ + * - Checks that valid major and minor numbers are returned. + * Test source + * ------------------------ + * - unit/device/hipDeviceComputeCapability.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceComputeCapability_ValidateVersion") { int major, minor; hipDevice_t device; diff --git a/projects/hip-tests/catch/unit/device/hipDeviceGetByPCIBusId.cc b/projects/hip-tests/catch/unit/device/hipDeviceGetByPCIBusId.cc index 51e69272dd..aef690fda0 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceGetByPCIBusId.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceGetByPCIBusId.cc @@ -20,11 +20,27 @@ #include +/** + * @addtogroup hipDeviceGetByPCIBusId hipDeviceGetByPCIBusId + * @{ + * @ingroup DriverTest + * `hipDeviceGetByPCIBusId(int* device, const char* pciBusId)` - + * Returns a handle to a compute device. + */ + #define SIZE 13 - /** - * scenario: Validates device number from pciBusIdstr string + * Test Description + * ------------------------ + * - Check that PCI bus ID is the same as the one returned from attributes. + * - Perform for each device. + * Test source + * ------------------------ + * - unit/device/hipDeviceGetByPCIBusId.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceGetByPCIBusId_Functional") { char pciBusId[SIZE]{}; @@ -49,10 +65,20 @@ TEST_CASE("Unit_hipDeviceGetByPCIBusId_Functional") { } } - /** - * Validates negative scenarios for hipDeviceGetByPCIBusId - * scenario: device = nullptr and pciBusIdstr = nullptr + * Test Description + * ------------------------ + * - Validates handling of `nullptr` arguments: + * -# When the output pointer to the device is `nullptr` + * - Expected output: do not return `hipSuccess` + * -# When the PCI bus ID pointer is `nullptr` + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/device/hipDeviceGetByPCIBusId.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceGetByPCIBusId_NegativeNullChk") { int device = -1; @@ -66,9 +92,19 @@ TEST_CASE("Unit_hipDeviceGetByPCIBusId_NegativeNullChk") { } /** - * Validates negative scenarios for hipDeviceGetByPCIBusId - * scenario1: Pass an empty like "" - * scenario2: Pass an shorter string "0000:" + * Test Description + * ------------------------ + * - Validates handling of invalid PCI bus ID strings: + * -# When PCI bus ID is an empty string + * - Expected output: do not return `hipSuccess` + * -# When PCI bus ID is a short string + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/device/hipDeviceGetByPCIBusId.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceGetByPCIBusId_NegativeInputString") { int device = -1; @@ -81,8 +117,17 @@ TEST_CASE("Unit_hipDeviceGetByPCIBusId_NegativeInputString") { } /** - * Validates negative scenarios for hipDeviceGetByPCIBusId - * scenario: Pass wrong bus id in pciBusIdstr + * Test Description + * ------------------------ + * - Validates handling of invalid PCI bus ID values: + * -# Passes non-existing PCI bus ID + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/device/hipDeviceGetByPCIBusId.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceGetByPCIBusId_WrongBusID") { int deviceCount = 0; diff --git a/projects/hip-tests/catch/unit/device/hipDeviceGetName.cc b/projects/hip-tests/catch/unit/device/hipDeviceGetName.cc index ec4913d146..8a5fcde577 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceGetName.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceGetName.cc @@ -17,10 +17,6 @@ OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Conformance test for checking functionality of - * hipError_t hipDeviceGetName(char* name, int len, hipDevice_t device); - */ #include #include #include @@ -29,16 +25,34 @@ THE SOFTWARE. #include #include +/** + * @addtogroup hipDeviceGetName hipDeviceGetName + * @{ + * @ingroup DriverTest + * `hipDeviceGetName(char* name, int len, hipDevice_t device)` - + * Returns an identifer string for the device. + */ + constexpr size_t LEN = 256; /** - * hipDeviceGetName tests - * Scenario1: Validates the name string with hipDeviceProp_t.name[256] - * Scenario2: Validates returned error code for name = nullptr - * Scenario3: Validates returned error code for len = 0 - * Scenario4: Validates returned error code for len < 0 - * Scenario5: Validates returned error code for an invalid device - * Scenario6: Validates partially filling the name into a char array + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# Valid devices and output pointer to the name is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# Valid devices and output name buffer length is 0 + * - Expected output: return `hipErrorInvalidValue` + * -# Valid devices and output name buffer has length -1 + * - Expected output: return `hipErrorInvalidValue` + * -# Invalid devices, device ordinal is out of bounds + * - Expected output: return `hipErrorInvalidDevice` + * Test source + * ------------------------ + * - unit/device/hipDeviceGetName.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceGetName_NegTst") { std::array name; @@ -87,6 +101,18 @@ TEST_CASE("Unit_hipDeviceGetName_NegTst") { } } +/** + * Test Description + * ------------------------ + * - Get the device name for each device. + * - Compare the name with the name returned from device properties. + * Test source + * ------------------------ + * - unit/device/hipDeviceGetName.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetName_CheckPropName") { int numDevices = 0; std::array name; @@ -103,6 +129,18 @@ TEST_CASE("Unit_hipDeviceGetName_CheckPropName") { } } +/** + * Test Description + * ------------------------ + * - Set name buffer length to the half of the name length. + * - Check that device name is successfuly returned. + * Test source + * ------------------------ + * - unit/device/hipDeviceGetName.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetName_PartialFill") { #if HT_AMD HipTest::HIP_SKIP_TEST("EXSWCPHIPT-108"); diff --git a/projects/hip-tests/catch/unit/device/hipDeviceGetP2PAttribute.cc b/projects/hip-tests/catch/unit/device/hipDeviceGetP2PAttribute.cc index e126856d1d..dd1ac34c3d 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceGetP2PAttribute.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceGetP2PAttribute.cc @@ -25,9 +25,24 @@ THE SOFTWARE. #include /** - * @brief Test all possible combination of attributes and devices for hipDeviceGetP2PAttribute. - * Verify that the output is within the range of acceptable values. - * + * @addtogroup hipDeviceGetP2PAttribute hipDeviceGetP2PAttribute + * @{ + * @ingroup DriverTest + * `hipDeviceGetP2PAttribute(int* value, hipDeviceP2PAttr attr, + * int srcDevice, int dstDevice)` - + * Returns a value for attr of link between two devices. + */ + +/** + * Test Description + * ------------------------ + * - Get all possible combinations of attributes between all pairs of devices. + * Test source + * ------------------------ + * - unit/device/hipDeviceGetP2PAttribute.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceGetP2PAttribute_Basic") { #if HT_AMD @@ -65,8 +80,28 @@ TEST_CASE("Unit_hipDeviceGetP2PAttribute_Basic") { } /** - * @brief Negative test scenarios for hipDeviceGetP2PAttribute - * + * Test Description + * ------------------------ + * - Verifies handling of invalid arguments: + * -# When output pointer to the value is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When attribute is invalid, out of bounds + * - Expected output: return `hipErrorInvalidValue` + * -# When device ordinal is negative (-1) + * - Expected output: return `hipErrorInvalidDevice` + * -# When device ordinal is out of bounds + * - Expected output: return `hipErrorInvalidDevice` + * -# When the src and dst devices are the same one + * - Expected output: return `hipErrorInvalidDevice` + * -# When some devices are hidden using environment variables + * - Expected output: different scenarios produce different return value + * Test source + * ------------------------ + * - unit/device/hipDeviceGetP2PAttribute.cc + * Test requirements + * ------------------------ + * - Platform specific (NVIDIA) + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceGetP2PAttribute_Negative") { #if HT_AMD diff --git a/projects/hip-tests/catch/unit/device/hipDeviceGetPCIBusId.cc b/projects/hip-tests/catch/unit/device/hipDeviceGetPCIBusId.cc index 4f82a59b0e..2ae3774395 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceGetPCIBusId.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceGetPCIBusId.cc @@ -25,6 +25,14 @@ #include +/** + * @addtogroup hipDeviceGetPCIBusId hipDeviceGetPCIBusId + * @{ + * @ingroup DriverTest + * `hipDeviceGetPCIBusId(char* pciBusId, int len, int device)` - + * Returns a PCI Bus Id string for the device, overloaded to take int device ID. + */ + #define MAX_DEVICE_LENGTH 20 namespace hipDeviceGetPCIBusIdTests { @@ -37,6 +45,18 @@ void getPciBusId(int deviceCount, } } // namespace hipDeviceGetPCIBusIdTests +/** + * Test Description + * ------------------------ + * - Check that PCI bus ID is the same as the one returned from attributes. + * - Perform for each device. + * Test source + * ------------------------ + * - unit/device/hipDeviceGetByPCIBusId.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetPCIBusId_Check_PciBusID_WithAttr") { int deviceCount = 0; HIP_CHECK(hipGetDeviceCount(&deviceCount)); @@ -71,6 +91,19 @@ TEST_CASE("Unit_hipDeviceGetPCIBusId_Check_PciBusID_WithAttr") { " hipDeviceGetAttribute matched for all gpus\n"); } +/** + * Test Description + * ------------------------ + * - Checks that an error is returned when the output buffer has length + * that is smaller than the full PCI bus ID. + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/device/hipDeviceGetPCIBusId.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGetPCIBusId_Negative_PartialFill") { std::array busID; @@ -95,14 +128,26 @@ TEST_CASE("Unit_hipDeviceGetPCIBusId_Negative_PartialFill") { REQUIRE(std::all_of(strEnd+1, end, [](char& c) { return c == fillValue; })); } - /** - * Validates negative scenarios for hipDeviceGetPCIBusId - * scenario1: pciBusId = nullptr - * scenario2: device = -1 (Invalid Device) - * scenario3: device = Non Existing Device - * scenario4: len = 0 - * scenario5: len < 0 + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the PCI bus ID is `nullptr` + * - Expected output: do not return `hipSuccess` + * -# When the length of the output buffer is 0 + * - Expected output: do not return `hipSuccess` + * -# When the length of the output buffer is less than 0 + * - Expected output: do not return `hipSuccess` + * -# When the device ordinal is negative (-1) + * - Expected output: do not return `hipSuccess` + * -# When the device ordinal is out of bounds + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/device/hipDeviceGetPCIBusId.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceGetPCIBusId_NegTst") { char pciBusId[MAX_DEVICE_LENGTH]; diff --git a/projects/hip-tests/catch/unit/device/hipDeviceGetUuid.cc b/projects/hip-tests/catch/unit/device/hipDeviceGetUuid.cc index d7557527ea..d495e9fe94 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceGetUuid.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceGetUuid.cc @@ -16,23 +16,29 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipDeviceGetUuid_Positive - Check if hipDeviceGetUuid api returns valid UUID -Unit_hipDeviceGetUuid_Negative - Test unsuccessful execution of hipDeviceGetUuid when nullptr - or invalid device is set as input parameter -*/ -/* - * Conformance test for checking functionality of - * hipError_t hipDeviceGetUuid(hipUUID* uuid, hipDevice_t device); - */ + #include #include #include /** - * hipDeviceGetUuid positive test - * Scenario1: Validates the returned UUID + * @addtogroup hipDeviceGetUuid hipDeviceGetUuid + * @{ + * @ingroup DriverTest + * `hipDeviceGetUuid(hipUUID* uuid, hipDevice_t device)` - + * Returns an UUID for the device.[BETA] + */ + +/** + * Test Description + * ------------------------ + * - Check that non-empty UUID is returned for each available device. + * Test source + * ------------------------ + * - unit/device/hipDeviceGetUuid.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceGetUuid_Positive") { hipDevice_t device; @@ -57,10 +63,21 @@ TEST_CASE("Unit_hipDeviceGetUuid_Positive") { } /** - * hipDeviceGetUuid negative tests - * Scenario2: Validates returned error code for UUID = nullptr - * Scenario3: Validates returned error code if device is -1 - * Scenario4: Validates returned error code if device is out of bounds + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the UUID is `nullptr` + * - Expected output: do not return `hipSuccess` + * -# When device ordinal is negative + * - Expected output: do not return `hipSuccess` + * -# When device ordinal is out of bounds + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/device/hipDeviceGetUuid.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceGetUuid_Negative") { int numDevices = 0; @@ -70,11 +87,8 @@ TEST_CASE("Unit_hipDeviceGetUuid_Negative") { if (numDevices > 0) { HIP_CHECK(hipDeviceGet(&device, 0)); - // Scenario 2 REQUIRE_FALSE(hipSuccess == hipDeviceGetUuid(nullptr, device)); - // Scenario 3 REQUIRE_FALSE(hipSuccess == hipDeviceGetUuid(&uuid, -1)); - // Scenario 4 REQUIRE_FALSE(hipSuccess == hipDeviceGetUuid(&uuid, numDevices)); } } diff --git a/projects/hip-tests/catch/unit/device/hipDeviceTotalMem.cc b/projects/hip-tests/catch/unit/device/hipDeviceTotalMem.cc index 0a236d2feb..7c21019424 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceTotalMem.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceTotalMem.cc @@ -17,19 +17,32 @@ OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Conformance test for checking functionality of - * hipError_t hipDeviceTotalMem(size_t* bytes, hipDevice_t device); - */ #include +/** + * @addtogroup hipDeviceTotalMem hipDeviceTotalMem + * @{ + * @ingroup DriverTest + * `hipDeviceTotalMem(size_t* bytes, hipDevice_t device)` - + * Returns the total amount of memory on the device. + */ /** - * hipDeviceTotalMem tests - * Scenario1: Validates if bytes = nullptr returns hip error code. - * Scenario2: Validates if error code is returned for device = -1. - * Scenario3: Validates if error code is returned for device = deviceCount. - * Scenario4: Compare total memory size with hipDeviceProp_t.totalGlobalMem for each device. + * Test Description + * ------------------------ + * - Validate handling of invalid arguments: + * -# When output pointer to the total memory is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When device ordinal is negative (-1) + * - Expected output: return `hipErrorInvalidDevice` + * -# When device ordinal is out of bounds + * - Expected output: return `hipErrorInvalidDevice` + * Test source + * ------------------------ + * - unit/device/hipDeviceTotalMem.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 */ TEST_CASE("Unit_hipDeviceTotalMem_NegTst") { #if HT_NVIDIA @@ -54,7 +67,18 @@ TEST_CASE("Unit_hipDeviceTotalMem_NegTst") { } } -// Scenario 4 +/** + * Test Description + * ------------------------ + * - Check that the returned number of bytes is the same as the + * one from device attributes. + * Test source + * ------------------------ + * - unit/device/hipDeviceTotalMem.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceTotalMem_ValidateTotalMem") { size_t totMem; int numDevices = 0; @@ -77,6 +101,19 @@ TEST_CASE("Unit_hipDeviceTotalMem_ValidateTotalMem") { REQUIRE(total == totMem); } +/** + * Test Description + * ------------------------ + * - Check that total memory is returned when other device is + * set than the one in the API call. + * Test source + * ------------------------ + * - unit/device/hipDeviceTotalMem.cc + * Test requirements + * ------------------------ + * - Multi-device test + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceTotalMem_NonSelectedDevice") { auto deviceCount = HipTest::getDeviceCount(); if (deviceCount < 2) { diff --git a/projects/hip-tests/catch/unit/device/hipDriverGetVersion.cc b/projects/hip-tests/catch/unit/device/hipDriverGetVersion.cc index 66f6d8e7e4..d3eb25e568 100644 --- a/projects/hip-tests/catch/unit/device/hipDriverGetVersion.cc +++ b/projects/hip-tests/catch/unit/device/hipDriverGetVersion.cc @@ -18,13 +18,29 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipDriverGetVersion_Positive - Test simple reading of HIP driver version with hipDriverGetVersion api -Unit_hipDriverGetVersion_Negative - Test unsuccessful execution of hipDriverGetVersion when nullptr is set as input parameter -*/ + #include +/** + * @addtogroup hipDriverGetVersion hipDriverGetVersion + * @{ + * @ingroup DriverTest + * `hipDriverGetVersion(int* driverVersion)` - + * Returns the approximate HIP driver version. + */ + +/** + * Test Description + * ------------------------ + * - Check that the returned driver version has valid value. + * - Both CUDA and HIP driver version can be returned, depending on the device. + * Test source + * ------------------------ + * - unit/device/hipDriverGetVersion.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDriverGetVersion_Positive") { int driverVersion = -1; @@ -33,6 +49,19 @@ TEST_CASE("Unit_hipDriverGetVersion_Positive") { INFO("Driver version " << driverVersion); } +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the driver version is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/device/hipDriverGetVersion.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDriverGetVersion_Negative") { // If initialization is attempted with nullptr, error shall be reported HIP_CHECK_ERROR(hipDriverGetVersion(nullptr), hipErrorInvalidValue); diff --git a/projects/hip-tests/catch/unit/device/hipInit.cc b/projects/hip-tests/catch/unit/device/hipInit.cc index f206af5756..9f5280c297 100644 --- a/projects/hip-tests/catch/unit/device/hipInit.cc +++ b/projects/hip-tests/catch/unit/device/hipInit.cc @@ -18,13 +18,29 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipInit_Positive - Test explicit HIP initalization with hipInit api -Unit_hipInit_Negative_InvalidFlag - Test unsuccessful HIP initalization with hipInit api when flag is invalid -*/ + #include +/** + * @addtogroup hipInit hipInit + * @{ + * @ingroup DriverTest + * `hipInit(unsigned int flags)` - + * Explicitly initializes the HIP runtime. + */ + +/** + * Test Description + * ------------------------ + * - Initialize HIP runtime. + * - Call a HIP API and check that the runtime is initialized successfully. + * Test source + * ------------------------ + * - unit/device/hipInit.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipInit_Positive") { HIP_CHECK(hipInit(0)); @@ -34,6 +50,19 @@ TEST_CASE("Unit_hipInit_Positive") { REQUIRE(count >= 0); } +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When flag has invalid value equal to -1 + * - Expected output: return `hipErrorInvalidValue` + * Test source + * ------------------------ + * - unit/device/hipInit.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipInit_Negative") { // If initialization is attempted with invalid flag, error shall be reported unsigned int invalid_flag = 1; diff --git a/projects/hip-tests/catch/unit/device/hipRuntimeGetVersion.cc b/projects/hip-tests/catch/unit/device/hipRuntimeGetVersion.cc index 6e0def63b7..6bca5c1a20 100644 --- a/projects/hip-tests/catch/unit/device/hipRuntimeGetVersion.cc +++ b/projects/hip-tests/catch/unit/device/hipRuntimeGetVersion.cc @@ -16,21 +16,32 @@ 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. */ -/* -Testcase Scenarios : -Unit_hipRuntimeGetVersion_Positive - Test simple reading of HIP runtime version with hipRuntimeGetVersion api -Unit_hipRuntimeGetVersion_Negative - Test unsuccessful execution of hipRuntimeGetVersion when nullptr is set as input parameter -*/ -/* - * Conformance test for checking functionality of - * hipError_t hipRuntimeGetVersion(int* runtimeVersion); +#include + +/** + * @addtogroup hipRuntimeGetVersion hipRuntimeGetVersion + * @{ + * @ingroup DriverTest + * `hipRuntimeGetVersion(int* runtimeVersion)` - + * Returns the approximate HIP runtime version. * On HIP/HCC path this function returns HIP runtime patch version * (a 5 digit code) however on * HIP/NVCC path this function return CUDA runtime version. */ -#include +/** + * Test Description + * ------------------------ + * - Checks that valid runtime version is returned. + * - Print out the runtime version. + * Test source + * ------------------------ + * - unit/device/hipRuntimeGetVersion.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipRuntimeGetVersion_Positive") { int runtimeVersion = -1; HIP_CHECK(hipRuntimeGetVersion(&runtimeVersion)); @@ -38,6 +49,19 @@ TEST_CASE("Unit_hipRuntimeGetVersion_Positive") { INFO("Runtime version " << runtimeVersion); } +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the runtime version is nullptr + * - Expected output: do not return `hipSuccess` + * Test source + * ------------------------ + * - unit/device/hipRuntimeGetVersion.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipRuntimeGetVersion_Negative") { // If initialization is attempted with nullptr, error shall be reported CHECK_FALSE(hipRuntimeGetVersion(nullptr) == hipSuccess); diff --git a/projects/hip-tests/catch/unit/device/hipSetGetDevice.cc b/projects/hip-tests/catch/unit/device/hipSetGetDevice.cc index 6b2f53f6b7..561bf6d6a7 100644 --- a/projects/hip-tests/catch/unit/device/hipSetGetDevice.cc +++ b/projects/hip-tests/catch/unit/device/hipSetGetDevice.cc @@ -214,6 +214,35 @@ TEST_CASE("Unit_hipSetGetDevice_Negative") { * @} */ +/** + * @addtogroup hipDeviceGet hipDeviceGet + * @{ + * @ingroup DriverTest + * `hipDeviceGet(hipDevice_t* device, int ordinal)` - + * Returns a handle to a compute device. + * ________________________ + * Test cases from other modules: + * - @ref Unit_hipSetDevice_BasicSetGet + * - @ref Unit_hipGetSetDevice_MultiThreaded + */ + +/** + * Test Description + * ------------------------ + * - Validates handling of invalid arguments: + * -# When output pointer to the device is `nullptr` + * - Expected output: return `hipErrorInvalidValue` + * -# When device ordinal is out of bounds + * - Expected output: return `hipErrorInvalidDevice` + * -# When device ordinal is negative + * - Expected output: return `hipErrorInvalidDevice` + * Test source + * ------------------------ + * - unit/device/hipSetGetDevice.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.2 + */ TEST_CASE("Unit_hipDeviceGet_Negative") { // TODO enable after EXSWCPHIPT-104 is fixed #if HT_NVIDIA From c8f4f91a73086f1ff43db12a7228f224e9001421 Mon Sep 17 00:00:00 2001 From: agunashe <86270081+agunashe@users.noreply.github.com> Date: Wed, 28 Jun 2023 03:16:59 -0700 Subject: [PATCH 12/32] SWDEV-327563 - skip Unit_hipDeviceGetUuid_Positive on Windows (#200) [ROCm/hip-tests commit: c2d51bad21a4eda35ba4f3219f6b31db2cde48e4] --- .../catch/hipTestMain/config/config_amd_windows_common.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_windows_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_windows_common.json index c88dfdfe7c..311d6ee70a 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_windows_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_windows_common.json @@ -167,6 +167,8 @@ "SWDEV-402082 - PAL Backend fails to reserve address on GPU except first one", "Unit_hipGraphInstantiateWithFlags_FlagAutoFreeOnLaunch_check", "SWDEV-398981 fails in stress test", - "Unit_hipStreamCreateWithPriority_MulthreadDefaultflag" + "Unit_hipStreamCreateWithPriority_MulthreadDefaultflag", + "Note: UUID returned empty on some windows nodes", + "Unit_hipDeviceGetUuid_Positive" ] } From 6f035718cc52d6b31ab0d8a7e0d2e45b2131387d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mirza=20Halil=C4=8Devi=C4=87?= <109971222+mirza-halilcevic@users.noreply.github.com> Date: Wed, 28 Jun 2023 16:46:25 +0200 Subject: [PATCH 13/32] EXSWHTEC-103 - Implement tests for hipDrvMemcpy3D APIs (#56) - Implement basic behavior checks in all copy directions - Implement synchronization behavior checks for expected behavior based on cuda docs - Implement positive tests for zero sized width and/or height copies, where no copy is expected to happen - Implement negative parameter tests - Implement all of the above for hipDrvMemcpy3D and hipDrvMemcpy3DAsync. - Disable failing tests on AMD. - Fix copyright disclaimer. - Add defect issue numbers. [ROCm/hip-tests commit: c695f1b146aac69550465bffcf4854d4ff496ff3] --- .../config/config_amd_linux_common.json | 3 + .../config/config_amd_windows_common.json | 3 + .../catch/include/memcpy3d_tests_common.hh | 215 +++++ .../catch/unit/memory/CMakeLists.txt | 2 + .../catch/unit/memory/hipDrvMemcpy3D.cc | 712 +++++----------- .../catch/unit/memory/hipDrvMemcpy3DAsync.cc | 760 +++++------------- .../unit/memory/hipDrvMemcpy3DAsync_old.cc | 594 ++++++++++++++ .../catch/unit/memory/hipDrvMemcpy3D_old.cc | 573 +++++++++++++ 8 files changed, 1783 insertions(+), 1079 deletions(-) create mode 100644 projects/hip-tests/catch/unit/memory/hipDrvMemcpy3DAsync_old.cc create mode 100644 projects/hip-tests/catch/unit/memory/hipDrvMemcpy3D_old.cc diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json index 9640959961..7a1b5c1f20 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json @@ -23,6 +23,9 @@ "Unit_hipGraphDestroyNode_Complx_ChkNumOfNodesNDep_ClonedGrph", "Unit_hipGraphDestroyNode_Complx_ChkNumOfNodesNDep_ChldNode", "Unit_hipMemGetAddressRange_Negative", + "NOTE: The following 2 tests are disabled due to defect - EXSWHTEC-238", + "Unit_hipDrvMemcpy3D_Positive_Array", + "Unit_hipDrvMemcpy3DAsync_Positive_Array", "Unit_hipMemRangeGetAttribute_Positive_AccessedBy_Basic", "Unit_hipMemRangeGetAttribute_Positive_AccessedBy_Partial_Range", "Unit_hipMemRangeGetAttributes_Negative_Parameters", diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_windows_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_windows_common.json index 311d6ee70a..6b7c976792 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_windows_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_windows_common.json @@ -109,6 +109,9 @@ "Unit_hipGraphDestroyNode_Complx_ChkNumOfNodesNDep_ClonedGrph", "Unit_hipGraphDestroyNode_Complx_ChkNumOfNodesNDep_ChldNode", "Unit_hipMemGetAddressRange_Negative", + "NOTE: The following 2 tests are disabled due to defect - EXSWHTEC-238", + "Unit_hipDrvMemcpy3D_Positive_Array", + "Unit_hipDrvMemcpy3DAsync_Positive_Array", "Unit_hipMemGetAddressRange_Positive", "Note: devicelib hangs and failures", "Unit_deviceAllocation_Malloc_PerThread_PrimitiveDataType", diff --git a/projects/hip-tests/catch/include/memcpy3d_tests_common.hh b/projects/hip-tests/catch/include/memcpy3d_tests_common.hh index eff00712ce..49f09c1e50 100644 --- a/projects/hip-tests/catch/include/memcpy3d_tests_common.hh +++ b/projects/hip-tests/catch/include/memcpy3d_tests_common.hh @@ -582,4 +582,219 @@ void Memcpy3DZeroWidthHeightDepth(F memcpy_func, const hipStream_t stream = null } ArrayFindIfNot(dst_alloc.ptr(), static_cast(42), alloc_size); } +} + +constexpr auto MemTypeHost() { +#if HT_AMD + return hipMemoryTypeHost; +#else + return CU_MEMORYTYPE_HOST; +#endif +} + +constexpr auto MemTypeDevice() { +#if HT_AMD + return hipMemoryTypeDevice; +#else + return CU_MEMORYTYPE_DEVICE; +#endif +} + +constexpr auto MemTypeArray() { +#if HT_AMD + return hipMemoryTypeArray; +#else + return CU_MEMORYTYPE_ARRAY; +#endif +} + +constexpr auto MemTypeUnified() { +#if HT_AMD + return hipMemoryTypeUnified; +#else + return CU_MEMORYTYPE_UNIFIED; +#endif +} + +using DrvPtrVariant = std::variant; + +template +hipError_t DrvMemcpy3DWrapper(DrvPtrVariant dst_ptr, hipPos dst_pos, DrvPtrVariant src_ptr, + hipPos src_pos, hipExtent extent, hipMemcpyKind kind, + hipStream_t stream = nullptr) { + HIP_MEMCPY3D parms = {0}; + + if (std::holds_alternative(dst_ptr)) { + parms.dstMemoryType = MemTypeArray(); + parms.dstArray = std::get(dst_ptr); + } else { + auto ptr = std::get(dst_ptr); + parms.dstPitch = ptr.pitch; + switch (kind) { + case hipMemcpyDeviceToHost: + case hipMemcpyHostToHost: + parms.dstMemoryType = MemTypeHost(); + parms.dstHost = ptr.ptr; + break; + case hipMemcpyDeviceToDevice: + case hipMemcpyHostToDevice: + parms.dstMemoryType = MemTypeDevice(); + parms.dstDevice = reinterpret_cast(ptr.ptr); + break; + case hipMemcpyDefault: + parms.dstMemoryType = MemTypeUnified(); + parms.dstDevice = reinterpret_cast(ptr.ptr); + break; + default: + assert(false); + } + } + + if (std::holds_alternative(src_ptr)) { + parms.srcMemoryType = MemTypeArray(); + parms.srcArray = std::get(src_ptr); + } else { + auto ptr = std::get(src_ptr); + parms.srcPitch = ptr.pitch; + switch (kind) { + case hipMemcpyDeviceToHost: + case hipMemcpyDeviceToDevice: + parms.srcMemoryType = MemTypeDevice(); + parms.srcDevice = reinterpret_cast(ptr.ptr); + break; + case hipMemcpyHostToDevice: + case hipMemcpyHostToHost: + parms.srcMemoryType = MemTypeHost(); + parms.srcHost = ptr.ptr; + break; + case hipMemcpyDefault: + parms.srcMemoryType = MemTypeUnified(); + parms.srcDevice = reinterpret_cast(ptr.ptr); + break; + default: + assert(false); + } + } + + parms.WidthInBytes = extent.width; + parms.Height = extent.height; + parms.Depth = extent.depth; + parms.srcXInBytes = src_pos.x; + parms.srcY = src_pos.y; + parms.srcZ = src_pos.z; + parms.dstXInBytes = dst_pos.x; + parms.dstY = dst_pos.y; + parms.dstZ = dst_pos.z; + + if constexpr (async) { + return hipDrvMemcpy3DAsync(&parms, stream); + } else { + return hipDrvMemcpy3D(&parms); + } +} + +template +void DrvMemcpy3DArrayHostShell(F memcpy_func, const hipStream_t kernel_stream = nullptr) { + constexpr hipExtent extent{127 * sizeof(int), 128, 8}; + + LinearAllocGuard src_host(LinearAllocs::hipHostMalloc, + extent.width * extent.height * extent.depth); + LinearAllocGuard dst_host(LinearAllocs::hipHostMalloc, + extent.width * extent.height * extent.depth); + + DrvArrayAllocGuard src_array(extent); + DrvArrayAllocGuard dst_array(extent); + + const auto f = [extent](size_t x, size_t y, size_t z) { + constexpr auto width_logical = extent.width / sizeof(int); + return z * width_logical * extent.height + y * width_logical + x; + }; + PitchedMemorySet(src_host.ptr(), extent.width, extent.width / sizeof(int), extent.height, + extent.depth, f); + + // Host -> Array + HIP_CHECK( + memcpy_func(src_array.ptr(), make_hipPos(0, 0, 0), + make_hipPitchedPtr(src_host.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), extent, hipMemcpyHostToDevice, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + // Array -> Array + HIP_CHECK(memcpy_func(dst_array.ptr(), make_hipPos(0, 0, 0), src_array.ptr(), + make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + // Array -> Host + HIP_CHECK( + memcpy_func(make_hipPitchedPtr(dst_host.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), dst_array.ptr(), make_hipPos(0, 0, 0), extent, + hipMemcpyDeviceToHost, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + PitchedMemoryVerify(dst_host.ptr(), extent.width, extent.width / sizeof(int), extent.height, + extent.depth, f); +} + +template +void DrvMemcpy3DArrayDeviceShell(F memcpy_func, const hipStream_t kernel_stream = nullptr) { + constexpr hipExtent extent{127 * sizeof(int), 128, 8}; + + LinearAllocGuard host_alloc(LinearAllocs::hipHostMalloc, + extent.width * extent.height * extent.depth); + + DrvArrayAllocGuard src_array(extent); + DrvArrayAllocGuard dst_array(extent); + + LinearAllocGuard3D src_device(extent); + LinearAllocGuard3D dst_device(extent); + + const dim3 threads_per_block(32, 32); + const dim3 blocks(src_device.width_logical() / threads_per_block.x + 1, + src_device.height() / threads_per_block.y + 1, src_device.depth()); + Iota<<>>(src_device.ptr(), src_device.pitch(), + src_device.width_logical(), src_device.height(), + src_device.depth()); + HIP_CHECK(hipGetLastError()); + + // Device -> Array + HIP_CHECK(memcpy_func(src_array.ptr(), make_hipPos(0, 0, 0), src_device.pitched_ptr(), + make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + // Array -> Array + HIP_CHECK(memcpy_func(dst_array.ptr(), make_hipPos(0, 0, 0), src_array.ptr(), + make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + // Array -> Device + HIP_CHECK(memcpy_func(dst_device.pitched_ptr(), make_hipPos(0, 0, 0), dst_array.ptr(), + make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + HIP_CHECK( + memcpy_func(make_hipPitchedPtr(host_alloc.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), dst_device.pitched_ptr(), make_hipPos(0, 0, 0), + dst_device.extent(), hipMemcpyDeviceToHost, kernel_stream)); + if constexpr (should_synchronize) { + HIP_CHECK(hipStreamSynchronize(kernel_stream)); + } + + const auto f = [extent](size_t x, size_t y, size_t z) { + constexpr auto width_logical = extent.width / sizeof(int); + return z * width_logical * extent.height + y * width_logical + x; + }; + PitchedMemoryVerify(host_alloc.ptr(), extent.width, extent.width / sizeof(int), extent.height, + extent.depth, f); } \ No newline at end of file diff --git a/projects/hip-tests/catch/unit/memory/CMakeLists.txt b/projects/hip-tests/catch/unit/memory/CMakeLists.txt index 585f749fed..f09f0579f4 100644 --- a/projects/hip-tests/catch/unit/memory/CMakeLists.txt +++ b/projects/hip-tests/catch/unit/memory/CMakeLists.txt @@ -92,7 +92,9 @@ set(TEST_SRC hipArrayCreate.cc hipArray3DCreate.cc hipDrvMemcpy3D.cc + hipDrvMemcpy3D_old.cc hipDrvMemcpy3DAsync.cc + hipDrvMemcpy3DAsync_old.cc hipPointerGetAttribute.cc hipDrvPtrGetAttributes.cc hipMemPrefetchAsync.cc diff --git a/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3D.cc b/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3D.cc index 0b524655a9..beed5b3ba8 100644 --- a/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3D.cc +++ b/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3D.cc @@ -1,13 +1,16 @@ /* 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 @@ -16,558 +19,209 @@ 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. */ -/* - * Test Scenarios - * 1. Verifying hipDrvMemcpy3D API for H2A,A2A,A2H scenarios - * 2. Verifying hipDrvMemcpy3D API for H2D,D2D,D2H scenarios - * 3. Verifying Negative Scenarios - * 4. Verifying Extent validation scenarios by passing 0 - * 5. Verifying hipDrvMemcpy3D API by allocating Memory in - * one GPU and trigger hipDrvMemcpy3D from peer GPU for - * H2D,D2D,D2H scenarios - * 6. Verifying hipDrvMemcpy3D API by allocating Memory in - * one GPU and trigger hipDrvMemcpy3D from peer GPU for - * H2A,A2A,A2H scenarios - * - * Scenarios 3 is temporarily suspended on AMD - * Scenario 5&6 are not supported in CUDA platform - */ -#include "hip_test_common.hh" -#include "hip_test_checkers.hh" +#include +#include -template -class DrvMemcpy3D { - int width, height, depth; - unsigned int size; - hipArray_Format formatKind; - hiparray arr, arr1; - size_t pitch_D, pitch_E; - HIP_MEMCPY3D myparms; - hipDeviceptr_t D_m, E_m; - T* hData{nullptr}; - public: - DrvMemcpy3D(int l_width, int l_height, int l_depth, - hipArray_Format l_format); - DrvMemcpy3D() = delete; - void AllocateMemory(); - void SetDefaultData(); - void HostArray_DrvMemcpy3D(bool device_context_change = false); - void HostDevice_DrvMemcpy3D(bool device_context_change = false); - void Extent_Validation(); - void NegativeTests(); - void DeAllocateMemory(); -}; +#include +#include +#include +#include -/* Intializes class variables */ -template -DrvMemcpy3D::DrvMemcpy3D(int l_width, int l_height, int l_depth, - hipArray_Format l_format) { - width = l_width; - height = l_height; - depth = l_depth; - formatKind = l_format; -} +TEST_CASE("Unit_hipDrvMemcpy3D_Positive_Basic") { + constexpr bool async = false; -/* Allocating Memory */ -template -void DrvMemcpy3D::AllocateMemory() { - size = width * height * depth * sizeof(T); - hData = reinterpret_cast(malloc(size)); - memset(hData, 0, size); - for (int i = 0; i < depth; i++) { - for (int j = 0; j < height; j++) { - for (int k = 0; k < width; k++) { - hData[i*width*height + j*width +k] = i*width*height + j*width + k; - } +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-236 + SECTION("Device to Host") { Memcpy3DDeviceToHostShell(DrvMemcpy3DWrapper<>); } +#endif + + SECTION("Device to Device") { + SECTION("Peer access disabled") { + Memcpy3DDeviceToDeviceShell(DrvMemcpy3DWrapper<>); + } + SECTION("Peer access enabled") { + Memcpy3DDeviceToDeviceShell(DrvMemcpy3DWrapper<>); } } - HIP_CHECK(hipMallocPitch(reinterpret_cast(&D_m), - &pitch_D, width*sizeof(T), height)); - HIP_CHECK(hipMallocPitch(reinterpret_cast(&E_m), - &pitch_E, width*sizeof(T), height)); - HIP_ARRAY3D_DESCRIPTOR *desc; - desc = reinterpret_cast - (malloc(sizeof(HIP_ARRAY3D_DESCRIPTOR))); - desc->Format = formatKind; - desc->NumChannels = 1; - desc->Width = width; - desc->Height = height; - desc->Depth = depth; - desc->Flags = hipArrayDefault; - HIP_CHECK(hipArray3DCreate(&arr, desc)); - HIP_CHECK(hipArray3DCreate(&arr1, desc)); + + SECTION("Host to Device") { Memcpy3DHostToDeviceShell(DrvMemcpy3DWrapper<>); } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-236 + SECTION("Host to Host") { Memcpy3DHostToHostShell(DrvMemcpy3DWrapper<>); } +#endif } -/* Setting the default data */ -template -void DrvMemcpy3D::SetDefaultData() { - memset(&myparms, 0x0, sizeof(HIP_MEMCPY3D)); - myparms.srcXInBytes = 0; - myparms.srcY = 0; - myparms.srcZ = 0; - myparms.srcLOD = 0; - myparms.dstXInBytes = 0; - myparms.dstY = 0; - myparms.dstZ = 0; - myparms.dstLOD = 0; - myparms.WidthInBytes = width*sizeof(T); - myparms.Height = height; - myparms.Depth = depth; +TEST_CASE("Unit_hipDrvMemcpy3D_Positive_Synchronization_Behavior") { + HIP_CHECK(hipDeviceSynchronize()); + + SECTION("Host to Device") { Memcpy3DHtoDSyncBehavior(DrvMemcpy3DWrapper<>, true); } + + SECTION("Device to Pageable Host") { + Memcpy3DDtoHPageableSyncBehavior(DrvMemcpy3DWrapper<>, true); + } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-236 + SECTION("Device to Pinned Host") { Memcpy3DDtoHPinnedSyncBehavior(DrvMemcpy3DWrapper<>, true); } +#endif + + SECTION("Device to Device") { +#if HT_NVIDIA + Memcpy3DDtoDSyncBehavior(DrvMemcpy3DWrapper<>, false); +#else + Memcpy3DDtoDSyncBehavior(DrvMemcpy3DWrapper<>, true); +#endif + } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-232 + SECTION("Host to Host") { Memcpy3DHtoHSyncBehavior(DrvMemcpy3DWrapper<>, true); } +#endif } -/* -This function verifies the negative scenarios of -hipDrvMemcpy3D API -*/ -template -void DrvMemcpy3D::NegativeTests() { - HIP_CHECK(hipSetDevice(0)); - AllocateMemory(); - SetDefaultData(); - int deviceId; - HIP_CHECK(hipGetDevice(&deviceId)); - unsigned int MaxPitch; - HIP_CHECK(hipDeviceGetAttribute(reinterpret_cast(&MaxPitch), - hipDeviceAttributeMaxPitch, deviceId)); - myparms.srcHost = hData; - myparms.dstArray = arr; - myparms.srcPitch = width * sizeof(T); - myparms.srcHeight = height; -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_HOST; - myparms.dstMemoryType = CU_MEMORYTYPE_ARRAY; -#else - myparms.srcMemoryType = hipMemoryTypeHost; - myparms.dstMemoryType = hipMemoryTypeArray; -#endif - - SECTION("Passing nullptr to Source Host") { - myparms.srcHost = nullptr; - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing both dst host and device") { - myparms.dstHost = hData; - myparms.dstArray = nullptr; - myparms.dstDevice = D_m; - myparms.WidthInBytes = pitch_D; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing max value to WidthInBytes") { - myparms.WidthInBytes = std::numeric_limits::max(); - myparms.Height = std::numeric_limits::max(); - myparms.Depth = std::numeric_limits::max(); - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing width > max width size") { - myparms.WidthInBytes = width*sizeof(T) + 1; - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing height > max height size") { - myparms.Height = height + 1; - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Passing depth > max depth size") { - myparms.Depth = depth + 1; - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("widthinbytes + srcXinBytes is out of bound") { - myparms.srcXInBytes = 1; - myparms.dstArray = nullptr; - myparms.dstDevice = hipDeviceptr_t(D_m); - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("widthinbytes + dstXinBytes is out of bound") { - myparms.dstXInBytes = pitch_D; - myparms.dstArray = nullptr; - myparms.dstDevice = hipDeviceptr_t(D_m); - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("srcY + height is out of bound") { - myparms.srcY = 1; - myparms.dstArray = nullptr; - myparms.dstDevice = hipDeviceptr_t(D_m); - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("dstY + height out of bounds") { - myparms.dstY = 1; - myparms.dstArray = nullptr; - myparms.dstDevice = hipDeviceptr_t(D_m); - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("src pitch greater than Max allowed pitch") { -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_DEVICE; - myparms.dstMemoryType = CU_MEMORYTYPE_HOST; -#else - myparms.srcMemoryType = hipMemoryTypeDevice; - myparms.dstMemoryType = hipMemoryTypeHost; -#endif - myparms.srcDevice = D_m; - myparms.srcHost = nullptr; - myparms.srcPitch = MaxPitch; - myparms.srcHeight = height; - myparms.dstHost = hData; - myparms.dstArray = nullptr; - myparms.dstPitch = width*sizeof(T); - myparms.dstHeight = height; - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("dst pitch greater than Max allowed pitch") { - myparms.dstDevice = hipDeviceptr_t(D_m); - myparms.dstArray = nullptr; - myparms.dstPitch = MaxPitch+1; - myparms.dstHeight = height; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Nullptr to src/dst device") { - myparms.dstDevice = hipDeviceptr_t(nullptr); - myparms.dstArray = nullptr; - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Nullptr to src/dst array") { - myparms.dstArray = nullptr; - REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); - } - - SECTION("Nullptr to hipDrvMemcpy3D") { - REQUIRE(hipDrvMemcpy3D(nullptr) != hipSuccess); - } - - DeAllocateMemory(); +TEST_CASE("Unit_hipDrvMemcpy3D_Positive_Parameters") { + constexpr bool async = false; + Memcpy3DZeroWidthHeightDepth(DrvMemcpy3DWrapper); } -/* -This function verifies the Extent validation scenarios of -hipDrvMemcpy3D API -*/ -template -void DrvMemcpy3D::Extent_Validation() { - HIP_CHECK(hipSetDevice(0)); - // Allocating the memory - AllocateMemory(); - // Setting default data - SetDefaultData(); -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_HOST; - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.srcMemoryType = hipMemoryTypeHost; - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - myparms.srcHost = hData; - myparms.srcPitch = width * sizeof(T); - myparms.srcHeight = height; - myparms.dstDevice = D_m; - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; - - SECTION("WidthInBytes is 0") { - myparms.WidthInBytes = 0; - HIP_CHECK(hipDrvMemcpy3D(&myparms)); - } - - SECTION("Height is 0") { - myparms.Height = 0; - HIP_CHECK(hipDrvMemcpy3D(&myparms)); - } - - SECTION("Depth is 0") { - myparms.Depth = 0; - HIP_CHECK(hipDrvMemcpy3D(&myparms)); - } - - DeAllocateMemory(); +// Disabled on AMD due to defect - EXSWHTEC-238 +TEST_CASE("Unit_hipDrvMemcpy3D_Positive_Array") { + constexpr bool async = false; + SECTION("Array from/to Host") { DrvMemcpy3DArrayHostShell(DrvMemcpy3DWrapper); } + SECTION("Array from/to Device") { DrvMemcpy3DArrayDeviceShell(DrvMemcpy3DWrapper); } } -/* -This Function verifies following functionalities of hipDrvMemcpy3D API -1. Host to Device copy -2. Device to Device -3. Device to Host -In the end validates the results. -This functionality is verified in 2 scenarios -1. Basic scenario on same GPU device -2. Device context change scenario where memory is allocated in 1 GPU - and hipDrvMemcpy3D API is trigerred from another GPU -*/ -template -void DrvMemcpy3D::HostDevice_DrvMemcpy3D(bool device_context_change) { - HIP_CHECK(hipSetDevice(0)); - bool skip_test = false; - int peerAccess = 0; - AllocateMemory(); - if (device_context_change) { - HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); - if (!peerAccess) { - WARN("skipped the testcase as no peer access"); - skip_test = true; - } else { - HIP_CHECK(hipSetDevice(1)); +TEST_CASE("Unit_hipDrvMemcpy3D_Negative_Parameters") { + constexpr hipExtent extent{128 * sizeof(int), 128, 8}; + + constexpr auto NegativeTests = [](hipPitchedPtr dst_ptr, hipPos dst_pos, hipPitchedPtr src_ptr, + hipPos src_pos, hipExtent extent, hipMemcpyKind kind) { + SECTION("dst_ptr.ptr == nullptr") { + hipPitchedPtr invalid_ptr = dst_ptr; + invalid_ptr.ptr = nullptr; + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); } - } - if (!skip_test) { - SetDefaultData(); -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_HOST; - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.srcMemoryType = hipMemoryTypeHost; - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - myparms.srcHost = hData; - myparms.srcPitch = width * sizeof(T); - myparms.srcHeight = height; - myparms.dstDevice = hipDeviceptr_t(D_m); - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; - HIP_CHECK(hipDrvMemcpy3D(&myparms)); - // Device to Device - SetDefaultData(); -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_DEVICE; - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.srcMemoryType = hipMemoryTypeDevice; - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - myparms.srcDevice = hipDeviceptr_t(D_m); - myparms.srcPitch = pitch_D; - myparms.srcHeight = height; - myparms.dstDevice = hipDeviceptr_t(E_m); - myparms.dstPitch = pitch_E; - myparms.dstHeight = height; - HIP_CHECK(hipDrvMemcpy3D(&myparms)); - T *hOutputData = reinterpret_cast(malloc(size)); - memset(hOutputData, 0, size); - - // Device to host - SetDefaultData(); -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_DEVICE; - myparms.dstMemoryType = CU_MEMORYTYPE_HOST; -#else - myparms.srcMemoryType = hipMemoryTypeDevice; - myparms.dstMemoryType = hipMemoryTypeHost; -#endif - myparms.srcDevice = hipDeviceptr_t(E_m); - myparms.srcPitch = pitch_E; - myparms.srcHeight = height; - myparms.dstHost = hOutputData; - myparms.dstPitch = width * sizeof(T); - myparms.dstHeight = height; - HIP_CHECK(hipDrvMemcpy3D(&myparms)); - - HipTest::checkArray(hData, hOutputData, width, height, depth); - free(hOutputData); - } - DeAllocateMemory(); -} - -/* -This Function verifies following functionalities of hipDrvMemcpy3D API -1. Host to Array copy -2. Array to Array -3. Array to Host -In the end validates the results. - -This functionality is verified in 2 scenarios -1. Basic scenario on same GPU device -2. Device context change scenario where memory is allocated in 1 GPU - and hipDrvMemcpy3D API is trigerred from another GPU -*/ -template -void DrvMemcpy3D::HostArray_DrvMemcpy3D(bool device_context_change) { - HIP_CHECK(hipSetDevice(0)); - bool skip_test = false; - int peerAccess = 0; - AllocateMemory(); - if (device_context_change) { - HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); - if (!peerAccess) { - WARN("skipped the testcase as no peer access"); - skip_test = true; - } else { - HIP_CHECK(hipSetDevice(1)); + SECTION("src_ptr.ptr == nullptr") { + hipPitchedPtr invalid_ptr = src_ptr; + invalid_ptr.ptr = nullptr; + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind), + hipErrorInvalidValue); } - } - if (!skip_test) { - SetDefaultData(); -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_HOST; - myparms.dstMemoryType = CU_MEMORYTYPE_ARRAY; -#else - myparms.srcMemoryType = hipMemoryTypeHost; - myparms.dstMemoryType = hipMemoryTypeArray; -#endif - myparms.srcHost = hData; - myparms.srcPitch = width * sizeof(T); - myparms.srcHeight = height; - myparms.dstArray = arr; - HIP_CHECK(hipDrvMemcpy3D(&myparms)); - // Array to Array - SetDefaultData(); -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_ARRAY; - myparms.dstMemoryType = CU_MEMORYTYPE_ARRAY; -#else - myparms.srcMemoryType = hipMemoryTypeArray; - myparms.dstMemoryType = hipMemoryTypeArray; -#endif - myparms.srcArray = arr; - myparms.dstArray = arr1; - HIP_CHECK(hipDrvMemcpy3D(&myparms)); - T *hOutputData = reinterpret_cast(malloc(size)); - memset(hOutputData, 0, size); - SetDefaultData(); - // Device to host -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_ARRAY; - myparms.dstMemoryType = CU_MEMORYTYPE_HOST; -#else - myparms.srcMemoryType = hipMemoryTypeArray; - myparms.dstMemoryType = hipMemoryTypeHost; -#endif - myparms.srcArray = arr1; - myparms.dstHost = hOutputData; - myparms.dstPitch = width * sizeof(T); - myparms.dstHeight = height; - HIP_CHECK(hipDrvMemcpy3D(&myparms)); - HipTest::checkArray(hData, hOutputData, width, height, depth); - free(hOutputData); - } - DeAllocateMemory(); -} -/* DeAllocating the memory */ -template -void DrvMemcpy3D::DeAllocateMemory() { - HIP_CHECK(hipArrayDestroy(arr)); - HIP_CHECK(hipArrayDestroy(arr1)); - free(hData); -} - -/* Verifying hipDrvMemcpy3D API Host to Array for different datatypes */ -TEMPLATE_TEST_CASE("Unit_hipDrvMemcpy3D_MultipleDataTypes", "", - uint8_t, int, float) { - for (int i = 1; i < 25; i++) { - if (std::is_same::value) { - DrvMemcpy3D memcpy3d_float(i, i, i, HIP_AD_FORMAT_FLOAT); - memcpy3d_float.HostArray_DrvMemcpy3D(); - } else if (std::is_same::value) { - DrvMemcpy3D memcpy3d_intx(i, i, i, HIP_AD_FORMAT_UNSIGNED_INT8); - memcpy3d_intx.HostArray_DrvMemcpy3D(); - } else if (std::is_same::value) { - DrvMemcpy3D memcpy3d_inty(i, i, i, HIP_AD_FORMAT_SIGNED_INT32); - memcpy3d_inty.HostArray_DrvMemcpy3D(); + SECTION("dst_ptr.pitch < width") { + hipPitchedPtr invalid_ptr = dst_ptr; + invalid_ptr.pitch = extent.width - 1; + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); } - } -} -/* This testcase verifies H2D copy of hipDrvMemcpy3D API */ -TEST_CASE("Unit_hipDrvMemcpy3D_HosttoDevice") { - DrvMemcpy3D memcpy3d_D2H_float(10, 10, 1, HIP_AD_FORMAT_FLOAT); - memcpy3d_D2H_float.HostDevice_DrvMemcpy3D(); -} + SECTION("src_ptr.pitch < width") { + hipPitchedPtr invalid_ptr = src_ptr; + invalid_ptr.pitch = extent.width - 1; + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } -/* This testcase verifies negative scenarios of hipDrvMemcpy3D API */ -#if HT_NVIDIA -TEST_CASE("Unit_hipDrvMemcpy3D_Negative") { - DrvMemcpy3D memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); - memcpy3d.NegativeTests(); -} + SECTION("dst_ptr.pitch > max pitch") { + int attr = 0; + HIP_CHECK(hipDeviceGetAttribute(&attr, hipDeviceAttributeMaxPitch, 0)); + hipPitchedPtr invalid_ptr = dst_ptr; + invalid_ptr.pitch = attr; + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("src_ptr.pitch > max pitch") { + int attr = 0; + HIP_CHECK(hipDeviceGetAttribute(&attr, hipDeviceAttributeMaxPitch, 0)); + hipPitchedPtr invalid_ptr = src_ptr; + invalid_ptr.pitch = attr; + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-237 + SECTION("extent.width + dst_pos.x > dst_ptr.pitch") { + hipPos invalid_pos = dst_pos; + invalid_pos.x = dst_ptr.pitch - extent.width + 1; + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("extent.width + src_pos.x > src_ptr.pitch") { + hipPos invalid_pos = src_pos; + invalid_pos.x = src_ptr.pitch - extent.width + 1; + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("dst_pos.y out of bounds") { + hipPos invalid_pos = dst_pos; + invalid_pos.y = 1; + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("src_pos.y out of bounds") { + hipPos invalid_pos = src_pos; + invalid_pos.y = 1; + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("dst_pos.z out of bounds") { + hipPos invalid_pos = dst_pos; + invalid_pos.z = 1; + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("src_pos.z out of bounds") { + hipPos invalid_pos = src_pos; + invalid_pos.z = 1; + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind), + hipErrorInvalidValue); + } #endif + }; -/* This testcase verifies extent validation scenarios of hipDrvMemcpy3D API */ -TEST_CASE("Unit_hipDrvMemcpy3D_ExtentValidation") { - DrvMemcpy3D memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); - memcpy3d.Extent_Validation(); -} - -#if HT_AMD -/* This testcase verifies H2D copy in device context -change scenario for hipDrvMemcpy3D API */ -TEST_CASE("Unit_hipDrvMemcpy3D_H2DDeviceContextChange") { - int numDevices = 0; - HIP_CHECK(hipGetDeviceCount(&numDevices)); - if (numDevices > 1) { - DrvMemcpy3D memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); - memcpy3d.HostDevice_DrvMemcpy3D(true); - } else { - SUCCEED("skipped testcase as Device count is < 2"); + SECTION("Host to Device") { + LinearAllocGuard3D device_alloc(extent); + LinearAllocGuard host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.pitch() * device_alloc.height() * device_alloc.depth()); + NegativeTests(device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + make_hipPitchedPtr(host_alloc.ptr(), device_alloc.pitch(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), extent, hipMemcpyHostToDevice); } -} - -/* This testcase verifies Host to Array copy in device context -change scenario for hipDrvMemcpy3D API */ -TEST_CASE("Unit_hipDrvMemcpy3D_Host2ArrayDeviceContextChange") { - int numDevices = 0; - HIP_CHECK(hipGetDeviceCount(&numDevices)); - if (numDevices > 1) { - DrvMemcpy3D memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); - memcpy3d.HostArray_DrvMemcpy3D(true); - } else { - SUCCEED("skipped testcase as Device count is < 2"); + SECTION("Device to Host") { + LinearAllocGuard3D device_alloc(extent); + LinearAllocGuard host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.pitch() * device_alloc.height() * device_alloc.depth()); + NegativeTests(make_hipPitchedPtr(host_alloc.ptr(), device_alloc.pitch(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), extent, + hipMemcpyDeviceToHost); } -} -#endif + + SECTION("Host to Host") { + LinearAllocGuard src_alloc(LinearAllocs::hipHostMalloc, + extent.width * extent.height * extent.depth); + LinearAllocGuard dst_alloc(LinearAllocs::hipHostMalloc, + extent.width * extent.height * extent.depth); + NegativeTests(make_hipPitchedPtr(dst_alloc.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), + make_hipPitchedPtr(src_alloc.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), extent, hipMemcpyHostToHost); + } + + SECTION("Device to Device") { + LinearAllocGuard3D src_alloc(extent); + LinearAllocGuard3D dst_alloc(extent); + NegativeTests(dst_alloc.pitched_ptr(), make_hipPos(0, 0, 0), src_alloc.pitched_ptr(), + make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice); + } +} \ No newline at end of file diff --git a/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3DAsync.cc b/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3DAsync.cc index 9f81da6250..746fdcae6b 100644 --- a/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3DAsync.cc +++ b/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3DAsync.cc @@ -1,13 +1,16 @@ /* 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 @@ -16,579 +19,236 @@ 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. */ -/* - * Test Scenarios - * 1. Verifying hipDrvMemcpy3DAsync API for H2A,A2A,A2H scenarios - * 2. Verifying hipDrvMemcpy3DAsync API for H2D,D2D,D2H scenarios - * 3. Verifying Negative Scenarios - * 4. Verifying Extent validation scenarios by passing 0 - * 5. Verifying hipDrvMemcpy3DAsync API by allocating Memory in - * one GPU and trigger hipDrvMemcpy3DAsync from peer GPU for - * H2D,D2D,D2H scenarios - * 6. Verifying hipDrvMemcpy3DAsync API by allocating Memory in - * one GPU and trigger hipDrvMemcpy3DAsync from peer GPU for - * H2A,A2A,A2H scenarios - * - * Scenarios 3 is temporarily excluded in AMD platform - * Scenario 5&6 are excluded in CUDA platform - */ -#include "hip_test_common.hh" -#include "hip_test_checkers.hh" +#include +#include -template -class DrvMemcpy3DAsync { - int width, height, depth; - unsigned int size; - hipArray_Format formatKind; - hiparray arr, arr1; - hipStream_t stream; - size_t pitch_D, pitch_E; - HIP_MEMCPY3D myparms; - hipDeviceptr_t D_m, E_m; - T* hData{nullptr}; - public: - DrvMemcpy3DAsync(int l_width, int l_height, int l_depth, - hipArray_Format l_format); - DrvMemcpy3DAsync() = delete; - void AllocateMemory(); - void SetDefaultData(); - void HostArray_DrvMemcpy3DAsync(bool device_context_change = false); - void HostDevice_DrvMemcpy3DAsync(bool device_context_change = false); - void Extent_Validation(); - void NegativeTests(); - void DeAllocateMemory(); -}; +#include +#include +#include +#include -/* Intializes class variables */ -template -DrvMemcpy3DAsync::DrvMemcpy3DAsync(int l_width, int l_height, int l_depth, - hipArray_Format l_format) { - width = l_width; - height = l_height; - depth = l_depth; - formatKind = l_format; -} +TEST_CASE("Unit_hipDrvMemcpy3DAsync_Positive_Basic") { + constexpr bool async = true; -/* Allocating Memory */ -template -void DrvMemcpy3DAsync::AllocateMemory() { - size = width * height * depth * sizeof(T); - hData = reinterpret_cast(malloc(size)); - memset(hData, 0, size); - for (int i = 0; i < depth; i++) { - for (int j = 0; j < height; j++) { - for (int k = 0; k < width; k++) { - hData[i*width*height + j*width +k] = i*width*height + j*width + k; - } + const auto stream_type = GENERATE(Streams::nullstream, Streams::perThread, Streams::created); + const StreamGuard stream_guard(stream_type); + const hipStream_t stream = stream_guard.stream(); + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-236 + SECTION("Device to Host") { Memcpy3DDeviceToHostShell(DrvMemcpy3DWrapper, stream); } +#endif + + SECTION("Device to Device") { + SECTION("Peer access disabled") { + Memcpy3DDeviceToDeviceShell(DrvMemcpy3DWrapper, stream); + } + SECTION("Peer access enabled") { + Memcpy3DDeviceToDeviceShell(DrvMemcpy3DWrapper, stream); } } - HIP_CHECK(hipStreamCreate(&stream)); - HIP_CHECK(hipMallocPitch(reinterpret_cast(&D_m), - &pitch_D, width*sizeof(T), height)); - HIP_CHECK(hipMallocPitch(reinterpret_cast(&E_m), - &pitch_E, width*sizeof(T), height)); - HIP_ARRAY3D_DESCRIPTOR *desc; - desc = reinterpret_cast - (malloc(sizeof(HIP_ARRAY3D_DESCRIPTOR))); - desc->Format = formatKind; - desc->NumChannels = 1; - desc->Width = width; - desc->Height = height; - desc->Depth = depth; - desc->Flags = hipArrayDefault; - HIP_CHECK(hipArray3DCreate(&arr, desc)); - HIP_CHECK(hipArray3DCreate(&arr1, desc)); + + SECTION("Host to Device") { Memcpy3DHostToDeviceShell(DrvMemcpy3DWrapper, stream); } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-236 + SECTION("Host to Host") { Memcpy3DHostToHostShell(DrvMemcpy3DWrapper, stream); } +#endif } -/* Setting the default data */ -template -void DrvMemcpy3DAsync::SetDefaultData() { - memset(&myparms, 0x0, sizeof(HIP_MEMCPY3D)); - myparms.srcXInBytes = 0; - myparms.srcY = 0; - myparms.srcZ = 0; - myparms.srcLOD = 0; - myparms.dstXInBytes = 0; - myparms.dstY = 0; - myparms.dstZ = 0; - myparms.dstLOD = 0; - myparms.WidthInBytes = width*sizeof(T); - myparms.Height = height; - myparms.Depth = depth; +TEST_CASE("Unit_hipDrvMemcpy3DAsync_Positive_Synchronization_Behavior") { + constexpr bool async = true; + + HIP_CHECK(hipDeviceSynchronize()); + + SECTION("Host to Device") { Memcpy3DHtoDSyncBehavior(DrvMemcpy3DWrapper, false); } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-233 + SECTION("Device to Pageable Host") { + Memcpy3DDtoHPageableSyncBehavior(DrvMemcpy3DWrapper, true); + } +#endif + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-236 + SECTION("Device to Pinned Host") { + Memcpy3DDtoHPinnedSyncBehavior(DrvMemcpy3DWrapper, false); + } +#endif + + SECTION("Device to Device") { Memcpy3DDtoDSyncBehavior(DrvMemcpy3DWrapper, false); } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-233 + SECTION("Host to Host") { Memcpy3DHtoHSyncBehavior(DrvMemcpy3DWrapper, true); } +#endif } -/* -This function verifies the negative scenarios of -hipDrvMemcpy3DAsync API -*/ -template -void DrvMemcpy3DAsync::NegativeTests() { - HIP_CHECK(hipSetDevice(0)); - AllocateMemory(); - SetDefaultData(); - int deviceId; - HIP_CHECK(hipGetDevice(&deviceId)); - unsigned int MaxPitch; - HIP_CHECK(hipDeviceGetAttribute(reinterpret_cast(&MaxPitch), - hipDeviceAttributeMaxPitch, deviceId)); - myparms.srcHost = hData; - myparms.dstArray = arr; - myparms.srcPitch = width * sizeof(T); - myparms.srcHeight = height; -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_HOST; - myparms.dstMemoryType = CU_MEMORYTYPE_ARRAY; -#else - myparms.srcMemoryType = hipMemoryTypeHost; - myparms.dstMemoryType = hipMemoryTypeArray; -#endif - - SECTION("Passing nullptr to Source Host") { - myparms.srcHost = nullptr; - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing both dst host and device") { - myparms.dstHost = hData; - myparms.dstArray = nullptr; - myparms.dstDevice = D_m; - myparms.WidthInBytes = pitch_D; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing max value to WidthInBytes") { - myparms.WidthInBytes = std::numeric_limits::max(); - myparms.Height = std::numeric_limits::max(); - myparms.Depth = std::numeric_limits::max(); - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing width > max width size") { - myparms.WidthInBytes = width*sizeof(T) + 1; - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing height > max height size") { - myparms.Height = height + 1; - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Passing depth > max depth size") { - myparms.Depth = depth + 1; - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("widthinbytes + srcXinBytes is out of bound") { - myparms.srcXInBytes = 1; - myparms.dstArray = nullptr; - myparms.dstDevice = hipDeviceptr_t(D_m); - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("widthinbytes + dstXinBytes is out of bound") { - myparms.dstXInBytes = pitch_D; - myparms.dstArray = nullptr; - myparms.dstDevice = hipDeviceptr_t(D_m); - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("srcY + height is out of bound") { - myparms.srcY = 1; - myparms.dstArray = nullptr; - myparms.dstDevice = hipDeviceptr_t(D_m); - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("dstY + height out of bounds") { - myparms.dstY = 1; - myparms.dstArray = nullptr; - myparms.dstDevice = hipDeviceptr_t(D_m); - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("src pitch greater than Max allowed pitch") { -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_DEVICE; - myparms.dstMemoryType = CU_MEMORYTYPE_HOST; -#else - myparms.srcMemoryType = hipMemoryTypeDevice; - myparms.dstMemoryType = hipMemoryTypeHost; -#endif - myparms.srcDevice = D_m; - myparms.srcHost = nullptr; - myparms.srcPitch = MaxPitch; - myparms.srcHeight = height; - myparms.dstHost = hData; - myparms.dstArray = nullptr; - myparms.dstPitch = width*sizeof(T); - myparms.dstHeight = height; - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("dst pitch greater than Max allowed pitch") { - myparms.dstDevice = hipDeviceptr_t(D_m); - myparms.dstArray = nullptr; - myparms.dstPitch = MaxPitch+1; - myparms.dstHeight = height; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Nullptr to src/dst device") { - myparms.dstDevice = hipDeviceptr_t(nullptr); - myparms.dstArray = nullptr; - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; -#if HT_NVIDIA - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Nullptr to src/dst array") { - myparms.dstArray = nullptr; - REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); - } - - SECTION("Nullptr to hipDrvMemcpy3DAsync") { - REQUIRE(hipDrvMemcpy3DAsync(nullptr, stream) != hipSuccess); - } - - DeAllocateMemory(); +TEST_CASE("Unit_hipDrvMemcpy3DAsync_Positive_Parameters") { + constexpr bool async = true; + Memcpy3DZeroWidthHeightDepth(DrvMemcpy3DWrapper); } -/* -This function verifies the Extent validation scenarios of -hipDrvMemcpy3DAsync API -*/ -template -void DrvMemcpy3DAsync::Extent_Validation() { - HIP_CHECK(hipSetDevice(0)); - // Allocating the memory - AllocateMemory(); - // Setting default data - SetDefaultData(); -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_HOST; - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.srcMemoryType = hipMemoryTypeHost; - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - myparms.srcHost = hData; - myparms.srcPitch = width * sizeof(T); - myparms.srcHeight = height; - myparms.dstDevice = D_m; - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; - - SECTION("WidthInBytes is 0") { - myparms.WidthInBytes = 0; - HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); - HIP_CHECK(hipStreamSynchronize(stream)); - } - - SECTION("Height is 0") { - myparms.Height = 0; - HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); - HIP_CHECK(hipStreamSynchronize(stream)); - } - - SECTION("Depth is 0") { - myparms.Depth = 0; - HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); - HIP_CHECK(hipStreamSynchronize(stream)); - } - - DeAllocateMemory(); +// Disabled on AMD due to defect - EXSWHTEC-238 +TEST_CASE("Unit_hipDrvMemcpy3DAsync_Positive_Array") { + constexpr bool async = true; + SECTION("Array from/to Host") { DrvMemcpy3DArrayHostShell(DrvMemcpy3DWrapper); } + SECTION("Array from/to Device") { DrvMemcpy3DArrayDeviceShell(DrvMemcpy3DWrapper); } } -/* -This Function verifies following functionalities of hipDrvMemcpy3DAsync API -1. Host to Device copy -2. Device to Device -3. Device to Host -In the end validates the results. -This functionality is verified in 2 scenarios -1. Basic scenario on same GPU device -2. Device context change scenario where memory is allocated in 1 GPU - and hipDrvMemcpy3DAsync API is trigerred from another GPU -*/ -template -void DrvMemcpy3DAsync::HostDevice_DrvMemcpy3DAsync - (bool device_context_change) { - HIP_CHECK(hipSetDevice(0)); - bool skip_test = false; - int peerAccess = 0; - AllocateMemory(); - if (device_context_change) { - HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); - if (!peerAccess) { - WARN("skipped the testcase as no peer access"); - skip_test = true; - } else { - HIP_CHECK(hipSetDevice(1)); +TEST_CASE("Unit_hipDrvMemcpy3DAsync_Negative_Parameters") { + constexpr bool async = true; + constexpr hipExtent extent{128 * sizeof(int), 128, 8}; + + constexpr auto NegativeTests = [](hipPitchedPtr dst_ptr, hipPos dst_pos, hipPitchedPtr src_ptr, + hipPos src_pos, hipExtent extent, hipMemcpyKind kind) { + SECTION("dst_ptr.ptr == nullptr") { + hipPitchedPtr invalid_ptr = dst_ptr; + invalid_ptr.ptr = nullptr; + HIP_CHECK_ERROR( + DrvMemcpy3DWrapper(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); } - } - if (!skip_test) { - SetDefaultData(); -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_HOST; - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.srcMemoryType = hipMemoryTypeHost; - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - myparms.srcHost = hData; - myparms.srcPitch = width * sizeof(T); - myparms.srcHeight = height; - myparms.dstDevice = hipDeviceptr_t(D_m); - myparms.dstPitch = pitch_D; - myparms.dstHeight = height; - HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); - HIP_CHECK(hipStreamSynchronize(stream)); - // Device to Device - SetDefaultData(); -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_DEVICE; - myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; -#else - myparms.srcMemoryType = hipMemoryTypeDevice; - myparms.dstMemoryType = hipMemoryTypeDevice; -#endif - myparms.srcDevice = hipDeviceptr_t(D_m); - myparms.srcPitch = pitch_D; - myparms.srcHeight = height; - myparms.dstDevice = hipDeviceptr_t(E_m); - myparms.dstPitch = pitch_E; - myparms.dstHeight = height; - HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); - HIP_CHECK(hipStreamSynchronize(stream)); - T *hOutputData = reinterpret_cast(malloc(size)); - memset(hOutputData, 0, size); - - // Device to host - SetDefaultData(); -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_DEVICE; - myparms.dstMemoryType = CU_MEMORYTYPE_HOST; -#else - myparms.srcMemoryType = hipMemoryTypeDevice; - myparms.dstMemoryType = hipMemoryTypeHost; -#endif - myparms.srcDevice = hipDeviceptr_t(E_m); - myparms.srcPitch = pitch_E; - myparms.srcHeight = height; - myparms.dstHost = hOutputData; - myparms.dstPitch = width * sizeof(T); - myparms.dstHeight = height; - HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); - HIP_CHECK(hipStreamSynchronize(stream)); - - HipTest::checkArray(hData, hOutputData, width, height, depth); - free(hOutputData); - } - DeAllocateMemory(); -} - -/* -This Function verifies following functionalities of hipDrvMemcpy3DAsync API -1. Host to Array copy -2. Array to Array -3. Array to Host -In the end validates the results. - -This functionality is verified in 2 scenarios -1. Basic scenario on same GPU device -2. Device context change scenario where memory is allocated in 1 GPU - and hipDrvMemcpy3DAsync API is trigerred from another GPU -*/ -template -void DrvMemcpy3DAsync::HostArray_DrvMemcpy3DAsync - (bool device_context_change) { - HIP_CHECK(hipSetDevice(0)); - bool skip_test = false; - int peerAccess = 0; - AllocateMemory(); - if (device_context_change) { - HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); - if (!peerAccess) { - WARN("skipped the testcase as no peer access"); - skip_test = true; - } else { - HIP_CHECK(hipSetDevice(1)); + SECTION("src_ptr.ptr == nullptr") { + hipPitchedPtr invalid_ptr = src_ptr; + invalid_ptr.ptr = nullptr; + HIP_CHECK_ERROR( + DrvMemcpy3DWrapper(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind), + hipErrorInvalidValue); } - } - if (!skip_test) { - SetDefaultData(); -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_HOST; - myparms.dstMemoryType = CU_MEMORYTYPE_ARRAY; -#else - myparms.srcMemoryType = hipMemoryTypeHost; - myparms.dstMemoryType = hipMemoryTypeArray; -#endif - myparms.srcHost = hData; - myparms.srcPitch = width * sizeof(T); - myparms.srcHeight = height; - myparms.dstArray = arr; - HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); - HIP_CHECK(hipStreamSynchronize(stream)); - // Array to Array - SetDefaultData(); -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_ARRAY; - myparms.dstMemoryType = CU_MEMORYTYPE_ARRAY; -#else - myparms.srcMemoryType = hipMemoryTypeArray; - myparms.dstMemoryType = hipMemoryTypeArray; -#endif - myparms.srcArray = arr; - myparms.dstArray = arr1; - HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); - HIP_CHECK(hipStreamSynchronize(stream)); - T *hOutputData = reinterpret_cast(malloc(size)); - memset(hOutputData, 0, size); - SetDefaultData(); - // Device to host -#if HT_NVIDIA - myparms.srcMemoryType = CU_MEMORYTYPE_ARRAY; - myparms.dstMemoryType = CU_MEMORYTYPE_HOST; -#else - myparms.srcMemoryType = hipMemoryTypeArray; - myparms.dstMemoryType = hipMemoryTypeHost; -#endif - myparms.srcArray = arr1; - myparms.dstHost = hOutputData; - myparms.dstPitch = width * sizeof(T); - myparms.dstHeight = height; - HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); - HIP_CHECK(hipStreamSynchronize(stream)); - HipTest::checkArray(hData, hOutputData, width, height, depth); - free(hOutputData); - } - DeAllocateMemory(); -} - -/* DeAllocating the memory */ -template -void DrvMemcpy3DAsync::DeAllocateMemory() { - HIP_CHECK(hipArrayDestroy(arr)); - HIP_CHECK(hipArrayDestroy(arr1)); - HIP_CHECK(hipStreamDestroy(stream)); - free(hData); -} - -/* Verifying hipDrvMemcpy3DAsync API Host to Array for different datatypes */ -TEMPLATE_TEST_CASE("Unit_hipDrvMemcpy3DAsync_MultipleDataTypes", "", - uint8_t, int, float) { - for (int i = 1; i < 25; i++) { - if (std::is_same::value) { - DrvMemcpy3DAsync memcpy3d_float(i, i, i, - HIP_AD_FORMAT_FLOAT); - memcpy3d_float.HostArray_DrvMemcpy3DAsync(); - } else if (std::is_same::value) { - DrvMemcpy3DAsync memcpy3d_intx(i, i, i, - HIP_AD_FORMAT_UNSIGNED_INT8); - memcpy3d_intx.HostArray_DrvMemcpy3DAsync(); - } else if (std::is_same::value) { - DrvMemcpy3DAsync memcpy3d_inty(i, i, i, - HIP_AD_FORMAT_SIGNED_INT32); - memcpy3d_inty.HostArray_DrvMemcpy3DAsync(); + SECTION("dst_ptr.pitch < width") { + hipPitchedPtr invalid_ptr = dst_ptr; + invalid_ptr.pitch = extent.width - 1; + HIP_CHECK_ERROR( + DrvMemcpy3DWrapper(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); } - } -} -/* This testcase verifies H2D copy of hipDrvMemcpy3DAsync API */ -TEST_CASE("Unit_hipDrvMemcpy3DAsync_HosttoDevice") { - DrvMemcpy3DAsync memcpy3d_D2H_float(10, 10, 1, HIP_AD_FORMAT_FLOAT); - memcpy3d_D2H_float.HostDevice_DrvMemcpy3DAsync(); -} + SECTION("src_ptr.pitch < width") { + hipPitchedPtr invalid_ptr = src_ptr; + invalid_ptr.pitch = extent.width - 1; + HIP_CHECK_ERROR( + DrvMemcpy3DWrapper(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } -/* This testcase verifies negative scenarios of hipDrvMemcpy3DAsync API */ -#if HT_NVIDIA -TEST_CASE("Unit_hipDrvMemcpy3DAsync_Negative") { - DrvMemcpy3DAsync memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); - memcpy3d.NegativeTests(); -} + SECTION("dst_ptr.pitch > max pitch") { + int attr = 0; + HIP_CHECK(hipDeviceGetAttribute(&attr, hipDeviceAttributeMaxPitch, 0)); + hipPitchedPtr invalid_ptr = dst_ptr; + invalid_ptr.pitch = attr; + HIP_CHECK_ERROR( + DrvMemcpy3DWrapper(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("src_ptr.pitch > max pitch") { + int attr = 0; + HIP_CHECK(hipDeviceGetAttribute(&attr, hipDeviceAttributeMaxPitch, 0)); + hipPitchedPtr invalid_ptr = src_ptr; + invalid_ptr.pitch = attr; + HIP_CHECK_ERROR( + DrvMemcpy3DWrapper(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-237 + SECTION("extent.width + dst_pos.x > dst_ptr.pitch") { + hipPos invalid_pos = dst_pos; + invalid_pos.x = dst_ptr.pitch - extent.width + 1; + HIP_CHECK_ERROR( + DrvMemcpy3DWrapper(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("extent.width + src_pos.x > src_ptr.pitch") { + hipPos invalid_pos = src_pos; + invalid_pos.x = src_ptr.pitch - extent.width + 1; + HIP_CHECK_ERROR( + DrvMemcpy3DWrapper(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("dst_pos.y out of bounds") { + hipPos invalid_pos = dst_pos; + invalid_pos.y = 1; + HIP_CHECK_ERROR( + DrvMemcpy3DWrapper(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("src_pos.y out of bounds") { + hipPos invalid_pos = src_pos; + invalid_pos.y = 1; + HIP_CHECK_ERROR( + DrvMemcpy3DWrapper(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("dst_pos.z out of bounds") { + hipPos invalid_pos = dst_pos; + invalid_pos.z = 1; + HIP_CHECK_ERROR( + DrvMemcpy3DWrapper(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind), + hipErrorInvalidValue); + } + + SECTION("src_pos.z out of bounds") { + hipPos invalid_pos = src_pos; + invalid_pos.z = 1; + HIP_CHECK_ERROR( + DrvMemcpy3DWrapper(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind), + hipErrorInvalidValue); + } #endif -/* This testcase verifies extent validation scenarios of - hipDrvMemcpy3DAsync API */ -TEST_CASE("Unit_hipDrvMemcpy3DAsync_ExtentValidation") { - DrvMemcpy3DAsync memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); - memcpy3d.Extent_Validation(); -} - -/* This testcase verifies H2D copy in device context -change scenario for hipDrvMemcpy3DAsync API */ -#if HT_AMD -TEST_CASE("Unit_hipDrvMemcpy3DAsync_H2DDeviceContextChange") { - int numDevices = 0; - HIP_CHECK(hipGetDeviceCount(&numDevices)); - if (numDevices > 1) { - DrvMemcpy3DAsync memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); - memcpy3d.HostDevice_DrvMemcpy3DAsync(true); - } else { - SUCCEED("skipped testcase as Device count is < 2"); - } -} - - -/* This testcase verifies Host to Array copy in device context -change scenario for hipDrvMemcpy3DAsync API */ -TEST_CASE("Unit_hipDrvMemcpy3DAsync_Host2ArrayDeviceContextChange") { - int numDevices = 0; - HIP_CHECK(hipGetDeviceCount(&numDevices)); - if (numDevices > 1) { - DrvMemcpy3DAsync memcpy3d(10, 10, 10, HIP_AD_FORMAT_FLOAT); - memcpy3d.HostArray_DrvMemcpy3DAsync(true); - } else { - SUCCEED("skipped testcase as Device count is < 2"); - } -} +#if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-235 + SECTION("Invalid stream") { + StreamGuard stream_guard(Streams::created); + HIP_CHECK(hipStreamDestroy(stream_guard.stream())); + HIP_CHECK_ERROR(DrvMemcpy3DWrapper(dst_ptr, dst_pos, src_ptr, src_pos, extent, kind, + stream_guard.stream()), + hipErrorContextIsDestroyed); + } #endif + }; + SECTION("Host to Device") { + LinearAllocGuard3D device_alloc(extent); + LinearAllocGuard host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.pitch() * device_alloc.height() * device_alloc.depth()); + NegativeTests(device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), + make_hipPitchedPtr(host_alloc.ptr(), device_alloc.pitch(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), extent, hipMemcpyHostToDevice); + } + SECTION("Device to Host") { + LinearAllocGuard3D device_alloc(extent); + LinearAllocGuard host_alloc( + LinearAllocs::hipHostMalloc, + device_alloc.pitch() * device_alloc.height() * device_alloc.depth()); + NegativeTests(make_hipPitchedPtr(host_alloc.ptr(), device_alloc.pitch(), device_alloc.width(), + device_alloc.height()), + make_hipPos(0, 0, 0), device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), extent, + hipMemcpyDeviceToHost); + } + + SECTION("Host to Host") { + LinearAllocGuard src_alloc(LinearAllocs::hipHostMalloc, + extent.width * extent.height * extent.depth); + LinearAllocGuard dst_alloc(LinearAllocs::hipHostMalloc, + extent.width * extent.height * extent.depth); + NegativeTests(make_hipPitchedPtr(dst_alloc.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), + make_hipPitchedPtr(src_alloc.ptr(), extent.width, extent.width, extent.height), + make_hipPos(0, 0, 0), extent, hipMemcpyHostToHost); + } + + SECTION("Device to Device") { + LinearAllocGuard3D src_alloc(extent); + LinearAllocGuard3D dst_alloc(extent); + NegativeTests(dst_alloc.pitched_ptr(), make_hipPos(0, 0, 0), src_alloc.pitched_ptr(), + make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice); + } +} \ No newline at end of file diff --git a/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3DAsync_old.cc b/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3DAsync_old.cc new file mode 100644 index 0000000000..9f81da6250 --- /dev/null +++ b/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3DAsync_old.cc @@ -0,0 +1,594 @@ +/* +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. +*/ +/* + * Test Scenarios + * 1. Verifying hipDrvMemcpy3DAsync API for H2A,A2A,A2H scenarios + * 2. Verifying hipDrvMemcpy3DAsync API for H2D,D2D,D2H scenarios + * 3. Verifying Negative Scenarios + * 4. Verifying Extent validation scenarios by passing 0 + * 5. Verifying hipDrvMemcpy3DAsync API by allocating Memory in + * one GPU and trigger hipDrvMemcpy3DAsync from peer GPU for + * H2D,D2D,D2H scenarios + * 6. Verifying hipDrvMemcpy3DAsync API by allocating Memory in + * one GPU and trigger hipDrvMemcpy3DAsync from peer GPU for + * H2A,A2A,A2H scenarios + * + * Scenarios 3 is temporarily excluded in AMD platform + * Scenario 5&6 are excluded in CUDA platform + */ + +#include "hip_test_common.hh" +#include "hip_test_checkers.hh" + +template +class DrvMemcpy3DAsync { + int width, height, depth; + unsigned int size; + hipArray_Format formatKind; + hiparray arr, arr1; + hipStream_t stream; + size_t pitch_D, pitch_E; + HIP_MEMCPY3D myparms; + hipDeviceptr_t D_m, E_m; + T* hData{nullptr}; + public: + DrvMemcpy3DAsync(int l_width, int l_height, int l_depth, + hipArray_Format l_format); + DrvMemcpy3DAsync() = delete; + void AllocateMemory(); + void SetDefaultData(); + void HostArray_DrvMemcpy3DAsync(bool device_context_change = false); + void HostDevice_DrvMemcpy3DAsync(bool device_context_change = false); + void Extent_Validation(); + void NegativeTests(); + void DeAllocateMemory(); +}; + +/* Intializes class variables */ +template +DrvMemcpy3DAsync::DrvMemcpy3DAsync(int l_width, int l_height, int l_depth, + hipArray_Format l_format) { + width = l_width; + height = l_height; + depth = l_depth; + formatKind = l_format; +} + +/* Allocating Memory */ +template +void DrvMemcpy3DAsync::AllocateMemory() { + size = width * height * depth * sizeof(T); + hData = reinterpret_cast(malloc(size)); + memset(hData, 0, size); + for (int i = 0; i < depth; i++) { + for (int j = 0; j < height; j++) { + for (int k = 0; k < width; k++) { + hData[i*width*height + j*width +k] = i*width*height + j*width + k; + } + } + } + HIP_CHECK(hipStreamCreate(&stream)); + HIP_CHECK(hipMallocPitch(reinterpret_cast(&D_m), + &pitch_D, width*sizeof(T), height)); + HIP_CHECK(hipMallocPitch(reinterpret_cast(&E_m), + &pitch_E, width*sizeof(T), height)); + HIP_ARRAY3D_DESCRIPTOR *desc; + desc = reinterpret_cast + (malloc(sizeof(HIP_ARRAY3D_DESCRIPTOR))); + desc->Format = formatKind; + desc->NumChannels = 1; + desc->Width = width; + desc->Height = height; + desc->Depth = depth; + desc->Flags = hipArrayDefault; + HIP_CHECK(hipArray3DCreate(&arr, desc)); + HIP_CHECK(hipArray3DCreate(&arr1, desc)); +} + +/* Setting the default data */ +template +void DrvMemcpy3DAsync::SetDefaultData() { + memset(&myparms, 0x0, sizeof(HIP_MEMCPY3D)); + myparms.srcXInBytes = 0; + myparms.srcY = 0; + myparms.srcZ = 0; + myparms.srcLOD = 0; + myparms.dstXInBytes = 0; + myparms.dstY = 0; + myparms.dstZ = 0; + myparms.dstLOD = 0; + myparms.WidthInBytes = width*sizeof(T); + myparms.Height = height; + myparms.Depth = depth; +} + +/* +This function verifies the negative scenarios of +hipDrvMemcpy3DAsync API +*/ +template +void DrvMemcpy3DAsync::NegativeTests() { + HIP_CHECK(hipSetDevice(0)); + AllocateMemory(); + SetDefaultData(); + int deviceId; + HIP_CHECK(hipGetDevice(&deviceId)); + unsigned int MaxPitch; + HIP_CHECK(hipDeviceGetAttribute(reinterpret_cast(&MaxPitch), + hipDeviceAttributeMaxPitch, deviceId)); + myparms.srcHost = hData; + myparms.dstArray = arr; + myparms.srcPitch = width * sizeof(T); + myparms.srcHeight = height; +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_HOST; + myparms.dstMemoryType = CU_MEMORYTYPE_ARRAY; +#else + myparms.srcMemoryType = hipMemoryTypeHost; + myparms.dstMemoryType = hipMemoryTypeArray; +#endif + + SECTION("Passing nullptr to Source Host") { + myparms.srcHost = nullptr; + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing both dst host and device") { + myparms.dstHost = hData; + myparms.dstArray = nullptr; + myparms.dstDevice = D_m; + myparms.WidthInBytes = pitch_D; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing max value to WidthInBytes") { + myparms.WidthInBytes = std::numeric_limits::max(); + myparms.Height = std::numeric_limits::max(); + myparms.Depth = std::numeric_limits::max(); + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing width > max width size") { + myparms.WidthInBytes = width*sizeof(T) + 1; + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing height > max height size") { + myparms.Height = height + 1; + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Passing depth > max depth size") { + myparms.Depth = depth + 1; + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("widthinbytes + srcXinBytes is out of bound") { + myparms.srcXInBytes = 1; + myparms.dstArray = nullptr; + myparms.dstDevice = hipDeviceptr_t(D_m); + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("widthinbytes + dstXinBytes is out of bound") { + myparms.dstXInBytes = pitch_D; + myparms.dstArray = nullptr; + myparms.dstDevice = hipDeviceptr_t(D_m); + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("srcY + height is out of bound") { + myparms.srcY = 1; + myparms.dstArray = nullptr; + myparms.dstDevice = hipDeviceptr_t(D_m); + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("dstY + height out of bounds") { + myparms.dstY = 1; + myparms.dstArray = nullptr; + myparms.dstDevice = hipDeviceptr_t(D_m); + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("src pitch greater than Max allowed pitch") { +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_DEVICE; + myparms.dstMemoryType = CU_MEMORYTYPE_HOST; +#else + myparms.srcMemoryType = hipMemoryTypeDevice; + myparms.dstMemoryType = hipMemoryTypeHost; +#endif + myparms.srcDevice = D_m; + myparms.srcHost = nullptr; + myparms.srcPitch = MaxPitch; + myparms.srcHeight = height; + myparms.dstHost = hData; + myparms.dstArray = nullptr; + myparms.dstPitch = width*sizeof(T); + myparms.dstHeight = height; + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("dst pitch greater than Max allowed pitch") { + myparms.dstDevice = hipDeviceptr_t(D_m); + myparms.dstArray = nullptr; + myparms.dstPitch = MaxPitch+1; + myparms.dstHeight = height; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Nullptr to src/dst device") { + myparms.dstDevice = hipDeviceptr_t(nullptr); + myparms.dstArray = nullptr; + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Nullptr to src/dst array") { + myparms.dstArray = nullptr; + REQUIRE(hipDrvMemcpy3DAsync(&myparms, stream) != hipSuccess); + } + + SECTION("Nullptr to hipDrvMemcpy3DAsync") { + REQUIRE(hipDrvMemcpy3DAsync(nullptr, stream) != hipSuccess); + } + + DeAllocateMemory(); +} +/* +This function verifies the Extent validation scenarios of +hipDrvMemcpy3DAsync API +*/ +template +void DrvMemcpy3DAsync::Extent_Validation() { + HIP_CHECK(hipSetDevice(0)); + // Allocating the memory + AllocateMemory(); + + // Setting default data + SetDefaultData(); +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_HOST; + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.srcMemoryType = hipMemoryTypeHost; + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + myparms.srcHost = hData; + myparms.srcPitch = width * sizeof(T); + myparms.srcHeight = height; + myparms.dstDevice = D_m; + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; + + SECTION("WidthInBytes is 0") { + myparms.WidthInBytes = 0; + HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); + HIP_CHECK(hipStreamSynchronize(stream)); + } + + SECTION("Height is 0") { + myparms.Height = 0; + HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); + HIP_CHECK(hipStreamSynchronize(stream)); + } + + SECTION("Depth is 0") { + myparms.Depth = 0; + HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); + HIP_CHECK(hipStreamSynchronize(stream)); + } + + DeAllocateMemory(); +} +/* +This Function verifies following functionalities of hipDrvMemcpy3DAsync API +1. Host to Device copy +2. Device to Device +3. Device to Host +In the end validates the results. + +This functionality is verified in 2 scenarios +1. Basic scenario on same GPU device +2. Device context change scenario where memory is allocated in 1 GPU + and hipDrvMemcpy3DAsync API is trigerred from another GPU +*/ +template +void DrvMemcpy3DAsync::HostDevice_DrvMemcpy3DAsync + (bool device_context_change) { + HIP_CHECK(hipSetDevice(0)); + bool skip_test = false; + int peerAccess = 0; + AllocateMemory(); + if (device_context_change) { + HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); + if (!peerAccess) { + WARN("skipped the testcase as no peer access"); + skip_test = true; + } else { + HIP_CHECK(hipSetDevice(1)); + } + } + if (!skip_test) { + SetDefaultData(); +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_HOST; + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.srcMemoryType = hipMemoryTypeHost; + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + myparms.srcHost = hData; + myparms.srcPitch = width * sizeof(T); + myparms.srcHeight = height; + myparms.dstDevice = hipDeviceptr_t(D_m); + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; + HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); + HIP_CHECK(hipStreamSynchronize(stream)); + + // Device to Device + SetDefaultData(); +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_DEVICE; + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.srcMemoryType = hipMemoryTypeDevice; + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + myparms.srcDevice = hipDeviceptr_t(D_m); + myparms.srcPitch = pitch_D; + myparms.srcHeight = height; + myparms.dstDevice = hipDeviceptr_t(E_m); + myparms.dstPitch = pitch_E; + myparms.dstHeight = height; + HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); + HIP_CHECK(hipStreamSynchronize(stream)); + T *hOutputData = reinterpret_cast(malloc(size)); + memset(hOutputData, 0, size); + + // Device to host + SetDefaultData(); +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_DEVICE; + myparms.dstMemoryType = CU_MEMORYTYPE_HOST; +#else + myparms.srcMemoryType = hipMemoryTypeDevice; + myparms.dstMemoryType = hipMemoryTypeHost; +#endif + myparms.srcDevice = hipDeviceptr_t(E_m); + myparms.srcPitch = pitch_E; + myparms.srcHeight = height; + myparms.dstHost = hOutputData; + myparms.dstPitch = width * sizeof(T); + myparms.dstHeight = height; + HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); + HIP_CHECK(hipStreamSynchronize(stream)); + + HipTest::checkArray(hData, hOutputData, width, height, depth); + free(hOutputData); + } + DeAllocateMemory(); +} + +/* +This Function verifies following functionalities of hipDrvMemcpy3DAsync API +1. Host to Array copy +2. Array to Array +3. Array to Host +In the end validates the results. + +This functionality is verified in 2 scenarios +1. Basic scenario on same GPU device +2. Device context change scenario where memory is allocated in 1 GPU + and hipDrvMemcpy3DAsync API is trigerred from another GPU +*/ +template +void DrvMemcpy3DAsync::HostArray_DrvMemcpy3DAsync + (bool device_context_change) { + HIP_CHECK(hipSetDevice(0)); + bool skip_test = false; + int peerAccess = 0; + AllocateMemory(); + if (device_context_change) { + HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); + if (!peerAccess) { + WARN("skipped the testcase as no peer access"); + skip_test = true; + } else { + HIP_CHECK(hipSetDevice(1)); + } + } + if (!skip_test) { + SetDefaultData(); +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_HOST; + myparms.dstMemoryType = CU_MEMORYTYPE_ARRAY; +#else + myparms.srcMemoryType = hipMemoryTypeHost; + myparms.dstMemoryType = hipMemoryTypeArray; +#endif + myparms.srcHost = hData; + myparms.srcPitch = width * sizeof(T); + myparms.srcHeight = height; + myparms.dstArray = arr; + HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); + HIP_CHECK(hipStreamSynchronize(stream)); + // Array to Array + SetDefaultData(); +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_ARRAY; + myparms.dstMemoryType = CU_MEMORYTYPE_ARRAY; +#else + myparms.srcMemoryType = hipMemoryTypeArray; + myparms.dstMemoryType = hipMemoryTypeArray; +#endif + myparms.srcArray = arr; + myparms.dstArray = arr1; + HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); + HIP_CHECK(hipStreamSynchronize(stream)); + T *hOutputData = reinterpret_cast(malloc(size)); + memset(hOutputData, 0, size); + SetDefaultData(); + // Device to host +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_ARRAY; + myparms.dstMemoryType = CU_MEMORYTYPE_HOST; +#else + myparms.srcMemoryType = hipMemoryTypeArray; + myparms.dstMemoryType = hipMemoryTypeHost; +#endif + myparms.srcArray = arr1; + myparms.dstHost = hOutputData; + myparms.dstPitch = width * sizeof(T); + myparms.dstHeight = height; + HIP_CHECK(hipDrvMemcpy3DAsync(&myparms, stream)); + HIP_CHECK(hipStreamSynchronize(stream)); + + HipTest::checkArray(hData, hOutputData, width, height, depth); + free(hOutputData); + } + DeAllocateMemory(); +} + +/* DeAllocating the memory */ +template +void DrvMemcpy3DAsync::DeAllocateMemory() { + HIP_CHECK(hipArrayDestroy(arr)); + HIP_CHECK(hipArrayDestroy(arr1)); + HIP_CHECK(hipStreamDestroy(stream)); + free(hData); +} + +/* Verifying hipDrvMemcpy3DAsync API Host to Array for different datatypes */ +TEMPLATE_TEST_CASE("Unit_hipDrvMemcpy3DAsync_MultipleDataTypes", "", + uint8_t, int, float) { + for (int i = 1; i < 25; i++) { + if (std::is_same::value) { + DrvMemcpy3DAsync memcpy3d_float(i, i, i, + HIP_AD_FORMAT_FLOAT); + memcpy3d_float.HostArray_DrvMemcpy3DAsync(); + } else if (std::is_same::value) { + DrvMemcpy3DAsync memcpy3d_intx(i, i, i, + HIP_AD_FORMAT_UNSIGNED_INT8); + memcpy3d_intx.HostArray_DrvMemcpy3DAsync(); + } else if (std::is_same::value) { + DrvMemcpy3DAsync memcpy3d_inty(i, i, i, + HIP_AD_FORMAT_SIGNED_INT32); + memcpy3d_inty.HostArray_DrvMemcpy3DAsync(); + } + } +} + +/* This testcase verifies H2D copy of hipDrvMemcpy3DAsync API */ +TEST_CASE("Unit_hipDrvMemcpy3DAsync_HosttoDevice") { + DrvMemcpy3DAsync memcpy3d_D2H_float(10, 10, 1, HIP_AD_FORMAT_FLOAT); + memcpy3d_D2H_float.HostDevice_DrvMemcpy3DAsync(); +} + +/* This testcase verifies negative scenarios of hipDrvMemcpy3DAsync API */ +#if HT_NVIDIA +TEST_CASE("Unit_hipDrvMemcpy3DAsync_Negative") { + DrvMemcpy3DAsync memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); + memcpy3d.NegativeTests(); +} +#endif + +/* This testcase verifies extent validation scenarios of + hipDrvMemcpy3DAsync API */ +TEST_CASE("Unit_hipDrvMemcpy3DAsync_ExtentValidation") { + DrvMemcpy3DAsync memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); + memcpy3d.Extent_Validation(); +} + +/* This testcase verifies H2D copy in device context +change scenario for hipDrvMemcpy3DAsync API */ +#if HT_AMD +TEST_CASE("Unit_hipDrvMemcpy3DAsync_H2DDeviceContextChange") { + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + if (numDevices > 1) { + DrvMemcpy3DAsync memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); + memcpy3d.HostDevice_DrvMemcpy3DAsync(true); + } else { + SUCCEED("skipped testcase as Device count is < 2"); + } +} + + +/* This testcase verifies Host to Array copy in device context +change scenario for hipDrvMemcpy3DAsync API */ +TEST_CASE("Unit_hipDrvMemcpy3DAsync_Host2ArrayDeviceContextChange") { + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + if (numDevices > 1) { + DrvMemcpy3DAsync memcpy3d(10, 10, 10, HIP_AD_FORMAT_FLOAT); + memcpy3d.HostArray_DrvMemcpy3DAsync(true); + } else { + SUCCEED("skipped testcase as Device count is < 2"); + } +} +#endif + + diff --git a/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3D_old.cc b/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3D_old.cc new file mode 100644 index 0000000000..0b524655a9 --- /dev/null +++ b/projects/hip-tests/catch/unit/memory/hipDrvMemcpy3D_old.cc @@ -0,0 +1,573 @@ +/* +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. +*/ +/* + * Test Scenarios + * 1. Verifying hipDrvMemcpy3D API for H2A,A2A,A2H scenarios + * 2. Verifying hipDrvMemcpy3D API for H2D,D2D,D2H scenarios + * 3. Verifying Negative Scenarios + * 4. Verifying Extent validation scenarios by passing 0 + * 5. Verifying hipDrvMemcpy3D API by allocating Memory in + * one GPU and trigger hipDrvMemcpy3D from peer GPU for + * H2D,D2D,D2H scenarios + * 6. Verifying hipDrvMemcpy3D API by allocating Memory in + * one GPU and trigger hipDrvMemcpy3D from peer GPU for + * H2A,A2A,A2H scenarios + * + * Scenarios 3 is temporarily suspended on AMD + * Scenario 5&6 are not supported in CUDA platform + */ + +#include "hip_test_common.hh" +#include "hip_test_checkers.hh" + +template +class DrvMemcpy3D { + int width, height, depth; + unsigned int size; + hipArray_Format formatKind; + hiparray arr, arr1; + size_t pitch_D, pitch_E; + HIP_MEMCPY3D myparms; + hipDeviceptr_t D_m, E_m; + T* hData{nullptr}; + public: + DrvMemcpy3D(int l_width, int l_height, int l_depth, + hipArray_Format l_format); + DrvMemcpy3D() = delete; + void AllocateMemory(); + void SetDefaultData(); + void HostArray_DrvMemcpy3D(bool device_context_change = false); + void HostDevice_DrvMemcpy3D(bool device_context_change = false); + void Extent_Validation(); + void NegativeTests(); + void DeAllocateMemory(); +}; + +/* Intializes class variables */ +template +DrvMemcpy3D::DrvMemcpy3D(int l_width, int l_height, int l_depth, + hipArray_Format l_format) { + width = l_width; + height = l_height; + depth = l_depth; + formatKind = l_format; +} + +/* Allocating Memory */ +template +void DrvMemcpy3D::AllocateMemory() { + size = width * height * depth * sizeof(T); + hData = reinterpret_cast(malloc(size)); + memset(hData, 0, size); + for (int i = 0; i < depth; i++) { + for (int j = 0; j < height; j++) { + for (int k = 0; k < width; k++) { + hData[i*width*height + j*width +k] = i*width*height + j*width + k; + } + } + } + HIP_CHECK(hipMallocPitch(reinterpret_cast(&D_m), + &pitch_D, width*sizeof(T), height)); + HIP_CHECK(hipMallocPitch(reinterpret_cast(&E_m), + &pitch_E, width*sizeof(T), height)); + HIP_ARRAY3D_DESCRIPTOR *desc; + desc = reinterpret_cast + (malloc(sizeof(HIP_ARRAY3D_DESCRIPTOR))); + desc->Format = formatKind; + desc->NumChannels = 1; + desc->Width = width; + desc->Height = height; + desc->Depth = depth; + desc->Flags = hipArrayDefault; + HIP_CHECK(hipArray3DCreate(&arr, desc)); + HIP_CHECK(hipArray3DCreate(&arr1, desc)); +} + +/* Setting the default data */ +template +void DrvMemcpy3D::SetDefaultData() { + memset(&myparms, 0x0, sizeof(HIP_MEMCPY3D)); + myparms.srcXInBytes = 0; + myparms.srcY = 0; + myparms.srcZ = 0; + myparms.srcLOD = 0; + myparms.dstXInBytes = 0; + myparms.dstY = 0; + myparms.dstZ = 0; + myparms.dstLOD = 0; + myparms.WidthInBytes = width*sizeof(T); + myparms.Height = height; + myparms.Depth = depth; +} + +/* +This function verifies the negative scenarios of +hipDrvMemcpy3D API +*/ +template +void DrvMemcpy3D::NegativeTests() { + HIP_CHECK(hipSetDevice(0)); + AllocateMemory(); + SetDefaultData(); + int deviceId; + HIP_CHECK(hipGetDevice(&deviceId)); + unsigned int MaxPitch; + HIP_CHECK(hipDeviceGetAttribute(reinterpret_cast(&MaxPitch), + hipDeviceAttributeMaxPitch, deviceId)); + myparms.srcHost = hData; + myparms.dstArray = arr; + myparms.srcPitch = width * sizeof(T); + myparms.srcHeight = height; +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_HOST; + myparms.dstMemoryType = CU_MEMORYTYPE_ARRAY; +#else + myparms.srcMemoryType = hipMemoryTypeHost; + myparms.dstMemoryType = hipMemoryTypeArray; +#endif + + SECTION("Passing nullptr to Source Host") { + myparms.srcHost = nullptr; + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing both dst host and device") { + myparms.dstHost = hData; + myparms.dstArray = nullptr; + myparms.dstDevice = D_m; + myparms.WidthInBytes = pitch_D; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing max value to WidthInBytes") { + myparms.WidthInBytes = std::numeric_limits::max(); + myparms.Height = std::numeric_limits::max(); + myparms.Depth = std::numeric_limits::max(); + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing width > max width size") { + myparms.WidthInBytes = width*sizeof(T) + 1; + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing height > max height size") { + myparms.Height = height + 1; + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Passing depth > max depth size") { + myparms.Depth = depth + 1; + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("widthinbytes + srcXinBytes is out of bound") { + myparms.srcXInBytes = 1; + myparms.dstArray = nullptr; + myparms.dstDevice = hipDeviceptr_t(D_m); + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("widthinbytes + dstXinBytes is out of bound") { + myparms.dstXInBytes = pitch_D; + myparms.dstArray = nullptr; + myparms.dstDevice = hipDeviceptr_t(D_m); + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("srcY + height is out of bound") { + myparms.srcY = 1; + myparms.dstArray = nullptr; + myparms.dstDevice = hipDeviceptr_t(D_m); + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("dstY + height out of bounds") { + myparms.dstY = 1; + myparms.dstArray = nullptr; + myparms.dstDevice = hipDeviceptr_t(D_m); + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("src pitch greater than Max allowed pitch") { +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_DEVICE; + myparms.dstMemoryType = CU_MEMORYTYPE_HOST; +#else + myparms.srcMemoryType = hipMemoryTypeDevice; + myparms.dstMemoryType = hipMemoryTypeHost; +#endif + myparms.srcDevice = D_m; + myparms.srcHost = nullptr; + myparms.srcPitch = MaxPitch; + myparms.srcHeight = height; + myparms.dstHost = hData; + myparms.dstArray = nullptr; + myparms.dstPitch = width*sizeof(T); + myparms.dstHeight = height; + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("dst pitch greater than Max allowed pitch") { + myparms.dstDevice = hipDeviceptr_t(D_m); + myparms.dstArray = nullptr; + myparms.dstPitch = MaxPitch+1; + myparms.dstHeight = height; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Nullptr to src/dst device") { + myparms.dstDevice = hipDeviceptr_t(nullptr); + myparms.dstArray = nullptr; + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; +#if HT_NVIDIA + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Nullptr to src/dst array") { + myparms.dstArray = nullptr; + REQUIRE(hipDrvMemcpy3D(&myparms) != hipSuccess); + } + + SECTION("Nullptr to hipDrvMemcpy3D") { + REQUIRE(hipDrvMemcpy3D(nullptr) != hipSuccess); + } + + DeAllocateMemory(); +} +/* +This function verifies the Extent validation scenarios of +hipDrvMemcpy3D API +*/ +template +void DrvMemcpy3D::Extent_Validation() { + HIP_CHECK(hipSetDevice(0)); + // Allocating the memory + AllocateMemory(); + + // Setting default data + SetDefaultData(); +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_HOST; + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.srcMemoryType = hipMemoryTypeHost; + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + myparms.srcHost = hData; + myparms.srcPitch = width * sizeof(T); + myparms.srcHeight = height; + myparms.dstDevice = D_m; + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; + + SECTION("WidthInBytes is 0") { + myparms.WidthInBytes = 0; + HIP_CHECK(hipDrvMemcpy3D(&myparms)); + } + + SECTION("Height is 0") { + myparms.Height = 0; + HIP_CHECK(hipDrvMemcpy3D(&myparms)); + } + + SECTION("Depth is 0") { + myparms.Depth = 0; + HIP_CHECK(hipDrvMemcpy3D(&myparms)); + } + + DeAllocateMemory(); +} +/* +This Function verifies following functionalities of hipDrvMemcpy3D API +1. Host to Device copy +2. Device to Device +3. Device to Host +In the end validates the results. + +This functionality is verified in 2 scenarios +1. Basic scenario on same GPU device +2. Device context change scenario where memory is allocated in 1 GPU + and hipDrvMemcpy3D API is trigerred from another GPU +*/ +template +void DrvMemcpy3D::HostDevice_DrvMemcpy3D(bool device_context_change) { + HIP_CHECK(hipSetDevice(0)); + bool skip_test = false; + int peerAccess = 0; + AllocateMemory(); + if (device_context_change) { + HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); + if (!peerAccess) { + WARN("skipped the testcase as no peer access"); + skip_test = true; + } else { + HIP_CHECK(hipSetDevice(1)); + } + } + if (!skip_test) { + SetDefaultData(); +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_HOST; + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.srcMemoryType = hipMemoryTypeHost; + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + myparms.srcHost = hData; + myparms.srcPitch = width * sizeof(T); + myparms.srcHeight = height; + myparms.dstDevice = hipDeviceptr_t(D_m); + myparms.dstPitch = pitch_D; + myparms.dstHeight = height; + HIP_CHECK(hipDrvMemcpy3D(&myparms)); + + // Device to Device + SetDefaultData(); +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_DEVICE; + myparms.dstMemoryType = CU_MEMORYTYPE_DEVICE; +#else + myparms.srcMemoryType = hipMemoryTypeDevice; + myparms.dstMemoryType = hipMemoryTypeDevice; +#endif + myparms.srcDevice = hipDeviceptr_t(D_m); + myparms.srcPitch = pitch_D; + myparms.srcHeight = height; + myparms.dstDevice = hipDeviceptr_t(E_m); + myparms.dstPitch = pitch_E; + myparms.dstHeight = height; + HIP_CHECK(hipDrvMemcpy3D(&myparms)); + T *hOutputData = reinterpret_cast(malloc(size)); + memset(hOutputData, 0, size); + + // Device to host + SetDefaultData(); +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_DEVICE; + myparms.dstMemoryType = CU_MEMORYTYPE_HOST; +#else + myparms.srcMemoryType = hipMemoryTypeDevice; + myparms.dstMemoryType = hipMemoryTypeHost; +#endif + myparms.srcDevice = hipDeviceptr_t(E_m); + myparms.srcPitch = pitch_E; + myparms.srcHeight = height; + myparms.dstHost = hOutputData; + myparms.dstPitch = width * sizeof(T); + myparms.dstHeight = height; + HIP_CHECK(hipDrvMemcpy3D(&myparms)); + + HipTest::checkArray(hData, hOutputData, width, height, depth); + free(hOutputData); + } + DeAllocateMemory(); +} + +/* +This Function verifies following functionalities of hipDrvMemcpy3D API +1. Host to Array copy +2. Array to Array +3. Array to Host +In the end validates the results. + +This functionality is verified in 2 scenarios +1. Basic scenario on same GPU device +2. Device context change scenario where memory is allocated in 1 GPU + and hipDrvMemcpy3D API is trigerred from another GPU +*/ +template +void DrvMemcpy3D::HostArray_DrvMemcpy3D(bool device_context_change) { + HIP_CHECK(hipSetDevice(0)); + bool skip_test = false; + int peerAccess = 0; + AllocateMemory(); + if (device_context_change) { + HIP_CHECK(hipDeviceCanAccessPeer(&peerAccess, 0, 1)); + if (!peerAccess) { + WARN("skipped the testcase as no peer access"); + skip_test = true; + } else { + HIP_CHECK(hipSetDevice(1)); + } + } + if (!skip_test) { + SetDefaultData(); +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_HOST; + myparms.dstMemoryType = CU_MEMORYTYPE_ARRAY; +#else + myparms.srcMemoryType = hipMemoryTypeHost; + myparms.dstMemoryType = hipMemoryTypeArray; +#endif + myparms.srcHost = hData; + myparms.srcPitch = width * sizeof(T); + myparms.srcHeight = height; + myparms.dstArray = arr; + HIP_CHECK(hipDrvMemcpy3D(&myparms)); + // Array to Array + SetDefaultData(); +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_ARRAY; + myparms.dstMemoryType = CU_MEMORYTYPE_ARRAY; +#else + myparms.srcMemoryType = hipMemoryTypeArray; + myparms.dstMemoryType = hipMemoryTypeArray; +#endif + myparms.srcArray = arr; + myparms.dstArray = arr1; + HIP_CHECK(hipDrvMemcpy3D(&myparms)); + T *hOutputData = reinterpret_cast(malloc(size)); + memset(hOutputData, 0, size); + SetDefaultData(); + // Device to host +#if HT_NVIDIA + myparms.srcMemoryType = CU_MEMORYTYPE_ARRAY; + myparms.dstMemoryType = CU_MEMORYTYPE_HOST; +#else + myparms.srcMemoryType = hipMemoryTypeArray; + myparms.dstMemoryType = hipMemoryTypeHost; +#endif + myparms.srcArray = arr1; + myparms.dstHost = hOutputData; + myparms.dstPitch = width * sizeof(T); + myparms.dstHeight = height; + HIP_CHECK(hipDrvMemcpy3D(&myparms)); + + HipTest::checkArray(hData, hOutputData, width, height, depth); + free(hOutputData); + } + DeAllocateMemory(); +} +/* DeAllocating the memory */ +template +void DrvMemcpy3D::DeAllocateMemory() { + HIP_CHECK(hipArrayDestroy(arr)); + HIP_CHECK(hipArrayDestroy(arr1)); + free(hData); +} + +/* Verifying hipDrvMemcpy3D API Host to Array for different datatypes */ +TEMPLATE_TEST_CASE("Unit_hipDrvMemcpy3D_MultipleDataTypes", "", + uint8_t, int, float) { + for (int i = 1; i < 25; i++) { + if (std::is_same::value) { + DrvMemcpy3D memcpy3d_float(i, i, i, HIP_AD_FORMAT_FLOAT); + memcpy3d_float.HostArray_DrvMemcpy3D(); + } else if (std::is_same::value) { + DrvMemcpy3D memcpy3d_intx(i, i, i, HIP_AD_FORMAT_UNSIGNED_INT8); + memcpy3d_intx.HostArray_DrvMemcpy3D(); + } else if (std::is_same::value) { + DrvMemcpy3D memcpy3d_inty(i, i, i, HIP_AD_FORMAT_SIGNED_INT32); + memcpy3d_inty.HostArray_DrvMemcpy3D(); + } + } +} + +/* This testcase verifies H2D copy of hipDrvMemcpy3D API */ +TEST_CASE("Unit_hipDrvMemcpy3D_HosttoDevice") { + DrvMemcpy3D memcpy3d_D2H_float(10, 10, 1, HIP_AD_FORMAT_FLOAT); + memcpy3d_D2H_float.HostDevice_DrvMemcpy3D(); +} + +/* This testcase verifies negative scenarios of hipDrvMemcpy3D API */ +#if HT_NVIDIA +TEST_CASE("Unit_hipDrvMemcpy3D_Negative") { + DrvMemcpy3D memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); + memcpy3d.NegativeTests(); +} +#endif + +/* This testcase verifies extent validation scenarios of hipDrvMemcpy3D API */ +TEST_CASE("Unit_hipDrvMemcpy3D_ExtentValidation") { + DrvMemcpy3D memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); + memcpy3d.Extent_Validation(); +} + +#if HT_AMD +/* This testcase verifies H2D copy in device context +change scenario for hipDrvMemcpy3D API */ +TEST_CASE("Unit_hipDrvMemcpy3D_H2DDeviceContextChange") { + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + if (numDevices > 1) { + DrvMemcpy3D memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); + memcpy3d.HostDevice_DrvMemcpy3D(true); + } else { + SUCCEED("skipped testcase as Device count is < 2"); + } +} + + +/* This testcase verifies Host to Array copy in device context +change scenario for hipDrvMemcpy3D API */ +TEST_CASE("Unit_hipDrvMemcpy3D_Host2ArrayDeviceContextChange") { + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + if (numDevices > 1) { + DrvMemcpy3D memcpy3d(10, 10, 1, HIP_AD_FORMAT_FLOAT); + memcpy3d.HostArray_DrvMemcpy3D(true); + } else { + SUCCEED("skipped testcase as Device count is < 2"); + } +} +#endif From 58afea607c54bc36befa2a41224b9d1cfa422a0d Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Wed, 28 Jun 2023 21:44:30 +0530 Subject: [PATCH 14/32] SWDEV-398174,SWDEV-398655,SWDEV-402054 - Fix runKernelForDuration() for Windows (#333) Change-Id: If0cb99aa66a132c8228fd0a6bb56fdf644a99eae [ROCm/hip-tests commit: a6ed21522de31cf8bb779ac1fb47845c6369311b] --- projects/hip-tests/catch/include/hip_test_common.hh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/projects/hip-tests/catch/include/hip_test_common.hh b/projects/hip-tests/catch/include/hip_test_common.hh index 7f9e859cd0..d4c44a813f 100644 --- a/projects/hip-tests/catch/include/hip_test_common.hh +++ b/projects/hip-tests/catch/include/hip_test_common.hh @@ -352,13 +352,13 @@ template <> struct MemTraits { namespace { -static __global__ void waitKernel(clock_t offset) { +static __global__ void waitKernel(size_t offset) { auto start = clock(); while ((clock() - start) < offset) { } } -static __global__ void waitKernel_gfx11(clock_t offset) { +static __global__ void waitKernel_gfx11(size_t offset) { #if HT_AMD auto start = wall_clock64(); while ((wall_clock64() - start) < offset) { @@ -374,8 +374,8 @@ static size_t findTicksPerSecond() { int device; HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); - clock_t devFreq = static_cast(prop.clockRate); // in kHz - clock_t clockTicksPerSecond = devFreq * 1000; + size_t devFreq = static_cast(prop.clockRate); // in kHz + size_t clockTicksPerSecond = devFreq * 1000; // init hipEvent_t start, stop; From 9f2135d1cf8e4cb5a971e7a10581496207f81149 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Wed, 28 Jun 2023 21:47:19 +0530 Subject: [PATCH 15/32] SWDEV-403766 - Pass exclusive flag. (#337) Change-Id: I83da5356b5874c3c4dc1f0e08d899079d5cfe385 [ROCm/hip-tests commit: 86b522692c2ba93221b9f2de83fab87d12de9c71] --- projects/hip-tests/catch/unit/device/hipDeviceReset.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/hip-tests/catch/unit/device/hipDeviceReset.cc b/projects/hip-tests/catch/unit/device/hipDeviceReset.cc index b65155db6f..6136a71a2b 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceReset.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceReset.cc @@ -69,7 +69,7 @@ TEST_CASE("Unit_hipDeviceReset_Positive_Basic") { : hipSharedMemBankSizeFourByte); REQUIRE((shared_mem_config_ret == hipSuccess || shared_mem_config_ret == hipErrorNotSupported)); - HIP_CHECK(hipSetDeviceFlags(flags_before ^ (1u << 2))); + HIP_CHECK(hipSetDeviceFlags(hipDeviceScheduleBlockingSync)); HIP_CHECK(hipDeviceReset()); @@ -134,7 +134,7 @@ TEST_CASE("Unit_hipDeviceReset_Positive_Threaded") { REQUIRE((shared_mem_config_ret == hipSuccess || shared_mem_config_ret == hipErrorNotSupported)); - HIP_CHECK(hipSetDeviceFlags(flags_before ^ (1u << 2))); + HIP_CHECK(hipSetDeviceFlags(hipDeviceScheduleBlockingSync)); std::thread([] { HIP_CHECK_THREAD(hipSetDevice(0)); From a120fa73947d5aba6ac5d498b5b6573150e035e1 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Wed, 28 Jun 2023 21:48:13 +0530 Subject: [PATCH 16/32] SWDEV-393746 - Fix for HIP-Sample tests failure 16, 17, 18,19 (#332) Change-Id: I088c1035f1f25e7a5cc65077ff0b8cd281fdaf55 [ROCm/hip-tests commit: 529d24573823db4006f9ce1b0db0a460c33e34bc] --- .../16_assembly_to_executable/Makefile | 12 ++++- .../16_assembly_to_executable/README.md | 34 +++++++++++-- .../17_llvm_ir_to_executable/Makefile | 20 +++++++- .../17_llvm_ir_to_executable/README.md | 49 +++++++++++++++++-- .../2_Cookbook/18_cmake_hip_device/README.md | 20 ++++++-- .../2_Cookbook/19_cmake_lang/README.md | 18 +++++-- 6 files changed, 131 insertions(+), 22 deletions(-) diff --git a/projects/hip-tests/samples/2_Cookbook/16_assembly_to_executable/Makefile b/projects/hip-tests/samples/2_Cookbook/16_assembly_to_executable/Makefile index 0a32aa2b9c..56917be6c3 100644 --- a/projects/hip-tests/samples/2_Cookbook/16_assembly_to_executable/Makefile +++ b/projects/hip-tests/samples/2_Cookbook/16_assembly_to_executable/Makefile @@ -47,6 +47,10 @@ GPU_ARCH2=gfx906 GPU_ARCH3=gfx908 GPU_ARCH4=gfx1010 GPU_ARCH5=gfx1030 +GPU_ARCH6=gfx1100 +GPU_ARCH7=gfx1101 +GPU_ARCH8=gfx1102 +GPU_ARCH9=gfx1103 .PHONY: test @@ -54,7 +58,7 @@ all: src_to_asm asm_to_exec src_to_asm: $(HIPCC) -c -S --cuda-host-only -target x86_64-linux-gnu -o $(SQ_HOST_ASM) $(SRCS) - $(HIPCC) -c -S --cuda-device-only --offload-arch=$(GPU_ARCH1) --offload-arch=$(GPU_ARCH2) --offload-arch=$(GPU_ARCH3) --offload-arch=$(GPU_ARCH4) --offload-arch=$(GPU_ARCH5) $(SRCS) + $(HIPCC) -c -S --cuda-device-only --offload-arch=$(GPU_ARCH1) --offload-arch=$(GPU_ARCH2) --offload-arch=$(GPU_ARCH3) --offload-arch=$(GPU_ARCH4) --offload-arch=$(GPU_ARCH5) --offload-arch=$(GPU_ARCH6) --offload-arch=$(GPU_ARCH7) --offload-arch=$(GPU_ARCH8) --offload-arch=$(GPU_ARCH9) $(SRCS) # You may modify the .s assembly files before the next step # By default, their names will be: @@ -73,7 +77,11 @@ asm_to_exec: $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH3) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH3).s -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH3).o $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH4) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH4).s -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH4).o $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH5) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH5).s -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH5).o - $(CLANG_OFFLOAD_BUNDLER) -type=o -bundle-align=4096 -targets=host-x86_64-unknown-linux,hip-amdgcn-amd-amdhsa-$(GPU_ARCH1),hip-amdgcn-amd-amdhsa-$(GPU_ARCH2),hip-amdgcn-amd-amdhsa-$(GPU_ARCH3),hip-amdgcn-amd-amdhsa-$(GPU_ARCH4),hip-amdgcn-amd-amdhsa-$(GPU_ARCH5) -inputs=/dev/null,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH1).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH2).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH3).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH4).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH5).o -outputs=$(SQ_DEVICE_HIPFB) + $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH6) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH6).s -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH6).o + $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH7) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH7).s -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH7).o + $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH8) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH8).s -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH8).o + $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH9) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH9).s -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH9).o + $(CLANG_OFFLOAD_BUNDLER) -type=o -bundle-align=4096 -targets=host-x86_64-unknown-linux,hip-amdgcn-amd-amdhsa-$(GPU_ARCH1),hip-amdgcn-amd-amdhsa-$(GPU_ARCH2),hip-amdgcn-amd-amdhsa-$(GPU_ARCH3),hip-amdgcn-amd-amdhsa-$(GPU_ARCH4),hip-amdgcn-amd-amdhsa-$(GPU_ARCH5),hip-amdgcn-amd-amdhsa-$(GPU_ARCH6),hip-amdgcn-amd-amdhsa-$(GPU_ARCH7),hip-amdgcn-amd-amdhsa-$(GPU_ARCH8),hip-amdgcn-amd-amdhsa-$(GPU_ARCH9) -inputs=/dev/null,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH1).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH2).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH3).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH4).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH5).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH6).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH7).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH8).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH9).o -outputs=$(SQ_DEVICE_HIPFB) $(LLVM_MC) $(MCIN_OBJ_GEN) -o $(SQ_DEVICE_OBJ) --filetype=obj $(HIPCC) $(SQ_HOST_OBJ) $(SQ_DEVICE_OBJ) -o $(SQ_ASM_EXE) diff --git a/projects/hip-tests/samples/2_Cookbook/16_assembly_to_executable/README.md b/projects/hip-tests/samples/2_Cookbook/16_assembly_to_executable/README.md index 6a2ce15a10..810a9c3064 100644 --- a/projects/hip-tests/samples/2_Cookbook/16_assembly_to_executable/README.md +++ b/projects/hip-tests/samples/2_Cookbook/16_assembly_to_executable/README.md @@ -9,12 +9,19 @@ This sample uses a previous HIP application sample, please see [0_Intro/square]( Using HIP flags `-c -S` will help generate the host x86_64 and the device AMDGCN assembly code when paired with `--cuda-host-only` and `--cuda-device-only` respectively. In this sample we use these commands: ``` /hip/bin/hipcc -c -S --cuda-host-only -target x86_64-linux-gnu -o square_host.s square.cpp -/hip/bin/hipcc -c -S --cuda-device-only --offload-arch=gfx900 --offload-arch=gfx906 square.cpp +/hip/bin/hipcc -c -S --cuda-device-only --offload-arch=gfx900 --offload-arch=gfx906 --offload-arch=gfx908 --offload-arch=gfx1010 --offload-arch=gfx1030 --offload-arch=gfx1100 --offload-arch=gfx1101 --offload-arch=gfx1102 --offload-arch=gfx1103 square.cpp ``` The device assembly will be output into two separate files: - square-hip-amdgcn-amd-amdhsa-gfx900.s - square-hip-amdgcn-amd-amdhsa-gfx906.s +- square-hip-amdgcn-amd-amdhsa-gfx908.s +- square-hip-amdgcn-amd-amdhsa-gfx1010.s +- square-hip-amdgcn-amd-amdhsa-gfx1030.s +- square-hip-amdgcn-amd-amdhsa-gfx1100.s +- square-hip-amdgcn-amd-amdhsa-gfx1101.s +- square-hip-amdgcn-amd-amdhsa-gfx1102.s +- square-hip-amdgcn-amd-amdhsa-gfx1103.s You may modify `--offload-arch` flag to build other archs and choose to enable or disable xnack and sram-ecc. @@ -30,7 +37,14 @@ However, the device assembly code will require a few extra steps. The device ass ``` /hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx900 square-hip-amdgcn-amd-amdhsa-gfx900.s -o square-hip-amdgcn-amd-amdhsa-gfx900.o /hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx906 square-hip-amdgcn-amd-amdhsa-gfx906.s -o square-hip-amdgcn-amd-amdhsa-gfx906.o -/llvm/bin/clang-offload-bundler -type=o -bundle-align=4096 -targets=host-x86_64-unknown-linux,hip-amdgcn-amd-amdhsa-gfx900,hip-amdgcn-amd-amdhsa-gfx906 -inputs=/dev/null,square-hip-amdgcn-amd-amdhsa-gfx900.o,square-hip-amdgcn-amd-amdhsa-gfx906.o -outputs=offload_bundle.hipfb +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx908 square-hip-amdgcn-amd-amdhsa-gfx908.s -o square-hip-amdgcn-amd-amdhsa-gfx908.o +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx1010 square-hip-amdgcn-amd-amdhsa-gfx1010.s -o square-hip-amdgcn-amd-amdhsa-gfx1010.o +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx1030 square-hip-amdgcn-amd-amdhsa-gfx1030.s -o square-hip-amdgcn-amd-amdhsa-gfx1030.o +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx1100 square-hip-amdgcn-amd-amdhsa-gfx1100.s -o square-hip-amdgcn-amd-amdhsa-gfx1100.o +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx1101 square-hip-amdgcn-amd-amdhsa-gfx1101.s -o square-hip-amdgcn-amd-amdhsa-gfx1101.o +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx1102 square-hip-amdgcn-amd-amdhsa-gfx1102.s -o square-hip-amdgcn-amd-amdhsa-gfx1102.o +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx1103 square-hip-amdgcn-amd-amdhsa-gfx1103.s -o square-hip-amdgcn-amd-amdhsa-gfx1103.o +/llvm/bin/clang-offload-bundler -type=o -bundle-align=4096 -targets=host-x86_64-unknown-linux,hip-amdgcn-amd-amdhsa-gfx900,hip-amdgcn-amd-amdhsa-gfx906,hip-amdgcn-amd-amdhsa-gfx908,hip-amdgcn-amd-amdhsa-gfx1010,hip-amdgcn-amd-amdhsa-gfx1030,hip-amdgcn-amd-amdhsa-gfx1100,hip-amdgcn-amd-amdhsa-gfx1101,hip-amdgcn-amd-amdhsa-gfx1102,hip-amdgcn-amd-amdhsa-gfx1103 -inputs=/dev/null,square-hip-amdgcn-amd-amdhsa-gfx900.o,square-hip-amdgcn-amd-amdhsa-gfx906.o,square-hip-amdgcn-amd-amdhsa-gfx908.o,square-hip-amdgcn-amd-amdhsa-gfx1010.o,square-hip-amdgcn-amd-amdhsa-gfx1030.o,square-hip-amdgcn-amd-amdhsa-gfx1100.o,square-hip-amdgcn-amd-amdhsa-gfx1101.o,square-hip-amdgcn-amd-amdhsa-gfx1102.o,square-hip-amdgcn-amd-amdhsa-gfx1103.o -outputs=offload_bundle.hipfb /llvm/bin/llvm-mc -triple x86_64-unknown-linux-gnu hip_obj_gen.mcin -o square_device.o --filetype=obj ``` @@ -40,14 +54,24 @@ Finally, using the system linker, hipcc, or clang, link the host and device obje ``` /hip/bin/hipcc square_host.o square_device.o -o square_asm.out ``` -If you haven't modified the GPU archs, this executable should run on both `gfx900` and `gfx906`. ## How to build and run this sample: Use these make commands to compile into assembly, compile assembly into executable, and execute it. - To compile the HIP application into host and device assembly: `make src_to_asm`. - To compile the assembly files into an executable: `make asm_to_exec`. -- To execute, run `./square_asm.out`. +- To execute, run +``` +./square_asm.out +info: running on device AMD Radeon Graphics +info: allocate host mem ( 7.63 MB) +info: allocate device mem ( 7.63 MB) +info: copy Host2Device +info: launch 'vector_square' kernel +info: copy Device2Host +info: check result +PASSED! +``` -**Note:** The default arch is `gfx900` and `gfx906`, this can be modified with make argument `GPU_ARCH1` and `GPU_ARCH2`. +**Note:** Currently, defined arch is `gfx900`, `gfx906`, `gfx908`, `gfx1010`,`gfx1030`,`gfx1100`,`gfx1101`,`gfx1102` and `gfx1103`. Any undefined arch can be modified with make argument `GPU_ARCHxx`. ## For More Information, please refer to the HIP FAQ. diff --git a/projects/hip-tests/samples/2_Cookbook/17_llvm_ir_to_executable/Makefile b/projects/hip-tests/samples/2_Cookbook/17_llvm_ir_to_executable/Makefile index d68304dcac..f9a334a56b 100644 --- a/projects/hip-tests/samples/2_Cookbook/17_llvm_ir_to_executable/Makefile +++ b/projects/hip-tests/samples/2_Cookbook/17_llvm_ir_to_executable/Makefile @@ -50,6 +50,10 @@ GPU_ARCH2=gfx906 GPU_ARCH3=gfx908 GPU_ARCH4=gfx1010 GPU_ARCH5=gfx1030 +GPU_ARCH6=gfx1100 +GPU_ARCH7=gfx1101 +GPU_ARCH8=gfx1102 +GPU_ARCH9=gfx1103 .PHONY: test @@ -57,7 +61,7 @@ all: src_to_ir bc_to_ll ll_to_bc ir_to_exec src_to_ir: $(HIPCC) -c -emit-llvm --cuda-host-only -target x86_64-linux-gnu -o $(SQ_HOST_BC) $(SRCS) - $(HIPCC) -c -emit-llvm --cuda-device-only --offload-arch=$(GPU_ARCH1) --offload-arch=$(GPU_ARCH2) --offload-arch=$(GPU_ARCH3) --offload-arch=$(GPU_ARCH4) --offload-arch=$(GPU_ARCH5) $(SRCS) + $(HIPCC) -c -emit-llvm --cuda-device-only --offload-arch=$(GPU_ARCH1) --offload-arch=$(GPU_ARCH2) --offload-arch=$(GPU_ARCH3) --offload-arch=$(GPU_ARCH4) --offload-arch=$(GPU_ARCH5) --offload-arch=$(GPU_ARCH6) --offload-arch=$(GPU_ARCH7) --offload-arch=$(GPU_ARCH8) --offload-arch=$(GPU_ARCH9) $(SRCS) # By default, the LLVM IR Bitcode file names will be: # square-hip-amdgcn-amd-amdhsa-gfx900.bc @@ -73,6 +77,10 @@ bc_to_ll: $(LLVM_DIS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH3).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH3).ll $(LLVM_DIS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH4).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH4).ll $(LLVM_DIS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH5).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH5).ll + $(LLVM_DIS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH6).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH6).ll + $(LLVM_DIS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH7).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH7).ll + $(LLVM_DIS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH8).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH8).ll + $(LLVM_DIS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH9).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH9).ll # You may modify the .ll LLVM IR files before the next step # @@ -85,6 +93,10 @@ ll_to_bc: $(LLVM_AS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH3).ll -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH3).bc $(LLVM_AS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH4).ll -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH4).bc $(LLVM_AS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH5).ll -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH5).bc + $(LLVM_AS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH6).ll -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH6).bc + $(LLVM_AS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH7).ll -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH7).bc + $(LLVM_AS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH8).ll -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH8).bc + $(LLVM_AS) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH9).ll -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH9).bc ir_to_exec: $(HIPCC) -c $(SQ_HOST_BC) -o $(SQ_HOST_OBJ) @@ -93,7 +105,11 @@ ir_to_exec: $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH3) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH3).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH3).o $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH4) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH4).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH4).o $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH5) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH5).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH5).o - $(CLANG_OFFLOAD_BUNDLER) -type=o -bundle-align=4096 -targets=host-x86_64-unknown-linux,hip-amdgcn-amd-amdhsa-$(GPU_ARCH1),hip-amdgcn-amd-amdhsa-$(GPU_ARCH2),hip-amdgcn-amd-amdhsa-$(GPU_ARCH3),hip-amdgcn-amd-amdhsa-$(GPU_ARCH4),hip-amdgcn-amd-amdhsa-$(GPU_ARCH5) -inputs=/dev/null,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH1).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH2).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH3).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH4).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH5).o -outputs=$(SQ_DEVICE_HIPFB) + $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH6) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH6).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH6).o + $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH7) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH7).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH7).o + $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH8) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH8).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH8).o + $(CLANG) -target amdgcn-amd-amdhsa -mcpu=$(GPU_ARCH9) square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH9).bc -o square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH9).o + $(CLANG_OFFLOAD_BUNDLER) -type=o -bundle-align=4096 -targets=host-x86_64-unknown-linux,hip-amdgcn-amd-amdhsa-$(GPU_ARCH1),hip-amdgcn-amd-amdhsa-$(GPU_ARCH2),hip-amdgcn-amd-amdhsa-$(GPU_ARCH3),hip-amdgcn-amd-amdhsa-$(GPU_ARCH4),hip-amdgcn-amd-amdhsa-$(GPU_ARCH5),hip-amdgcn-amd-amdhsa-$(GPU_ARCH6),hip-amdgcn-amd-amdhsa-$(GPU_ARCH7),hip-amdgcn-amd-amdhsa-$(GPU_ARCH8),hip-amdgcn-amd-amdhsa-$(GPU_ARCH9) -inputs=/dev/null,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH1).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH2).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH3).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH4).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH5).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH6).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH7).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH8).o,square-hip-amdgcn-amd-amdhsa-$(GPU_ARCH9).o -outputs=$(SQ_DEVICE_HIPFB) $(LLVM_MC) $(MCIN_OBJ_GEN) -o $(SQ_DEVICE_OBJ) --filetype=obj $(HIPCC) $(SQ_HOST_OBJ) $(SQ_DEVICE_OBJ) -o $(SQ_IR_EXE) diff --git a/projects/hip-tests/samples/2_Cookbook/17_llvm_ir_to_executable/README.md b/projects/hip-tests/samples/2_Cookbook/17_llvm_ir_to_executable/README.md index 45cd0cb7df..e04b675392 100644 --- a/projects/hip-tests/samples/2_Cookbook/17_llvm_ir_to_executable/README.md +++ b/projects/hip-tests/samples/2_Cookbook/17_llvm_ir_to_executable/README.md @@ -9,11 +9,18 @@ This sample uses a previous HIP application sample, please see [0_Intro/square]( Using HIP flags `-c -emit-llvm` will help generate the host x86_64 and the device LLVM bitcode when paired with `--cuda-host-only` and `--cuda-device-only` respectively. In this sample we use these commands: ``` /hip/bin/hipcc -c -emit-llvm --cuda-host-only -target x86_64-linux-gnu -o square_host.bc square.cpp -/hip/bin/hipcc -c -emit-llvm --cuda-device-only --offload-arch=gfx900 --offload-arch=gfx906 square.cpp +/hip/bin/hipcc -c -emit-llvm --cuda-device-only --offload-arch=gfx900 --offload-arch=gfx906 --offload-arch=gfx908 --offload-arch=gfx1010 --offload-arch=gfx1030 --offload-arch=gfx1100 --offload-arch=gfx1101 --offload-arch=gfx1102 --offload-arch=gfx1103 square.cpp ``` The device LLVM IR bitcode will be output into two separate files: - square-hip-amdgcn-amd-amdhsa-gfx900.bc - square-hip-amdgcn-amd-amdhsa-gfx906.bc +- square-hip-amdgcn-amd-amdhsa-gfx908.bc +- square-hip-amdgcn-amd-amdhsa-gfx1010.bc +- square-hip-amdgcn-amd-amdhsa-gfx1030.bc +- square-hip-amdgcn-amd-amdhsa-gfx1100.bc +- square-hip-amdgcn-amd-amdhsa-gfx1101.bc +- square-hip-amdgcn-amd-amdhsa-gfx1102.bc +- square-hip-amdgcn-amd-amdhsa-gfx1103.bc You may modify `--offload-arch` flag to build other archs and choose to enable or disable xnack and sram-ecc. @@ -21,6 +28,13 @@ To transform the LLVM bitcode into human readable LLVM IR, use these commands: ``` /llvm/bin/llvm-dis square-hip-amdgcn-amd-amdhsa-gfx900.bc -o square-hip-amdgcn-amd-amdhsa-gfx900.ll /llvm/bin/llvm-dis square-hip-amdgcn-amd-amdhsa-gfx906.bc -o square-hip-amdgcn-amd-amdhsa-gfx906.ll +/llvm/bin/llvm-dis square-hip-amdgcn-amd-amdhsa-gfx908.bc -o square-hip-amdgcn-amd-amdhsa-gfx908.ll +/llvm/bin/llvm-dis square-hip-amdgcn-amd-amdhsa-gfx1010.bc -o square-hip-amdgcn-amd-amdhsa-gfx1010.ll +/llvm/bin/llvm-dis square-hip-amdgcn-amd-amdhsa-gfx1030.bc -o square-hip-amdgcn-amd-amdhsa-gfx1030.ll +/llvm/bin/llvm-dis square-hip-amdgcn-amd-amdhsa-gfx1100.bc -o square-hip-amdgcn-amd-amdhsa-gfx1100.ll +/llvm/bin/llvm-dis square-hip-amdgcn-amd-amdhsa-gfx1101.bc -o square-hip-amdgcn-amd-amdhsa-gfx1101.ll +/llvm/bin/llvm-dis square-hip-amdgcn-amd-amdhsa-gfx1102.bc -o square-hip-amdgcn-amd-amdhsa-gfx1102.ll +/llvm/bin/llvm-dis square-hip-amdgcn-amd-amdhsa-gfx1103.bc -o square-hip-amdgcn-amd-amdhsa-gfx1103.ll ``` **Warning:** We cannot ensure any compiler besides the ROCm hipcc and clang will be compatible with this process. Also, there is no guarantee that the starting IR produced with `-x cl` will run with HIP runtime. Experimenting with other compilers or starting IR will be the responsibility of the developer. @@ -41,9 +55,23 @@ However, the device IR will require a few extra steps. The device bitcodes needs ``` /hip/../llvm/bin/llvm-as square-hip-amdgcn-amd-amdhsa-gfx900.ll -o square-hip-amdgcn-amd-amdhsa-gfx900.bc /hip/../llvm/bin/llvm-as square-hip-amdgcn-amd-amdhsa-gfx906.ll -o square-hip-amdgcn-amd-amdhsa-gfx906.bc +/hip/../llvm/bin/llvm-as square-hip-amdgcn-amd-amdhsa-gfx908.ll -o square-hip-amdgcn-amd-amdhsa-gfx908.bc +/hip/../llvm/bin/llvm-as square-hip-amdgcn-amd-amdhsa-gfx1010.ll -o square-hip-amdgcn-amd-amdhsa-gfx1010.bc +/hip/../llvm/bin/llvm-as square-hip-amdgcn-amd-amdhsa-gfx1030.ll -o square-hip-amdgcn-amd-amdhsa-gfx1030.bc +/hip/../llvm/bin/llvm-as square-hip-amdgcn-amd-amdhsa-gfx1100.ll -o square-hip-amdgcn-amd-amdhsa-gfx1100.bc +/hip/../llvm/bin/llvm-as square-hip-amdgcn-amd-amdhsa-gfx1101.ll -o square-hip-amdgcn-amd-amdhsa-gfx1101.bc +/hip/../llvm/bin/llvm-as square-hip-amdgcn-amd-amdhsa-gfx1102.ll -o square-hip-amdgcn-amd-amdhsa-gfx1102.bc +/hip/../llvm/bin/llvm-as square-hip-amdgcn-amd-amdhsa-gfx1103.ll -o square-hip-amdgcn-amd-amdhsa-gfx1103.bc /hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx900 square-hip-amdgcn-amd-amdhsa-gfx900.bc -o square-hip-amdgcn-amd-amdhsa-gfx900.o /hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx906 square-hip-amdgcn-amd-amdhsa-gfx906.bc -o square-hip-amdgcn-amd-amdhsa-gfx906.o -/hip/../llvm/bin/clang-offload-bundler -type=o -bundle-align=4096 -targets=host-x86_64-unknown-linux,hip-amdgcn-amd-amdhsa-gfx900,hip-amdgcn-amd-amdhsa-gfx906 -inputs=/dev/null,square-hip-amdgcn-amd-amdhsa-gfx900.o,square-hip-amdgcn-amd-amdhsa-gfx906.o -outputs=offload_bundle.hipfb +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx908 square-hip-amdgcn-amd-amdhsa-gfx900.bc -o square-hip-amdgcn-amd-amdhsa-gfx908.o +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx1010 square-hip-amdgcn-amd-amdhsa-gfx906.bc -o square-hip-amdgcn-amd-amdhsa-gfx1010.o +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx1030 square-hip-amdgcn-amd-amdhsa-gfx900.bc -o square-hip-amdgcn-amd-amdhsa-gfx1030.o +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx1100 square-hip-amdgcn-amd-amdhsa-gfx906.bc -o square-hip-amdgcn-amd-amdhsa-gfx1100.o +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx1101 square-hip-amdgcn-amd-amdhsa-gfx900.bc -o square-hip-amdgcn-amd-amdhsa-gfx1101.o +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx1102 square-hip-amdgcn-amd-amdhsa-gfx906.bc -o square-hip-amdgcn-amd-amdhsa-gfx1102.o +/hip/../llvm/bin/clang -target amdgcn-amd-amdhsa -mcpu=gfx1103 square-hip-amdgcn-amd-amdhsa-gfx900.bc -o square-hip-amdgcn-amd-amdhsa-gfx1103.o +/hip/../llvm/bin/clang-offload-bundler -type=o -bundle-align=4096 -targets=host-x86_64-unknown-linux,hip-amdgcn-amd-amdhsa-gfx900,hip-amdgcn-amd-amdhsa-gfx906,hip-amdgcn-amd-amdhsa-gfx908,hip-amdgcn-amd-amdhsa-gfx1010,hip-amdgcn-amd-amdhsa-gfx1030,hip-amdgcn-amd-amdhsa-gfx1100,hip-amdgcn-amd-amdhsa-gfx1101,hip-amdgcn-amd-amdhsa-gfx1102,hip-amdgcn-amd-amdhsa-gfx1103 -inputs=/dev/null,square-hip-amdgcn-amd-amdhsa-gfx900.o,square-hip-amdgcn-amd-amdhsa-gfx906.o,square-hip-amdgcn-amd-amdhsa-gfx908.o,square-hip-amdgcn-amd-amdhsa-gfx1010.o,square-hip-amdgcn-amd-amdhsa-gfx1030.o,square-hip-amdgcn-amd-amdhsa-gfx1100.o,square-hip-amdgcn-amd-amdhsa-gfx1101.o,square-hip-amdgcn-amd-amdhsa-gfx1102.o,square-hip-amdgcn-amd-amdhsa-gfx1103.o -outputs=offload_bundle.hipfb /llvm/bin/llvm-mc hip_obj_gen.mcin -o square_device.o --filetype=obj ``` @@ -53,7 +81,7 @@ Finally, using the system linker, hipcc, or clang, link the host and device obje ``` /hip/bin/hipcc square_host.o square_device.o -o square_ir.out ``` -If you haven't modified the GPU archs, this executable should run on both `gfx900` and `gfx906`. +If you haven't modified the GPU archs, this executable should run on the defined `gfx900`, `gfx906`, `gfx908`, `gfx1010`, `gfx1030`, `gfx1100`, `gfx1101`, `gfx1102` and `gfx1103`. ## How to build and run this sample: Use these make commands to compile into LLVM IR, compile IR into executable, and execute it. @@ -61,8 +89,19 @@ Use these make commands to compile into LLVM IR, compile IR into executable, and - To disassembly the LLVM IR bitcode into human readable LLVM IR: `make bc_to_ll`. - To assembly the human readable LLVM IR bitcode back into LLVM IR bitcode: `make ll_to_bc`. - To compile the LLVM IR files into an executable: `make ir_to_exec`. -- To execute, run `./square_ir.out`. +- To execute, run +``` +./square_ir.out +info: running on device AMD Radeon Graphics +info: allocate host mem ( 7.63 MB) +info: allocate device mem ( 7.63 MB) +info: copy Host2Device +info: launch 'vector_square' kernel +info: copy Device2Host +info: check result +PASSED! +``` -**Note:** The default arch is `gfx900` and `gfx906`, this can be modified with make argument `GPU_ARCH1` and `GPU_ARCH2`. +**Note:** Any undefined arch can be modified with make argument `GPU_ARCHxx`. ## For More Information, please refer to the HIP FAQ. diff --git a/projects/hip-tests/samples/2_Cookbook/18_cmake_hip_device/README.md b/projects/hip-tests/samples/2_Cookbook/18_cmake_hip_device/README.md index d9e31d806e..5c4bb488d9 100644 --- a/projects/hip-tests/samples/2_Cookbook/18_cmake_hip_device/README.md +++ b/projects/hip-tests/samples/2_Cookbook/18_cmake_hip_device/README.md @@ -1,16 +1,28 @@ ### This will test linking hip::device interface in cmake I. Build + +``` mkdir -p build; cd build -rm -rf *; CXX=`hipconfig -l`/clang++ cmake .. +rm -rf *; +CXX="$(hipconfig -l)"/clang++ cmake -DCMAKE_PREFIX_PATH=/opt/rocm .. make +``` + +Note, users may need to add ADMGPU support as command line option, if test failed to run, for example, +``` +CXX="$(hipconfig -l)"/clang++ cmake -DCMAKE_PREFIX_PATH=/opt/rocm -DAMDGPU_TARGETS="gfx1102" .. +``` II. Test -$ ./test_cpp -info: running on device Vega 20 [Radeon Pro Vega 20] + +``` +$ ../test_cpp +info: running on device AMD Radeon Graphics info: allocate host mem ( 7.63 MB) info: allocate device mem ( 7.63 MB) info: copy Host2Device info: launch 'vector_square' kernel info: copy Device2Host info: check result -PASSED! \ No newline at end of file +PASSED! +``` diff --git a/projects/hip-tests/samples/2_Cookbook/19_cmake_lang/README.md b/projects/hip-tests/samples/2_Cookbook/19_cmake_lang/README.md index 5ba5ef98e8..284bec8655 100644 --- a/projects/hip-tests/samples/2_Cookbook/19_cmake_lang/README.md +++ b/projects/hip-tests/samples/2_Cookbook/19_cmake_lang/README.md @@ -7,14 +7,24 @@ I. Prepare sudo apt install gfortran II. Build +``` mkdir -p build; cd build -rm -rf *; CXX=`hipconfig -l`/clang++ FC=$(which gfortran) cmake .. +rm -rf *; +CXX="$(hipconfig -l)"/clang++ FC=$(which gfortran) cmake -DCMAKE_PREFIX_PATH=/opt/rocm .. +cmake .. make +``` +Note, users may need to add AMD GPU support, if test failed, for example, +``` +CXX="$(hipconfig -l)"/clang++ FC=$(which gfortran) cmake -DCMAKE_PREFIX_PATH=/opt/rocm -DAMDGPU_TARGETS="gfx1102" .. +``` III. Test -# ./test_fortran +``` +./test_fortran Succeeded testing Fortran! -# ./test_cpp -Device name Device 66a7 +./test_cpp +Device name AMD Radeon Graphics PASSED! +``` From 535c95c4847c2012681323b2269f3276381301b3 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Wed, 28 Jun 2023 21:59:03 +0530 Subject: [PATCH 17/32] SWDEV-393746 - Fix HIP sample failures-21, 22, 23 (#331) Change-Id: Id839cf24ba5f16897428b19c0299ea781a5a6d09 [ROCm/hip-tests commit: 90de01adb937189158d9ea3e5bce24ce891622d3] --- .../2_Cookbook/21_cmake_hip_cxx_clang/README.md | 12 ++++++++---- .../samples/2_Cookbook/22_cmake_hip_lang/README.md | 9 ++++++++- .../samples/2_Cookbook/23_cmake_hiprtc/README.md | 9 ++++++++- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/projects/hip-tests/samples/2_Cookbook/21_cmake_hip_cxx_clang/README.md b/projects/hip-tests/samples/2_Cookbook/21_cmake_hip_cxx_clang/README.md index 3d9765308c..a7d362a990 100644 --- a/projects/hip-tests/samples/2_Cookbook/21_cmake_hip_cxx_clang/README.md +++ b/projects/hip-tests/samples/2_Cookbook/21_cmake_hip_cxx_clang/README.md @@ -1,15 +1,18 @@ ### This sample tests CXX Language support with amdclang++ I. Build + +``` mkdir -p build; cd build rm -rf *; -CXX=`hipconfig -l`/amdclang++ cmake .. (or) -cmake -DCMAKE_CXX_COMPILER=/opt/rocm/bin/amdclang++ .. (or) -cmake -DCMAKE_CXX_COMPILER=/opt/rocm-X.Y.Z/llvm/bin/amdclang++ .. +CXX="$(hipconfig -l)"/amdclang++ cmake -DCMAKE_PREFIX_PATH=/opt/rocm .. make +``` II. Test + +``` $ ./square -info: running on device Vega 20 [Radeon Pro Vega 20] +info: running on device AMD Radeon Graphics info: allocate host mem ( 7.63 MB) info: allocate device mem ( 7.63 MB) info: copy Host2Device @@ -17,3 +20,4 @@ info: launch 'vector_square' kernel info: copy Device2Host info: check result PASSED! +``` diff --git a/projects/hip-tests/samples/2_Cookbook/22_cmake_hip_lang/README.md b/projects/hip-tests/samples/2_Cookbook/22_cmake_hip_lang/README.md index 7f7ac025b1..5ba33f8362 100644 --- a/projects/hip-tests/samples/2_Cookbook/22_cmake_hip_lang/README.md +++ b/projects/hip-tests/samples/2_Cookbook/22_cmake_hip_lang/README.md @@ -1,10 +1,16 @@ ### This will test HIP language support in upstream CMake I. Build + +``` mkdir -p build; cd build -rm -rf *; cmake -DCMAKE_PREFIX_PATH=/opt/rocm/ .. +rm -rf *; +cmake -DCMAKE_PREFIX_PATH=/opt/rocm .. make +``` II. Test + +``` $ ./square info: running on device info: allocate host mem ( 7.63 MB) @@ -14,3 +20,4 @@ info: launch 'vector_square' kernel info: copy Device2Host info: check result PASSED! +``` diff --git a/projects/hip-tests/samples/2_Cookbook/23_cmake_hiprtc/README.md b/projects/hip-tests/samples/2_Cookbook/23_cmake_hiprtc/README.md index 2831619d19..cb270e6466 100644 --- a/projects/hip-tests/samples/2_Cookbook/23_cmake_hiprtc/README.md +++ b/projects/hip-tests/samples/2_Cookbook/23_cmake_hiprtc/README.md @@ -1,9 +1,16 @@ ### This will test linking hiprtc::hiprtc interface in cmake I. Build + +``` mkdir -p build; cd build -rm -rf *; CXX=amdclang++ cmake -DCMAKE_PREFIX_PATH=/opt/rocm/hip .. +rm -rf *; +CXX="$(hipconfig -l)"/amdclang++ cmake -DCMAKE_PREFIX_PATH=/opt/rocm .. make +``` II. Test + +``` $ ./test SAXPY test completed +``` From 8862d9a8954720bed0319454ce25974a86337929 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 08:54:26 +0530 Subject: [PATCH 18/32] SWDEV-390849: Added new test cases for hipMemCpy with offset applied in src/dst pointers. (#263) Change-Id: I252ac08a8deb1e6f213e56bc92ed7ef4579f67c9 [ROCm/hip-tests commit: 8431248ca0d72b36c46c6dc1ea926e8f34e1079f] --- .../catch/unit/memory/hipMemcpy2D.cc | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/projects/hip-tests/catch/unit/memory/hipMemcpy2D.cc b/projects/hip-tests/catch/unit/memory/hipMemcpy2D.cc index 27e011089c..d598e2600b 100644 --- a/projects/hip-tests/catch/unit/memory/hipMemcpy2D.cc +++ b/projects/hip-tests/catch/unit/memory/hipMemcpy2D.cc @@ -99,6 +99,76 @@ TEMPLATE_TEST_CASE("Unit_hipMemcpy2D_H2D-D2D-D2H", "" REQUIRE(HipTest::checkArray(A_h, B_h, COLUMNS, ROWS) == true); + // DeAllocating the memory + HIP_CHECK(hipFree(A_d)); + HIP_CHECK(hipFree(B_d)); + if (mem_type) { + HipTest::freeArrays(nullptr, nullptr, nullptr, + A_h, B_h, C_h, true); + } else { + HipTest::freeArrays(nullptr, nullptr, nullptr, + A_h, B_h, C_h, false); + } +} +/* +This testcase performs the following scenarios of hipMemcpy2D API on same GPU. +1. H2D-D2D-D2H for Host Memory<-->Device Memory +2. H2D-D2D-D2H for Pinned Host Memory<-->Device Memory +The src and dst input pointers to hipMemCpy2D add an offset to the pointers +returned by the allocation functions. + +Input : "A_h" initialized based on data type + "A_h" --> "A_d" using H2D copy + "A_d" --> "B_d" using D2D copy + "B_d" --> "B_h" using D2H copy +Output: Validating A_h with B_h both should be equal for + the number of COLUMNS and ROWS copied +*/ +TEMPLATE_TEST_CASE("Unit_hipMemcpy2D_H2D-D2D-D2H_WithOffset", "" + , int, float, double) { + // 1 refers to pinned host memory + auto mem_type = GENERATE(0, 1); + HIP_CHECK(hipSetDevice(0)); + TestType *A_h{nullptr}, *B_h{nullptr}, *C_h{nullptr}, *A_d{nullptr}, + *B_d{nullptr}; + size_t pitch_A, pitch_B; + size_t width{NUM_W * sizeof(TestType)}; + + // Allocating memory + if (mem_type) { + HipTest::initArrays(nullptr, nullptr, nullptr, + &A_h, &B_h, &C_h, NUM_W*NUM_H, true); + } else { + HipTest::initArrays(nullptr, nullptr, nullptr, + &A_h, &B_h, &C_h, NUM_W*NUM_H, false); + } + HIP_CHECK(hipMallocPitch(reinterpret_cast(&A_d), + &pitch_A, width, NUM_H)); + HIP_CHECK(hipMallocPitch(reinterpret_cast(&B_d), + &pitch_B, width, NUM_H)); + + // Initialize the data + HipTest::setDefaultData(NUM_W*NUM_H, A_h, B_h, C_h); + + // Host to Device + HIP_CHECK(hipMemcpy2D(A_d+COLUMNS*sizeof(TestType), pitch_A, A_h, COLUMNS*sizeof(TestType), + COLUMNS*sizeof(TestType), ROWS, hipMemcpyHostToDevice)); + + // Performs D2D on same GPU device + HIP_CHECK(hipMemcpy2D(B_d+COLUMNS*sizeof(TestType), pitch_B, A_d+COLUMNS*sizeof(TestType), + pitch_A, COLUMNS*sizeof(TestType), + ROWS, hipMemcpyDeviceToDevice)); + + // hipMemcpy2D Device to Host + HIP_CHECK(hipMemcpy2D(B_h, COLUMNS*sizeof(TestType), B_d+COLUMNS*sizeof(TestType), pitch_B, + COLUMNS*sizeof(TestType), ROWS, + hipMemcpyDeviceToHost)); + + + // Validating the result + REQUIRE(HipTest::checkArray(A_h, B_h, COLUMNS, ROWS) == true); + + // DeAllocating the memory HIP_CHECK(hipFree(A_d)); HIP_CHECK(hipFree(B_d)); From 8aa3e159bb3ec012a908d19fc30f0adc2dd13080 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 08:54:47 +0530 Subject: [PATCH 19/32] SWDEV-388952 - Re-enable Unit_hipStreamSetCaptureDependencies_Positive_Functional test (#304) Change-Id: Iaa65b1562c707e513d94939f423b89b67eaa5cf0 [ROCm/hip-tests commit: ee04de73f8402da10862339a977393e7b206e372] --- .../catch/hipTestMain/config/config_amd_linux_common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json index 7a1b5c1f20..7f3c8c74d8 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json @@ -33,7 +33,7 @@ "Unit_hipStreamAttachMemAsync_Positive_AttachGlobal", "Unit_hipStreamAttachMemAsync_Negative_Parameters", "Unit_hipMemGetAddressRange_Positive", - "Unit_hipStreamGetCaptureInfo_Nullstream_CaptureInfo", + "Unit_hipGraphAddMemcpyNode1D_Negative_Basic", "intermittent issue: corrupted double-linked list", "Unit_hipGraphRetainUserObject_Functional_2", "intermittent issue: failure expected but sucess returned", From 00c348bf3dfa25e618814a32bd6f95a6fde6a0e0 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 08:55:01 +0530 Subject: [PATCH 20/32] SWDEV-388954 - Enable Unit_hipGraphMemcpyNodeSetParamsFromSymbol_Positive_Basic (#311) Change-Id: I9b28a4ddb6d757646ef0dcda9d4e746c2cd0ed19 [ROCm/hip-tests commit: b839c2b3c37ca1daec79d6b6821adbd8b712d0de] --- .../catch/hipTestMain/config/config_amd_linux_common.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json index 7f3c8c74d8..d0a68fab84 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json @@ -15,7 +15,8 @@ "Unit_hipDeviceReset_Positive_Threaded", "Unit_hipOccupancyMaxActiveBlocksPerMultiprocessor_Negative_Parameters", "Unit_hipGraphMemcpyNodeSetParamsToSymbol_Positive_Basic", - "Unit_hipGraphMemcpyNodeSetParamsFromSymbol_Positive_Basic", + "Unit_hipGraphExecMemcpyNodeSetParamsToSymbol_Positive_Basic", + "Unit_hipGraphExecMemcpyNodeSetParamsFromSymbol_Positive_Basic", "Unit_hipKernelNameRef_Negative_Parameters", "Unit_hipMemAdvise_AccessedBy_All_Devices", "Unit_hipMemAdvise_No_Flag_Interference", From 2c456ea6b7b6ff8cbe87b7444f71f9f56915e277 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 08:57:20 +0530 Subject: [PATCH 21/32] SWDEV-367877 - add test to detect graph topology (#314) - detect cycle and return error - check whether cycle is resolved by removing edge - remove egde from graph check for cycle and correct operation Change-Id: I8fdab97c8fab6a66b252944f3db04d008bc68aaa [ROCm/hip-tests commit: c24c6674aeaced94ee8f92be700f098316077a23] --- .../hip-tests/catch/unit/graph/CMakeLists.txt | 1 + .../catch/unit/graph/hipGraphCycle.cc | 244 ++++++++++++++++++ 2 files changed, 245 insertions(+) create mode 100644 projects/hip-tests/catch/unit/graph/hipGraphCycle.cc diff --git a/projects/hip-tests/catch/unit/graph/CMakeLists.txt b/projects/hip-tests/catch/unit/graph/CMakeLists.txt index 57c7ecb4eb..9ff1d63537 100644 --- a/projects/hip-tests/catch/unit/graph/CMakeLists.txt +++ b/projects/hip-tests/catch/unit/graph/CMakeLists.txt @@ -109,6 +109,7 @@ set(TEST_SRC hipGraphExecDestroy.cc hipGraphUpload.cc hipGraphKernelNodeCopyAttributes.cc + hipGraphCycle.cc hipGraphKernelNodeGetAttribute.cc ) diff --git a/projects/hip-tests/catch/unit/graph/hipGraphCycle.cc b/projects/hip-tests/catch/unit/graph/hipGraphCycle.cc new file mode 100644 index 0000000000..dedf4dd558 --- /dev/null +++ b/projects/hip-tests/catch/unit/graph/hipGraphCycle.cc @@ -0,0 +1,244 @@ +/* +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. +*/ + +/** +Testcase Scenarios : + 1) Purpose is to check for topology of graph + 2) Basic tests with manually added nodes, make graph cyclic + 3) Basic tests with manually added nodes, remove edges from graph making sure + node levels are correct if graph is not cyclic in a previously cyclic graph. +*/ + +#include +#include +#include + +/** + * Tests basic functionality of cycle detection in hipGraph APIs by + * Adding manual empty nodes + * Cyclic graph, cycle formation first, then adding more nodes + */ +TEST_CASE("Unit_hipGraph_BasicCyclic1") { + hipGraph_t graph; + hipStream_t streamForGraph; + hipGraphExec_t graphExec; + hipGraphNode_t emptyNode1, emptyNode2, emptyNode3, emptyNode4, emptyNode5, emptyNode6; + HIP_CHECK(hipGraphCreate(&graph, 0)); + // Create emptyNode and add it to graph with dependency + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode1, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode2, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode3, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode4, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode5, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode6, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode1, &emptyNode2, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode2, &emptyNode3, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode3, &emptyNode1, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode4, &emptyNode1, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode5, &emptyNode4, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode5, &emptyNode6, 1)); + HIP_CHECK(hipStreamCreate(&streamForGraph)); + REQUIRE(hipErrorInvalidValue == hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0)); + HIP_CHECK(hipStreamDestroy(streamForGraph)); +} + +/** + * Tests basic functionality of cycle detection in hipGraph APIs by + * Adding manual empty nodes + * Cyclic graph, cycle formation first, Remove edge to resolve cycle + */ +TEST_CASE("Unit_hipGraph_BasicCyclic2") { + hipGraph_t graph; + hipStream_t streamForGraph; + hipGraphExec_t graphExec; + hipGraphNode_t emptyNode1, emptyNode2, emptyNode3, emptyNode4, emptyNode5; + HIP_CHECK(hipGraphCreate(&graph, 0)); + // Create emptyNode and add it to graph with dependency + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode1, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode2, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode3, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode4, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode5, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode1, &emptyNode2, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode2, &emptyNode3, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode3, &emptyNode1, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode4, &emptyNode1, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode5, &emptyNode4, 1)); + HIP_CHECK(hipGraphRemoveDependencies(graph, &emptyNode3, &emptyNode1, 1)); + HIP_CHECK(hipStreamCreate(&streamForGraph)); + HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0)); + HIP_CHECK(hipStreamDestroy(streamForGraph)); +} + +/** + * Tests basic functionality of cycle detection in hipGraph APIs by + * Adding manual empty nodes + * Cyclic graph, cycle formation first, Remove edge causes disconnected graph which is still + * cyclic + */ +TEST_CASE("Unit_hipGraph_BasicCyclic3") { + hipGraph_t graph; + hipStream_t streamForGraph; + hipGraphExec_t graphExec; + hipGraphNode_t emptyNode1, emptyNode2, emptyNode3, emptyNode4, emptyNode5, emptyNode6; + HIP_CHECK(hipGraphCreate(&graph, 0)); + // Create emptyNode and add it to graph with dependency + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode1, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode2, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode3, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode4, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode5, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode6, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode1, &emptyNode2, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode2, &emptyNode3, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode3, &emptyNode1, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode4, &emptyNode1, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode5, &emptyNode4, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode5, &emptyNode6, 1)); + HIP_CHECK(hipGraphRemoveDependencies(graph, &emptyNode5, &emptyNode4, 1)); + HIP_CHECK(hipStreamCreate(&streamForGraph)); + REQUIRE(hipErrorInvalidValue == hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0)); + HIP_CHECK(hipStreamDestroy(streamForGraph)); +} + +/** + * Tests basic functionality of cycle detection in hipGraph APIs by + * Adding manual empty nodes + * Uncyclic graph, removing edge from middle of linear graph + */ +TEST_CASE("Unit_hipGraph_BasicCyclic4") { + int N = 1024 * 1024; + int Nbytes = N * sizeof(int); + hipGraph_t graph; + hipGraphExec_t graphExec; + hipStream_t stream; + int *X_d, *Y_d, *X_h, *Y_h; + + HipTest::initArrays(&X_d, &Y_d, nullptr, &X_h, &Y_h, nullptr, N, false); + + constexpr size_t memSetVal = 9; + hipGraphNode_t kMemCpyH2D_X, memcpyD2D, memcpyD2H_RC, emptyNode1; + + HIP_CHECK(hipStreamCreate(&stream)); + HIP_CHECK(hipGraphCreate(&graph, 0)); + + HIP_CHECK(hipGraphAddMemcpyNode1D(&kMemCpyH2D_X, graph, nullptr, 0, X_d, X_h, Nbytes, + hipMemcpyHostToDevice)); + + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2D, graph, nullptr, 0, Y_d, X_d, Nbytes, + hipMemcpyDeviceToDevice)); + + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_RC, graph, nullptr, 0, Y_h, Y_d, Nbytes, + hipMemcpyDeviceToHost)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode1, graph, nullptr, 0)); + + HIP_CHECK(hipGraphAddDependencies(graph, &kMemCpyH2D_X, &emptyNode1, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode1, &memcpyD2D, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2D, &memcpyD2H_RC, 1)); + + HIP_CHECK(hipGraphRemoveDependencies(graph, &kMemCpyH2D_X, &emptyNode1, 1)); + HIP_CHECK(hipGraphRemoveDependencies(graph, &emptyNode1, &memcpyD2D, 1)); + HIP_CHECK(hipGraphDestroyNode(emptyNode1)); + + HIP_CHECK(hipGraphAddDependencies(graph, &kMemCpyH2D_X, &memcpyD2D, 1)); + + // Instantiate and launch the graph + HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0)); + HIP_CHECK(hipGraphLaunch(graphExec, stream)); + HIP_CHECK(hipStreamSynchronize(stream)); + + // Verify graph result as X_h == Y_h + for (size_t i = 0; i < N; i++) { + if (Y_h[i] != X_h[i]) { + INFO("Validation failed for graph at index " << i << " Y_h[i] " << Y_h[i] << " X_h[i] " + << X_h[i]); + REQUIRE(false); + } + } + HipTest::freeArrays(X_d, Y_d, nullptr, X_h, Y_h, nullptr, false); + HIP_CHECK(hipGraphExecDestroy(graphExec)); + HIP_CHECK(hipGraphDestroy(graph)); + HIP_CHECK(hipStreamDestroy(stream)); +} + +/** + * Tests basic functionality of cycle detection in hipGraph APIs by + * Adding manual empty nodes + * cyclic graph, removing edge to resolve cycle and remove edge from middle of graph + */ +TEST_CASE("Unit_hipGraph_BasicCyclic5") { + int N = 1024 * 1024; + int Nbytes = N * sizeof(int); + hipGraph_t graph; + hipGraphExec_t graphExec; + hipStream_t stream; + int *X_d, *Y_d, *X_h, *Y_h; + + HipTest::initArrays(&X_d, &Y_d, nullptr, &X_h, &Y_h, nullptr, N, false); + + constexpr size_t memSetVal = 9; + hipGraphNode_t kMemCpyH2D_X, memcpyD2D, memcpyD2H_RC, emptyNode1, emptyNode2, emptyNode3; + + HIP_CHECK(hipStreamCreate(&stream)); + HIP_CHECK(hipGraphCreate(&graph, 0)); + + HIP_CHECK(hipGraphAddMemcpyNode1D(&kMemCpyH2D_X, graph, nullptr, 0, X_d, X_h, Nbytes, + hipMemcpyHostToDevice)); + + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2D, graph, nullptr, 0, Y_d, X_d, Nbytes, + hipMemcpyDeviceToDevice)); + + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_RC, graph, nullptr, 0, Y_h, Y_d, Nbytes, + hipMemcpyDeviceToHost)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode1, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode2, graph, nullptr, 0)); + HIP_CHECK(hipGraphAddEmptyNode(&emptyNode3, graph, nullptr, 0)); + + HIP_CHECK(hipGraphAddDependencies(graph, &kMemCpyH2D_X, &emptyNode1, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode1, &memcpyD2D, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2D, &memcpyD2H_RC, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpyD2H_RC, &emptyNode2, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode2, &emptyNode3, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &emptyNode3, &memcpyD2H_RC, 1)); + + HIP_CHECK(hipGraphRemoveDependencies(graph, &kMemCpyH2D_X, &emptyNode1, 1)); + HIP_CHECK(hipGraphRemoveDependencies(graph, &emptyNode1, &memcpyD2D, 1)); + HIP_CHECK(hipGraphDestroyNode(emptyNode1)); + + HIP_CHECK(hipGraphAddDependencies(graph, &kMemCpyH2D_X, &memcpyD2D, 1)); + HIP_CHECK(hipGraphRemoveDependencies(graph, &emptyNode3, &memcpyD2H_RC, 1)); + + // Instantiate and launch the graph + HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0)); + HIP_CHECK(hipGraphLaunch(graphExec, stream)); + HIP_CHECK(hipStreamSynchronize(stream)); + + // Verify graph result as X_h == Y_h + for (size_t i = 0; i < N; i++) { + if (Y_h[i] != X_h[i]) { + INFO("Validation failed for graph at index " << i << " Y_h[i] " << Y_h[i] << " X_h[i] " + << X_h[i]); + REQUIRE(false); + } + } + HipTest::freeArrays(X_d, Y_d, nullptr, X_h, Y_h, nullptr, false); + HIP_CHECK(hipGraphExecDestroy(graphExec)); + HIP_CHECK(hipGraphDestroy(graph)); + HIP_CHECK(hipStreamDestroy(stream)); +} \ No newline at end of file From 9916a91962b1abb96359b5635a07575140a72670 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 08:57:38 +0530 Subject: [PATCH 22/32] SWDEV-389825 - intermittent failure on multithread test (#315) - remove null stream from operation with other created streams on multithread test - some general test fix Change-Id: Icec7436f92a2d90dcee93ed5cdc4c8934d803fde [ROCm/hip-tests commit: a7ab47589b9e2ae1ddfe95946be115f4b6a875d9] --- .../stream/hipStreamCreateWithPriority.cc | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/projects/hip-tests/catch/unit/stream/hipStreamCreateWithPriority.cc b/projects/hip-tests/catch/unit/stream/hipStreamCreateWithPriority.cc index 03b34e4da1..9bc8bb32bf 100644 --- a/projects/hip-tests/catch/unit/stream/hipStreamCreateWithPriority.cc +++ b/projects/hip-tests/catch/unit/stream/hipStreamCreateWithPriority.cc @@ -256,6 +256,8 @@ bool runFuncTestsForAllPriorityLevelsMultThread(unsigned int flags) { int priority; int priority_low; int priority_high; + std::vector stream_set{}; + hipStream_t stream{}; // Test is to get the Stream Priority Range HIP_CHECK(hipDeviceGetStreamPriorityRange(&priority_low, &priority_high)); @@ -265,23 +267,19 @@ bool runFuncTestsForAllPriorityLevelsMultThread(unsigned int flags) { return true; } - int numOfPriorities = priority_low - priority_high; + int numOfPriorities = priority_low - priority_high + 1; INFO("numOfPriorities : " << numOfPriorities); - // 0 idx is for default stream - std::vector stream(numOfPriorities + 1); - stream[0] = 0; - // Create a stream for each of the priority levels - int count = 1; - for (priority = priority_high; priority < priority_low; priority++) { - HIP_CHECK(hipStreamCreateWithPriority(&stream[count++], flags, + for (priority = priority_high; priority <= priority_low; priority++) { + HIP_CHECK(hipStreamCreateWithPriority(&stream, flags, priority)); + stream_set.push_back(stream); } for (int i = 0; i < TOTALTHREADS; i++) { T[i] = std::thread(queueTasksInStreams, - &stream, numOfPriorities + 1); + &stream_set, numOfPriorities); } for (int i=0; i < TOTALTHREADS; i++) { @@ -294,9 +292,9 @@ bool runFuncTestsForAllPriorityLevelsMultThread(unsigned int flags) { } // Destroy the stream for each of the priority levels - count = 1; - for (priority = priority_high; priority < priority_low; priority++) { - HIP_CHECK(hipStreamDestroy(stream[count++])); + size_t set_size = stream_set.size(); + for (int i = 0; i < set_size; i++) { + HIP_CHECK(hipStreamDestroy(stream_set[i])); } return TestPassed; } From 011b44b4820a82d976ab0be7cc6e2f156cfa55c9 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 08:57:51 +0530 Subject: [PATCH 23/32] SWDEV-393910 - Port gfx940 changes to mainline. (#321) Change-Id: I77e70bcb15fbd38b1c79c1f68b7e483b2b3e0daf [ROCm/hip-tests commit: d33ccb3569673f0a30930a4cb7a5a58cd6ee6b4c] --- .../catch/hipTestMain/CMakeLists.txt | 2 +- .../catch/hipTestMain/hip_test_context.cc | 1 + .../catch/hipTestMain/hip_test_features.cc | 45 +++++++++++++++++++ .../catch/include/hip_test_features.hh | 38 ++++++++++++++++ .../multiproc/hipMemCoherencyTstMProc.cc | 6 ++- .../AtomicAdd_Coherent_withnoUnsafeflag.cc | 12 ++--- .../AtomicAdd_Coherent_withoutflag.cc | 8 ++-- .../AtomicAdd_Coherent_withunsafeflag.cc | 7 +-- .../AtomicAdd_NonCoherent_withnoUnsafeflag.cc | 8 ++-- .../AtomicAdd_NonCoherent_withoutflag.cc | 7 +-- .../AtomicAdd_NonCoherent_withunsafeflag.cc | 8 ++-- .../catch/unit/deviceLib/BuiltIns_fadd.cc | 17 +++---- .../catch/unit/deviceLib/CMakeLists.txt | 19 +++++++- .../catch/unit/deviceLib/unsafeAtomicAdd.cc | 3 +- ...safeAtomicAdd_Coherent_withnounsafeflag.cc | 7 +-- .../unsafeAtomicAdd_Coherent_withoutflag.cc | 7 +-- ...unsafeAtomicAdd_Coherent_withunsafeflag.cc | 5 ++- ...eAtomicAdd_NonCoherent_withnounsafeflag.cc | 7 +-- ...unsafeAtomicAdd_NonCoherent_withoutflag.cc | 7 +-- ...afeAtomicAdd_NonCoherent_withunsafeflag.cc | 7 +-- .../unit/deviceLib/unsafeAtomicAdd_RTC.cc | 25 ++++++----- .../catch/unit/memory/hipMemAdvise_old.cc | 9 ++-- .../unit/texture/hipTextureObj3DCheckModes.cc | 9 ++-- 23 files changed, 190 insertions(+), 74 deletions(-) create mode 100644 projects/hip-tests/catch/hipTestMain/hip_test_features.cc create mode 100644 projects/hip-tests/catch/include/hip_test_features.hh diff --git a/projects/hip-tests/catch/hipTestMain/CMakeLists.txt b/projects/hip-tests/catch/hipTestMain/CMakeLists.txt index 13407032a8..95b7a09547 100644 --- a/projects/hip-tests/catch/hipTestMain/CMakeLists.txt +++ b/projects/hip-tests/catch/hipTestMain/CMakeLists.txt @@ -22,7 +22,7 @@ if(CMAKE_BUILD_TYPE MATCHES "^Debug$") add_definitions(-DHT_LOG_ENABLE) endif() -add_library(Main_Object EXCLUDE_FROM_ALL OBJECT main.cc hip_test_context.cc) +add_library(Main_Object EXCLUDE_FROM_ALL OBJECT main.cc hip_test_context.cc hip_test_features.cc) if(HIP_PLATFORM MATCHES "amd") set_property(TARGET Main_Object PROPERTY CXX_STANDARD 17) else() diff --git a/projects/hip-tests/catch/hipTestMain/hip_test_context.cc b/projects/hip-tests/catch/hipTestMain/hip_test_context.cc index eb2893a00c..f30a747d59 100644 --- a/projects/hip-tests/catch/hipTestMain/hip_test_context.cc +++ b/projects/hip-tests/catch/hipTestMain/hip_test_context.cc @@ -6,6 +6,7 @@ #include #include "hip_test_context.hh" #include "hip_test_filesystem.hh" +#include "hip_test_features.hh" void TestContext::detectOS() { #if (HT_WIN == 1) diff --git a/projects/hip-tests/catch/hipTestMain/hip_test_features.cc b/projects/hip-tests/catch/hipTestMain/hip_test_features.cc new file mode 100644 index 0000000000..b53811be03 --- /dev/null +++ b/projects/hip-tests/catch/hipTestMain/hip_test_features.cc @@ -0,0 +1,45 @@ +#include "hip_test_features.hh" + +#include +#include + +#include "hip_test_context.hh" + +std::vector> GCNArchFeatMap = { + {"gfx90a", "gfx940", "gfx941", "gfx942"}, // CT_FEATURE_FINEGRAIN_HWSUPPORT + {"gfx90a", "gfx940", "gfx941", "gfx942"}, // CT_FEATURE_HMM + {"gfx90a", "gfx940", "gfx941", "gfx942"}, // CT_FEATURE_TEXTURES_NOT_SUPPORTED +}; + +#if HT_AMD +std::string TrimAndGetGFXName(const std::string& full_gfx_name) { + std::string gfx_name(""); + + // Split the first part of the delimiter + std::string delimiter = ":"; + auto pos = full_gfx_name.find(delimiter); + if (pos == std::string::npos) { + gfx_name = full_gfx_name; + } else { + gfx_name = full_gfx_name.substr(0, pos); + } + + assert(gfx_name.substr(0,3) == "gfx"); + return gfx_name; +} +#endif + +// Check if the GCN Maps +bool CheckIfFeatSupported(enum CTFeatures test_feat, std::string gcn_arch) { +#if HT_NVIDIA + return true; // returning true since feature check does not exist for NV. +#elif HT_AMD + assert(test_feat >= 0 && test_feat < CTFeatures::CT_FEATURE_LAST); + gcn_arch = TrimAndGetGFXName(gcn_arch); + assert(gcn_arch != ""); + return (GCNArchFeatMap[test_feat].find(gcn_arch) != GCNArchFeatMap[test_feat].cend()); +#else + std::cout<<"Platform has to be either AMD or NVIDIA, asserting..."< +#include +#include +#include + +// Catch Test Features +typedef enum CTFeatures { + CT_FEATURE_FINEGRAIN_HWSUPPORT = 0x0, // FINEGRAIN Supported Hardware. + CT_FEATURE_HMM = 0x1, // HMM Enabled + CT_FEATURE_TEXTURES_NOT_SUPPORTED = 0x2, // Textures not supported + CT_FEATURE_LAST = 0x3 +} CTFeatures; + +bool CheckIfFeatSupported(enum CTFeatures test_feat, std::string gcn_arch); diff --git a/projects/hip-tests/catch/multiproc/hipMemCoherencyTstMProc.cc b/projects/hip-tests/catch/multiproc/hipMemCoherencyTstMProc.cc index 8579aabc27..576f8d8bc2 100644 --- a/projects/hip-tests/catch/multiproc/hipMemCoherencyTstMProc.cc +++ b/projects/hip-tests/catch/multiproc/hipMemCoherencyTstMProc.cc @@ -33,6 +33,7 @@ */ #include +#include #include #include #include @@ -158,11 +159,12 @@ TEST_CASE("Unit_malloc_CoherentTst") { hipDeviceProp_t prop; HIPCHECK(hipGetDeviceProperties(&prop, 0)); char *p = NULL; - p = strstr(prop.gcnArchName, "gfx90a"); - if (p) { + + 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]); diff --git a/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_Coherent_withnoUnsafeflag.cc b/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_Coherent_withnoUnsafeflag.cc index 58e0d1d6a2..2c6effaa89 100644 --- a/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_Coherent_withnoUnsafeflag.cc +++ b/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_Coherent_withnoUnsafeflag.cc @@ -22,11 +22,12 @@ AtomicAdd on FineGrainMemory 1. The following test scenario verifies atomicAdd on fineGrain memory with -mno-unsafe-atomics flag -This testcase works only on gfx90a. +This testcase works only on gfx90a, gfx940, gfx941, gfx942. */ -#include -#include +#include +#include +#include #define INC_VAL 10 @@ -53,7 +54,8 @@ TEMPLATE_TEST_CASE("Unit_AtomicAdd_Coherentwithnounsafeflag", "", HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -86,7 +88,7 @@ TEMPLATE_TEST_CASE("Unit_AtomicAdd_Coherentwithnounsafeflag", "", HIP_CHECK(hipHostFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_Coherent_withoutflag.cc b/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_Coherent_withoutflag.cc index 300b84fed0..e068b94cc2 100644 --- a/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_Coherent_withoutflag.cc +++ b/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_Coherent_withoutflag.cc @@ -22,12 +22,12 @@ AtomicAdd on FineGrainMemory 1. The following test scenario verifies atomicAdd on fineGrain memory without any unsafeatomics flag -This testcase works only on gfx90a. +This testcase works only on gfx90a, gfx940, gfx941, gfx942. */ #include #include - +#include #define INC_VAL 10 #define INITIAL_VAL 5 @@ -52,7 +52,7 @@ TEMPLATE_TEST_CASE("Unit_AtomicAdd_Coherentwithoutflag", "", HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -85,7 +85,7 @@ TEMPLATE_TEST_CASE("Unit_AtomicAdd_Coherentwithoutflag", "", HIP_CHECK(hipHostFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_Coherent_withunsafeflag.cc b/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_Coherent_withunsafeflag.cc index 5472b6225f..b9fffb5de5 100644 --- a/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_Coherent_withunsafeflag.cc +++ b/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_Coherent_withunsafeflag.cc @@ -22,11 +22,12 @@ AtomicAdd on FineGrainMemory 1. The following test scenario verifies atomicAdd on fineGrain memory with -munsafe-fp-atomics flag -This testcase works only on gfx90a. +This testcase works only on gfx90a, gfx940, gfx941, gfx942. */ #include #include +#include #define INC_VAL 10 #define INITIAL_VAL 5 @@ -52,7 +53,7 @@ TEMPLATE_TEST_CASE("Unit_AtomicAdd_CoherentwithUnsafeflag", "", HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -94,7 +95,7 @@ TEMPLATE_TEST_CASE("Unit_AtomicAdd_CoherentwithUnsafeflag", "", HIP_CHECK(hipHostFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_NonCoherent_withnoUnsafeflag.cc b/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_NonCoherent_withnoUnsafeflag.cc index 98df491998..00ded36a21 100644 --- a/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_NonCoherent_withnoUnsafeflag.cc +++ b/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_NonCoherent_withnoUnsafeflag.cc @@ -22,12 +22,12 @@ AtomicAdd on CoarseGrainMemory 1. The following test scenario verifies atomicAdd on CoarseGrain memory with -mno-unsafe-atomics flag -This testcase works only on gfx90a. +This testcase works only on gfx90a, gfx940, gfx941, gfx942. */ #include #include - +#include #define INC_VAL 10 #define INITIAL_VAL 5 @@ -52,7 +52,7 @@ TEMPLATE_TEST_CASE("Unit_AtomicAdd_NonCoherentwithnounsafeflag", "", HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -86,7 +86,7 @@ TEMPLATE_TEST_CASE("Unit_AtomicAdd_NonCoherentwithnounsafeflag", "", HIP_CHECK(hipHostFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_NonCoherent_withoutflag.cc b/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_NonCoherent_withoutflag.cc index 38ba5a5690..6e88a26afc 100644 --- a/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_NonCoherent_withoutflag.cc +++ b/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_NonCoherent_withoutflag.cc @@ -22,11 +22,12 @@ AtomicAdd on CoarseGrainMemory 1. The following test scenario verifies atomicAdd on CoarseGrain memory without any unsafeatomics flag -This testcase works only on gfx90a. +This testcase works only on gfx90a, gfx940, gfx941, gfx942. */ #include #include +#include #define INC_VAL 10 #define INITIAL_VAL 5 @@ -52,7 +53,7 @@ TEMPLATE_TEST_CASE("Unit_AtomicAdd_NonCoherentwithoutflag", "", HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -86,7 +87,7 @@ TEMPLATE_TEST_CASE("Unit_AtomicAdd_NonCoherentwithoutflag", "", HIP_CHECK(hipHostFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_NonCoherent_withunsafeflag.cc b/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_NonCoherent_withunsafeflag.cc index 6bfff7262c..5cfb70c816 100644 --- a/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_NonCoherent_withunsafeflag.cc +++ b/projects/hip-tests/catch/unit/deviceLib/AtomicAdd_NonCoherent_withunsafeflag.cc @@ -22,12 +22,12 @@ AtomicAdd on CoarseGrainMemory 1. The following test scenario verifies atomicAdd on CoarseGrain memory with -munsafe-fp-atomics flag -This testcase works only on gfx90a. +This testcase works only on gfx90a, gfx940, gfx941, gfx942. */ #include #include - +#include #define INC_VAL 10 #define INITIAL_VAL 5 @@ -52,7 +52,7 @@ TEMPLATE_TEST_CASE("Unit_AtomicAdd_NonCoherentwithUnsafeflag", "", HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -93,7 +93,7 @@ TEMPLATE_TEST_CASE("Unit_AtomicAdd_NonCoherentwithUnsafeflag", "", HIP_CHECK(hipHostFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/BuiltIns_fadd.cc b/projects/hip-tests/catch/unit/deviceLib/BuiltIns_fadd.cc index 0819f90b2c..769b0dc97a 100644 --- a/projects/hip-tests/catch/unit/deviceLib/BuiltIns_fadd.cc +++ b/projects/hip-tests/catch/unit/deviceLib/BuiltIns_fadd.cc @@ -28,6 +28,7 @@ This testfile verifies __builtin_amdgcn_global_atomic_fadd_f64 API scenarios #include #include +#include #include #define INC_VAL 10 @@ -57,7 +58,7 @@ TEST_CASE("Unit_BuiltInAtomicAdd_CoherentGlobalMem") { HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does support HostPinned Memory"); } else { @@ -85,7 +86,7 @@ TEST_CASE("Unit_BuiltInAtomicAdd_CoherentGlobalMem") { HIP_CHECK(hipFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942 Hence" "skipping the testcase for this GPU " << device); } } @@ -103,7 +104,7 @@ TEST_CASE("Unit_BuiltInAtomicAdd_NonCoherentGlobalMem") { HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -129,7 +130,7 @@ TEST_CASE("Unit_BuiltInAtomicAdd_NonCoherentGlobalMem") { free(B_h); } } else { - SUCCEED("Memory model feature is only supported for gfx90a" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942" "Hence skipping the testcase for GPU-0"); } } @@ -146,7 +147,7 @@ TEST_CASE("Unit_BuiltInAtomicAdd_CoherentGlobalMemWithRtc") { HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -208,7 +209,7 @@ TEST_CASE("Unit_BuiltInAtomicAdd_CoherentGlobalMemWithRtc") { free(B_h); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } @@ -226,7 +227,7 @@ TEST_CASE("Unit_BuiltInAtomicAdd_NonCoherentGlobalMemWithRtc") { HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does support HostPinned Memory"); } else { @@ -288,7 +289,7 @@ TEST_CASE("Unit_BuiltInAtomicAdd_NonCoherentGlobalMemWithRtc") { free(B_h); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/CMakeLists.txt b/projects/hip-tests/catch/unit/deviceLib/CMakeLists.txt index 60fafe7d99..b2718f39bb 100644 --- a/projects/hip-tests/catch/unit/deviceLib/CMakeLists.txt +++ b/projects/hip-tests/catch/unit/deviceLib/CMakeLists.txt @@ -86,11 +86,26 @@ add_custom_target(kerDevAllocSingleKer.code -I${CMAKE_CURRENT_SOURCE_DIR}/../../../../include/ -I${CMAKE_CURRENT_SOURCE_DIR}/../../include --rocm-path=${ROCM_PATH}) +# Accepted archs to compile this cmake file +set(ACCEPTED_OFFLOAD_ARCHS gfx90a gfx940 gfx941 gfx942) +function(CheckAcceptedArchs OFFLOAD_ARCH_STR_LOCAL) + set(ARCH_CHECK -1 PARENT_SCOPE) + string(REGEX MATCHALL "--offload-arch=gfx[0-9a-z]+" OFFLOAD_ARCH_LIST ${OFFLOAD_ARCH_STR_LOCAL}) + foreach(OFFLOAD_ARCH IN LISTS OFFLOAD_ARCH_LIST) + string(REGEX MATCHALL "--offload-arch=(gfx[0-9a-z]+)" matches ${OFFLOAD_ARCH}) + if (CMAKE_MATCH_COUNT EQUAL 1) + if (CMAKE_MATCH_1 IN_LIST ACCEPTED_OFFLOAD_ARCHS) + set(ARCH_CHECK 1 PARENT_SCOPE) + endif() # CMAKE_MATCH_1 + endif() # CMAKE_MATCH_COUNT + endforeach() # OFFLOAD_ARCH_LIST +endfunction() # CheckAcceptedArchs + if(HIP_PLATFORM MATCHES "amd") if (DEFINED OFFLOAD_ARCH_STR) - string(FIND ${OFFLOAD_ARCH_STR} "gfx90a" ARCH_CHECK) + CheckAcceptedArchs(${OFFLOAD_ARCH_STR}) elseif(DEFINED $ENV{HCC_AMDGPU_TARGET}) - string(FIND $ENV{HCC_AMDGPU_TARGET} "gfx90a" ARCH_CHECK) + CheckAcceptedArchs($ENV{HCC_AMDGPU_TARGET}) else() set(ARCH_CHECK -1) endif() diff --git a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd.cc b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd.cc index a4e005404b..9d6ce388db 100644 --- a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd.cc +++ b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd.cc @@ -21,6 +21,7 @@ THE SOFTWARE. */ #include +#include #include #include @@ -52,7 +53,7 @@ TEST_CASE("Unit_unsafeAtomicAdd") { HIP_CHECK(hipGetDeviceProperties(&props, device)); std::string gfxName(props.gcnArchName); - if (gfxName == "gfx90a" || gfxName.find("gfx90a:") == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { hiprtcProgram prog; hiprtcCreateProgram(&prog, // prog kernel, // buffer diff --git a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_Coherent_withnounsafeflag.cc b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_Coherent_withnounsafeflag.cc index 596fb1ef04..91b2fc433f 100644 --- a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_Coherent_withnounsafeflag.cc +++ b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_Coherent_withnounsafeflag.cc @@ -22,11 +22,12 @@ AtomicAdd on FineGrainMemory 1. The following test scenario verifies unsafeatomicAdd on fineGrain memory with -mno-unsafe-fp-atomics flag -This testcase works only on gfx90a. +This testcase works only on gfx90a, gfx940, gfx941, gfx942. */ #include #include +#include #define INC_VAL 10 #define INITIAL_VAL 5 @@ -52,7 +53,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_CoherentwithnoUnsafeflag", "", HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -94,7 +95,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_CoherentwithnoUnsafeflag", "", HIP_CHECK(hipHostFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_Coherent_withoutflag.cc b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_Coherent_withoutflag.cc index 685f91c6ca..9999c39344 100644 --- a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_Coherent_withoutflag.cc +++ b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_Coherent_withoutflag.cc @@ -22,11 +22,12 @@ AtomicAdd on FineGrainMemory 1. The following test scenario verifies unsafeatomicAdd on fineGrain memory without atomics flag -This testcase works only on gfx90a. +This testcase works only on gfx90a, gfx940, gfx941, gfx942. */ #include #include +#include #define INC_VAL 10 #define INITIAL_VAL 5 @@ -52,7 +53,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_Coherentwithoutflag", "", HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -94,7 +95,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_Coherentwithoutflag", "", HIP_CHECK(hipHostFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_Coherent_withunsafeflag.cc b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_Coherent_withunsafeflag.cc index 4263e412e1..cbe614995f 100644 --- a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_Coherent_withunsafeflag.cc +++ b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_Coherent_withunsafeflag.cc @@ -27,6 +27,7 @@ This testcase works only on gfx90a. #include #include +#include #define INC_VAL 10 #define INITIAL_VAL 5 @@ -53,7 +54,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_CoherentwithUnsafeflag", "", HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -95,7 +96,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_CoherentwithUnsafeflag", "", HIP_CHECK(hipHostFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_NonCoherent_withnounsafeflag.cc b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_NonCoherent_withnounsafeflag.cc index b0f1d86421..c12b30d9f3 100644 --- a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_NonCoherent_withnounsafeflag.cc +++ b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_NonCoherent_withnounsafeflag.cc @@ -22,11 +22,12 @@ AtomicAdd on CoarseGrainMemory 1. The following test scenario verifies unsafeAtomicAdd on CoarseGrain memory with -mno-unsafe-fp-atomics flag -This testcase works only on gfx90a. +This testcase works only on gfx90a, gfx940, gfx941, gfx942. */ #include #include +#include #define INC_VAL 10 #define INITIAL_VAL 5 @@ -51,7 +52,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_NonCoherentnounsafeatomicsflag", "", HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -92,7 +93,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_NonCoherentnounsafeatomicsflag", "", HIP_CHECK(hipHostFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_NonCoherent_withoutflag.cc b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_NonCoherent_withoutflag.cc index fc298a8592..21e071493b 100644 --- a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_NonCoherent_withoutflag.cc +++ b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_NonCoherent_withoutflag.cc @@ -22,11 +22,12 @@ unsafeAtomicAdd on CoarseGrainMemory 1. The following test scenario verifies unsafeAtomicAdd on CoarseGrain memory without any unsafeatomics flag -This testcase works only on gfx90a. +This testcase works only on gfx90a, gfx940, gfx941, gfx942. */ #include #include +#include #define INC_VAL 10 #define INITIAL_VAL 5 @@ -51,7 +52,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_NonCoherentwithoutflag", "", HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -92,7 +93,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_NonCoherentwithoutflag", "", HIP_CHECK(hipHostFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_NonCoherent_withunsafeflag.cc b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_NonCoherent_withunsafeflag.cc index bff5e00483..f8d6cf0b5e 100644 --- a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_NonCoherent_withunsafeflag.cc +++ b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_NonCoherent_withunsafeflag.cc @@ -22,11 +22,12 @@ unsafeAtomicAdd on CoarseGrainMemory 1. The following test scenario verifies unsafeAtomicAdd on CoarseGrain memory with unsafeatomics flag -This testcase works only on gfx90a. +This testcase works only on gfx90a, gfx940, gfx941, gfx942. */ #include #include +#include #define INC_VAL 10 #define INITIAL_VAL 5 @@ -51,7 +52,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_NonCoherentwithunsafeatomicsflag", "", HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { if (prop.canMapHostMemory != 1) { SUCCEED("Does not support HostPinned Memory"); } else { @@ -92,7 +93,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_NonCoherentwithunsafeatomicsflag", "", HIP_CHECK(hipHostFree(result)); } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_RTC.cc b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_RTC.cc index e0003e5528..b91d15cf62 100644 --- a/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_RTC.cc +++ b/projects/hip-tests/catch/unit/deviceLib/unsafeAtomicAdd_RTC.cc @@ -31,6 +31,7 @@ unsafeAtomicAdd Scenarios with hipRTC: #include #include +#include #include #define INCREMENT_VAL 10 #define INITIAL_VAL 5 @@ -66,7 +67,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_CoherentRTCnounsafeatomicflag", "", HIP_CHECK(hipGetDeviceProperties(&props, device)); std::string gfxName(props.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { hiprtcProgram prog; if (std::is_same::value) { hiprtcCreateProgram(&prog, // prog @@ -135,7 +136,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_CoherentRTCnounsafeatomicflag", "", } HIP_CHECK(hipModuleUnload(module)); } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } @@ -156,7 +157,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_CoherentRTCunsafeatomicflag", "", HIP_CHECK(hipGetDeviceProperties(&props, device)); std::string gfxName(props.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { hiprtcProgram prog; if (std::is_same::value) { hiprtcCreateProgram(&prog, // prog @@ -227,7 +228,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_CoherentRTCunsafeatomicflag", "", } HIP_CHECK(hipModuleUnload(module)); } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } @@ -245,7 +246,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_CoherentRTCwithoutflag", "", HIP_CHECK(hipGetDeviceProperties(&props, device)); std::string gfxName(props.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if(CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { hiprtcProgram prog; if (std::is_same::value) { hiprtcCreateProgram(&prog, // prog @@ -315,7 +316,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_CoherentRTCwithoutflag", "", } HIP_CHECK(hipModuleUnload(module)); } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } @@ -332,7 +333,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_NonCoherentRTCnounsafeatomicflag", "", HIP_CHECK(hipGetDeviceProperties(&props, device)); std::string gfxName(props.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { hiprtcProgram prog; if (std::is_same::value) { hiprtcCreateProgram(&prog, // prog @@ -401,7 +402,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_NonCoherentRTCnounsafeatomicflag", "", } HIP_CHECK(hipModuleUnload(module)); } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } @@ -419,7 +420,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_NonCoherentRTCunsafeatomicflag", "", HIP_CHECK(hipGetDeviceProperties(&props, device)); std::string gfxName(props.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if(CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { hiprtcProgram prog; if (std::is_same::value) { hiprtcCreateProgram(&prog, // prog @@ -489,7 +490,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_NonCoherentRTCunsafeatomicflag", "", } HIP_CHECK(hipModuleUnload(module)); } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } @@ -507,7 +508,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_NonCoherentRTC", "", HIP_CHECK(hipGetDeviceProperties(&props, device)); std::string gfxName(props.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_FINEGRAIN_HWSUPPORT, gfxName)) { hiprtcProgram prog; if (std::is_same::value) { hiprtcCreateProgram(&prog, // prog @@ -577,7 +578,7 @@ TEMPLATE_TEST_CASE("Unit_unsafeAtomicAdd_NonCoherentRTC", "", } HIP_CHECK(hipModuleUnload(module)); } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + SUCCEED("Memory model feature is only supported for gfx90a, gfx940, gfx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } } diff --git a/projects/hip-tests/catch/unit/memory/hipMemAdvise_old.cc b/projects/hip-tests/catch/unit/memory/hipMemAdvise_old.cc index b951998053..8b7350a7a6 100644 --- a/projects/hip-tests/catch/unit/memory/hipMemAdvise_old.cc +++ b/projects/hip-tests/catch/unit/memory/hipMemAdvise_old.cc @@ -67,6 +67,7 @@ THE SOFTWARE. */ #include +#include #if __linux__ #include #include @@ -661,7 +662,7 @@ TEST_CASE("Unit_hipMemAdvise_TstAlignedAllocMem") { WARN("Unable to turn on HSA_XNACK, hence terminating the Test case!"); REQUIRE(false); } - // The following code block checks for gfx90a so as to skip if the device is not MI200 + // The following code block checks for gfx90a,940,941,942 so as to skip if the device is not hipDeviceProp_t prop; int device; @@ -669,7 +670,7 @@ TEST_CASE("Unit_hipMemAdvise_TstAlignedAllocMem") { HIP_CHECK(hipGetDeviceProperties(&prop, device)); std::string gfxName(prop.gcnArchName); - if ((gfxName == "gfx90a" || gfxName.find("gfx90a:")) == 0) { + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_HMM, prop.gcnArchName)) { int stat = 0; if (fork() == 0) { // The below part should be inside fork @@ -726,9 +727,9 @@ TEST_CASE("Unit_hipMemAdvise_TstAlignedAllocMem") { } } } else { - SUCCEED("Memory model feature is only supported for gfx90a, Hence" + 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, Hence" + WARN("Memory model feature is only supported for gfx90a, gfx940, gx941, gfx942, Hence" "skipping the testcase for this GPU " << device); } diff --git a/projects/hip-tests/catch/unit/texture/hipTextureObj3DCheckModes.cc b/projects/hip-tests/catch/unit/texture/hipTextureObj3DCheckModes.cc index 04d8433566..538237b4ad 100644 --- a/projects/hip-tests/catch/unit/texture/hipTextureObj3DCheckModes.cc +++ b/projects/hip-tests/catch/unit/texture/hipTextureObj3DCheckModes.cc @@ -18,10 +18,11 @@ THE SOFTWARE. */ #include +#include #include #include -bool isGfx90a = false; +bool LinearFilter3D = false; template __global__ void tex3DKernel(float *outputData, hipTextureObject_t textureObject, @@ -95,7 +96,7 @@ static void runTest(const int width, const int height, const int depth, const fl if (res != hipSuccess) { HIP_CHECK(hipFreeArray(arr)); free(hData); - if (res == hipErrorNotSupported && isGfx90a) { + if (res == hipErrorNotSupported && LinearFilter3D) { printf("gfx90a doesn't support 3D linear filter! Skipped!\n"); } else { result = false; @@ -153,8 +154,8 @@ TEST_CASE("Unit_hipTextureObj3DCheckModes") { int device = 0; hipDeviceProp_t props; HIPCHECK(hipGetDeviceProperties(&props, device)); - if (!strncmp(props.gcnArchName, "gfx90a", strlen("gfx90a"))) { - isGfx90a = true; + if (CheckIfFeatSupported(CTFeatures::CT_FEATURE_TEXTURES_NOT_SUPPORTED, props.gcnArchName)) { + LinearFilter3D = true; } SECTION("hipAddressModeClamp, hipFilterModePoint, regularCoords") { From 06275b085dfb1c5cad7058553a1a55e4166dc05b Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 08:58:19 +0530 Subject: [PATCH 24/32] SWDEV-395279 - Move the headers needed to compile perftests in hip-tests (#322) Change-Id: I9e8cea9d2cd08fb17d8955696b83404dc24a9d2b [ROCm/hip-tests commit: b14648cc31904e22cdb6dde73ff366c27cdc142f] --- projects/hip-tests/perftests/test_common.cpp | 261 +++++++++ projects/hip-tests/perftests/test_common.h | 586 +++++++++++++++++++ projects/hip-tests/perftests/timer.cpp | 116 ++++ projects/hip-tests/perftests/timer.h | 28 + 4 files changed, 991 insertions(+) create mode 100644 projects/hip-tests/perftests/test_common.cpp create mode 100644 projects/hip-tests/perftests/test_common.h create mode 100644 projects/hip-tests/perftests/timer.cpp create mode 100644 projects/hip-tests/perftests/timer.h diff --git a/projects/hip-tests/perftests/test_common.cpp b/projects/hip-tests/perftests/test_common.cpp new file mode 100644 index 0000000000..ec76df0427 --- /dev/null +++ b/projects/hip-tests/perftests/test_common.cpp @@ -0,0 +1,261 @@ +/* +Copyright (c) 2015 - 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 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 "test_common.h" + +#include +#ifdef __linux__ +#include +#elif defined(_WIN32) +#include +#endif + +// standard global variables that can be set on command line +size_t N = 4 * 1024 * 1024; +char memsetval = 0x42; +int memsetD32val = 0xDEADBEEF; +short memsetD16val = 0xDEAD; +char memsetD8val = 0xDE; +int iterations = 1; +unsigned blocksPerCU = 6; // to hide latency +unsigned threadsPerBlock = 256; +int textureFilterMode = 0; // 0: hipFilterModePoint; 1: hipFilterModeLinear +int p_gpuDevice = 0; +unsigned p_verbose = 0; +int p_tests = -1; /*which tests to run. Interpretation is left to each test. default:all*/ +int debug_test = 0; +#ifdef _WIN64 +const char* HIP_VISIBLE_DEVICES_STR = "HIP_VISIBLE_DEVICES="; +const char* CUDA_VISIBLE_DEVICES_STR = "CUDA_VISIBLE_DEVICES="; +const char* PATH_SEPERATOR_STR = "\\"; +const char* NULL_DEVICE = "NUL:"; +#else +const char* HIP_VISIBLE_DEVICES_STR = "HIP_VISIBLE_DEVICES"; +const char* CUDA_VISIBLE_DEVICES_STR = "CUDA_VISIBLE_DEVICES"; +const char* PATH_SEPERATOR_STR = "/"; +const char* NULL_DEVICE = "/dev/null"; +#endif + +#ifdef _WIN64 +// Windows does not have rand_r, use srand and rand instead. +int rand_r(unsigned int* s) { + srand(*s); + return rand(); +} +#endif + +// Get Free Memory from the system +static size_t getMemoryAmount() { +#if __linux__ + struct sysinfo info; + int _ = sysinfo(&info); + return info.freeram / (1024 * 1024); // MB +#elif defined(_WIN32) + MEMORYSTATUSEX statex; + statex.dwLength = sizeof(statex); + GlobalMemoryStatusEx(&statex); + return (statex.ullAvailPhys / (1024 * 1024)); // MB +#endif +} + +size_t getHostThreadCount(const size_t memPerThread, const size_t maxThreads) { + if (memPerThread == 0) return 0; + auto memAmount = getMemoryAmount(); + const auto processor_count = std::thread::hardware_concurrency(); + if (processor_count == 0 || memAmount == 0) return 0; + size_t thread_count = 0; + if ((processor_count * memPerThread) < memAmount) + thread_count = processor_count; + else + thread_count = reinterpret_cast(memAmount / memPerThread); + if (maxThreads > 0) { + return (thread_count > maxThreads) ? maxThreads : thread_count; + } + return thread_count; +} + +// Function to determine if the device is of gfx11 architecture +bool IsGfx11() { +#if defined(__HIP_PLATFORM_NVIDIA__) + return false; +#elif defined(__HIP_PLATFORM_AMD__) + int device = -1; + hipDeviceProp_t props{}; + HIPCHECK(hipGetDevice(&device)); + HIPCHECK(hipGetDeviceProperties(&props, device)); + + // Get GCN Arch Name and compare to check if it is gfx11 + std::string arch = std::string(props.gcnArchName); + auto pos = arch.find(":"); + if (pos != std::string::npos) + arch = arch.substr(0, pos); + + if(arch.size() >= 5) + arch = arch.substr(0,5); + + return (arch == std::string("gfx11")) ? true : false; +#else + std::cout<<"Have to be either Nvidia or AMD platform, asserting"<= argc || !HipTest::parseSize(argv[i], &N)) { + failed("Bad N size argument"); + } + } else if (!strcmp(arg, "--threadsPerBlock")) { + if (++i >= argc || !HipTest::parseUInt(argv[i], &threadsPerBlock)) { + failed("Bad threadsPerBlock argument"); + } + } else if (!strcmp(arg, "--blocksPerCU")) { + if (++i >= argc || !HipTest::parseUInt(argv[i], &blocksPerCU)) { + failed("Bad blocksPerCU argument"); + } + } else if (!strcmp(arg, "--memsetval")) { + int ex; + if (++i >= argc || !HipTest::parseInt(argv[i], &ex)) { + failed("Bad memsetval argument"); + } + memsetval = ex; + } else if (!strcmp(arg, "--memsetD32val")) { + int ex; + if (++i >= argc || !HipTest::parseInt(argv[i], &ex)) { + failed("Bad memsetD32val argument"); + } + memsetD32val = ex; + } else if (!strcmp(arg, "--memsetD16val")) { + int ex; + if (++i >= argc || !HipTest::parseInt(argv[i], &ex)) { + failed("Bad memsetD16val argument"); + } + memsetD16val = ex; + } else if (!strcmp(arg, "--memsetD8val")) { + int ex; + if (++i >= argc || !HipTest::parseInt(argv[i], &ex)) { + failed("Bad memsetD8val argument"); + } + memsetD8val = ex; + } else if (!strcmp(arg, "--textureFilterMode")) { + int mode; + if (++i >= argc || !HipTest::parseInt(argv[i], &mode)) { + failed("Bad textureFilterMode argument"); + } + textureFilterMode = mode; + } else if (!strcmp(arg, "--iterations") || (!strcmp(arg, "-i"))) { + if (++i >= argc || !HipTest::parseInt(argv[i], &iterations)) { + failed("Bad iterations argument"); + } + } else if (!strcmp(arg, "--gpu") || (!strcmp(arg, "-gpuDevice")) || (!strcmp(arg, "-g"))) { + if (++i >= argc || !HipTest::parseInt(argv[i], &p_gpuDevice)) { + failed("Bad gpuDevice argument"); + } + + } else if (!strcmp(arg, "--verbose") || (!strcmp(arg, "-v"))) { + if (++i >= argc || !HipTest::parseUInt(argv[i], &p_verbose)) { + failed("Bad verbose argument"); + } + } else if (!strcmp(arg, "--tests") || (!strcmp(arg, "-t"))) { + if (++i >= argc || !HipTest::parseInt(argv[i], &p_tests)) { + failed("Bad tests argument"); + } + + } else if (!strcmp(arg, "--debug") || (!strcmp(arg, "-d"))) { + if (++i >= argc || !HipTest::parseInt(argv[i], &debug_test)) { + failed("Bad tests argument"); + } + } else { + if (failOnUndefinedArg) { + failed("Bad argument '%s'", arg); + } else { + argv[extraArgs++] = argv[i]; + } + } + }; + + return extraArgs; +} + + +unsigned setNumBlocks(unsigned blocksPerCU, unsigned threadsPerBlock, size_t N) { + int device; + HIPCHECK(hipGetDevice(&device)); + hipDeviceProp_t props; + HIPCHECK(hipGetDeviceProperties(&props, device)); + + unsigned blocks = props.multiProcessorCount * blocksPerCU; + if (blocks * threadsPerBlock > N) { + blocks = (N + threadsPerBlock - 1) / threadsPerBlock; + } + + return blocks; +} + +} // namespace HipTest diff --git a/projects/hip-tests/perftests/test_common.h b/projects/hip-tests/perftests/test_common.h new file mode 100644 index 0000000000..853ab1f0da --- /dev/null +++ b/projects/hip-tests/perftests/test_common.h @@ -0,0 +1,586 @@ +/* +Copyright (c) 2015 - 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 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. +*/ + +/* + * File is intended to C and CPP compliant hence any CPP specic changes + * should be added into CPP section + * + */ +#pragma once + +#ifdef __cplusplus + #include + #include + #if __CUDACC__ + #include + #else + #include + #endif +#endif + +// ************************ GCC section ************************** +#include + +#include "hip/hip_runtime.h" +#include "hip/hip_runtime_api.h" + +#define HC __attribute__((hc)) + +#define KNRM "\x1B[0m" +#define KRED "\x1B[31m" +#define KGRN "\x1B[32m" +#define KYEL "\x1B[33m" +#define KBLU "\x1B[34m" +#define KMAG "\x1B[35m" +#define KCYN "\x1B[36m" +#define KWHT "\x1B[37m" + +// HIP Skip Return code set at cmake +#define HIP_SKIP_RETURN_CODE 127 +#define HIP_ENABLE_SKIP_TESTS 0 + +// Recommended thresholds for Tests +#define MAX_THREADS 100 + +inline bool hip_skip_tests_enabled() { + return HIP_ENABLE_SKIP_TESTS; +} + +inline int hip_skip_retcode() { + // HIP Skip Return code set at cmake + return HIP_SKIP_RETURN_CODE; +} + +// This must be called in the end of main() to indicate test passed with success. +// If it's called somewhere else, compiling issues or unexpected result will arise. +#define passed() \ + printf("%sPASSED!%s\n", KGRN, KNRM); \ + return 0; + +// The real "assert" would have written to stderr. But it is +// sufficient to just fflush here without getting pedantic. This also +// ensures that we don't lose any earlier writes to stdout. +#define failed(...) \ + printf("%serror: ", KRED); \ + printf(__VA_ARGS__); \ + printf("\n"); \ + printf("error: TEST FAILED\n%s", KNRM); \ + fflush(NULL); \ + abort(); + +#define warn(...) \ + printf("%swarn: ", KYEL); \ + printf(__VA_ARGS__); \ + printf("\n"); \ + printf("warn: TEST WARNING\n%s", KNRM); + +#define HIP_PRINT_STATUS(status) \ + std::cout << hipGetErrorName(status) << " at line: " << __LINE__ << std::endl; + +#define HIPCHECK(error) \ + { \ + hipError_t localError = error; \ + if ((localError != hipSuccess) && (localError != hipErrorPeerAccessAlreadyEnabled)) { \ + printf("%serror: '%s'(%d) from %s at %s:%d%s\n", KRED, hipGetErrorString(localError), \ + localError, #error, __FILE__, __LINE__, KNRM); \ + failed("API returned error code."); \ + } \ + } + +#define HIPASSERT(condition) \ + if (!(condition)) { \ + failed("%sassertion %s at %s:%d%s \n", KRED, #condition, __FILE__, __LINE__, KNRM); \ + } + + +#define HIPCHECK_API(API_CALL, EXPECTED_ERROR) \ + { \ + hipError_t _e = (API_CALL); \ + if (_e != (EXPECTED_ERROR)) { \ + failed("%sAPI '%s' returned %d(%s) but test expected %d(%s) at %s:%d%s \n", KRED, \ + #API_CALL, _e, hipGetErrorName(_e), EXPECTED_ERROR, \ + hipGetErrorName(EXPECTED_ERROR), __FILE__, __LINE__, KNRM); \ + } \ + } + +#define HIPCHECK_RETURN_ONFAIL(func) \ + do { \ + hipError_t herror = (func); \ + if (herror != hipSuccess) { \ + return herror; \ + } \ + } while (0); + +#ifdef _WIN64 +#include +#define aligned_alloc(x,y) _aligned_malloc(y,x) +#define aligned_free(x) _aligned_free(x) +#define popen(x,y) _popen(x,y) +#define pclose(x) _pclose(x) +#define setenv(x,y,z) _putenv_s(x,y) +#define unsetenv _putenv +#define fileno(x) _fileno(x) +#define dup(x) _dup(x) +#define dup2(x,y) _dup2(x,y) +#define pipe(x,y,z) _pipe(x,y,z) +#define sleep(x) _sleep(x) +#else +#define aligned_free(x) free(x) +#endif + +// standard command-line variables: +extern size_t N; +extern char memsetval; +extern int memsetD32val; +extern short memsetD16val; +extern char memsetD8val; +extern int iterations; +extern unsigned blocksPerCU; +extern unsigned threadsPerBlock; +extern int textureFilterMode; +extern int p_gpuDevice; +extern unsigned p_verbose; +extern int p_tests; +extern int debug_test; +extern const char* HIP_VISIBLE_DEVICES_STR; +extern const char* CUDA_VISIBLE_DEVICES_STR; +extern const char* PATH_SEPERATOR_STR; +extern const char* NULL_DEVICE; + +// ********************* CPP section ********************* +#ifdef __cplusplus + +#ifdef __HIP_PLATFORM_HCC +#define TYPENAME(T) typeid(T).name() +#else +#define TYPENAME(T) "?" +#endif + +#ifdef _WIN64 +int rand_r(unsigned int* s); +#endif + +// Get Optimal Thread count size +size_t getHostThreadCount(const size_t memPerThread = 200 /* MB */, const size_t maxThreads = 0); + +namespace HipTest { + +// Returns the current system time in microseconds +inline long long get_time() { +#if __CUDACC__ + struct timeval tv; + gettimeofday(&tv, 0); + return (tv.tv_sec * 1000000) + tv.tv_usec; +#else + return std::chrono::high_resolution_clock::now().time_since_epoch() + /std::chrono::microseconds(1); +#endif +} + +double elapsed_time(long long startTimeUs, long long stopTimeUs); + +int parseSize(const char* str, size_t* output); +int parseUInt(const char* str, unsigned int* output); +int parseInt(const char* str, int* output); +int parseStandardArguments(int argc, char* argv[], bool failOnUndefinedArg); + +unsigned setNumBlocks(unsigned blocksPerCU, unsigned threadsPerBlock, size_t N); + +template // pointer type +void checkArray(T hData, T hOutputData, size_t width, size_t height,size_t depth) { + for (int i = 0; i < depth; i++) { + for (int j = 0; j < height; j++) { + for (int k = 0; k < width; k++) { + int offset = i*width*height + j*width + k; + if (hData[offset] != hOutputData[offset]) { + std::cerr << '[' << i << ',' << j << ',' << k << "]:" << hData[offset] << "----" + << hOutputData[offset]<<" "; + failed("mistmatch at:%d %d %d",i,j,k); + } + } + } + } +} + +template +void checkArray(T input, T output, size_t height, size_t width) { + for(int i=0; i +__global__ void vectorADD(const T* A_d, const T* B_d, T* C_d, size_t NELEM) { + size_t offset = (blockIdx.x * blockDim.x + threadIdx.x); + size_t stride = blockDim.x * gridDim.x; + + for (size_t i = offset; i < NELEM; i += stride) { + C_d[i] = A_d[i] + B_d[i]; + } +} + + +template +__global__ void vectorADDReverse(const T* A_d, const T* B_d, T* C_d, + size_t NELEM) { + size_t offset = (blockIdx.x * blockDim.x + threadIdx.x); + size_t stride = blockDim.x * gridDim.x; + + for (int64_t i = NELEM - stride + offset; i >= 0; i -= stride) { + C_d[i] = A_d[i] + B_d[i]; + } +} + + +template +__global__ void addCount(const T* A_d, T* C_d, size_t NELEM, int count) { + size_t offset = (blockIdx.x * blockDim.x + threadIdx.x); + size_t stride = blockDim.x * gridDim.x; + + // Deliberately do this in an inefficient way to increase kernel runtime + for (int i = 0; i < count; i++) { + for (size_t i = offset; i < NELEM; i += stride) { + C_d[i] = A_d[i] + (T)count; + } + } +} + + +template +__global__ void addCountReverse(const T* A_d, T* C_d, int64_t NELEM, int count) { + size_t offset = (blockIdx.x * blockDim.x + threadIdx.x); + size_t stride = blockDim.x * gridDim.x; + + // Deliberately do this in an inefficient way to increase kernel runtime + for (int i = 0; i < count; i++) { + for (int64_t i = NELEM - stride + offset; i >= 0; i -= stride) { + C_d[i] = A_d[i] + (T)count; + } + } +} + + +template +__global__ void memsetReverse(T* C_d, T val, int64_t NELEM) { + size_t offset = (blockIdx.x * blockDim.x + threadIdx.x); + size_t stride = blockDim.x * gridDim.x; + + for (int64_t i = NELEM - stride + offset; i >= 0; i -= stride) { + C_d[i] = val; + } +} + + +template +void setDefaultData(size_t numElements, T* A_h, T* B_h, T* C_h) { + // Initialize the host data: + for (size_t i = 0; i < numElements; i++) { + if (A_h) (A_h)[i] = 3.146f + i; // Pi + if (B_h) (B_h)[i] = 1.618f + i; // Phi + if (C_h) (C_h)[i] = 0.0f + i; + } +} + + +template +void initArraysForHost(T** A_h, T** B_h, T** C_h, size_t N, bool usePinnedHost = false) { + size_t Nbytes = N * sizeof(T); + + if (usePinnedHost) { + if (A_h) { + HIPCHECK(hipHostMalloc(reinterpret_cast(A_h), Nbytes)); + } + if (B_h) { + HIPCHECK(hipHostMalloc(reinterpret_cast(B_h), Nbytes)); + } + if (C_h) { + HIPCHECK(hipHostMalloc(reinterpret_cast(C_h), Nbytes)); + } + } else { + if (A_h) { + *A_h = (T*)malloc(Nbytes); + HIPASSERT(*A_h != NULL); + } + + if (B_h) { + *B_h = (T*)malloc(Nbytes); + HIPASSERT(*B_h != NULL); + } + + if (C_h) { + *C_h = (T*)malloc(Nbytes); + HIPASSERT(*C_h != NULL); + } + } + + setDefaultData(N, A_h ? *A_h : NULL, B_h ? *B_h : NULL, C_h ? *C_h : NULL); +} + + +template +void initArrays(T** A_d, T** B_d, T** C_d, T** A_h, T** B_h, T** C_h, size_t N, + bool usePinnedHost = false) { + size_t Nbytes = N * sizeof(T); + + if (A_d) { + HIPCHECK(hipMalloc(A_d, Nbytes)); + } + if (B_d) { + HIPCHECK(hipMalloc(B_d, Nbytes)); + } + if (C_d) { + HIPCHECK(hipMalloc(C_d, Nbytes)); + } + + initArraysForHost(A_h, B_h, C_h, N, usePinnedHost); +} + + +template +void freeArraysForHost(T* A_h, T* B_h, T* C_h, bool usePinnedHost) { + if (usePinnedHost) { + if (A_h) { + HIPCHECK(hipHostFree(A_h)); + } + if (B_h) { + HIPCHECK(hipHostFree(B_h)); + } + if (C_h) { + HIPCHECK(hipHostFree(C_h)); + } + } else { + if (A_h) { + free(A_h); + } + if (B_h) { + free(B_h); + } + if (C_h) { + free(C_h); + } + } +} + +template +void freeArrays(T* A_d, T* B_d, T* C_d, T* A_h, T* B_h, T* C_h, bool usePinnedHost) { + if (A_d) { + HIPCHECK(hipFree(A_d)); + } + if (B_d) { + HIPCHECK(hipFree(B_d)); + } + if (C_d) { + HIPCHECK(hipFree(C_d)); + } + + freeArraysForHost(A_h, B_h, C_h, usePinnedHost); +} + +#if defined(__HIP_PLATFORM_AMD__) +template +void initArrays2DPitch(T** A_d, T** B_d, T** C_d, size_t* pitch_A, size_t* pitch_B, size_t* pitch_C, + size_t numW, size_t numH) { + if (A_d) { + HIPCHECK(hipMallocPitch((void**)A_d, pitch_A, numW * sizeof(T), numH)); + } + if (B_d) { + HIPCHECK(hipMallocPitch((void**)B_d, pitch_B, numW * sizeof(T), numH)); + } + if (C_d) { + HIPCHECK(hipMallocPitch((void**)C_d, pitch_C, numW * sizeof(T), numH)); + } + + HIPASSERT(*pitch_A == *pitch_B); + HIPASSERT(*pitch_A == *pitch_C) +} + +inline void initHIPArrays(hipArray** A_d, hipArray** B_d, hipArray** C_d, + const hipChannelFormatDesc* desc, const size_t numW, const size_t numH, + const unsigned int flags) { + if (A_d) { + HIPCHECK(hipMallocArray(A_d, desc, numW, numH, flags)); + } + if (B_d) { + HIPCHECK(hipMallocArray(B_d, desc, numW, numH, flags)); + } + if (C_d) { + HIPCHECK(hipMallocArray(C_d, desc, numW, numH, flags)); + } +} +#endif + +// Assumes C_h contains vector add of A_h + B_h +// Calls the test "failed" macro if a mismatch is detected. +template +size_t checkVectorADD(T* A_h, T* B_h, T* result_H, size_t N, bool expectMatch = true, + bool reportMismatch = true) { + size_t mismatchCount = 0; + size_t firstMismatch = 0; + size_t mismatchesToPrint = 10; + for (size_t i = 0; i < N; i++) { + T expected = A_h[i] + B_h[i]; + if (result_H[i] != expected) { + if (mismatchCount == 0) { + firstMismatch = i; + } + mismatchCount++; + if ((mismatchCount <= mismatchesToPrint) && expectMatch) { + std::cout << std::fixed << std::setprecision(32); + std::cout << "At " << i << std::endl; + std::cout << " Computed:" << result_H[i] << std::endl; + std::cout << " Expected:" << expected << std::endl; + } + } + } + + if (reportMismatch) { + if (expectMatch) { + if (mismatchCount) { + failed("%zu mismatches ; first at index:%zu\n", mismatchCount, firstMismatch); + } + } else { + if (mismatchCount == 0) { + failed("expected mismatches but did not detect any!"); + } + } + } + + return mismatchCount; +} + + +// Assumes C_h contains vector add of A_h + B_h +// Calls the test "failed" macro if a mismatch is detected. +template +void checkTest(T* expected_H, T* result_H, size_t N, bool expectMatch = true) { + size_t mismatchCount = 0; + size_t firstMismatch = 0; + size_t mismatchesToPrint = 10; + for (size_t i = 0; i < N; i++) { + if (result_H[i] != expected_H[i]) { + if (mismatchCount == 0) { + firstMismatch = i; + } + mismatchCount++; + if ((mismatchCount <= mismatchesToPrint) && expectMatch) { + std::cout << std::fixed << std::setprecision(32); + std::cout << "At " << i << std::endl; + std::cout << " Computed:" << result_H[i] << std::endl; + std::cout << " Expected:" << expected_H[i] << std::endl; + } + } + } + + if (expectMatch) { + if (mismatchCount) { + fprintf(stderr, "%zu mismatches ; first at index:%zu\n", mismatchCount, firstMismatch); + // failed("%zu mismatches ; first at index:%zu\n", mismatchCount, firstMismatch); + } + } else { + if (mismatchCount == 0) { + failed("expected mismatches but did not detect any!"); + } + } +} + + +//--- +struct Pinned { + static const bool isPinned = true; + static const char* str() { return "Pinned"; }; + + static void* Alloc(size_t sizeBytes) { + void* p; + HIPCHECK(hipHostMalloc((void**)&p, sizeBytes)); + return p; + }; +}; + + +//--- +struct Unpinned { + static const bool isPinned = false; + static const char* str() { return "Unpinned"; }; + + static void* Alloc(size_t sizeBytes) { + void* p = malloc(sizeBytes); + HIPASSERT(p); + return p; + }; +}; + + +struct Memcpy { + static const char* str() { return "Memcpy"; }; +}; + +struct MemcpyAsync { + static const char* str() { return "MemcpyAsync"; }; +}; + + +template +struct MemTraits; + + +template <> +struct MemTraits { + static void Copy(void* dest, const void* src, size_t sizeBytes, hipMemcpyKind kind, + hipStream_t stream) { + HIPCHECK(hipMemcpy(dest, src, sizeBytes, kind)); + } +}; + + +template <> +struct MemTraits { + static void Copy(void* dest, const void* src, size_t sizeBytes, hipMemcpyKind kind, + hipStream_t stream) { + HIPCHECK(hipMemcpyAsync(dest, src, sizeBytes, kind, stream)); + } +}; + +inline bool isImageSupported() { + int imageSupport = 1; +#ifdef __HIP_PLATFORM_AMD__ + HIPCHECK(hipDeviceGetAttribute(&imageSupport, hipDeviceAttributeImageSupport, + p_gpuDevice)); +#endif + return imageSupport != 0; +} + +}; // namespace HipTest + +// This must be called in the beginning of image test app's main() to indicate whether image +// is supported. +#define checkImageSupport() \ + if (!HipTest::isImageSupported()) \ + { printf("Texture is not support on the device. Skipped.\n"); passed(); } +#endif //__cplusplus + +// Function to determine if the device is of gfx11 architecture +bool IsGfx11(); \ No newline at end of file diff --git a/projects/hip-tests/perftests/timer.cpp b/projects/hip-tests/perftests/timer.cpp new file mode 100644 index 0000000000..ea9c6ea1d9 --- /dev/null +++ b/projects/hip-tests/perftests/timer.cpp @@ -0,0 +1,116 @@ +#include "timer.h" + +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#define VC_EXTRALEAN +#include +#pragma comment(lib, "user32") +#endif + +#ifdef __linux__ +#include +#define NANOSECONDS_PER_SEC 1000000000 +#endif + +CPerfCounter::CPerfCounter() : _clocks(0), _start(0) +{ + +#ifdef _WIN32 + + QueryPerformanceFrequency((LARGE_INTEGER *)&_freq); + +#endif + +#ifdef __linux__ + _freq = NANOSECONDS_PER_SEC; +#endif + +} + +CPerfCounter::~CPerfCounter() +{ + // EMPTY! +} + +void +CPerfCounter::Start(void) +{ + +#ifdef _WIN32 + + if( _start ) + { + MessageBox(NULL, "Bad Perf Counter Start", "Error", MB_OK); + exit(0); + } + QueryPerformanceCounter((LARGE_INTEGER *)&_start); + +#endif +#ifdef __linux__ + + struct timespec s; + clock_gettime(CLOCK_MONOTONIC, &s); + _start = (i64)s.tv_sec * NANOSECONDS_PER_SEC + (i64)s.tv_nsec ; + +#endif + +} + +void +CPerfCounter::Stop(void) +{ + i64 n; + +#ifdef _WIN32 + + if( !_start ) + { + MessageBox(NULL, "Bad Perf Counter Stop", "Error", MB_OK); + exit(0); + } + + QueryPerformanceCounter((LARGE_INTEGER *)&n); + +#endif +#ifdef __linux__ + + struct timespec s; + clock_gettime(CLOCK_MONOTONIC, &s); + n = (i64)s.tv_sec * NANOSECONDS_PER_SEC + (i64)s.tv_nsec ; + +#endif + + n -= _start; + _start = 0; + _clocks += n; +} + +void +CPerfCounter::Reset(void) +{ + +#ifdef _WIN32 + if( _start ) + { + MessageBox(NULL, "Bad Perf Counter Reset", "Error", MB_OK); + exit(0); + } +#endif + _clocks = 0; +} + +double +CPerfCounter::GetElapsedTime(void) +{ +#ifdef _WIN32 + if( _start ) { + MessageBox(NULL, "Trying to get time while still running.", "Error", MB_OK); + exit(0); + } +#endif + + return (double)_clocks / (double)_freq; + +} diff --git a/projects/hip-tests/perftests/timer.h b/projects/hip-tests/perftests/timer.h new file mode 100644 index 0000000000..28bfeff74b --- /dev/null +++ b/projects/hip-tests/perftests/timer.h @@ -0,0 +1,28 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ + +#ifdef _WIN32 +typedef __int64 i64 ; +#endif +#ifdef __linux__ +typedef long long i64; +#endif + +class CPerfCounter { + +public: + CPerfCounter(); + ~CPerfCounter(); + void Start(void); + void Stop(void); + void Reset(void); + double GetElapsedTime(void); + +private: + + i64 _freq; + i64 _clocks; + i64 _start; +}; + +#endif // _TIMER_H_ From 2b68ab02ca3b176e0d93a49cfdac56c24fa6b4bb Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 08:58:35 +0530 Subject: [PATCH 25/32] SWDEV-396615 - check for managed memory support (#323) Change-Id: Ib8afef16ac90489c08c761b2a2ce34c1ba671e6b [ROCm/hip-tests commit: 0498738189c2b0bb77abc54f20da7336a27f90d7] --- .../catch/TypeQualifiers/hipManagedKeyword.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/projects/hip-tests/catch/TypeQualifiers/hipManagedKeyword.cc b/projects/hip-tests/catch/TypeQualifiers/hipManagedKeyword.cc index 4d6a97b119..9221372992 100644 --- a/projects/hip-tests/catch/TypeQualifiers/hipManagedKeyword.cc +++ b/projects/hip-tests/catch/TypeQualifiers/hipManagedKeyword.cc @@ -67,6 +67,17 @@ TEST_CASE("Unit_hipManagedKeyword_MultiGpu") { int numDevices = 0; HIP_CHECK(hipGetDeviceCount(&numDevices)); + for (int i = 0; i < numDevices; i++){ + int managed_memory = 0; + HIPCHECK(hipDeviceGetAttribute(&managed_memory, + hipDeviceAttributeManagedMemory, + i)); + if (!managed_memory) { + HipTest::HIP_SKIP_TEST("managed memory access not supported on device"); + return; + } + } + for (int i = 0; i < numDevices; i++) { HIP_CHECK(hipSetDevice(i)); GPU_func<<< 1, 1 >>>(); From 56ed440ee5d661419f3036d7dfb706aab6fa5f29 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 08:59:20 +0530 Subject: [PATCH 26/32] SWDEV-379359 - [catch2][dtest] hipGraphKernelNodeSetAttribute API test (#325) Change-Id: Iff63f523301031fc3f01b84475b9ee3c0a5bb236 [ROCm/hip-tests commit: 961435236fac59df62e65cdf0171f06d47f18360] --- .../hip-tests/catch/unit/graph/CMakeLists.txt | 1 + .../graph/hipGraphKernelNodeSetAttribute.cc | 370 ++++++++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 projects/hip-tests/catch/unit/graph/hipGraphKernelNodeSetAttribute.cc diff --git a/projects/hip-tests/catch/unit/graph/CMakeLists.txt b/projects/hip-tests/catch/unit/graph/CMakeLists.txt index 9ff1d63537..88a4fba56b 100644 --- a/projects/hip-tests/catch/unit/graph/CMakeLists.txt +++ b/projects/hip-tests/catch/unit/graph/CMakeLists.txt @@ -111,6 +111,7 @@ set(TEST_SRC hipGraphKernelNodeCopyAttributes.cc hipGraphCycle.cc hipGraphKernelNodeGetAttribute.cc + hipGraphKernelNodeSetAttribute.cc ) if(HIP_PLATFORM MATCHES "amd") diff --git a/projects/hip-tests/catch/unit/graph/hipGraphKernelNodeSetAttribute.cc b/projects/hip-tests/catch/unit/graph/hipGraphKernelNodeSetAttribute.cc new file mode 100644 index 0000000000..ac476b2546 --- /dev/null +++ b/projects/hip-tests/catch/unit/graph/hipGraphKernelNodeSetAttribute.cc @@ -0,0 +1,370 @@ +/* +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 +#include +#include + +/** +* @addtogroup hipGraphKernelNodeSetAttribute hipGraphKernelNodeSetAttribute +* @{ +* @ingroup GraphTest +* `hipGraphKernelNodeSetAttribute(hipGraphNode_t hNode, +* hipKernelNodeAttrID attr, const hipKernelNodeAttrValue* value )` - +* Sets node attribute. +*/ + +/** +* Test Description +* ------------------------ +*  - Functional Test for API - hipGraphKernelNodeSetAttribute +* 1) Check hipGraphKernelNodeSetAttribute for AccessPolicyWindow attributes +* 2) Check hipGraphKernelNodeSetAttribute for cooperative attributes +* 3) Check hipGraphKernelNodeSetAttribute for window cooperative attributes +* Test source +* ------------------------ +*  - unit/graph/hipGraphKernelNodeGetAttribute.cc +* Test requirements +* ------------------------ +*  - HIP_VERSION >= 5.6 +*/ + +static bool validateKernelNodeAttrValue(hipKernelNodeAttrValue in, + hipKernelNodeAttrValue out) { + if ((in.accessPolicyWindow.base_ptr != out.accessPolicyWindow.base_ptr) || + (in.accessPolicyWindow.hitProp != out.accessPolicyWindow.hitProp) || + (in.accessPolicyWindow.hitRatio != out.accessPolicyWindow.hitRatio) || + (in.accessPolicyWindow.missProp != out.accessPolicyWindow.missProp) || + (in.accessPolicyWindow.num_bytes != out.accessPolicyWindow.num_bytes) || + (in.cooperative != out.cooperative)) { + return false; + } + return true; +} + +TEST_CASE("Unit_hipGraphKernelNodeSetAttribute_Functional") { + constexpr size_t N = 1024; + constexpr size_t Nbytes = N * sizeof(int); + constexpr auto blocksPerCU = 6; // to hide latency + constexpr auto threadsPerBlock = 256; + hipGraph_t graph; + hipGraphExec_t graphExec; + hipGraphNode_t memcpy_A, memcpy_B, memcpy_C, kernel_vecAdd; + hipKernelNodeParams kNodeParams{}; + hipStream_t stream; + int *A_d, *B_d, *C_d; + int *A_h, *B_h, *C_h; + size_t NElem{N}; + + HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false); + unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N); + + HIP_CHECK(hipGraphCreate(&graph, 0)); + HIP_CHECK(hipStreamCreate(&stream)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpy_A, graph, nullptr, 0, A_d, A_h, + Nbytes, hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpy_B, graph, nullptr, 0, B_d, B_h, + Nbytes, hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpy_C, graph, nullptr, 0, C_h, C_d, + Nbytes, hipMemcpyDeviceToHost)); + + void* kernelArgs[] = {&A_d, &B_d, &C_d, reinterpret_cast(&NElem)}; + kNodeParams.func = reinterpret_cast(HipTest::vectorADD); + kNodeParams.gridDim = dim3(blocks); + kNodeParams.blockDim = dim3(threadsPerBlock); + kNodeParams.sharedMemBytes = 0; + kNodeParams.kernelParams = reinterpret_cast(kernelArgs); + kNodeParams.extra = nullptr; + HIP_CHECK(hipGraphAddKernelNode(&kernel_vecAdd, graph, nullptr, 0, + &kNodeParams)); + + // Create dependencies + HIP_CHECK(hipGraphAddDependencies(graph, &memcpy_A, &kernel_vecAdd, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &memcpy_B, &kernel_vecAdd, 1)); + HIP_CHECK(hipGraphAddDependencies(graph, &kernel_vecAdd, &memcpy_C, 1)); + + hipKernelNodeAttrValue value_in, value_out; + + SECTION("Check hipGraphKernelNodeSetAttribute for AccessPolicyWindow") { + memset(&value_in, 0, sizeof(hipKernelNodeAttrValue)); + memset(&value_out, 0, sizeof(hipKernelNodeAttrValue)); + + HIP_CHECK(hipGraphKernelNodeGetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in)); + + value_in.accessPolicyWindow.hitRatio = 0.8; + value_in.accessPolicyWindow.hitProp = hipAccessPropertyPersisting; + value_in.accessPolicyWindow.missProp = hipAccessPropertyStreaming; + + HIP_CHECK(hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in)); + + HIP_CHECK(hipGraphKernelNodeGetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_out)); + REQUIRE(true == validateKernelNodeAttrValue(value_in, value_out)); + } + SECTION("Check hipGraphKernelNodeSetAttribute for cooperative") { + memset(&value_in, 0, sizeof(hipKernelNodeAttrValue)); + memset(&value_out, 0, sizeof(hipKernelNodeAttrValue)); + + HIP_CHECK(hipGraphKernelNodeGetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in)); + + value_in.cooperative = 2; + + HIP_CHECK(hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in)); + + HIP_CHECK(hipGraphKernelNodeGetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_out)); + REQUIRE(true == validateKernelNodeAttrValue(value_in, value_out)); + } + + SECTION("Check hipGraphKernelNodeSetAttribute for window and cooperative") { + memset(&value_in, 0, sizeof(hipKernelNodeAttrValue)); + memset(&value_out, 0, sizeof(hipKernelNodeAttrValue)); + + HIP_CHECK(hipGraphKernelNodeGetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in)); + + value_in.cooperative = 8; + value_in.accessPolicyWindow.hitRatio = 0.1; + value_in.accessPolicyWindow.hitProp = hipAccessPropertyPersisting; + value_in.accessPolicyWindow.missProp = hipAccessPropertyNormal; + + HIP_CHECK(hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in)); + + HIP_CHECK(hipGraphKernelNodeGetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_out)); + REQUIRE(true == validateKernelNodeAttrValue(value_in, value_out)); + } + + // Instantiate and launch the graph + HIP_CHECK(hipGraphInstantiate(&graphExec, graph, NULL, NULL, 0)); + HIP_CHECK(hipGraphLaunch(graphExec, stream)); + HIP_CHECK(hipStreamSynchronize(stream)); + + // Verify graph execution result + HipTest::checkVectorADD(A_h, B_h, C_h, N); + + HipTest::freeArrays(A_d, B_d, C_d, A_h, B_h, C_h, false); + HIP_CHECK(hipGraphExecDestroy(graphExec)); + HIP_CHECK(hipGraphDestroy(graph)); + HIP_CHECK(hipStreamDestroy(stream)); +} + +/** +* Test Description +* ------------------------ +*  - Negative/argument Test for API - hipGraphKernelNodeSetAttribute +* 1) Pass kernel node as nullptr for Set attribute api and verify +* 2) Pass KernelNodeAttrID as invalid value for Set attribute api and verify +* 3) Pass KernelNodeAttrID as INT_MAX value for Get attribute api and verify +* 4) Pass KernelNodeAttrValue as nullptr for Set attribute api and verify +* 5) Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow +* and pass value missProp as hipAccessPropertyPersisting +* 6) Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow +* and pass value hitProp as hipAccessPropertyPersisting +* 7) Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow +* and pass value accessPolicyWindow.hitRatio as 1.4 +* 8) Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow +* and pass value accessPolicyWindow.hitRatio as 0 +* 9) Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow +* and pass value accessPolicyWindow.hitRatio as 1 +* 10) Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow +* and pass value accessPolicyWindow.hitRatio as -1.8 +* 11) Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow +* and pass value accessPolicyWindow.hitRatio as -0.6 +* 12) Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow +* and pass accessPolicyWindow.num_bytes as 1024 & hitRatio as 0.6 +* 13) Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow" +* and pass accessPolicyWindow.num_bytes as 1 GB & hitRatio as -0.6 +* 14) Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow +* and pass value accessPolicyWindow.num_bytes as 1 MB +* 15) Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow +* and pass value base_ptr as nullptr +* Test source +* ------------------------ +*  - unit/graph/hipGraphKernelNodeSetAttribute.cc +* Test requirements +* ------------------------ +*  - HIP_VERSION >= 5.6 +*/ + +TEST_CASE("Unit_hipGraphKernelNodeSetAttribute_Negative") { + constexpr size_t N = 1024; + constexpr size_t Nbytes = N * sizeof(int); + constexpr auto blocksPerCU = 6; // to hide latency + constexpr auto threadsPerBlock = 256; + hipGraph_t graph; + hipGraphNode_t memcpy_A, memcpy_B, memcpy_C, kernel_vecAdd; + hipKernelNodeParams kNodeParams{}; + hipStream_t stream; + int *A_d, *B_d, *C_d; + int *A_h, *B_h, *C_h; + size_t NElem{N}; + hipError_t ret; + + HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false); + unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N); + + HIP_CHECK(hipGraphCreate(&graph, 0)); + HIP_CHECK(hipStreamCreate(&stream)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpy_A, graph, nullptr, 0, A_d, A_h, + Nbytes, hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpy_B, graph, nullptr, 0, B_d, B_h, + Nbytes, hipMemcpyHostToDevice)); + HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpy_C, graph, nullptr, 0, C_h, C_d, + Nbytes, hipMemcpyDeviceToHost)); + + void* kernelArgs[] = {&A_d, &B_d, &C_d, reinterpret_cast(&NElem)}; + kNodeParams.func = reinterpret_cast(HipTest::vectorADD); + kNodeParams.gridDim = dim3(blocks); + kNodeParams.blockDim = dim3(threadsPerBlock); + kNodeParams.sharedMemBytes = 0; + kNodeParams.kernelParams = reinterpret_cast(kernelArgs); + kNodeParams.extra = nullptr; + HIP_CHECK(hipGraphAddKernelNode(&kernel_vecAdd, graph, nullptr, 0, + &kNodeParams)); + + hipKernelNodeAttrValue value_in, value_out; + memset(&value_in, 0, sizeof(hipKernelNodeAttrValue)); + memset(&value_out, 0, sizeof(hipKernelNodeAttrValue)); + HIP_CHECK(hipGraphKernelNodeGetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in)); + memcpy(&value_out, &value_in, sizeof(hipKernelNodeAttrValue)); + + SECTION("Pass kernel node as nullptr for Set attribute api") { + ret = hipGraphKernelNodeSetAttribute(nullptr, + hipKernelNodeAttributeAccessPolicyWindow, &value_in); + REQUIRE(hipErrorInvalidValue == ret); + } + SECTION("Pass KernelNodeAttrID as invalid value for Set attribute api") { + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttrID(-1), &value_in); + REQUIRE(hipErrorInvalidValue == ret); + } + SECTION("Pass KernelNodeAttrID as INT_MAX value for Set attribute api") { + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttrID(INT_MAX), &value_in); + REQUIRE(hipErrorInvalidValue == ret); + } +#if HT_AMD // getting SIGSEGV error in Cuda Setup + SECTION("Pass KernelNodeAttrValue as nullptr for Set attribute api") { + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, nullptr); + REQUIRE(hipErrorInvalidValue == ret); + } +#endif + SECTION("Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow" + " and pass value missProp as hipAccessPropertyPersisting") { + memcpy(&value_in, &value_out, sizeof(hipKernelNodeAttrValue)); + value_in.accessPolicyWindow.missProp = hipAccessPropertyPersisting; + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in); + REQUIRE(hipErrorInvalidValue == ret); + } + SECTION("Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow" + " and pass value hitProp as hipAccessPropertyPersisting") { + memcpy(&value_in, &value_out, sizeof(hipKernelNodeAttrValue)); + value_in.accessPolicyWindow.hitProp = hipAccessPropertyPersisting; + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in); + REQUIRE(hipSuccess == ret); + } + SECTION("Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow" + " and pass value accessPolicyWindow.hitRatio as 1.4") { + memcpy(&value_in, &value_out, sizeof(hipKernelNodeAttrValue)); + value_in.accessPolicyWindow.hitRatio = 1.4; + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in); + REQUIRE(hipErrorInvalidValue == ret); + } + SECTION("Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow" + " and pass value accessPolicyWindow.hitRatio as 0") { + memcpy(&value_in, &value_out, sizeof(hipKernelNodeAttrValue)); + value_in.accessPolicyWindow.hitRatio = 0; + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in); + REQUIRE(hipSuccess == ret); + } + SECTION("Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow" + " and pass value accessPolicyWindow.hitRatio as 1") { + memcpy(&value_in, &value_out, sizeof(hipKernelNodeAttrValue)); + value_in.accessPolicyWindow.hitRatio = 1; + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in); + REQUIRE(hipSuccess == ret); + } + SECTION("Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow" + " and pass value accessPolicyWindow.hitRatio as -1.8") { + memcpy(&value_in, &value_out, sizeof(hipKernelNodeAttrValue)); + value_in.accessPolicyWindow.hitRatio = -1.8; + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in); + REQUIRE(hipErrorInvalidValue == ret); + } + SECTION("Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow" + " and pass value accessPolicyWindow.hitRatio as -0.6") { + memcpy(&value_in, &value_out, sizeof(hipKernelNodeAttrValue)); + value_in.accessPolicyWindow.hitRatio = -0.6; + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in); + REQUIRE(hipErrorInvalidValue == ret); + } + SECTION("Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow" + " & pass accessPolicyWindow.num_bytes as 1024 & hitRatio as 0.6") { + memcpy(&value_in, &value_out, sizeof(hipKernelNodeAttrValue)); + value_in.accessPolicyWindow.num_bytes = 1024; + value_in.accessPolicyWindow.hitRatio = 0.6; + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in); + REQUIRE(hipErrorInvalidValue == ret); + } + SECTION("Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow" + " & pass accessPolicyWindow.num_bytes as 1 GB & hitRatio as -0.6") { + memcpy(&value_in, &value_out, sizeof(hipKernelNodeAttrValue)); + value_in.accessPolicyWindow.num_bytes = 1024 * 1024 * 1024; + value_in.accessPolicyWindow.hitRatio = -0.6; + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in); + REQUIRE(hipErrorInvalidValue == ret); + } + SECTION("Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow" + " and pass value accessPolicyWindow.num_bytes as 1 MB") { + memcpy(&value_in, &value_out, sizeof(hipKernelNodeAttrValue)); + value_in.accessPolicyWindow.num_bytes = 1024 * 1024; + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in); + REQUIRE(hipErrorInvalidValue == ret); + } + SECTION("Pass KernelNodeAttrID as hipKernelNodeAttributeAccessPolicyWindow" + " and pass value base_ptr as nullptr") { + memcpy(&value_in, &value_out, sizeof(hipKernelNodeAttrValue)); + value_in.accessPolicyWindow.base_ptr = nullptr; + ret = hipGraphKernelNodeSetAttribute(kernel_vecAdd, + hipKernelNodeAttributeAccessPolicyWindow, &value_in); + REQUIRE(hipSuccess == ret); + } + + HipTest::freeArrays(A_d, B_d, C_d, A_h, B_h, C_h, false); + HIP_CHECK(hipGraphDestroy(graph)); + HIP_CHECK(hipStreamDestroy(stream)); +} From 230833b77bd48e1811e9410f48f4cbf9e6b7614c Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 08:59:32 +0530 Subject: [PATCH 27/32] SWDEV-388937 - Re enable test (#328) Change-Id: I1a1ec2f370e3dff4ba0c952665f254d11548dc53 [ROCm/hip-tests commit: 01697418be8518012ba3b356fab85602a56dfefe] --- .../catch/hipTestMain/config/config_amd_linux_common.json | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json index d0a68fab84..67b5252719 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json @@ -22,7 +22,6 @@ "Unit_hipMemAdvise_No_Flag_Interference", "Unit_hipGraphDestroyNode_Complx_ChkNumOfNodesNDep", "Unit_hipGraphDestroyNode_Complx_ChkNumOfNodesNDep_ClonedGrph", - "Unit_hipGraphDestroyNode_Complx_ChkNumOfNodesNDep_ChldNode", "Unit_hipMemGetAddressRange_Negative", "NOTE: The following 2 tests are disabled due to defect - EXSWHTEC-238", "Unit_hipDrvMemcpy3D_Positive_Array", From 428a6078840a25277cd841b30e595af417014718 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 08:59:50 +0530 Subject: [PATCH 28/32] SWDEV-400119 - Added Unit_hipMemGetInfo_FreeLessThanTotal (#329) Change-Id: Ia023d41ce4f941a03bccb8bf7dd59021e19d83b8 [ROCm/hip-tests commit: 839f3f5f02a5f6dc3ac93df5997993f90e343349] --- .../hip-tests/catch/unit/memory/hipMemGetInfo.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/projects/hip-tests/catch/unit/memory/hipMemGetInfo.cc b/projects/hip-tests/catch/unit/memory/hipMemGetInfo.cc index 24d42bd8b4..80feaeb239 100644 --- a/projects/hip-tests/catch/unit/memory/hipMemGetInfo.cc +++ b/projects/hip-tests/catch/unit/memory/hipMemGetInfo.cc @@ -574,3 +574,18 @@ TEST_CASE("Unit_hipMemGetInfo_Negative") { HIP_CHECK(hipFree(A_mem)); } + +TEST_CASE("Unit_hipMemGetInfo_FreeLessThanTotal") { + unsigned int *A_mem{nullptr}; + size_t freeMemInit, totalMemInit; + size_t freeMem, totalMem; + + HIP_CHECK(hipMemGetInfo(&freeMemInit, &totalMemInit)); + REQUIRE(freeMemInit <= totalMemInit); + HIP_CHECK(hipMalloc(&A_mem, 1024)); + HIP_CHECK(hipMemGetInfo(&freeMem, &totalMem)); + REQUIRE(freeMem < totalMem); + REQUIRE(totalMem == totalMemInit); + + HIP_CHECK(hipFree(A_mem)); +} From 455aa631a9b419655e1bd7ed0112e49d65b796a2 Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 09:04:30 +0530 Subject: [PATCH 29/32] SWDEV-388937, SWDEV-388930 - Re-enable previously skipped tests (#334) * SWDEV-388937, SWDEV-388930 - Re-enable previously skipped tests Change-Id: I5849c137cde2d37a8f1cca7dd701b3e1eba3cbc2 [ROCm/hip-tests commit: 4bafb63c02903123b34f041bbc2c2e5fc6daaeb0] --- .../catch/hipTestMain/config/config_amd_linux_common.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json index 67b5252719..a360f7fb16 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json @@ -20,8 +20,6 @@ "Unit_hipKernelNameRef_Negative_Parameters", "Unit_hipMemAdvise_AccessedBy_All_Devices", "Unit_hipMemAdvise_No_Flag_Interference", - "Unit_hipGraphDestroyNode_Complx_ChkNumOfNodesNDep", - "Unit_hipGraphDestroyNode_Complx_ChkNumOfNodesNDep_ClonedGrph", "Unit_hipMemGetAddressRange_Negative", "NOTE: The following 2 tests are disabled due to defect - EXSWHTEC-238", "Unit_hipDrvMemcpy3D_Positive_Array", From 726c83a48b2b5cdddf1a1cdddeb8f79c8d8cc7af Mon Sep 17 00:00:00 2001 From: ROCm CI Service Account <66695075+rocm-ci@users.noreply.github.com> Date: Thu, 29 Jun 2023 09:04:53 +0530 Subject: [PATCH 30/32] SWDEV-398980 - Fix Unit_hipMemcpyPeer_Positive_Synchronization_Behavior (#335) Change-Id: I8ed51134a351f5303c10c9cfad8485e1493bec4d [ROCm/hip-tests commit: 1ab7f46fdad243821dccef2ef64f0bc7a03092b0] --- .../catch/hipTestMain/config/config_amd_linux_common.json | 2 -- projects/hip-tests/catch/unit/memory/hipMemcpyPeer.cc | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json index a360f7fb16..1a7f2056c7 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json @@ -63,8 +63,6 @@ "Unit_hipMemcpyWithStream_MultiThread", "SWDEV-398977 fails in stress tests", "Unit_hipMemset2DSync", - "SWDEV-398980 fails in Stress test", - "Unit_hipMemcpyPeer_Positive_Synchronization_Behavior", "SWDEV-398981 fails in stress test", "Unit_hipStreamCreateWithPriority_MulthreadDefaultflag", "=== Below tests fail in stress test on 23/06/23 ===", diff --git a/projects/hip-tests/catch/unit/memory/hipMemcpyPeer.cc b/projects/hip-tests/catch/unit/memory/hipMemcpyPeer.cc index 95698b63df..c04a84c027 100644 --- a/projects/hip-tests/catch/unit/memory/hipMemcpyPeer.cc +++ b/projects/hip-tests/catch/unit/memory/hipMemcpyPeer.cc @@ -125,6 +125,7 @@ TEST_CASE("Unit_hipMemcpyPeer_Positive_Synchronization_Behavior") { LinearAllocGuard src_alloc(LinearAllocs::hipMalloc, kPageSize); HIP_CHECK(hipSetDevice(dst_device)); LinearAllocGuard dst_alloc(LinearAllocs::hipMalloc, kPageSize); + LaunchDelayKernel(std::chrono::milliseconds{100}, nullptr); HIP_CHECK(hipSetDevice(src_device)); LaunchDelayKernel(std::chrono::milliseconds{100}, nullptr); From 362da9a9f1f3b5e9e0b0bbac64ba3b1fde3ca2d9 Mon Sep 17 00:00:00 2001 From: Jatin Chaudhary <51944368+cjatin@users.noreply.github.com> Date: Tue, 4 Jul 2023 06:19:19 +0100 Subject: [PATCH 31/32] SWDEV-408621 - Fix windows CI breakage (#343) Change-Id: I8e7f8b614cee917214c3eec0023fe1c4c68d991a [ROCm/hip-tests commit: fe9515a99a58ae38bcfb87b3a4f94123c3c21ff5] --- .../hip-tests/catch/unit/graph/CMakeLists.txt | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/projects/hip-tests/catch/unit/graph/CMakeLists.txt b/projects/hip-tests/catch/unit/graph/CMakeLists.txt index 88a4fba56b..034063060f 100644 --- a/projects/hip-tests/catch/unit/graph/CMakeLists.txt +++ b/projects/hip-tests/catch/unit/graph/CMakeLists.txt @@ -18,7 +18,11 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -# 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 hipGraphAddEmptyNode.cc hipGraphAddDependencies.cc @@ -65,7 +69,20 @@ set(TEST_SRC hipStreamBeginCapture.cc hipStreamBeginCapture_old.cc hipStreamIsCapturing.cc - hipStreamIsCapturing_old.cc + hipStreamIsCapturing_old.cc) + +if(HIP_PLATFORM MATCHES "amd") + set(AMD_SRC + hipStreamCaptureExtModuleLaunchKernel.cc + ) + set(TEST_SRC ${TEST_SRC} ${AMD_SRC}) +endif() + +hip_add_exe_to_target(NAME GraphsTest1 + TEST_SRC ${TEST_SRC} + TEST_TARGET_NAME build_tests) + +set(TEST_SRC hipStreamGetCaptureInfo.cc hipStreamGetCaptureInfo_old.cc hipStreamEndCapture.cc @@ -111,17 +128,9 @@ set(TEST_SRC hipGraphKernelNodeCopyAttributes.cc hipGraphCycle.cc hipGraphKernelNodeGetAttribute.cc - hipGraphKernelNodeSetAttribute.cc -) + hipGraphKernelNodeSetAttribute.cc) -if(HIP_PLATFORM MATCHES "amd") - set(AMD_SRC - hipStreamCaptureExtModuleLaunchKernel.cc - ) - set(TEST_SRC ${TEST_SRC} ${AMD_SRC}) -endif() - -hip_add_exe_to_target(NAME GraphsTest +hip_add_exe_to_target(NAME GraphsTest2 TEST_SRC ${TEST_SRC} TEST_TARGET_NAME build_tests) From 276fc44d34e7caeaa72d82fdbdffbb0d557bdbb2 Mon Sep 17 00:00:00 2001 From: Maneesh Gupta Date: Thu, 6 Jul 2023 14:21:34 +0530 Subject: [PATCH 32/32] Update config_amd_linux_common.json Disable unstable tests based on stress testing - 30Jun [ROCm/hip-tests commit: dfa8015901316bd0e9798a7922bd563dfed00133] --- .../catch/hipTestMain/config/config_amd_linux_common.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json index 1a7f2056c7..b9c0e7c79f 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux_common.json @@ -81,6 +81,10 @@ "Unit_hipGraphClone_Test_hipGraphExecMemcpyNodeSetParams", "Unit_hipGraphClone_Test_hipGraphMemcpyNodeSetParams1D_and_exec", "Unit_hipStreamValue_Wait64_Blocking_NoMask_And", - "Unit_hipStreamValue_Wait64_Blocking_NoMask_Nor" + "Unit_hipStreamValue_Wait64_Blocking_NoMask_Nor", + "=== Below tests fail in stress test on 30/06/23 ===", + "Unit_hipStreamValue_Wait32_Blocking_NoMask_Nor", + "Unit_hipStreamValue_Write - TestParams", + "Unit_hipMemcpyParam2DAsync_multiDevice-StreamOnDiffDevice" ] }