SWDEV-299127 - Merge 'develop' into 'amd-staging'
Change-Id: I126fc5009ed46697b2af46b4726902895251b0b4
Этот коммит содержится в:
поставляемый
+4
-4
@@ -28,7 +28,7 @@ def hipBuildTest(String backendLabel) {
|
||||
}
|
||||
}
|
||||
}
|
||||
stage("Build - HIT framework") {
|
||||
stage("Build - HIT framework ${backendLabel}") {
|
||||
// Running the build on hipamd workspace
|
||||
dir("${WORKSPACE}/hipamd") {
|
||||
sh """#!/usr/bin/env bash
|
||||
@@ -52,7 +52,7 @@ def hipBuildTest(String backendLabel) {
|
||||
}
|
||||
}
|
||||
timeout(time: 1, unit: 'HOURS') {
|
||||
stage('HIP Unit Tests - HIT framework') {
|
||||
stage('HIP Unit Tests - HIT framework ${backendLabel}') {
|
||||
dir("${WORKSPACE}/hipamd/build") {
|
||||
sh """#!/usr/bin/env bash
|
||||
set -x
|
||||
@@ -67,7 +67,7 @@ def hipBuildTest(String backendLabel) {
|
||||
}
|
||||
}
|
||||
}
|
||||
stage("Build - Catch2 framework") {
|
||||
stage("Build - Catch2 framework ${backendLabel}") {
|
||||
// Running the build on hipamd workspace
|
||||
dir("${WORKSPACE}/hipamd") {
|
||||
sh """#!/usr/bin/env bash
|
||||
@@ -94,7 +94,7 @@ def hipBuildTest(String backendLabel) {
|
||||
}
|
||||
}
|
||||
timeout(time: 1, unit: 'HOURS') {
|
||||
stage('HIP Unit Tests - Catch2 framework') {
|
||||
stage('HIP Unit Tests - Catch2 framework ${backendLabel}') {
|
||||
dir("${WORKSPACE}/hipamd/build") {
|
||||
sh """#!/usr/bin/env bash
|
||||
set -x
|
||||
|
||||
@@ -187,11 +187,6 @@ if ($HIP_PLATFORM eq "amd") {
|
||||
print ("HIP_CLANG_TARGET=$HIP_CLANG_TARGET\n");
|
||||
}
|
||||
|
||||
if ($isWindows) {
|
||||
$HIPCXXFLAGS .= " -std=c++14 -fms-extensions -fms-compatibility";
|
||||
} else {
|
||||
$HIPCXXFLAGS .= " -std=c++11";
|
||||
}
|
||||
$HIPCXXFLAGS .= " -isystem \"$HIP_CLANG_INCLUDE_PATH/..\"";
|
||||
$HIPCFLAGS .= " -isystem \"$HIP_CLANG_INCLUDE_PATH/..\"";
|
||||
$HIPLDFLAGS .= " -L\"$HIP_LIB_PATH\"";
|
||||
|
||||
@@ -142,7 +142,7 @@ typedef enum HIPresourcetype_enum {
|
||||
HIP_RESOURCE_TYPE_MIPMAPPED_ARRAY = 0x01, /**< Mipmapped array resource */
|
||||
HIP_RESOURCE_TYPE_LINEAR = 0x02, /**< Linear resource */
|
||||
HIP_RESOURCE_TYPE_PITCH2D = 0x03 /**< Pitch 2D resource */
|
||||
} HIPresourcetype;
|
||||
} HIPresourcetype, hipResourcetype;
|
||||
/**
|
||||
* hip address modes
|
||||
*/
|
||||
|
||||
@@ -1842,7 +1842,7 @@ hipError_t hipGetLastError(void);
|
||||
*/
|
||||
hipError_t hipPeekAtLastError(void);
|
||||
/**
|
||||
* @brief Return name of the specified error code in text form.
|
||||
* @brief Return hip error as text string form.
|
||||
*
|
||||
* @param hip_error Error code to convert to name.
|
||||
* @return const char pointer to the NULL-terminated error name
|
||||
@@ -1856,11 +1856,29 @@ const char* hipGetErrorName(hipError_t hip_error);
|
||||
* @param hipError Error code to convert to string.
|
||||
* @return const char pointer to the NULL-terminated error string
|
||||
*
|
||||
* @warning : on HCC, this function returns the name of the error (same as hipGetErrorName)
|
||||
*
|
||||
* @see hipGetErrorName, hipGetLastError, hipPeakAtLastError, hipError_t
|
||||
*/
|
||||
const char* hipGetErrorString(hipError_t hipError);
|
||||
/**
|
||||
* @brief Return hip error as text string form.
|
||||
*
|
||||
* @param [in] hipError Error code to convert to string.
|
||||
* @param [out] const char pointer to the NULL-terminated error string
|
||||
* @return #hipSuccess, #hipErrorInvalidValue
|
||||
*
|
||||
* @see hipGetErrorName, hipGetLastError, hipPeakAtLastError, hipError_t
|
||||
*/
|
||||
hipError_t hipDrvGetErrorName(hipError_t hipError, const char** errorString);
|
||||
/**
|
||||
* @brief Return handy text string message to explain the error which occurred
|
||||
*
|
||||
* @param [in] hipError Error code to convert to string.
|
||||
* @param [out] const char pointer to the NULL-terminated error string
|
||||
* @return #hipSuccess, #hipErrorInvalidValue
|
||||
*
|
||||
* @see hipGetErrorName, hipGetLastError, hipPeakAtLastError, hipError_t
|
||||
*/
|
||||
hipError_t hipDrvGetErrorString(hipError_t hipError, const char** errorString);
|
||||
// end doxygen Error
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -5,19 +5,11 @@
|
||||
"Unit_printf_flags",
|
||||
"Unit_printf_specifier",
|
||||
"Unit_hipTextureMipmapObj2D_Check",
|
||||
"Unit_hipManagedKeyword_MultiGpu",
|
||||
"Unit_hipGraphAddHostNode_ClonedGraphwithHostNode",
|
||||
"Unit_hipEventIpc",
|
||||
"Unit_hipMalloc3D_Negative",
|
||||
"Unit_hipPointerGetAttribute_MappedMem",
|
||||
"Unit_hipStreamBeginCapture_BasicFunctional",
|
||||
"Unit_hipStreamBeginCapture_hipStreamPerThread",
|
||||
"Unit_hiprtc_functional",
|
||||
"Unit_hipStreamValue_Write",
|
||||
"Unit_hipStreamGetCaptureInfo_BasicFunctional",
|
||||
"Unit_hipStreamGetCaptureInfo_hipStreamPerThread",
|
||||
"Unit_hipStreamGetCaptureInfo_UniqueID",
|
||||
"Unit_hipStreamGetCaptureInfo_ArgValidation",
|
||||
"Unit_hipMemPoolApi_Basic",
|
||||
"Unit_hipMemPoolApi_BasicAlloc",
|
||||
"Unit_hipMemPoolApi_BasicTrim",
|
||||
@@ -41,9 +33,18 @@
|
||||
"Unit_hipArrayCreate_happy - float2",
|
||||
"Unit_hipArrayCreate_happy - float4",
|
||||
"Unit_hipMemVmm_Basic",
|
||||
"Unit_hipGraphKernelNodeSetParams_Functional",
|
||||
"Unit_hipGraphExecKernelNodeSetParams_Negative",
|
||||
"Unit_hipGraphExecKernelNodeSetParams_Functional",
|
||||
"Unit_hipGraphMemcpyNodeSetParams1D_Functional"
|
||||
"Unit_hipGraphExecMemcpyNodeSetParamsToSymbol_Functional",
|
||||
"Unit_hipMallocManaged_MultiChunkMultiDevice",
|
||||
"Unit_hipMallocManaged_TwoPointers - int",
|
||||
"Unit_hipMallocManaged_TwoPointers - float",
|
||||
"Unit_hipMallocManaged_TwoPointers - double",
|
||||
"Unit_hipMallocManaged_DeviceContextChange - unsigned char",
|
||||
"Unit_hipMallocManaged_DeviceContextChange - int",
|
||||
"Unit_hipMallocManaged_DeviceContextChange - float",
|
||||
"Unit_hipMallocManaged_DeviceContextChange - double",
|
||||
"Unit_hipGraphNodeGetDependentNodes_Functional",
|
||||
"Unit_hipGraphNodeGetDependentNodes_ParamValidation",
|
||||
"Unit_hipGraphNodeGetDependencies_Functional",
|
||||
"Unit_hipGraphNodeGetDependencies_ParamValidation"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ Testcase Scenarios :
|
||||
* Defines
|
||||
*/
|
||||
#define LIB_ROCMSMI "librocm_smi64.so"
|
||||
#define ALLOC_SIZE (1*1024*1024)
|
||||
#define ALLOC_SIZE (30*1024*1024)
|
||||
|
||||
/**
|
||||
* Global variables
|
||||
@@ -221,7 +221,11 @@ static bool validatePageTableAllocations(const char *devList, int visDevCnt) {
|
||||
}
|
||||
|
||||
for (indx = 0; indx < numdev; indx++) {
|
||||
if (current[indx] - prev[indx])
|
||||
// For visible hip devices, there should be increase in VRAM usage
|
||||
// due to page table allocations
|
||||
// For NON visible hip devices, there can be reduction in VRAM usage
|
||||
// due to removal of page tables from them
|
||||
if (current[indx] > prev[indx])
|
||||
changeCnt++;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,9 @@ set(TEST_SRC
|
||||
hipGraphExecKernelNodeSetParams.cc
|
||||
hipGraphLaunch.cc
|
||||
hipGraphMemcpyNodeSetParams1D.cc
|
||||
hipGraphExecMemcpyNodeSetParamsToSymbol.cc
|
||||
hipGraphNodeGetDependentNodes.cc
|
||||
hipGraphNodeGetDependencies.cc
|
||||
)
|
||||
|
||||
hip_add_exe_to_target(NAME GraphsTest
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, 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 of hipGraphExecMemcpyNodeSetParamsToSymbol API:
|
||||
Functional :
|
||||
1) Allocate global symbol memory, Instantiate a graph with memcpy node,
|
||||
obtain executable graph and update the node params with set exec api call.
|
||||
Make sure they are taking effect.
|
||||
2) Allocate const symbol memory, Instantiate a graph with memcpy node,
|
||||
obtain executable graph and update the node params with set exec api call.
|
||||
Make sure they are taking effect.
|
||||
Negative :
|
||||
1) Pass hGraphExec as nullptr and check if api returns error.
|
||||
2) Pass GraphNode as nullptr and check if api returns error.
|
||||
3) Pass symbol ptr as nullptr, api expected to return error code.
|
||||
4) Pass source ptr as nullptr, api expected to return error code.
|
||||
5) Pass count as zero, api expected to return error code.
|
||||
6) Pass offset+count greater than allocated size, api expected to return error code.
|
||||
7) Pass same symbol pointer as source ptr and destination ptr, api expected to return error code.
|
||||
8) Pass Pass both dstn ptr and source ptr as 2 different symbol ptr, api expected to return error code.
|
||||
9) Copy from device ptr to host ptr but pass kind as different, api expected to return error code.
|
||||
10) Check with other graph node but pass same graphExec, api expected to return error code.
|
||||
*/
|
||||
|
||||
#include <hip_test_common.hh>
|
||||
#include <hip_test_checkers.hh>
|
||||
#include <limits>
|
||||
#define SIZE 256
|
||||
|
||||
__device__ int globalIn[SIZE], globalOut[SIZE];
|
||||
__device__ __constant__ int globalConst[SIZE];
|
||||
|
||||
__global__ void MemcpyToSymbolExecKernel(int* B_d) {
|
||||
for (int i = 0 ; i < SIZE; i++) {
|
||||
B_d[i] = globalIn[i];
|
||||
}
|
||||
}
|
||||
|
||||
__global__ void MemcpyToConstSymbolExecKernel(int* B_d) {
|
||||
for (int i = 0 ; i < SIZE; i++) {
|
||||
B_d[i] = globalConst[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* This testcase verifies negative scenarios of
|
||||
hipGraphExecMemcpyNodeSetParamsToSymbol API */
|
||||
TEST_CASE("Unit_hipGraphExecMemcpyNodeSetParamsToSymbol_Negative") {
|
||||
constexpr size_t Nbytes = SIZE * sizeof(int);
|
||||
int *A_d{nullptr}, *B_d{nullptr}, *C_d{nullptr};
|
||||
int *A_h{nullptr}, *B_h{nullptr};
|
||||
HipTest::initArrays<int>(&A_d, &B_d, &C_d,
|
||||
&A_h, &B_h, nullptr, SIZE, false);
|
||||
|
||||
hipGraph_t graph;
|
||||
hipError_t ret;
|
||||
hipGraphExec_t graphExec;
|
||||
hipGraphNode_t memcpyToSymbolNode, memcpyH2D;
|
||||
std::vector<hipGraphNode_t> dependencies;
|
||||
HIP_CHECK(hipGraphCreate(&graph, 0));
|
||||
|
||||
// Adding MemcpyNode
|
||||
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D, graph, nullptr, 0, A_d, A_h,
|
||||
Nbytes, hipMemcpyHostToDevice));
|
||||
dependencies.push_back(memcpyH2D);
|
||||
|
||||
HIP_CHECK(hipGraphAddMemcpyNodeToSymbol(&memcpyToSymbolNode, graph,
|
||||
dependencies.data(),
|
||||
dependencies.size(),
|
||||
HIP_SYMBOL(globalIn),
|
||||
C_d, Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice));
|
||||
dependencies.clear();
|
||||
dependencies.push_back(memcpyToSymbolNode);
|
||||
|
||||
HIP_CHECK(hipGraphMemcpyNodeSetParamsToSymbol(memcpyToSymbolNode,
|
||||
HIP_SYMBOL(globalIn), A_d,
|
||||
Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice));
|
||||
|
||||
// Instantiate the graph
|
||||
HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0));
|
||||
|
||||
SECTION("Pass hGraphExec as nullptr") {
|
||||
ret = hipGraphExecMemcpyNodeSetParamsToSymbol(nullptr,
|
||||
memcpyToSymbolNode,
|
||||
HIP_SYMBOL(globalIn),
|
||||
B_d, Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice);
|
||||
REQUIRE(hipErrorInvalidValue == ret);
|
||||
}
|
||||
SECTION("Pass GraphNode as nullptr") {
|
||||
ret = hipGraphExecMemcpyNodeSetParamsToSymbol(graphExec,
|
||||
nullptr,
|
||||
HIP_SYMBOL(globalIn),
|
||||
B_d, Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice);
|
||||
REQUIRE(hipErrorInvalidValue == ret);
|
||||
}
|
||||
SECTION("Pass symbol ptr as nullptr") {
|
||||
ret = hipGraphExecMemcpyNodeSetParamsToSymbol(graphExec,
|
||||
memcpyToSymbolNode,
|
||||
nullptr,
|
||||
B_d, Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice);
|
||||
REQUIRE(hipErrorInvalidSymbol == ret);
|
||||
}
|
||||
SECTION("Pass source ptr as nullptr") {
|
||||
ret = hipGraphExecMemcpyNodeSetParamsToSymbol(graphExec,
|
||||
memcpyToSymbolNode,
|
||||
HIP_SYMBOL(globalIn),
|
||||
nullptr, Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice);
|
||||
REQUIRE(hipErrorInvalidValue == ret);
|
||||
}
|
||||
SECTION("Pass count as zero") {
|
||||
ret = hipGraphExecMemcpyNodeSetParamsToSymbol(graphExec,
|
||||
memcpyToSymbolNode,
|
||||
HIP_SYMBOL(globalIn),
|
||||
B_d, 0, 0,
|
||||
hipMemcpyDeviceToDevice);
|
||||
REQUIRE(hipErrorInvalidValue == ret);
|
||||
}
|
||||
SECTION("Pass offset+count greater than allocated size") {
|
||||
ret = hipGraphExecMemcpyNodeSetParamsToSymbol(graphExec,
|
||||
memcpyToSymbolNode,
|
||||
HIP_SYMBOL(globalIn),
|
||||
B_d, Nbytes, 10,
|
||||
hipMemcpyDeviceToDevice);
|
||||
REQUIRE(hipErrorInvalidValue == ret);
|
||||
}
|
||||
SECTION("Pass same symbol pointer as source ptr and destination ptr") {
|
||||
ret = hipGraphExecMemcpyNodeSetParamsToSymbol(graphExec,
|
||||
memcpyToSymbolNode,
|
||||
HIP_SYMBOL(globalIn),
|
||||
HIP_SYMBOL(globalIn),
|
||||
Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice);
|
||||
REQUIRE(hipErrorInvalidValue == ret);
|
||||
}
|
||||
SECTION("Pass both dstn ptr and source ptr as 2 different symbol ptr") {
|
||||
ret = hipGraphExecMemcpyNodeSetParamsToSymbol(graphExec,
|
||||
memcpyToSymbolNode,
|
||||
HIP_SYMBOL(globalIn),
|
||||
HIP_SYMBOL(globalOut),
|
||||
Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice);
|
||||
REQUIRE(hipErrorInvalidValue == ret);
|
||||
}
|
||||
SECTION("Copy from device ptr to host ptr but pass kind as different") {
|
||||
ret = hipGraphExecMemcpyNodeSetParamsToSymbol(graphExec,
|
||||
memcpyToSymbolNode,
|
||||
HIP_SYMBOL(globalIn),
|
||||
B_h,
|
||||
Nbytes, 0,
|
||||
hipMemcpyDeviceToHost);
|
||||
REQUIRE(hipSuccess != ret);
|
||||
}
|
||||
SECTION("Check with other graph node but pass same graphExec") {
|
||||
hipGraph_t graph1;
|
||||
hipGraphNode_t memcpyToSymbolNode1{};
|
||||
HIP_CHECK(hipGraphCreate(&graph1, 0));
|
||||
HIP_CHECK(hipGraphAddMemcpyNodeToSymbol(&memcpyToSymbolNode1, graph1,
|
||||
nullptr,
|
||||
0,
|
||||
HIP_SYMBOL(globalOut),
|
||||
A_d, Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice));
|
||||
ret = hipGraphExecMemcpyNodeSetParamsToSymbol(graphExec,
|
||||
memcpyToSymbolNode1,
|
||||
HIP_SYMBOL(globalOut),
|
||||
HIP_SYMBOL(globalIn),
|
||||
Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice);
|
||||
REQUIRE(hipErrorInvalidValue == ret);
|
||||
}
|
||||
|
||||
HipTest::freeArrays<int>(A_d, B_d, C_d,
|
||||
A_h, B_h, nullptr, false);
|
||||
HIP_CHECK(hipGraphExecDestroy(graphExec));
|
||||
HIP_CHECK(hipGraphDestroy(graph));
|
||||
}
|
||||
|
||||
static
|
||||
void hipGraphExecMemcpyNodeSetParamsToSymbol_GlobalMem(bool useConstVar) {
|
||||
constexpr size_t Nbytes = SIZE * sizeof(int);
|
||||
constexpr auto blocksPerCU = 6; // to hide latency
|
||||
constexpr auto threadsPerBlock = 256;
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, SIZE);
|
||||
hipGraphNode_t memcpytosymbolkernel, memcpyD2H_B;
|
||||
hipKernelNodeParams kernelNodeParams{};
|
||||
int *A_d{nullptr}, *B_d{nullptr}, *C_d{nullptr};
|
||||
int *A_h{nullptr}, *B_h{nullptr};
|
||||
HipTest::initArrays<int>(&A_d, &B_d, &C_d,
|
||||
&A_h, &B_h, nullptr, SIZE, false);
|
||||
|
||||
hipGraph_t graph;
|
||||
hipGraphExec_t graphExec;
|
||||
hipGraphNode_t memcpyToSymbolNode, memcpyH2D_A;
|
||||
std::vector<hipGraphNode_t> dependencies;
|
||||
HIP_CHECK(hipGraphCreate(&graph, 0));
|
||||
|
||||
// Adding MemcpyNode
|
||||
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, 0, A_d, A_h,
|
||||
Nbytes, hipMemcpyHostToDevice));
|
||||
dependencies.push_back(memcpyH2D_A);
|
||||
|
||||
if (useConstVar) {
|
||||
HIP_CHECK(hipGraphAddMemcpyNodeToSymbol(&memcpyToSymbolNode, graph,
|
||||
dependencies.data(),
|
||||
dependencies.size(),
|
||||
HIP_SYMBOL(globalConst),
|
||||
C_d, Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice));
|
||||
} else {
|
||||
HIP_CHECK(hipGraphAddMemcpyNodeToSymbol(&memcpyToSymbolNode, graph,
|
||||
dependencies.data(),
|
||||
dependencies.size(),
|
||||
HIP_SYMBOL(globalIn),
|
||||
C_d, Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice));
|
||||
}
|
||||
dependencies.clear();
|
||||
dependencies.push_back(memcpyToSymbolNode);
|
||||
|
||||
// Adding Kernel node
|
||||
void* kernelArgs1[] = {&B_d};
|
||||
if (useConstVar) {
|
||||
kernelNodeParams.func =
|
||||
reinterpret_cast<void *>(MemcpyToConstSymbolExecKernel);
|
||||
} else {
|
||||
kernelNodeParams.func = reinterpret_cast<void *>(MemcpyToSymbolExecKernel);
|
||||
}
|
||||
kernelNodeParams.gridDim = dim3(blocks);
|
||||
kernelNodeParams.blockDim = dim3(threadsPerBlock);
|
||||
kernelNodeParams.sharedMemBytes = 0;
|
||||
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgs1);
|
||||
kernelNodeParams.extra = nullptr;
|
||||
HIP_CHECK(hipGraphAddKernelNode(&memcpytosymbolkernel, graph,
|
||||
dependencies.data(), dependencies.size(),
|
||||
&kernelNodeParams));
|
||||
dependencies.clear();
|
||||
dependencies.push_back(memcpytosymbolkernel);
|
||||
|
||||
// Adding MemcpyNode
|
||||
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H_B, graph, dependencies.data(),
|
||||
dependencies.size(), B_h, B_d,
|
||||
Nbytes, hipMemcpyDeviceToHost));
|
||||
|
||||
// Instantiate the graph
|
||||
HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0));
|
||||
|
||||
// Update the node with source pointer from C_d to A_d
|
||||
if (useConstVar) {
|
||||
HIP_CHECK(hipGraphExecMemcpyNodeSetParamsToSymbol(graphExec,
|
||||
memcpyToSymbolNode,
|
||||
HIP_SYMBOL(globalConst), A_d,
|
||||
Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice));
|
||||
} else {
|
||||
HIP_CHECK(hipGraphExecMemcpyNodeSetParamsToSymbol(graphExec,
|
||||
memcpyToSymbolNode,
|
||||
HIP_SYMBOL(globalIn), A_d,
|
||||
Nbytes, 0,
|
||||
hipMemcpyDeviceToDevice));
|
||||
}
|
||||
|
||||
HIP_CHECK(hipGraphLaunch(graphExec, 0));
|
||||
|
||||
// Validating the result
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
if (B_h[i] != A_h[i]) {
|
||||
WARN("Validation failed B_h[i] " << B_h[i] << "A_h[i] " << A_h[i]);
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
|
||||
HipTest::freeArrays<int>(A_d, B_d, C_d,
|
||||
A_h, B_h, nullptr, false);
|
||||
HIP_CHECK(hipGraphExecDestroy(graphExec));
|
||||
HIP_CHECK(hipGraphDestroy(graph));
|
||||
}
|
||||
|
||||
/* Test verifies hipGraphExecMemcpyNodeSetParamsToSymbol Functional scenario.
|
||||
1) Allocate global symbol memory, Instantiate a graph with memcpy node,
|
||||
obtain executable graph and update the node params with set exec api call.
|
||||
Make sure they are taking effect.
|
||||
2) Allocate const symbol memory, Instantiate a graph with memcpy node,
|
||||
obtain executable graph and update the node params with set exec api call.
|
||||
Make sure they are taking effect.
|
||||
*/
|
||||
TEST_CASE("Unit_hipGraphExecMemcpyNodeSetParamsToSymbol_Functional") {
|
||||
SECTION("Check and update with Global Device Symbol Memory") {
|
||||
hipGraphExecMemcpyNodeSetParamsToSymbol_GlobalMem(false);
|
||||
}
|
||||
SECTION("Check and update with Constant Global Device Symbol Memory") {
|
||||
hipGraphExecMemcpyNodeSetParamsToSymbol_GlobalMem(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, 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
|
||||
------------------
|
||||
Functional:
|
||||
1) Create a graph and add nodes with dependencies. Try to fetch dependencies of a node added and verify the api returns the node's
|
||||
dependencies that were defined.
|
||||
2) When pDependencies is passed as nullptr, verify pNumDependencies returns actual number of dependencies of node.
|
||||
3) When pNumDependencies is higher than the actual number of dependencies, the remaining entries in pDependencies will be set to NULL,
|
||||
and the number of nodes actually obtained will be returned in pNumDependencies.
|
||||
4) When pNumDependencies is lesser than the actual number of dependencies, api should return the requested number of dependencies.
|
||||
|
||||
Argument Validation:
|
||||
1) Verify the api returns pNumDependencies(0) when node passed is a root node.
|
||||
2) Pass node as nullptr and verify api doesn’t crash, returns error code.
|
||||
3) Pass pNumDependencies as nullptr and verify api doesn’t crash, returns error code.
|
||||
4) Pass node as un-initialized/invalid parameter and verify api returns error code.
|
||||
|
||||
*/
|
||||
|
||||
#include <hip_test_common.hh>
|
||||
#include <hip_test_checkers.hh>
|
||||
#include <hip_test_kernels.hh>
|
||||
|
||||
static __global__ void updateResult(int* C_d, int* Res_d, int 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) {
|
||||
Res_d[i] = C_d[i] + val;
|
||||
}
|
||||
}
|
||||
|
||||
static __global__ void vectorSum(const int* A_d, const int* B_d,
|
||||
const int* C_d, int* Res_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) {
|
||||
Res_d[i] = A_d[i] + B_d[i] + C_d[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify api when GetDependencies is requested
|
||||
* for actual number of nodes.
|
||||
*/
|
||||
static void queryActualNumOfDeps(const std::vector<hipGraphNode_t> &Nlist,
|
||||
hipGraphNode_t kernel_vecAdd, size_t numDeps) {
|
||||
hipGraphNode_t* depnodes;
|
||||
int numBytes = sizeof(hipGraphNode_t) * numDeps;
|
||||
depnodes = reinterpret_cast<hipGraphNode_t *>(malloc(numBytes));
|
||||
REQUIRE(depnodes != nullptr);
|
||||
HIP_CHECK(hipGraphNodeGetDependencies(kernel_vecAdd, depnodes, &numDeps));
|
||||
REQUIRE(numDeps == Nlist.size());
|
||||
|
||||
// Verify all dependencies are present in the node entries returned
|
||||
for (auto Node : Nlist) {
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < numDeps; i++) {
|
||||
if (Node == depnodes[i]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
INFO("Dependency node " << Node << " not present in returned list");
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
free(depnodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify api when GetDependencies queried
|
||||
* for greater number than actual number of nodes.
|
||||
*/
|
||||
static void queryGreaterNumOfDeps(const std::vector<hipGraphNode_t> &Nlist,
|
||||
hipGraphNode_t kernel_vecAdd, size_t numDeps) {
|
||||
constexpr auto addlEntries = 4;
|
||||
hipGraphNode_t* depnodes;
|
||||
size_t totDeps = numDeps + addlEntries;
|
||||
int numBytes = sizeof(hipGraphNode_t) * totDeps;
|
||||
depnodes = reinterpret_cast<hipGraphNode_t *>(malloc(numBytes));
|
||||
REQUIRE(depnodes != nullptr);
|
||||
HIP_CHECK(hipGraphNodeGetDependencies(kernel_vecAdd, depnodes, &totDeps));
|
||||
REQUIRE(totDeps == Nlist.size());
|
||||
|
||||
for (auto i = numDeps; i < numDeps + addlEntries; i++) {
|
||||
REQUIRE(depnodes[i] == nullptr);
|
||||
}
|
||||
|
||||
// Verify all dependencies are present in the node entries returned
|
||||
for (auto Node : Nlist) {
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < numDeps; i++) {
|
||||
if (Node == depnodes[i]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
INFO("Dependency node " << Node << " not present in returned list");
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
free(depnodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify api when GetDependencies queried
|
||||
* for lesser number than actual number of nodes.
|
||||
*/
|
||||
static void queryLesserNumOfDeps(const std::vector<hipGraphNode_t> &Nlist,
|
||||
hipGraphNode_t kernel_vecAdd, size_t numDeps) {
|
||||
size_t totDeps = numDeps - 1;
|
||||
hipGraphNode_t* depnodes;
|
||||
int numBytes = sizeof(hipGraphNode_t) * totDeps;
|
||||
size_t count{};
|
||||
depnodes = reinterpret_cast<hipGraphNode_t *>(malloc(numBytes));
|
||||
REQUIRE(depnodes != nullptr);
|
||||
HIP_CHECK(hipGraphNodeGetDependencies(kernel_vecAdd, depnodes, &totDeps));
|
||||
REQUIRE(totDeps == Nlist.size() - 1);
|
||||
|
||||
// Verify all dependencies are present in the node entries returned
|
||||
for (auto Node : Nlist) {
|
||||
for (size_t i = 0; i < totDeps; i++) {
|
||||
if (Node == depnodes[i]) {
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
REQUIRE(count == totDeps);
|
||||
free(depnodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional Test for getting dependencies of node in graph and verifying execution
|
||||
*/
|
||||
TEST_CASE("Unit_hipGraphNodeGetDependencies_Functional") {
|
||||
constexpr size_t N = 1024;
|
||||
constexpr size_t Nbytes = N * sizeof(int);
|
||||
constexpr auto blocksPerCU = 6; // to hide latency
|
||||
constexpr auto threadsPerBlock = 256;
|
||||
hipGraphNode_t kernel_vecSqr{}, kernel_vecAdd{};
|
||||
hipGraphNode_t kernelmod1{}, kernelmod2{}, kernelmod3{};
|
||||
hipGraphNode_t memcpyD2H{}, memcpyH2D_A{};
|
||||
hipKernelNodeParams kernelNodeParams{};
|
||||
hipGraph_t graph{};
|
||||
size_t numDeps{};
|
||||
hipStream_t streamForGraph;
|
||||
int *A_d, *C_d;
|
||||
int *A_h, *C_h;
|
||||
int *Res1_d, *Res2_d, *Res3_d;
|
||||
int *Sum_d, *Sum_h;
|
||||
hipGraphExec_t graphExec;
|
||||
size_t NElem{N};
|
||||
|
||||
HIP_CHECK(hipStreamCreate(&streamForGraph));
|
||||
HIP_CHECK(hipGraphCreate(&graph, 0));
|
||||
|
||||
HipTest::initArrays<int>(&A_d, &C_d, &Sum_d, &A_h, &C_h, &Sum_h, N);
|
||||
HipTest::initArrays<int>(&Res1_d, &Res2_d, &Res3_d,
|
||||
nullptr, nullptr, nullptr, N);
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
|
||||
// Initialize input buffer and vecsqr result
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
A_h[i] = i + 1;
|
||||
C_h[i] = A_h[i] * A_h[i];
|
||||
}
|
||||
|
||||
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, 0, A_d, A_h,
|
||||
Nbytes, hipMemcpyHostToDevice));
|
||||
|
||||
void* kernelArgsVS[] = {&A_d, &C_d, reinterpret_cast<void *>(&NElem)};
|
||||
memset(&kernelNodeParams, 0, sizeof(kernelNodeParams));
|
||||
kernelNodeParams.func =
|
||||
reinterpret_cast<void *>(HipTest::vector_square<int>);
|
||||
kernelNodeParams.gridDim = dim3(blocks);
|
||||
kernelNodeParams.blockDim = dim3(threadsPerBlock);
|
||||
kernelNodeParams.sharedMemBytes = 0;
|
||||
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgsVS);
|
||||
kernelNodeParams.extra = nullptr;
|
||||
HIP_CHECK(hipGraphAddKernelNode(&kernel_vecSqr, graph, &memcpyH2D_A, 1,
|
||||
&kernelNodeParams));
|
||||
|
||||
// Create multiple nodes dependent on vecSqr node.
|
||||
// Dependent nodes takes vecSqr input and computes output independently.
|
||||
std::vector<hipGraphNode_t> nodelist;
|
||||
int incValue1{1};
|
||||
void* kernelArgs1[] = {&C_d, &Res1_d, &incValue1,
|
||||
reinterpret_cast<void *>(&NElem)};
|
||||
memset(&kernelNodeParams, 0, sizeof(kernelNodeParams));
|
||||
kernelNodeParams.func =
|
||||
reinterpret_cast<void *>(updateResult);
|
||||
kernelNodeParams.gridDim = dim3(blocks);
|
||||
kernelNodeParams.blockDim = dim3(threadsPerBlock);
|
||||
kernelNodeParams.sharedMemBytes = 0;
|
||||
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgs1);
|
||||
kernelNodeParams.extra = nullptr;
|
||||
HIP_CHECK(hipGraphAddKernelNode(&kernelmod1, graph, &kernel_vecSqr, 1,
|
||||
&kernelNodeParams));
|
||||
nodelist.push_back(kernelmod1);
|
||||
|
||||
int incValue2{2};
|
||||
void* kernelArgs2[] = {&C_d, &Res2_d, &incValue2,
|
||||
reinterpret_cast<void *>(&NElem)};
|
||||
memset(&kernelNodeParams, 0, sizeof(kernelNodeParams));
|
||||
kernelNodeParams.func =
|
||||
reinterpret_cast<void *>(updateResult);
|
||||
kernelNodeParams.gridDim = dim3(blocks);
|
||||
kernelNodeParams.blockDim = dim3(threadsPerBlock);
|
||||
kernelNodeParams.sharedMemBytes = 0;
|
||||
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgs2);
|
||||
kernelNodeParams.extra = nullptr;
|
||||
HIP_CHECK(hipGraphAddKernelNode(&kernelmod2, graph, &kernel_vecSqr, 1,
|
||||
&kernelNodeParams));
|
||||
nodelist.push_back(kernelmod2);
|
||||
|
||||
int incValue3{3};
|
||||
void* kernelArgs3[] = {&C_d, &Res3_d, &incValue3,
|
||||
reinterpret_cast<void *>(&NElem)};
|
||||
memset(&kernelNodeParams, 0, sizeof(kernelNodeParams));
|
||||
kernelNodeParams.func =
|
||||
reinterpret_cast<void *>(updateResult);
|
||||
kernelNodeParams.gridDim = dim3(blocks);
|
||||
kernelNodeParams.blockDim = dim3(threadsPerBlock);
|
||||
kernelNodeParams.sharedMemBytes = 0;
|
||||
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgs3);
|
||||
kernelNodeParams.extra = nullptr;
|
||||
HIP_CHECK(hipGraphAddKernelNode(&kernelmod3, graph, &kernel_vecSqr, 1,
|
||||
&kernelNodeParams));
|
||||
nodelist.push_back(kernelmod3);
|
||||
|
||||
// Compute sum from all dependent nodes
|
||||
void* kernelArgsAdd[] = {&Res1_d, &Res2_d, &Res3_d, &Sum_d,
|
||||
reinterpret_cast<void *>(&NElem)};
|
||||
memset(&kernelNodeParams, 0, sizeof(kernelNodeParams));
|
||||
kernelNodeParams.func =
|
||||
reinterpret_cast<void *>(vectorSum);
|
||||
kernelNodeParams.gridDim = dim3(blocks);
|
||||
kernelNodeParams.blockDim = dim3(threadsPerBlock);
|
||||
kernelNodeParams.sharedMemBytes = 0;
|
||||
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgsAdd);
|
||||
kernelNodeParams.extra = nullptr;
|
||||
HIP_CHECK(hipGraphAddKernelNode(&kernel_vecAdd, graph,
|
||||
nodelist.data(), nodelist.size(),
|
||||
&kernelNodeParams));
|
||||
|
||||
HIP_CHECK(hipGraphNodeGetDependencies(kernel_vecAdd, nullptr, &numDeps));
|
||||
REQUIRE(numDeps == nodelist.size());
|
||||
|
||||
// Verify api When Dependencies are requested for actual number of nodes.
|
||||
queryActualNumOfDeps(nodelist, kernel_vecAdd, numDeps);
|
||||
|
||||
// Verify api When Dependencies are requested for more than
|
||||
// actual number of nodes.
|
||||
queryGreaterNumOfDeps(nodelist, kernel_vecAdd, numDeps);
|
||||
|
||||
// Verify api When Dependencies are requested for less than
|
||||
// actual number of nodes.
|
||||
queryLesserNumOfDeps(nodelist, kernel_vecAdd, numDeps);
|
||||
|
||||
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H, graph, &kernel_vecAdd, 1,
|
||||
Sum_h, Sum_d,
|
||||
Nbytes, hipMemcpyDeviceToHost));
|
||||
|
||||
// Instantiate and launch the graph
|
||||
HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0));
|
||||
HIP_CHECK(hipGraphLaunch(graphExec, streamForGraph));
|
||||
HIP_CHECK(hipStreamSynchronize(streamForGraph));
|
||||
|
||||
// Validate the computation
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
if ( Sum_h[i] != ( (C_h[i] + incValue1)
|
||||
+ (C_h[i] + incValue2)
|
||||
+ (C_h[i] + incValue3) ) ) {
|
||||
INFO("Sum not matching at " << i << " Sum_h[i] " << Sum_h[i]
|
||||
<< " C_h[i] " << C_h[i]);
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
|
||||
HipTest::freeArrays<int>(A_d, C_d, Sum_d, A_h, C_h, Sum_h, false);
|
||||
HipTest::freeArrays<int>(Res1_d, Res2_d, Res3_d,
|
||||
nullptr, nullptr, nullptr, false);
|
||||
HIP_CHECK(hipGraphExecDestroy(graphExec));
|
||||
HIP_CHECK(hipGraphDestroy(graph));
|
||||
HIP_CHECK(hipStreamDestroy(streamForGraph));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test performs api parameter validation by passing various values
|
||||
* as input and output parameters and validates the behavior.
|
||||
* Test will include both negative and positive scenarios.
|
||||
*/
|
||||
TEST_CASE("Unit_hipGraphNodeGetDependencies_ParamValidation") {
|
||||
hipGraph_t graph{};
|
||||
const int numBytes = 100;
|
||||
size_t numDeps{1};
|
||||
hipGraphNode_t memsetNode{}, depnodes{};
|
||||
hipError_t ret{};
|
||||
char *A_d;
|
||||
|
||||
HIP_CHECK(hipGraphCreate(&graph, 0));
|
||||
HIP_CHECK(hipMalloc(&A_d, numBytes));
|
||||
hipMemsetParams memsetParams{};
|
||||
memsetParams.dst = reinterpret_cast<void*>(A_d);
|
||||
memsetParams.value = 1;
|
||||
memsetParams.pitch = 0;
|
||||
memsetParams.elementSize = sizeof(char);
|
||||
memsetParams.width = numBytes * sizeof(char);
|
||||
memsetParams.height = 1;
|
||||
HIP_CHECK(hipGraphAddMemsetNode(&memsetNode, graph, nullptr,
|
||||
0, &memsetParams));
|
||||
|
||||
SECTION("node passed is a root node") {
|
||||
ret = hipGraphNodeGetDependencies(memsetNode, &depnodes, &numDeps);
|
||||
|
||||
// Api expected to return success and no dependencies.
|
||||
REQUIRE(ret == hipSuccess);
|
||||
REQUIRE(numDeps == 0);
|
||||
}
|
||||
|
||||
SECTION("node as nullptr") {
|
||||
ret = hipGraphNodeGetDependencies(nullptr, &depnodes, &numDeps);
|
||||
REQUIRE(ret == hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
SECTION("NumDependencies as nullptr") {
|
||||
ret = hipGraphNodeGetDependencies(memsetNode, &depnodes, nullptr);
|
||||
REQUIRE(ret == hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
SECTION("node as un-initialized/invalid parameter") {
|
||||
hipGraphNode_t uninit_node{};
|
||||
ret = hipGraphNodeGetDependencies(uninit_node, &depnodes, &numDeps);
|
||||
REQUIRE(ret == hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_CHECK(hipGraphDestroy(graph));
|
||||
HIP_CHECK(hipFree(A_d));
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, 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
|
||||
------------------
|
||||
Functional:
|
||||
1) Create a graph and add nodes with dependencies. Query for dependent nodes of the node passed and verify the result with dependencies defined.
|
||||
2) When pDependentNodes is passed as nullptr, verify pNumDependentNodes returns the number of dependent nodes.
|
||||
3) When pNumDependentNodes is higher than the actual number of dependent nodes, the remaining entries in pDependentNodes will be set to NULL,
|
||||
and the number of nodes actually obtained will be returned in pNumDependentNodes.
|
||||
4) When pNumDependentNodes is lesser than the actual number of dependent nodes, api should return the requested number of nodes in pDependentNodes.
|
||||
|
||||
Argument Validation:
|
||||
1) Add a single node in graph and pass the node to api. Verify the api returns dependent nodes as 0.
|
||||
2) Pass node as nullptr and verify api doesn’t crash, returns error code.
|
||||
3) Pass pNumDependentNodes as nullptr and verify api doesn’t crash, returns error code.
|
||||
4) Pass node as un-initialized/invalid parameter and verify api returns error code.
|
||||
|
||||
*/
|
||||
|
||||
#include <hip_test_common.hh>
|
||||
#include <hip_test_checkers.hh>
|
||||
#include <hip_test_kernels.hh>
|
||||
|
||||
static __global__ void updateResult(int* C_d, int* Res_d, int 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) {
|
||||
Res_d[i] = C_d[i] + val;
|
||||
}
|
||||
}
|
||||
|
||||
static __global__ void vectorSum(const int* A_d, const int* B_d,
|
||||
const int* C_d, int* Res_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) {
|
||||
Res_d[i] = A_d[i] + B_d[i] + C_d[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify api when GetDependent nodes is requested
|
||||
* for actual number of nodes.
|
||||
*/
|
||||
static void queryActualNumOfDepNodes(const std::vector<hipGraphNode_t> &Nlist,
|
||||
hipGraphNode_t kernel_vecSqr, size_t numDeps) {
|
||||
hipGraphNode_t* depnodes;
|
||||
int numBytes = sizeof(hipGraphNode_t) * numDeps;
|
||||
depnodes = reinterpret_cast<hipGraphNode_t *>(malloc(numBytes));
|
||||
REQUIRE(depnodes != nullptr);
|
||||
HIP_CHECK(hipGraphNodeGetDependentNodes(kernel_vecSqr, depnodes, &numDeps));
|
||||
REQUIRE(numDeps == Nlist.size());
|
||||
|
||||
// Verify all dependent nodes are present in the node entries returned
|
||||
for (auto Node : Nlist) {
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < numDeps; i++) {
|
||||
if (Node == depnodes[i]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
INFO("Dependent node " << Node << " not present in returned list");
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
free(depnodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify api when GetDependent nodes queried
|
||||
* for greater number than actual number of nodes.
|
||||
*/
|
||||
static void queryGreaterNumOfDepNodes(const std::vector<hipGraphNode_t> &Nlist,
|
||||
hipGraphNode_t kernel_vecSqr, size_t numDeps) {
|
||||
constexpr auto addlEntries = 4;
|
||||
hipGraphNode_t* depnodes;
|
||||
size_t totDeps = numDeps + addlEntries;
|
||||
int numBytes = sizeof(hipGraphNode_t) * totDeps;
|
||||
depnodes = reinterpret_cast<hipGraphNode_t *>(malloc(numBytes));
|
||||
REQUIRE(depnodes != nullptr);
|
||||
HIP_CHECK(hipGraphNodeGetDependentNodes(kernel_vecSqr, depnodes, &totDeps));
|
||||
REQUIRE(totDeps == Nlist.size());
|
||||
|
||||
for (auto i = numDeps; i < numDeps + addlEntries; i++) {
|
||||
REQUIRE(depnodes[i] == nullptr);
|
||||
}
|
||||
|
||||
// Verify all dependent nodes are present in the node entries returned
|
||||
for (auto Node : Nlist) {
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < numDeps; i++) {
|
||||
if (Node == depnodes[i]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
INFO("Dependent node " << Node << " not present in returned list");
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
free(depnodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify api when GetDependent nodes queried
|
||||
* for lesser number than actual number of nodes.
|
||||
*/
|
||||
static void queryLesserNumOfDepNodes(const std::vector<hipGraphNode_t> &Nlist,
|
||||
hipGraphNode_t kernel_vecSqr, size_t numDeps) {
|
||||
size_t totDeps = numDeps - 1;
|
||||
hipGraphNode_t* depnodes;
|
||||
int numBytes = sizeof(hipGraphNode_t) * totDeps;
|
||||
size_t count{};
|
||||
depnodes = reinterpret_cast<hipGraphNode_t *>(malloc(numBytes));
|
||||
REQUIRE(depnodes != nullptr);
|
||||
HIP_CHECK(hipGraphNodeGetDependentNodes(kernel_vecSqr, depnodes, &totDeps));
|
||||
REQUIRE(totDeps == Nlist.size() - 1);
|
||||
|
||||
// Verify all dependent nodes are present in the node entries returned
|
||||
for (auto Node : Nlist) {
|
||||
for (size_t i = 0; i < totDeps; i++) {
|
||||
if (Node == depnodes[i]) {
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
REQUIRE(count == totDeps);
|
||||
free(depnodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional Test for getting dependent nodes in graph and verifying execution
|
||||
*/
|
||||
TEST_CASE("Unit_hipGraphNodeGetDependentNodes_Functional") {
|
||||
constexpr size_t N = 1024;
|
||||
constexpr size_t Nbytes = N * sizeof(int);
|
||||
constexpr auto blocksPerCU = 6; // to hide latency
|
||||
constexpr auto threadsPerBlock = 256;
|
||||
hipGraphNode_t kernel_vecSqr{}, kernel_vecAdd{};
|
||||
hipGraphNode_t kernelmod1{}, kernelmod2{}, kernelmod3{};
|
||||
hipGraphNode_t memcpyD2H{}, memcpyH2D_A{};
|
||||
hipKernelNodeParams kernelNodeParams{};
|
||||
hipGraph_t graph{};
|
||||
size_t numDeps{};
|
||||
hipStream_t streamForGraph;
|
||||
int *A_d, *C_d;
|
||||
int *A_h, *C_h;
|
||||
int *Res1_d, *Res2_d, *Res3_d;
|
||||
int *Sum_d, *Sum_h;
|
||||
hipGraphExec_t graphExec;
|
||||
size_t NElem{N};
|
||||
|
||||
HIP_CHECK(hipStreamCreate(&streamForGraph));
|
||||
HIP_CHECK(hipGraphCreate(&graph, 0));
|
||||
|
||||
HipTest::initArrays<int>(&A_d, &C_d, &Sum_d, &A_h, &C_h, &Sum_h, N);
|
||||
HipTest::initArrays<int>(&Res1_d, &Res2_d, &Res3_d,
|
||||
nullptr, nullptr, nullptr, N);
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
|
||||
// Initialize input buffer and vecsqr result
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
A_h[i] = i + 1;
|
||||
C_h[i] = A_h[i] * A_h[i];
|
||||
}
|
||||
|
||||
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyH2D_A, graph, nullptr, 0, A_d, A_h,
|
||||
Nbytes, hipMemcpyHostToDevice));
|
||||
|
||||
void* kernelArgsVS[] = {&A_d, &C_d, reinterpret_cast<void *>(&NElem)};
|
||||
memset(&kernelNodeParams, 0, sizeof(kernelNodeParams));
|
||||
kernelNodeParams.func =
|
||||
reinterpret_cast<void *>(HipTest::vector_square<int>);
|
||||
kernelNodeParams.gridDim = dim3(blocks);
|
||||
kernelNodeParams.blockDim = dim3(threadsPerBlock);
|
||||
kernelNodeParams.sharedMemBytes = 0;
|
||||
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgsVS);
|
||||
kernelNodeParams.extra = nullptr;
|
||||
HIP_CHECK(hipGraphAddKernelNode(&kernel_vecSqr, graph, &memcpyH2D_A, 1,
|
||||
&kernelNodeParams));
|
||||
|
||||
// Create multiple nodes dependent on vecSqr node.
|
||||
// Dependent nodes takes vecSqr input and computes output independently.
|
||||
std::vector<hipGraphNode_t> nodelist;
|
||||
int incValue1{1};
|
||||
void* kernelArgs1[] = {&C_d, &Res1_d, &incValue1,
|
||||
reinterpret_cast<void *>(&NElem)};
|
||||
memset(&kernelNodeParams, 0, sizeof(kernelNodeParams));
|
||||
kernelNodeParams.func =
|
||||
reinterpret_cast<void *>(updateResult);
|
||||
kernelNodeParams.gridDim = dim3(blocks);
|
||||
kernelNodeParams.blockDim = dim3(threadsPerBlock);
|
||||
kernelNodeParams.sharedMemBytes = 0;
|
||||
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgs1);
|
||||
kernelNodeParams.extra = nullptr;
|
||||
HIP_CHECK(hipGraphAddKernelNode(&kernelmod1, graph, &kernel_vecSqr, 1,
|
||||
&kernelNodeParams));
|
||||
nodelist.push_back(kernelmod1);
|
||||
|
||||
int incValue2{2};
|
||||
void* kernelArgs2[] = {&C_d, &Res2_d, &incValue2,
|
||||
reinterpret_cast<void *>(&NElem)};
|
||||
memset(&kernelNodeParams, 0, sizeof(kernelNodeParams));
|
||||
kernelNodeParams.func =
|
||||
reinterpret_cast<void *>(updateResult);
|
||||
kernelNodeParams.gridDim = dim3(blocks);
|
||||
kernelNodeParams.blockDim = dim3(threadsPerBlock);
|
||||
kernelNodeParams.sharedMemBytes = 0;
|
||||
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgs2);
|
||||
kernelNodeParams.extra = nullptr;
|
||||
HIP_CHECK(hipGraphAddKernelNode(&kernelmod2, graph, &kernel_vecSqr, 1,
|
||||
&kernelNodeParams));
|
||||
nodelist.push_back(kernelmod2);
|
||||
|
||||
int incValue3{3};
|
||||
void* kernelArgs3[] = {&C_d, &Res3_d, &incValue3,
|
||||
reinterpret_cast<void *>(&NElem)};
|
||||
memset(&kernelNodeParams, 0, sizeof(kernelNodeParams));
|
||||
kernelNodeParams.func =
|
||||
reinterpret_cast<void *>(updateResult);
|
||||
kernelNodeParams.gridDim = dim3(blocks);
|
||||
kernelNodeParams.blockDim = dim3(threadsPerBlock);
|
||||
kernelNodeParams.sharedMemBytes = 0;
|
||||
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgs3);
|
||||
kernelNodeParams.extra = nullptr;
|
||||
HIP_CHECK(hipGraphAddKernelNode(&kernelmod3, graph, &kernel_vecSqr, 1,
|
||||
&kernelNodeParams));
|
||||
nodelist.push_back(kernelmod3);
|
||||
|
||||
HIP_CHECK(hipGraphNodeGetDependentNodes(kernel_vecSqr, nullptr, &numDeps));
|
||||
REQUIRE(numDeps == nodelist.size());
|
||||
|
||||
// Verify api When Dependent nodes are requested for actual number of nodes.
|
||||
queryActualNumOfDepNodes(nodelist, kernel_vecSqr, numDeps);
|
||||
|
||||
// Verify api When Dependent nodes are requested for more than
|
||||
// actual number of nodes.
|
||||
queryGreaterNumOfDepNodes(nodelist, kernel_vecSqr, numDeps);
|
||||
|
||||
// Verify api When Dependent nodes are requested for less than
|
||||
// actual number of nodes.
|
||||
queryLesserNumOfDepNodes(nodelist, kernel_vecSqr, numDeps);
|
||||
|
||||
// Compute sum from all dependent nodes
|
||||
void* kernelArgsAdd[] = {&Res1_d, &Res2_d, &Res3_d, &Sum_d,
|
||||
reinterpret_cast<void *>(&NElem)};
|
||||
memset(&kernelNodeParams, 0, sizeof(kernelNodeParams));
|
||||
kernelNodeParams.func =
|
||||
reinterpret_cast<void *>(vectorSum);
|
||||
kernelNodeParams.gridDim = dim3(blocks);
|
||||
kernelNodeParams.blockDim = dim3(threadsPerBlock);
|
||||
kernelNodeParams.sharedMemBytes = 0;
|
||||
kernelNodeParams.kernelParams = reinterpret_cast<void**>(kernelArgsAdd);
|
||||
kernelNodeParams.extra = nullptr;
|
||||
HIP_CHECK(hipGraphAddKernelNode(&kernel_vecAdd, graph,
|
||||
nodelist.data(), nodelist.size(),
|
||||
&kernelNodeParams));
|
||||
HIP_CHECK(hipGraphAddMemcpyNode1D(&memcpyD2H, graph, &kernel_vecAdd, 1,
|
||||
Sum_h, Sum_d,
|
||||
Nbytes, hipMemcpyDeviceToHost));
|
||||
|
||||
// Instantiate and launch the graph
|
||||
HIP_CHECK(hipGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0));
|
||||
HIP_CHECK(hipGraphLaunch(graphExec, streamForGraph));
|
||||
HIP_CHECK(hipStreamSynchronize(streamForGraph));
|
||||
|
||||
// Validate the computation
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
if ( Sum_h[i] != ( (C_h[i] + incValue1)
|
||||
+ (C_h[i] + incValue2)
|
||||
+ (C_h[i] + incValue3) ) ) {
|
||||
INFO("Sum not matching at " << i << " Sum_h[i] " << Sum_h[i]
|
||||
<< " C_h[i] " << C_h[i]);
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
|
||||
HipTest::freeArrays<int>(A_d, C_d, Sum_d, A_h, C_h, Sum_h, false);
|
||||
HipTest::freeArrays<int>(Res1_d, Res2_d, Res3_d,
|
||||
nullptr, nullptr, nullptr, false);
|
||||
HIP_CHECK(hipGraphExecDestroy(graphExec));
|
||||
HIP_CHECK(hipGraphDestroy(graph));
|
||||
HIP_CHECK(hipStreamDestroy(streamForGraph));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test performs api parameter validation by passing various values
|
||||
* as input and output parameters and validates the behavior.
|
||||
* Test will include both negative and positive scenarios.
|
||||
*/
|
||||
TEST_CASE("Unit_hipGraphNodeGetDependentNodes_ParamValidation") {
|
||||
hipGraph_t graph{};
|
||||
const int numBytes = 100;
|
||||
size_t numDeps{1};
|
||||
hipGraphNode_t memsetNode{}, depnodes{};
|
||||
hipError_t ret{};
|
||||
char *A_d;
|
||||
|
||||
HIP_CHECK(hipGraphCreate(&graph, 0));
|
||||
HIP_CHECK(hipMalloc(&A_d, numBytes));
|
||||
hipMemsetParams memsetParams{};
|
||||
memsetParams.dst = reinterpret_cast<void*>(A_d);
|
||||
memsetParams.value = 1;
|
||||
memsetParams.pitch = 0;
|
||||
memsetParams.elementSize = sizeof(char);
|
||||
memsetParams.width = numBytes * sizeof(char);
|
||||
memsetParams.height = 1;
|
||||
HIP_CHECK(hipGraphAddMemsetNode(&memsetNode, graph, nullptr,
|
||||
0, &memsetParams));
|
||||
|
||||
SECTION("single node in graph") {
|
||||
ret = hipGraphNodeGetDependentNodes(memsetNode, &depnodes, &numDeps);
|
||||
|
||||
// Api expected to return success and no dependent nodes.
|
||||
REQUIRE(ret == hipSuccess);
|
||||
REQUIRE(numDeps == 0);
|
||||
}
|
||||
|
||||
SECTION("node as nullptr") {
|
||||
ret = hipGraphNodeGetDependentNodes(nullptr, &depnodes, &numDeps);
|
||||
REQUIRE(ret == hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
SECTION("NumDependentNodes as nullptr") {
|
||||
ret = hipGraphNodeGetDependentNodes(memsetNode, &depnodes, nullptr);
|
||||
REQUIRE(ret == hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
SECTION("node as un-initialized/invalid parameter") {
|
||||
hipGraphNode_t uninit_node{};
|
||||
ret = hipGraphNodeGetDependentNodes(uninit_node, &depnodes, &numDeps);
|
||||
REQUIRE(ret == hipErrorInvalidValue);
|
||||
}
|
||||
|
||||
HIP_CHECK(hipGraphDestroy(graph));
|
||||
HIP_CHECK(hipFree(A_d));
|
||||
}
|
||||
@@ -552,9 +552,13 @@ void Memcpy3D<T>::simple_Memcpy3D() {
|
||||
*/
|
||||
TEMPLATE_TEST_CASE("Unit_hipMemcpy3D_Basic", "[hipMemcpy3D]",
|
||||
int, unsigned int, float) {
|
||||
int numDevices = 0;
|
||||
auto i = GENERATE(10, 100, 1024, 10*1024);
|
||||
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<TestType, float>::value) {
|
||||
|
||||
@@ -662,7 +662,11 @@ TEMPLATE_TEST_CASE("Unit_hipMemcpy3DAsync_Basic",
|
||||
int, unsigned int, float) {
|
||||
int numDevices = 0;
|
||||
HIP_CHECK(hipGetDeviceCount(&numDevices));
|
||||
auto i = GENERATE(10, 100, 1024, 10*1024);
|
||||
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<TestType, int>::value) {
|
||||
|
||||
@@ -61,7 +61,7 @@ Testcase Scenarios :
|
||||
*/
|
||||
#define LIB_ROCMSMI "librocm_smi64.so"
|
||||
#define NUM_BYTES 1000
|
||||
#define ALLOC_SIZE (1*1024*1024)
|
||||
#define ALLOC_SIZE (30*1024*1024)
|
||||
|
||||
|
||||
/**
|
||||
@@ -246,7 +246,11 @@ bool validatePageTableAllocations(const char *devList, int devCnt) {
|
||||
}
|
||||
|
||||
for (indx = 0; indx < numdev; indx++) {
|
||||
if (current[indx] - prev[indx])
|
||||
// For visible hip devices, there should be increase in VRAM usage
|
||||
// due to page table allocations
|
||||
// For NON visible hip devices, there can be reduction in VRAM usage
|
||||
// due to removal of page tables from them
|
||||
if (current[indx] > prev[indx])
|
||||
changeCnt++;
|
||||
}
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user