Merge branch 'amd-master-next' into amd-npi-next
Change-Id: Id241c60d6c2ceb4049c3ec15d9fe06baf28bcb3a
This commit is contained in:
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
Copyright (c) 2020-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.
|
||||
*/
|
||||
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../test_common.cpp NVCC_OPTIONS -std=c++11
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include "test_common.h"
|
||||
#include "hip/hip_fp16.h"
|
||||
|
||||
#define test_passed(test_name) \
|
||||
printf("%s %s PASSED!%s\n", KGRN, #test_name, KNRM);
|
||||
|
||||
enum half2Op {
|
||||
HALF2_OP_HEQ2 = 0,
|
||||
HALF2_OP_HNE2,
|
||||
HALF2_OP_HLE2,
|
||||
HALF2_OP_HGE2,
|
||||
HALF2_OP_HLT2,
|
||||
HALF2_OP_HGT2,
|
||||
HALF2_OP_MAX
|
||||
};
|
||||
|
||||
enum half2Test {
|
||||
HALF2_TEST_FUNCTION = 0,
|
||||
HALF2_TEST_NAN,
|
||||
HALF2_TEST_MAX
|
||||
};
|
||||
|
||||
// Kernels for half2 comparision functions
|
||||
|
||||
__global__
|
||||
void __half2Compare(float* result_D, __half2 a, int n, int half2Op,
|
||||
int testType) {
|
||||
size_t gputhread = (blockIdx.x * blockDim.x + threadIdx.x);
|
||||
size_t stride = blockDim.x * gridDim.x;
|
||||
|
||||
for (size_t i = gputhread; i < n; i += stride) {
|
||||
switch (half2Op) {
|
||||
case HALF2_OP_HEQ2:
|
||||
if (testType == HALF2_TEST_FUNCTION) {
|
||||
result_D[i] = __high2float(__heq2(__hadd2(a, __half2{1, 1}),
|
||||
__half2{2, 2}));
|
||||
} else {
|
||||
result_D[i] = __high2float(__heq2(__h2div(a, __half2{0, 0}),
|
||||
__half2{0, 0}));
|
||||
}
|
||||
break;
|
||||
case HALF2_OP_HNE2:
|
||||
result_D[i] = __high2float(__hne2(__hadd2(a, __half2{1, 1}),
|
||||
__half2{2, 2}));
|
||||
break;
|
||||
case HALF2_OP_HLE2:
|
||||
if (testType == HALF2_TEST_FUNCTION) {
|
||||
result_D[i] = __high2float(__hle2(__hadd2(a, __half2{1, 1}),
|
||||
__half2{3, 3}));
|
||||
} else {
|
||||
result_D[i] = __high2float(__hle2(__h2div(a, __half2{0, 0}),
|
||||
__half2{0, 0}));
|
||||
}
|
||||
break;
|
||||
case HALF2_OP_HGE2:
|
||||
if (testType == HALF2_TEST_FUNCTION) {
|
||||
result_D[i] = __high2float(__hge2(__hadd2(a, __half2{1, 1}),
|
||||
__half2{2, 2}));
|
||||
} else {
|
||||
result_D[i] = __high2float(__hge2(__h2div(a, __half2{0, 0}),
|
||||
__half2{0, 0}));
|
||||
}
|
||||
break;
|
||||
case HALF2_OP_HLT2:
|
||||
if (testType == HALF2_TEST_FUNCTION) {
|
||||
result_D[i] = __high2float(__hlt2(__hadd2(a, __half2{1, 1}),
|
||||
__half2{3, 3}));
|
||||
} else {
|
||||
result_D[i] = __high2float(__hlt2(__h2div(a, __half2{0, 0}),
|
||||
__half2{0, 0}));
|
||||
}
|
||||
break;
|
||||
case HALF2_OP_HGT2:
|
||||
if (testType == HALF2_TEST_FUNCTION) {
|
||||
result_D[i] = __high2float(__hgt2(__hadd2(a, __half2{1, 1}),
|
||||
__half2{3, 3}));
|
||||
} else {
|
||||
result_D[i] = __high2float(__hgt2(__h2div(a, __half2{0, 0}),
|
||||
__half2{0, 0}));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool isFailed(float expectedValue, float *result_H, int size) {
|
||||
for (int index = 0; index < size; index++) {
|
||||
if (expectedValue != result_H[index]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int main() {
|
||||
const int n = 64;
|
||||
float* result_H = reinterpret_cast<float*>(malloc(n*sizeof(float)));
|
||||
float* result_D;
|
||||
bool bFunctionalTestFailed = false;
|
||||
bool bNanTestFailed = false;
|
||||
int index = 0;
|
||||
HIPCHECK(hipMalloc(&result_D, n*sizeof(float)));
|
||||
|
||||
// kernel launch and hipmemcpy operation to get return value for heq2
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{1, 1}, n, HALF2_OP_HEQ2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(1.0, result_H, n)) {
|
||||
printf("heq2: failure when arguments are equal\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{2, 2}, n, HALF2_OP_HEQ2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(0.0, result_H, n)) {
|
||||
printf("heq2: failure when arguments are not equal\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
// kernel launch and hipmemcpy operation to get return value for hne2
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{2, 2}, n, HALF2_OP_HNE2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(1.0, result_H, n)) {
|
||||
printf("hne2: failure when arguments are not equal\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{1, 1}, n, HALF2_OP_HNE2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(0.0, result_H, n)) {
|
||||
printf("hne2: failure when arguments are equal\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
// kernel launch and hipmemcpy operation to get return value for hle2
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{1, 1}, n, HALF2_OP_HLE2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(1.0, result_H, n)) {
|
||||
printf("hle2: failure when argument is less than equal\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{2, 2}, n, HALF2_OP_HLE2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(1.0, result_H, n)) {
|
||||
printf("hle2: failure when argument is equal\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{3, 3}, n, HALF2_OP_HLE2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(0.0, result_H, n)) {
|
||||
printf("hle2: failure when argument is greater\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
// kernel launch and hipmemcpy operation to get return value for hge2
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{2, 2}, n, HALF2_OP_HGE2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(1.0, result_H, n)) {
|
||||
printf("hge2: failure when argument is greater\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{1, 1}, n, HALF2_OP_HGE2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(1.0, result_H, n)) {
|
||||
printf("hge2: failure when argument is equal\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{0, 0}, n, HALF2_OP_HGE2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(0.0, result_H, n)) {
|
||||
printf("hge2: failure when argument is less\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
// kernel launch and hipmemcpy operation to get return value for hlt2
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{1, 1}, n, HALF2_OP_HLT2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(1.0, result_H, n)) {
|
||||
printf("hlt2: failure when argument is less\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{2, 2}, n, HALF2_OP_HLT2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(0.0, result_H, n)) {
|
||||
printf("hlt2: failure when argument is equal\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{3, 3}, n, HALF2_OP_HLT2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(0.0, result_H, n)) {
|
||||
printf("hlt2: failure when argument is greater\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
// kernel launch and hipmemcpy operation to get return value for hgt2
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{3, 3}, n, HALF2_OP_HGT2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(1.0, result_H, n)) {
|
||||
printf("hgt2: failure when argument is greater\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{2, 2}, n, HALF2_OP_HGT2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(0.0, result_H, n)) {
|
||||
printf("hgt2: failure when argument is equal\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{1, 1}, n, HALF2_OP_HGT2,
|
||||
HALF2_TEST_FUNCTION);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(0.0, result_H, n)) {
|
||||
printf("hgt2: failure when argument is less\n");
|
||||
bFunctionalTestFailed = true;
|
||||
}
|
||||
|
||||
for (int nanFunctionTest = HALF2_OP_HEQ2; nanFunctionTest < HALF2_OP_MAX;
|
||||
nanFunctionTest++) {
|
||||
// HNE2 will not have a NaN test
|
||||
if (nanFunctionTest != HALF2_OP_HNE2) {
|
||||
hipLaunchKernelGGL(__half2Compare, dim3(1, 1, 1), dim3(1, 1, 1), 0, 0,
|
||||
result_D, __half2{0, 0}, n, nanFunctionTest,
|
||||
HALF2_TEST_NAN);
|
||||
hipDeviceSynchronize();
|
||||
HIPCHECK(hipMemcpy(result_H, result_D, n*sizeof(float),
|
||||
hipMemcpyDeviceToHost));
|
||||
if (isFailed(0.0, result_H, n)) {
|
||||
printf("NaN test failed for half function: %d\n", nanFunctionTest);
|
||||
bNanTestFailed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hipFree(result_D);
|
||||
free(result_H);
|
||||
|
||||
if ((false == bFunctionalTestFailed) && (false == bNanTestFailed)) {
|
||||
passed();
|
||||
} else {
|
||||
failed("Some Half2 tests failed");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -186,6 +186,14 @@ void test_fp16() {
|
||||
CHECK_SIMPLE([]__device__(){ return min<__fp16>(1.0f, 2.0f); }, 1.0f);
|
||||
}
|
||||
|
||||
void test_pown() {
|
||||
CHECK_SIMPLE([]__device__(){ return powif(2.0f, 2); }, 4.0f);
|
||||
CHECK_SIMPLE([]__device__(){ return powi(2.0, 2); }, 4.0);
|
||||
CHECK_SIMPLE([]__device__(){ return pow(2.0f, 2); }, 4.0f);
|
||||
CHECK_SIMPLE([]__device__(){ return pow(2.0, 2); }, 4.0);
|
||||
CHECK_SIMPLE([]__device__(){ return pow(2.0f16, 2); }, 4.0f16);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
HipTest::parseStandardArguments(argc, argv, true);
|
||||
|
||||
@@ -195,5 +203,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
test_fp16();
|
||||
|
||||
test_pown();
|
||||
|
||||
passed();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
Copyright (c) 2020 - 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.
|
||||
*/
|
||||
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../test_common.cpp
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include "test_common.h"
|
||||
|
||||
#define ASSERT_EQUAL(lhs, rhs) assert(lhs == rhs)
|
||||
|
||||
static __global__
|
||||
void kernel_syncthreads_and(int *syncTestD,
|
||||
int *allThreadsZeroD,
|
||||
int *allThreadsOneD,
|
||||
int *oneThreadZeroD,
|
||||
int *allThreadsMinusOneD)
|
||||
{
|
||||
int blockSize = blockDim.x;
|
||||
int predicate = 10;
|
||||
// First block index starts with 0, and second block index starts
|
||||
// with blockSize
|
||||
int i = (blockIdx.x == 0) ? threadIdx.x : blockSize + threadIdx.x;
|
||||
|
||||
// At very first, we need to ensure work-group level syncronization
|
||||
// properly happened, don't bother about predicate testing for now.
|
||||
// Thread 0 and thread 1 writes to shared memory. After call to api,
|
||||
// every thread reads shared memory, and store product for verification
|
||||
__shared__ int sm[2];
|
||||
if (threadIdx.x == 0)
|
||||
sm[0] = 10;
|
||||
else if (threadIdx.x == 1)
|
||||
sm[1] = 20;
|
||||
__syncthreads_and(predicate);
|
||||
syncTestD[i] = sm[0] * sm[1];
|
||||
|
||||
// All threads pass 0 as predicate value, result should be 0
|
||||
predicate = 0;
|
||||
allThreadsZeroD[i] = __syncthreads_and(predicate);
|
||||
|
||||
// All threads pass 1 as predicate value, result should be 1
|
||||
predicate = 1;
|
||||
allThreadsOneD[i] = __syncthreads_and(predicate);
|
||||
|
||||
// Thread 0 pass 0, and all other threads 1 as predicate value,
|
||||
// result should be 0
|
||||
predicate = (threadIdx.x == 0) ? 0 : 1;
|
||||
oneThreadZeroD[i] = __syncthreads_and(predicate);
|
||||
|
||||
// All threads pass -1 as predicate value, result should be 1
|
||||
predicate = -1;
|
||||
allThreadsMinusOneD[i] = __syncthreads_and(predicate);
|
||||
}
|
||||
|
||||
static void test_syncthreads_and(int blockSize)
|
||||
{
|
||||
int nBytes = sizeof(int) * 2 * blockSize;
|
||||
int * syncTestD, *syncTestH;
|
||||
int *allThreadsZeroD, *allThreadsZeroH;
|
||||
int *allThreadsOneD, *allThreadsOneH;
|
||||
int *oneThreadZeroD, *oneThreadZeroH;
|
||||
int *allThreadsMinusOneD, *allThreadsMinusOneH;
|
||||
|
||||
// Allocate device memory
|
||||
ASSERT_EQUAL(hipMalloc((void**)&syncTestD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&allThreadsZeroD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&allThreadsOneD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&oneThreadZeroD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&allThreadsMinusOneD, nBytes), hipSuccess);
|
||||
|
||||
// Allocate host memory
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&syncTestH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&allThreadsZeroH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&allThreadsOneH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&oneThreadZeroH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&allThreadsMinusOneH, nBytes), hipSuccess);
|
||||
|
||||
// Launch Kernel
|
||||
hipLaunchKernelGGL(kernel_syncthreads_and,
|
||||
2,
|
||||
blockSize,
|
||||
0,
|
||||
0,
|
||||
syncTestD,
|
||||
allThreadsZeroD,
|
||||
allThreadsOneD,
|
||||
oneThreadZeroD,
|
||||
allThreadsMinusOneD);
|
||||
|
||||
// Copy result from device to host
|
||||
ASSERT_EQUAL(hipMemcpy(syncTestH, syncTestD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(allThreadsZeroH, allThreadsZeroD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(allThreadsOneH, allThreadsOneD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(oneThreadZeroH, oneThreadZeroD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(allThreadsMinusOneH, allThreadsMinusOneD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
|
||||
// Validate results for both blocks together
|
||||
for (int i = 0; i < 2 * blockSize; ++i) {
|
||||
ASSERT_EQUAL(syncTestH[i], 200);
|
||||
ASSERT_EQUAL(allThreadsZeroH[i], 0);
|
||||
ASSERT_EQUAL(allThreadsOneH[i], 1);
|
||||
ASSERT_EQUAL(oneThreadZeroH[i], 0);
|
||||
ASSERT_EQUAL(allThreadsMinusOneH[i], 1);
|
||||
}
|
||||
|
||||
// Free device memory
|
||||
ASSERT_EQUAL(hipFree(syncTestD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(allThreadsZeroD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(allThreadsOneD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(oneThreadZeroD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(allThreadsMinusOneD), hipSuccess);
|
||||
|
||||
//Free host memory
|
||||
ASSERT_EQUAL(hipHostFree(syncTestH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(allThreadsZeroH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(allThreadsOneH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(oneThreadZeroH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(allThreadsMinusOneH), hipSuccess);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int blockSizes[] = {10, 40, 70, 130, 240, 723, 32, 64, 128, 256, 512, 1024};
|
||||
for (int i = 0; i < (sizeof(blockSizes) / sizeof(blockSizes[0])); ++i)
|
||||
test_syncthreads_and(blockSizes[i]);
|
||||
passed();
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
Copyright (c) 2020 - 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.
|
||||
*/
|
||||
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../test_common.cpp
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include "test_common.h"
|
||||
|
||||
#define ASSERT_EQUAL(lhs, rhs) assert(lhs == rhs)
|
||||
|
||||
static __global__
|
||||
void kernel_syncthreads_count(int *syncTestD,
|
||||
int *allThreadsZeroD,
|
||||
int *allThreadsOneD,
|
||||
int *oddThreadsOneD,
|
||||
int *allThreadsMinusOneD,
|
||||
int *allThreadsIdD)
|
||||
{
|
||||
int blockSize = blockDim.x;
|
||||
int predicate = 10;
|
||||
// First block index starts with 0, and second block index starts
|
||||
// with blockSize
|
||||
int i = (blockIdx.x == 0) ? threadIdx.x : blockSize + threadIdx.x;
|
||||
|
||||
// At very first, we need to ensure work-group level syncronization
|
||||
// properly happened, don't bother about predicate testing for now.
|
||||
// Thread 0 and thread 1 writes to shared memory. After call to api,
|
||||
// every thread reads shared memory, and store sum for verification
|
||||
__shared__ int sm[2];
|
||||
if (threadIdx.x == 0)
|
||||
sm[0] = 10;
|
||||
else if (threadIdx.x == 1)
|
||||
sm[1] = 20;
|
||||
__syncthreads_count(predicate);
|
||||
syncTestD[i] = sm[0] + sm[1];
|
||||
|
||||
// All threads pass 0 as predicate value, result should be 0
|
||||
predicate = 0;
|
||||
allThreadsZeroD[i] = __syncthreads_count(predicate);
|
||||
|
||||
// All threads pass 1 as predicate value, result should be blockSize
|
||||
predicate = 1;
|
||||
allThreadsOneD[i] = __syncthreads_count(predicate);
|
||||
|
||||
// Odd numbered threads pass 1, and even numbered threads pass 0, as
|
||||
// predicate value, result should be blockSize / 2
|
||||
predicate = threadIdx.x % 2;
|
||||
oddThreadsOneD[i] = __syncthreads_count(predicate);
|
||||
|
||||
// All threads pass -1 as predicate value, result should blockSize
|
||||
predicate = -1;
|
||||
allThreadsMinusOneD[i] = __syncthreads_count(predicate);
|
||||
|
||||
// Each thread pass its ID as predicate value, result should be blockSize - 1
|
||||
predicate = threadIdx.x;
|
||||
allThreadsIdD[i] = __syncthreads_count(predicate);
|
||||
}
|
||||
|
||||
void test_syncthreads_count(int blockSize)
|
||||
{
|
||||
int nBytes = sizeof(int) * 2 * blockSize;
|
||||
int * syncTestD, *syncTestH;
|
||||
int *allThreadsZeroD, *allThreadsZeroH;
|
||||
int *allThreadsOneD, *allThreadsOneH;
|
||||
int *oddThreadsOneD, *oddThreadsOneH;
|
||||
int *allThreadsMinusOneD, *allThreadsMinusOneH;
|
||||
int *allThreadsIdD, *allThreadsIdH;
|
||||
|
||||
// Allocate device memory
|
||||
ASSERT_EQUAL(hipMalloc((void**)&syncTestD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&allThreadsZeroD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&allThreadsOneD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&oddThreadsOneD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&allThreadsMinusOneD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&allThreadsIdD, nBytes), hipSuccess);
|
||||
|
||||
// Allocate host memory
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&syncTestH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&allThreadsZeroH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&allThreadsOneH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&oddThreadsOneH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&allThreadsMinusOneH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&allThreadsIdH, nBytes), hipSuccess);
|
||||
|
||||
// Launch Kernel
|
||||
hipLaunchKernelGGL(kernel_syncthreads_count,
|
||||
2,
|
||||
blockSize,
|
||||
0,
|
||||
0,
|
||||
syncTestD,
|
||||
allThreadsZeroD,
|
||||
allThreadsOneD,
|
||||
oddThreadsOneD,
|
||||
allThreadsMinusOneD,
|
||||
allThreadsIdD);
|
||||
|
||||
// Copy result from device to host
|
||||
ASSERT_EQUAL(hipMemcpy(syncTestH, syncTestD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(allThreadsZeroH, allThreadsZeroD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(allThreadsOneH, allThreadsOneD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(oddThreadsOneH, oddThreadsOneD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(allThreadsMinusOneH, allThreadsMinusOneD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(allThreadsIdH, allThreadsIdD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
|
||||
// Validate results for both the blocks together
|
||||
for (int i = 0; i < 2 * blockSize; ++i) {
|
||||
ASSERT_EQUAL(syncTestH[i], 30);
|
||||
ASSERT_EQUAL(allThreadsZeroH[i], 0);
|
||||
ASSERT_EQUAL(allThreadsOneH[i], blockSize);
|
||||
ASSERT_EQUAL(oddThreadsOneH[i], blockSize / 2);
|
||||
ASSERT_EQUAL(allThreadsMinusOneH[i], blockSize);
|
||||
ASSERT_EQUAL(allThreadsIdH[i], (blockSize-1));
|
||||
}
|
||||
|
||||
// Free device memory
|
||||
ASSERT_EQUAL(hipFree(syncTestD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(allThreadsZeroD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(allThreadsOneD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(oddThreadsOneD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(allThreadsMinusOneD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(allThreadsIdD), hipSuccess);
|
||||
|
||||
//Free host memory
|
||||
ASSERT_EQUAL(hipHostFree(syncTestH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(allThreadsZeroH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(allThreadsOneH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(oddThreadsOneH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(allThreadsMinusOneH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(allThreadsIdH), hipSuccess);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int blockSizes[] = {10, 40, 70, 130, 240, 723, 32, 64, 128, 256, 512, 1024};
|
||||
for (int i = 0; i < (sizeof(blockSizes) / sizeof(blockSizes[0])); ++i)
|
||||
test_syncthreads_count(blockSizes[i]);
|
||||
passed();
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
Copyright (c) 2020 - 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.
|
||||
*/
|
||||
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../test_common.cpp
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include "test_common.h"
|
||||
|
||||
#define ASSERT_EQUAL(lhs, rhs) assert(lhs == rhs)
|
||||
|
||||
static __global__
|
||||
void kernel_syncthreads_or(int *syncTestD,
|
||||
int *allThreadsZeroD,
|
||||
int *allThreadsOneD,
|
||||
int *oneThreadOneD,
|
||||
int *allThreadsMinusOneD)
|
||||
{
|
||||
int blockSize = blockDim.x;
|
||||
int predicate = 10;
|
||||
// First block index starts with 0, and second block index starts
|
||||
// with blockSize
|
||||
int i = (blockIdx.x == 0) ? threadIdx.x : blockSize + threadIdx.x;
|
||||
|
||||
// At very first, we need to ensure work-group level syncronization
|
||||
// properly happened, don't bother about predicate testing for now.
|
||||
// Thread 0 and thread 1 writes to shared memory. After call to api,
|
||||
// every thread reads shared memory, and store subtraction for verification
|
||||
__shared__ int sm[2];
|
||||
if (threadIdx.x == 0)
|
||||
sm[0] = 10;
|
||||
else if (threadIdx.x == 1)
|
||||
sm[1] = 20;
|
||||
__syncthreads_or(predicate);
|
||||
syncTestD[i] = sm[1] - sm[0];
|
||||
|
||||
// All threads pass 0 as predicate value, result should be 0
|
||||
predicate = 0;
|
||||
allThreadsZeroD[i] = __syncthreads_or(predicate);
|
||||
|
||||
// All threads pass 1 as predicate value, result should be 1
|
||||
predicate = 1;
|
||||
allThreadsOneD[i] = __syncthreads_or(predicate);
|
||||
|
||||
// Thread 0 pass 1, and all other threads 0 as predicate value,
|
||||
// result should be 1
|
||||
predicate = (threadIdx.x == 0) ? 1 : 0;
|
||||
oneThreadOneD[i] = __syncthreads_or(predicate);
|
||||
|
||||
// All threads pass -1 as predicate value, result should be 1
|
||||
predicate = -1;
|
||||
allThreadsMinusOneD[i] = __syncthreads_or(predicate);
|
||||
}
|
||||
|
||||
static void test_syncthreads_or(int blockSize)
|
||||
{
|
||||
int nBytes = sizeof(int) * 2 * blockSize;
|
||||
int * syncTestD, *syncTestH;
|
||||
int *allThreadsZeroD, *allThreadsZeroH;
|
||||
int *allThreadsOneD, *allThreadsOneH;
|
||||
int *oneThreadOneD, *oneThreadOneH;
|
||||
int *allThreadsMinusOneD, *allThreadsMinusOneH;
|
||||
|
||||
// Allocate device memory
|
||||
ASSERT_EQUAL(hipMalloc((void**)&syncTestD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&allThreadsZeroD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&allThreadsOneD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&oneThreadOneD, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipMalloc((void**)&allThreadsMinusOneD, nBytes), hipSuccess);
|
||||
|
||||
// Allocate host memory
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&syncTestH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&allThreadsZeroH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&allThreadsOneH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&oneThreadOneH, nBytes), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostMalloc((void**)&allThreadsMinusOneH, nBytes), hipSuccess);
|
||||
|
||||
// Launch Kernel
|
||||
hipLaunchKernelGGL(kernel_syncthreads_or,
|
||||
2,
|
||||
blockSize,
|
||||
0,
|
||||
0,
|
||||
syncTestD,
|
||||
allThreadsZeroD,
|
||||
allThreadsOneD,
|
||||
oneThreadOneD,
|
||||
allThreadsMinusOneD);
|
||||
|
||||
// Copy result from device to host
|
||||
ASSERT_EQUAL(hipMemcpy(syncTestH, syncTestD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(allThreadsZeroH, allThreadsZeroD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(allThreadsOneH, allThreadsOneD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(oneThreadOneH, oneThreadOneD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
ASSERT_EQUAL(hipMemcpy(allThreadsMinusOneH, allThreadsMinusOneD, nBytes, hipMemcpyDeviceToHost),
|
||||
hipSuccess);
|
||||
|
||||
// Validate results for both blocks together
|
||||
for (int i = 0; i < 2 * blockSize; ++i) {
|
||||
ASSERT_EQUAL(syncTestH[i], 10);
|
||||
ASSERT_EQUAL(allThreadsZeroH[i], 0);
|
||||
ASSERT_EQUAL(allThreadsOneH[i], 1);
|
||||
ASSERT_EQUAL(oneThreadOneH[i], 1);
|
||||
ASSERT_EQUAL(allThreadsMinusOneH[i], 1);
|
||||
}
|
||||
|
||||
// Free device memory
|
||||
ASSERT_EQUAL(hipFree(syncTestD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(allThreadsZeroD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(allThreadsOneD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(oneThreadOneD), hipSuccess);
|
||||
ASSERT_EQUAL(hipFree(allThreadsMinusOneD), hipSuccess);
|
||||
|
||||
//Free host memory
|
||||
ASSERT_EQUAL(hipHostFree(syncTestH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(allThreadsZeroH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(allThreadsOneH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(oneThreadOneH), hipSuccess);
|
||||
ASSERT_EQUAL(hipHostFree(allThreadsMinusOneH), hipSuccess);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int blockSizes[] = {10, 40, 70, 130, 240, 723, 32, 64, 128, 256, 512, 1024};
|
||||
for (int i = 0; i < (sizeof(blockSizes) / sizeof(blockSizes[0])); ++i)
|
||||
test_syncthreads_or(blockSizes[i]);
|
||||
passed();
|
||||
}
|
||||
Executable
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright (c) 2015-2017 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.
|
||||
*/
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../test_common.cpp
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include "test_common.h"
|
||||
|
||||
#define N 1024
|
||||
#define OFFSET 128
|
||||
|
||||
void single_process() {
|
||||
int* ipc_dptr = nullptr;
|
||||
int* ipc_hptr = nullptr;
|
||||
int* ipc_out_dptr = nullptr;
|
||||
int* ipc_out_hptr = nullptr;
|
||||
|
||||
int* ipc_offset_dptr = nullptr;
|
||||
|
||||
hipIpcMemHandle_t ipc_handle;
|
||||
hipIpcMemHandle_t ipc_offset_handle;
|
||||
|
||||
HIPCHECK(hipMalloc((void**)&ipc_dptr, N * sizeof(int)));
|
||||
|
||||
// Negative, Make sure we return error when an offset of original ptr is passed
|
||||
ipc_offset_dptr = ipc_dptr + (OFFSET * sizeof(int));
|
||||
assert(hipErrorInvalidDevicePointer == hipIpcGetMemHandle(&ipc_offset_handle, ipc_offset_dptr));
|
||||
|
||||
// Get handle for the device_ptr
|
||||
HIPCHECK(hipIpcGetMemHandle(&ipc_handle, ipc_dptr));
|
||||
|
||||
// Set Values @ Host Ptr
|
||||
ipc_hptr = new int[N];
|
||||
for (size_t idx = 0; idx < N; ++idx) {
|
||||
ipc_hptr[idx] = idx;
|
||||
}
|
||||
|
||||
// Copy values to Device ptr
|
||||
HIPCHECK(hipMemset(ipc_dptr, 0x00, (N * sizeof(int))));
|
||||
HIPCHECK(hipMemcpy(ipc_dptr, ipc_hptr, (N * sizeof(int)), hipMemcpyHostToDevice));
|
||||
|
||||
// Open handle to get dev_ptr
|
||||
ipc_out_hptr = new int[N];
|
||||
memset(ipc_out_hptr, 0x00, (N * sizeof(int)));
|
||||
HIPCHECK(hipIpcOpenMemHandle((void**)&ipc_out_dptr, ipc_handle, 0));
|
||||
|
||||
// Copy Values from Device to Host and Check for correctness
|
||||
HIPCHECK(hipMemcpy(ipc_out_hptr, ipc_out_dptr, (N * sizeof(int)), hipMemcpyDeviceToHost));
|
||||
for (size_t idx = 0; idx < N; ++idx) {
|
||||
if(ipc_out_hptr[idx] != idx) {
|
||||
std::cout<<"Failing @ idx: "<<idx<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
//Close All Mem Handle
|
||||
HIPCHECK(hipIpcCloseMemHandle(ipc_out_dptr));
|
||||
HIPCHECK(hipFree(ipc_dptr));
|
||||
|
||||
delete[] ipc_hptr;
|
||||
delete[] ipc_out_hptr;
|
||||
}
|
||||
|
||||
void multi_process() {
|
||||
//To create and open IPC handle via multiple process
|
||||
}
|
||||
|
||||
int main() {
|
||||
single_process();
|
||||
multi_process();
|
||||
passed();
|
||||
}
|
||||
@@ -571,6 +571,10 @@ __global__ void hipLaunchKernelStructFunc21(
|
||||
|
||||
__global__ void vAdd(float* a) {}
|
||||
|
||||
template<class T1, class T2>
|
||||
__global__ void myKernel(T1 a, T2 b) {}
|
||||
|
||||
|
||||
//---
|
||||
// Some wrapper macro for testing:
|
||||
#define WRAP(...) __VA_ARGS__
|
||||
@@ -913,6 +917,18 @@ int main() {
|
||||
hipLaunchKernelGGL(HIP_KERNEL_NAME(vAdd), dim3(1024), 1, 0, 0, Ad);
|
||||
hipLaunchKernelGGL(HIP_KERNEL_NAME(vAdd), dim3(1024), dim3(1), 0, 0, Ad);
|
||||
|
||||
// Test: Passing macro to hipLaunchKernelGGL
|
||||
#define KERNEL_CONFIG dim3(1024), dim3(1), 0, 0
|
||||
hipLaunchKernelGGL(HIP_KERNEL_NAME(vAdd), KERNEL_CONFIG, Ad);
|
||||
|
||||
// Test: Same thing with templates:
|
||||
int a;
|
||||
float b;
|
||||
hipLaunchKernelGGL(HIP_KERNEL_NAME(myKernel<int, float>), KERNEL_CONFIG, a, b);
|
||||
|
||||
#define TYPE_PARAM_CONFIG int, float
|
||||
hipLaunchKernelGGL(HIP_KERNEL_NAME(myKernel<TYPE_PARAM_CONFIG>), KERNEL_CONFIG, a, b);
|
||||
|
||||
// Test: Passing hipLaunchKernelGGL inside another macro:
|
||||
float e0;
|
||||
MY_LAUNCH_MACRO(hipLaunchKernelGGL(vAdd, dim3(1024),
|
||||
|
||||
@@ -1,51 +1,168 @@
|
||||
/*
|
||||
Copyright (c) 2015-2017 Advanced Micro Devices, Inc. All rights reserved.
|
||||
* Copyright (c) 2015-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.
|
||||
*/
|
||||
|
||||
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 to compare
|
||||
* 1.pciBusID from hipDeviceGetPCIBusId and hipDeviceGetAttribute **
|
||||
* 2.{pciDomainID, pciBusID, pciDeviceID} values hipDeviceGetPCIBusId vs lspci **
|
||||
*/
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp
|
||||
* TEST: %t
|
||||
* BUILD: %t %s ../../test_common.cpp NVCC_OPTIONS -std=c++11
|
||||
* TEST_NAMED: %t hipDeviceGetPCIBusId-vs-hipDeviceGetAttribute --tests 0x1
|
||||
* TEST_NAMED: %t hipDeviceGetPCIBusId-vs-lspci --tests 0x2
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "test_common.h"
|
||||
#define MAX_DEVICE_LENGTH 20
|
||||
|
||||
int main(void) {
|
||||
char pciBusId[13];
|
||||
int deviceCount = 0;
|
||||
HIPCHECK(hipGetDeviceCount(&deviceCount));
|
||||
HIPASSERT(deviceCount != 0);
|
||||
for (int i = 0; i < deviceCount; i++) {
|
||||
int pciBusID = -1;
|
||||
int pciDeviceID = -1;
|
||||
int pciDomainID = -1;
|
||||
int tempPciBusId = -1;
|
||||
HIPCHECK(hipDeviceGetPCIBusId(&pciBusId[0], 13, i));
|
||||
sscanf(pciBusId, "%04x:%02x:%02x", &pciDomainID, &pciBusID, &pciDeviceID);
|
||||
HIPCHECK(hipDeviceGetAttribute(&tempPciBusId, hipDeviceAttributePciBusId, i));
|
||||
if (pciBusID != tempPciBusId) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
passed();
|
||||
static bool getPciBusId(int deviceCount, char hipDeviceList[][MAX_DEVICE_LENGTH]) {
|
||||
for (int i = 0; i < deviceCount; i++) {
|
||||
HIPCHECK(hipDeviceGetPCIBusId(hipDeviceList[i], MAX_DEVICE_LENGTH, i));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool comparePciBusIDWithHipDeviceGetAttribute() {
|
||||
bool testResult = true;
|
||||
int deviceCount = 0;
|
||||
HIPCHECK(hipGetDeviceCount(&deviceCount));
|
||||
HIPASSERT(deviceCount != 0);
|
||||
printf("No.of gpus in the system: %d\n", deviceCount);
|
||||
char hipDeviceList[deviceCount][MAX_DEVICE_LENGTH];
|
||||
char pciDeviceList[deviceCount][MAX_DEVICE_LENGTH];
|
||||
|
||||
getPciBusId(deviceCount, hipDeviceList);
|
||||
|
||||
for (int i = 0; i < deviceCount; i++) {
|
||||
int pciBusID = -1;
|
||||
int pciDeviceID = -1;
|
||||
int pciDomainID = -1;
|
||||
int tempPciBusId = -1;
|
||||
sscanf(hipDeviceList[i], "%04x:%02x:%02x", &pciDomainID, &pciBusID,
|
||||
&pciDeviceID);
|
||||
HIPCHECK(hipDeviceGetAttribute(&tempPciBusId, hipDeviceAttributePciBusId, i));
|
||||
if (pciBusID != tempPciBusId) {
|
||||
testResult = false;
|
||||
printf("pciBusID from hipDeviceGetPCIBusId mismatched to that from "
|
||||
"hipDeviceGetAttribute for gpu %d\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
printf("pciBusID output of both hipDeviceGetPCIBusId and"
|
||||
" hipDeviceGetAttribute matched for all gpus\n");
|
||||
return testResult;
|
||||
}
|
||||
|
||||
bool compareHipDeviceGetPCIBusIdWithLspci() {
|
||||
FILE *fpipe;
|
||||
bool testResult = false;
|
||||
|
||||
{
|
||||
// Check if lspci is installed, if not, don't proceed
|
||||
char const *cmd = "lspci --version";
|
||||
char *lspciCheck;
|
||||
char temp[20];
|
||||
fpipe = popen(cmd, "r");
|
||||
|
||||
if (fpipe == nullptr) {
|
||||
printf("Unable to create command file\n");
|
||||
return testResult;
|
||||
}
|
||||
|
||||
lspciCheck = fgets(temp, 20, fpipe);
|
||||
pclose(fpipe);
|
||||
|
||||
if (!lspciCheck) {
|
||||
printf("lspci not found. Skipping the test\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int deviceCount = 0;
|
||||
HIPCHECK(hipGetDeviceCount(&deviceCount));
|
||||
HIPASSERT(deviceCount != 0);
|
||||
printf("No.of gpus in the system: %d\n", deviceCount);
|
||||
char hipDeviceList[deviceCount][MAX_DEVICE_LENGTH];
|
||||
char pciDeviceList[deviceCount][MAX_DEVICE_LENGTH];
|
||||
|
||||
getPciBusId(deviceCount, hipDeviceList);
|
||||
|
||||
// Get lspci device list and compare with hip device list
|
||||
char const *command = "lspci -D | grep controller | grep AMD/ATI | "
|
||||
"cut -d ' ' -f 1";
|
||||
fpipe = popen(command, "r");
|
||||
|
||||
if (fpipe == nullptr) {
|
||||
printf("Unable to create command file\n");
|
||||
return testResult;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
int deviceMatchCount = 0;
|
||||
|
||||
while (fgets(pciDeviceList[index], sizeof(pciDeviceList[index]), fpipe)) {
|
||||
bool bMatchFound = false;
|
||||
for (int deviceNo = 0; deviceNo < deviceCount; deviceNo++) {
|
||||
if (!strncmp(pciDeviceList[index], hipDeviceList[deviceNo], 10)) {
|
||||
deviceMatchCount++;
|
||||
bMatchFound = true;
|
||||
}
|
||||
}
|
||||
if (bMatchFound == false) {
|
||||
printf("PCI device: %s is not reported by HIP\n", pciDeviceList[index]);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
pclose(fpipe);
|
||||
|
||||
if (deviceMatchCount == deviceCount) {
|
||||
printf("hip and lspci output for {pciDomainID, pciBusID, pciDeviceID} "
|
||||
"matched for all gpus\n");
|
||||
testResult = true;
|
||||
} else {
|
||||
printf("Mismatch in number GPUs reported by HIP with lscpi\n");
|
||||
}
|
||||
return testResult;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
bool testResult = true;
|
||||
HipTest::parseStandardArguments(argc, argv, true);
|
||||
|
||||
if (p_tests & 0x1) {
|
||||
testResult &= comparePciBusIDWithHipDeviceGetAttribute();
|
||||
}
|
||||
|
||||
if (p_tests & 0x2) {
|
||||
#ifdef __unix__
|
||||
testResult &= compareHipDeviceGetPCIBusIdWithLspci();
|
||||
#else
|
||||
printf("Detected non-linux OS. Skipping the test\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (testResult) {
|
||||
passed();
|
||||
} else {
|
||||
failed("one or more tests failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,5 +145,6 @@ int main(int argc, char* argv[]) {
|
||||
CHECK(test_hipDeviceGetAttribute(deviceId, hipDeviceAttributeKernelExecTimeout, props.kernelExecTimeoutEnabled));
|
||||
CHECK(test_hipDeviceGetAttribute(deviceId, hipDeviceAttributeCanMapHostMemory, props.canMapHostMemory));
|
||||
CHECK(test_hipDeviceGetAttribute(deviceId, hipDeviceAttributeEccEnabled, props.ECCEnabled));
|
||||
CHECK(test_hipDeviceGetAttribute(deviceId, hipDeviceAttributeAsicRevision, props.asicRevision));
|
||||
passed();
|
||||
};
|
||||
|
||||
Regular → Executable
+8
-4
@@ -39,6 +39,9 @@ int main() {
|
||||
|
||||
HIPCHECK(hipGetDeviceCount(&numDevices));
|
||||
if (numDevices > 1) {
|
||||
int canAccessPeer = 0;
|
||||
hipDeviceCanAccessPeer(&canAccessPeer, 0, 1);
|
||||
if (canAccessPeer) {
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
||||
@@ -47,23 +50,21 @@ int main() {
|
||||
HIPCHECK(hipMalloc(&Y_d, Nbytes));
|
||||
HIPCHECK(hipMalloc(&Z_d, Nbytes));
|
||||
|
||||
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HIPCHECK(hipMemcpy(A_d, A_h, Nbytes, hipMemcpyHostToDevice));
|
||||
HIPCHECK(hipMemcpy(B_d, B_h, Nbytes, hipMemcpyHostToDevice));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, 0,
|
||||
static_cast<const int*>(A_d), static_cast<const int*>(B_d), C_d, N);
|
||||
static_cast<const int*>(A_d), static_cast<const int*>(B_d), C_d, N);
|
||||
HIPCHECK(hipMemcpy(C_h, C_d, Nbytes, hipMemcpyDeviceToHost));
|
||||
HIPCHECK(hipDeviceSynchronize());
|
||||
HipTest::checkVectorADD(A_h, B_h, C_h, N);
|
||||
|
||||
|
||||
HIPCHECK(hipSetDevice(1));
|
||||
HIPCHECK(hipMemcpyDtoD((hipDeviceptr_t)X_d, (hipDeviceptr_t)A_d, Nbytes));
|
||||
HIPCHECK(hipMemcpyDtoD((hipDeviceptr_t)Y_d, (hipDeviceptr_t)B_d, Nbytes));
|
||||
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, 0,
|
||||
static_cast<const int*>(X_d), static_cast<const int*>(Y_d), Z_d, N);
|
||||
static_cast<const int*>(X_d), static_cast<const int*>(Y_d), Z_d, N);
|
||||
HIPCHECK(hipMemcpyDtoH(C_h, (hipDeviceptr_t)Z_d, Nbytes));
|
||||
HIPCHECK(hipDeviceSynchronize());
|
||||
HipTest::checkVectorADD(A_h, B_h, C_h, N);
|
||||
@@ -72,6 +73,9 @@ int main() {
|
||||
HIPCHECK(hipFree(X_d));
|
||||
HIPCHECK(hipFree(Y_d));
|
||||
HIPCHECK(hipFree(Z_d));
|
||||
} else {
|
||||
std::cout<<"Machine does not seem to have P2P Capabilities, Empty Pass"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
passed();
|
||||
|
||||
Regular → Executable
+7
@@ -40,6 +40,10 @@ int main() {
|
||||
|
||||
HIPCHECK(hipGetDeviceCount(&numDevices));
|
||||
if (numDevices > 1) {
|
||||
|
||||
int canAccessPeer = 0;
|
||||
hipDeviceCanAccessPeer(&canAccessPeer, 0, 1);
|
||||
if (canAccessPeer) {
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
||||
@@ -75,6 +79,9 @@ int main() {
|
||||
HIPCHECK(hipFree(X_d));
|
||||
HIPCHECK(hipFree(Y_d));
|
||||
HIPCHECK(hipFree(Z_d));
|
||||
} else {
|
||||
std::cout<<"Machine does not seem to have P2P Capabilities, Empty Pass"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
passed();
|
||||
|
||||
Regular → Executable
+6
@@ -39,6 +39,9 @@ int main() {
|
||||
|
||||
HIPCHECK(hipGetDeviceCount(&numDevices));
|
||||
if (numDevices > 1) {
|
||||
int canAccessPeer = 0;
|
||||
hipDeviceCanAccessPeer(&canAccessPeer, 0, 1);
|
||||
if (canAccessPeer) {
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
||||
@@ -72,6 +75,9 @@ int main() {
|
||||
HIPCHECK(hipFree(X_d));
|
||||
HIPCHECK(hipFree(Y_d));
|
||||
HIPCHECK(hipFree(Z_d));
|
||||
} else {
|
||||
std::cout<<"Machine does not seem to have P2P Capabilities, Empty Pass"<<std::endl;
|
||||
}
|
||||
}
|
||||
passed();
|
||||
}
|
||||
|
||||
Regular → Executable
+7
@@ -42,6 +42,10 @@ int main() {
|
||||
|
||||
HIPCHECK(hipGetDeviceCount(&numDevices));
|
||||
if (numDevices > 1) {
|
||||
|
||||
int canAccessPeer = 0;
|
||||
hipDeviceCanAccessPeer(&canAccessPeer, 0, 1);
|
||||
if (canAccessPeer) {
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
||||
@@ -77,6 +81,9 @@ int main() {
|
||||
HIPCHECK(hipFree(X_d));
|
||||
HIPCHECK(hipFree(Y_d));
|
||||
HIPCHECK(hipFree(Z_d));
|
||||
} else {
|
||||
std::cout<<"Machine does not seem to have P2P Capabilities, Empty Pass"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
passed();
|
||||
|
||||
Regular → Executable
+476
-22
@@ -18,9 +18,9 @@ THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Conformance test for checking functionality of
|
||||
* hipError_t hipMemcpyPeer(void* dst, int dstDeviceId, const void* src, int srcDeviceId, size_t
|
||||
* sizeBytes);
|
||||
* Different test for checking functionality of
|
||||
* hipError_t hipMemcpyWithStream(void* dst, const void* src, size_t sizeBytes,hipMemcpyKind kind,
|
||||
* hipStream_t stream);
|
||||
*/
|
||||
|
||||
/* HIT_START
|
||||
@@ -31,27 +31,481 @@ THE SOFTWARE.
|
||||
|
||||
#include "test_common.h"
|
||||
|
||||
int main() {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int *A_d, *B_d, *C_d;
|
||||
int *A_h, *B_h, *C_h;
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
||||
#define test_passed(test_name) printf("%s %s PASSED!%s\n", KGRN, #test_name, KNRM);
|
||||
#define test_failed(test_name) printf("%s %s FAILED!%s\n", KRED, #test_name, KNRM);
|
||||
|
||||
hipStream_t stream;
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(A_d, A_h, Nbytes, hipMemcpyHostToDevice, stream));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d, B_h, Nbytes, hipMemcpyHostToDevice,stream));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, stream,
|
||||
static_cast<const int*>(A_d), static_cast<const int*>(B_d), C_d, N);
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
HIPCHECK(hipMemcpy(C_h, C_d, Nbytes, hipMemcpyDeviceToHost));
|
||||
HipTest::checkVectorADD(A_h, B_h, C_h, N);
|
||||
class HipMemcpyWithStreamtests {
|
||||
public:
|
||||
// Test hipMemcpyWithStream with one streams and launch kernel in
|
||||
// that stream, verify the data
|
||||
void TestwithOnestream(void);
|
||||
// Test hipMemcpyWithStream with two streams and launch kernels in
|
||||
// two streams, verify the data
|
||||
void TestwithTwoStream(void);
|
||||
// Test hipMemcpyWithStream with one stream for each gpu and launch
|
||||
// kernels in each, verify the data
|
||||
void TestOnMultiGPUwithOneStream(void);
|
||||
// Test hipMemcpyWithStream to copy data from device to host (hipMemcpyDeviceToHost)
|
||||
void TestkindDtoH(void);
|
||||
// Test hipMemcpyWithStream with hipMemcpyDeviceToDevice on MultiGPU
|
||||
void TestkindDtoD(void);
|
||||
// Test hipMemcpyWithStream with hipMemcpyHostToHost
|
||||
void TestkindHtoH(void);
|
||||
// Test hipMemcpyWithStream with hipMemcpyDefault
|
||||
void TestkindDefault(void);
|
||||
// Test hipMemcpyWithStream with hipMemcpyDefault for device to device transfer case
|
||||
void TestkindDefaultForDtoD(void);
|
||||
// Test hipMemcpyWithStream with hipMemcpyDeviceToDevice on same device
|
||||
void TestDtoDonSameDevice(void);
|
||||
};
|
||||
|
||||
HipTest::freeArrays(A_d, B_d, C_d, A_h, B_h, C_h, false);
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
passed();
|
||||
void HipMemcpyWithStreamtests::TestwithOnestream(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int *A_d, *B_d, *C_d;
|
||||
int *A_h, *B_h, *C_h;
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
||||
|
||||
hipStream_t stream;
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(A_d, A_h, Nbytes, hipMemcpyHostToDevice, stream));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d, B_h, Nbytes, hipMemcpyHostToDevice, stream));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, stream,
|
||||
static_cast<const int*>(A_d), static_cast<const int*>(B_d), C_d, N);
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
HIPCHECK(hipMemcpy(C_h, C_d, Nbytes, hipMemcpyDeviceToHost));
|
||||
HipTest::checkVectorADD(A_h, B_h, C_h, N);
|
||||
|
||||
HipTest::freeArrays(A_d, B_d, C_d, A_h, B_h, C_h, false);
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamtests::TestwithTwoStream(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int noOfstreams = 2;
|
||||
int *A_d[noOfstreams], *B_d[noOfstreams], *C_d[noOfstreams];
|
||||
int *A_h[noOfstreams], *B_h[noOfstreams], *C_h[noOfstreams];
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HipTest::initArrays(&A_d[i], &B_d[i], &C_d[i], &A_h[i], &B_h[i], &C_h[i], N, false);
|
||||
}
|
||||
|
||||
hipStream_t stream[noOfstreams];
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipStreamCreate(&stream[i]));
|
||||
}
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[i], A_h[i], Nbytes, hipMemcpyHostToDevice, stream[i]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[i], B_h[i], Nbytes, hipMemcpyHostToDevice, stream[i]));
|
||||
}
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, stream[i],
|
||||
static_cast<const int*>(A_d[i]), static_cast<const int*>(B_d[i]), C_d[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipStreamSynchronize(stream[i]));
|
||||
HIPCHECK(hipMemcpy(C_h[i], C_d[i], Nbytes, hipMemcpyDeviceToHost));
|
||||
HipTest::checkVectorADD(A_h[i], B_h[i], C_h[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HipTest::freeArrays(A_d[i], B_d[i], C_d[i], A_h[i], B_h[i], C_h[i], false);
|
||||
HIPCHECK(hipStreamDestroy(stream[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamtests::TestDtoDonSameDevice(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int noOfstreams = 2;
|
||||
int *A_d[noOfstreams], *B_d[noOfstreams], *C_d[noOfstreams];
|
||||
int *A_h[noOfstreams], *B_h[noOfstreams], *C_h[noOfstreams];
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
|
||||
HipTest::initArrays(&A_d[0], &B_d[0], &C_d[0], &A_h[0], &B_h[0], &C_h[0], N, false);
|
||||
|
||||
|
||||
hipStream_t stream[noOfstreams];
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HIPCHECK(hipStreamCreate(&stream[i]));
|
||||
}
|
||||
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HIPCHECK(hipMalloc(&A_d[1], Nbytes));
|
||||
HIPCHECK(hipMalloc(&B_d[1], Nbytes));
|
||||
HIPCHECK(hipMalloc(&C_d[1], Nbytes));
|
||||
C_h[1] = reinterpret_cast<int*>(malloc(Nbytes));
|
||||
HIPASSERT(C_h[1] != NULL);
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[0], A_h[0], Nbytes, hipMemcpyHostToDevice, stream[0]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[0], B_h[0], Nbytes, hipMemcpyHostToDevice, stream[0]));
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[1], A_d[0], Nbytes, hipMemcpyDeviceToDevice, stream[1]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[1], B_d[0], Nbytes, hipMemcpyDeviceToDevice, stream[1]));
|
||||
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, stream[i],
|
||||
static_cast<const int*>(A_d[i]), static_cast<const int*>(B_d[i]), C_d[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HIPCHECK(hipStreamSynchronize(stream[i]));
|
||||
HIPCHECK(hipMemcpy(C_h[i], C_d[i], Nbytes, hipMemcpyDeviceToHost));
|
||||
HipTest::checkVectorADD(A_h[0], B_h[0], C_h[i], N);
|
||||
}
|
||||
|
||||
|
||||
HipTest::freeArrays(A_d[0], B_d[0], C_d[0], A_h[0], B_h[0], C_h[0], false);
|
||||
|
||||
if (A_d[1]) {
|
||||
HIPCHECK(hipFree(A_d[1]));
|
||||
}
|
||||
if (B_d[1]) {
|
||||
HIPCHECK(hipFree(B_d[1]));
|
||||
}
|
||||
if (C_d[1]) {
|
||||
HIPCHECK(hipFree(C_d[1]));
|
||||
}
|
||||
if (C_h[1]) {
|
||||
free(C_h[1]);
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipStreamDestroy(stream[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamtests::TestOnMultiGPUwithOneStream(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HIPCHECK(hipGetDeviceCount(&numDevices));
|
||||
// If you have single GPU machine the return
|
||||
if (numDevices <= 1) {
|
||||
return;
|
||||
}
|
||||
int *A_d[numDevices], *B_d[numDevices], *C_d[numDevices];
|
||||
int *A_h[numDevices], *B_h[numDevices], *C_h[numDevices];
|
||||
|
||||
hipStream_t stream[numDevices];
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipStreamCreate(&stream[i]));
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HipTest::initArrays(&A_d[i], &B_d[i], &C_d[i], &A_h[i], &B_h[i], &C_h[i], N, false);
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[i], A_h[i], Nbytes, hipMemcpyHostToDevice, stream[i]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[i], B_h[i], Nbytes, hipMemcpyHostToDevice, stream[i]));
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, stream[i],
|
||||
static_cast<const int*>(A_d[i]), static_cast<const int*>(B_d[i]), C_d[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipStreamSynchronize(stream[i]));
|
||||
HIPCHECK(hipMemcpy(C_h[i], C_d[i], Nbytes, hipMemcpyDeviceToHost));
|
||||
HipTest::checkVectorADD(A_h[i], B_h[i], C_h[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HipTest::freeArrays(A_d[i], B_d[i], C_d[i], A_h[i], B_h[i], C_h[i], false);
|
||||
HIPCHECK(hipStreamDestroy(stream[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamtests::TestkindDtoH(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int *A_d, *B_d, *C_d;
|
||||
int *A_h, *B_h, *C_h;
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
||||
|
||||
hipStream_t stream;
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(A_d, A_h, Nbytes, hipMemcpyHostToDevice, stream));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d, B_h, Nbytes, hipMemcpyHostToDevice, stream));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, stream,
|
||||
static_cast<const int*>(A_d), static_cast<const int*>(B_d), C_d, N);
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
HIPCHECK(hipMemcpyWithStream(C_h, C_d, Nbytes, hipMemcpyDeviceToHost, stream));
|
||||
HipTest::checkVectorADD(A_h, B_h, C_h, N);
|
||||
|
||||
HipTest::freeArrays(A_d, B_d, C_d, A_h, B_h, C_h, false);
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
}
|
||||
|
||||
|
||||
void HipMemcpyWithStreamtests::TestkindDtoD(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HIPCHECK(hipGetDeviceCount(&numDevices));
|
||||
// If you have single GPU machine the return
|
||||
if (numDevices <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int canAccessPeer = 0;
|
||||
hipDeviceCanAccessPeer(&canAccessPeer, 0, 1);
|
||||
if (!canAccessPeer) {
|
||||
std::cout<<"Machine does not seem to have P2P Capabilities"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
int *A_d[numDevices], *B_d[numDevices], *C_d[numDevices];
|
||||
int *A_h[numDevices], *B_h[numDevices], *C_h[numDevices];
|
||||
|
||||
hipStream_t stream[numDevices];
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipStreamCreate(&stream[i]));
|
||||
}
|
||||
|
||||
// Initialize and create the host and device elements for first device
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HipTest::initArrays(&A_d[0], &B_d[0], &C_d[0], &A_h[0], &B_h[0], &C_h[0], N, false);
|
||||
|
||||
for (int i=1; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i))
|
||||
HIPCHECK(hipMalloc(&A_d[i], Nbytes));
|
||||
HIPCHECK(hipMalloc(&B_d[i], Nbytes));
|
||||
HIPCHECK(hipMalloc(&C_d[i], Nbytes));
|
||||
C_h[i] = reinterpret_cast<int*>(malloc(Nbytes));
|
||||
HIPASSERT(C_h[i] != NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[0], A_h[0], Nbytes, hipMemcpyHostToDevice, stream[0]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[0], B_h[0], Nbytes, hipMemcpyHostToDevice, stream[0]));
|
||||
|
||||
for (int i=1; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[i], A_d[0], Nbytes, hipMemcpyDeviceToDevice, stream[i]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[i], B_d[0], Nbytes, hipMemcpyDeviceToDevice, stream[i]));
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, stream[i],
|
||||
static_cast<const int*>(A_d[i]), static_cast<const int*>(B_d[i]), C_d[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipStreamSynchronize(stream[i]));
|
||||
HIPCHECK(hipMemcpy(C_h[i], C_d[i], Nbytes, hipMemcpyDeviceToHost));
|
||||
HipTest::checkVectorADD(A_h[0], B_h[0], C_h[i], N);
|
||||
}
|
||||
|
||||
HipTest::freeArrays(A_d[0], B_d[0], C_d[0], A_h[0], B_h[0], C_h[0], false);
|
||||
HIPCHECK(hipStreamDestroy(stream[0]));
|
||||
|
||||
for (int i=1; i < numDevices; ++i) {
|
||||
if (A_d[i]) {
|
||||
HIPCHECK(hipFree(A_d[i]));
|
||||
}
|
||||
if (B_d[i]) {
|
||||
HIPCHECK(hipFree(B_d[i]));
|
||||
}
|
||||
if (C_d[i]) {
|
||||
HIPCHECK(hipFree(C_d[i]));
|
||||
}
|
||||
if (C_h[i]) {
|
||||
free(C_h[i]);
|
||||
}
|
||||
HIPCHECK(hipStreamDestroy(stream[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamtests::TestkindDefault(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int *A_d, *B_d, *C_d;
|
||||
int *A_h, *B_h, *C_h;
|
||||
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
||||
|
||||
hipStream_t stream;
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(A_d, A_h, Nbytes, hipMemcpyDefault, stream));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d, B_h, Nbytes, hipMemcpyDefault, stream));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, stream,
|
||||
static_cast<const int*>(A_d), static_cast<const int*>(B_d), C_d, N);
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
HIPCHECK(hipMemcpyWithStream(C_h, C_d, Nbytes, hipMemcpyDefault, stream));
|
||||
HipTest::checkVectorADD(A_h, B_h, C_h, N);
|
||||
|
||||
HipTest::freeArrays(A_d, B_d, C_d, A_h, B_h, C_h, false);
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamtests::TestkindDefaultForDtoD(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HIPCHECK(hipGetDeviceCount(&numDevices));
|
||||
// If you have single GPU machine the return
|
||||
if (numDevices <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int *A_d[numDevices], *B_d[numDevices], *C_d[numDevices];
|
||||
int *A_h[numDevices], *B_h[numDevices], *C_h[numDevices];
|
||||
|
||||
// Initialize and create the host and device elements for first device
|
||||
HipTest::initArrays(&A_d[0], &B_d[0], &C_d[0], &A_h[0], &B_h[0], &C_h[0], N, false);
|
||||
|
||||
for (int i=1; i < numDevices; ++i) {
|
||||
HIPCHECK(hipMalloc(&A_d[i], Nbytes));
|
||||
HIPCHECK(hipMalloc(&B_d[i], Nbytes));
|
||||
HIPCHECK(hipMalloc(&C_d[i], Nbytes));
|
||||
C_h[i] = reinterpret_cast<int*>(malloc(Nbytes));
|
||||
HIPASSERT(C_h[i] != NULL);
|
||||
}
|
||||
|
||||
hipStream_t stream[numDevices];
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipStreamCreate(&stream[i]));
|
||||
}
|
||||
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[0], A_h[0], Nbytes, hipMemcpyHostToDevice, stream[0]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[0], B_h[0], Nbytes, hipMemcpyHostToDevice, stream[0]));
|
||||
|
||||
for (int i=1; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[i], A_d[0], Nbytes, hipMemcpyDefault, stream[i]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[i], B_d[0], Nbytes, hipMemcpyDefault, stream[i]));
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, stream[i],
|
||||
static_cast<const int*>(A_d[i]), static_cast<const int*>(B_d[i]), C_d[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipStreamSynchronize(stream[i]));
|
||||
HIPCHECK(hipMemcpy(C_h[i], C_d[i], Nbytes, hipMemcpyDeviceToHost));
|
||||
HipTest::checkVectorADD(A_h[0], B_h[0], C_h[i], N);
|
||||
}
|
||||
|
||||
HipTest::freeArrays(A_d[0], B_d[0], C_d[0], A_h[0], B_h[0], C_h[0], false);
|
||||
HIPCHECK(hipStreamDestroy(stream[0]));
|
||||
|
||||
for (int i=1; i < numDevices; ++i) {
|
||||
if (A_d[i]) {
|
||||
HIPCHECK(hipFree(A_d[i]));
|
||||
}
|
||||
if (B_d[i]) {
|
||||
HIPCHECK(hipFree(B_d[i]));
|
||||
}
|
||||
if (C_d[i]) {
|
||||
HIPCHECK(hipFree(C_d[i]));
|
||||
}
|
||||
if (C_h[i]) {
|
||||
free(C_h[i]);
|
||||
}
|
||||
HIPCHECK(hipStreamDestroy(stream[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamtests::TestkindHtoH(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int *A_h, *B_h;
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
|
||||
// Allocate memory to A_h and B_h
|
||||
A_h = static_cast<int*>(malloc(Nbytes));
|
||||
HIPASSERT(A_h != NULL);
|
||||
B_h = static_cast<int*>(malloc(Nbytes));
|
||||
HIPASSERT(B_h != NULL);
|
||||
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (A_h) (A_h)[i] = 3.146f + i; // Pi
|
||||
}
|
||||
|
||||
hipStream_t stream;
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(B_h, A_h, Nbytes, hipMemcpyHostToHost, stream));
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
HIPASSERT(A_h[i] == B_h[i]);
|
||||
}
|
||||
|
||||
if (A_h) {
|
||||
free(A_h);
|
||||
}
|
||||
if (B_h) {
|
||||
free(B_h);
|
||||
}
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
}
|
||||
|
||||
int main() {
|
||||
HipMemcpyWithStreamtests tests;
|
||||
tests.TestwithOnestream();
|
||||
test_passed(TestwithOnestream);
|
||||
tests.TestwithTwoStream();
|
||||
test_passed(TestwithTwoStream);
|
||||
tests.TestkindDtoH();
|
||||
test_passed(TestkindsDtoH);
|
||||
tests.TestkindDefault();
|
||||
test_passed(TestkindDefault);
|
||||
tests.TestDtoDonSameDevice();
|
||||
test_passed(TestDtoDonSameDevice);
|
||||
tests.TestOnMultiGPUwithOneStream();
|
||||
test_passed(TestOnMultiGPUwithOneStream);
|
||||
tests.TestkindDtoD();
|
||||
test_passed(TestkindDtoD);
|
||||
tests.TestkindDefaultForDtoD();
|
||||
test_passed(TestkindDefaultForDtoD);
|
||||
tests.TestkindHtoH();
|
||||
test_passed(TestkindsHtoH);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
Copyright (c) 2020-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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Different test for checking functionality of
|
||||
* hipError_t hipMemcpyWithStream(void* dst, const void* src, size_t sizeBytes,
|
||||
* hipMemcpyKind kind, hipStream_t stream);
|
||||
*/
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include "test_common.h"
|
||||
|
||||
#define LEN 64
|
||||
#define SIZE LEN << 2
|
||||
#define THREADS 2
|
||||
#define MAX_THREADS 16
|
||||
|
||||
|
||||
#define test_passed(test_name) printf("%s %s PASSED!%s\n", \
|
||||
KGRN, #test_name, KNRM);
|
||||
#define test_failed(test_name) printf("%s %s FAILED!%s\n", \
|
||||
KRED, #test_name, KNRM);
|
||||
|
||||
enum class ops
|
||||
{ TestwithOnestream,
|
||||
TestwithTwoStream,
|
||||
TestOnMultiGPUwithOneStream,
|
||||
TestkindDtoH,
|
||||
TestkindDtoD,
|
||||
TestkindHtoH,
|
||||
TestkindDefault,
|
||||
TestkindDefaultForDtoD,
|
||||
TestDtoDonSameDevice,
|
||||
END_OF_LIST
|
||||
};
|
||||
|
||||
|
||||
class HipMemcpyWithStreamMultiThreadtests {
|
||||
// Test hipMemcpyWithStream with one streams and launch kernel in
|
||||
// that stream, verify the data.
|
||||
void TestwithOnestream(void);
|
||||
// Test hipMemcpyWithStream with two streams and launch kernels in
|
||||
// two streams, verify the data.
|
||||
void TestwithTwoStream(void);
|
||||
// Test hipMemcpyWithStream with one stream for each gpu and launch
|
||||
// kernels in each, verify the data
|
||||
void TestOnMultiGPUwithOneStream(void);
|
||||
// Test hipMemcpyWithStream to copy data from
|
||||
// device to host (hipMemcpyDeviceToHost).
|
||||
void TestkindDtoH(void);
|
||||
// Test hipMemcpyWithStream with hipMemcpyDeviceToDevice on MultiGPU.
|
||||
void TestkindDtoD(void);
|
||||
// Test hipMemcpyWithStream with hipMemcpyHostToHost.
|
||||
void TestkindHtoH(void);
|
||||
// Test hipMemcpyWithStream with hipMemcpyDefault.
|
||||
void TestkindDefault(void);
|
||||
// Test hipMemcpyWithStream with hipMemcpyDefault for
|
||||
// device to device transfer case.
|
||||
void TestkindDefaultForDtoD(void);
|
||||
// Test hipMemcpyWithStream with hipMemcpyDeviceToDevice on same device.
|
||||
void TestDtoDonSameDevice(void);
|
||||
|
||||
public:
|
||||
// run all the tests on multithreaded.
|
||||
void TestwithMultiThreaded(ops op);
|
||||
};
|
||||
|
||||
struct joinable_thread : std::thread {
|
||||
template <class... Xs>
|
||||
explicit joinable_thread(Xs&&... xs) : std::thread(std::forward<Xs>(xs)...)
|
||||
{} // NOLINT
|
||||
|
||||
joinable_thread& operator=(joinable_thread&& other) = default;
|
||||
joinable_thread(joinable_thread&& other) = default;
|
||||
|
||||
~joinable_thread() {
|
||||
if (this->joinable())
|
||||
this->join();
|
||||
}
|
||||
};
|
||||
|
||||
void HipMemcpyWithStreamMultiThreadtests::TestwithOnestream(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int *A_d, *B_d, *C_d;
|
||||
int *A_h, *B_h, *C_h;
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
||||
|
||||
hipStream_t stream;
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(A_d, A_h, Nbytes,
|
||||
hipMemcpyHostToDevice, stream));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d, B_h, Nbytes,
|
||||
hipMemcpyHostToDevice, stream));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock),
|
||||
0, stream, static_cast<const int*>(A_d),
|
||||
static_cast<const int*>(B_d), C_d, N);
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
HIPCHECK(hipMemcpy(C_h, C_d, Nbytes, hipMemcpyDeviceToHost));
|
||||
HipTest::checkVectorADD(A_h, B_h, C_h, N);
|
||||
|
||||
HipTest::freeArrays(A_d, B_d, C_d, A_h, B_h, C_h, false);
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamMultiThreadtests::TestwithTwoStream(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int noOfstreams = 2;
|
||||
int *A_d[noOfstreams], *B_d[noOfstreams], *C_d[noOfstreams];
|
||||
int *A_h[noOfstreams], *B_h[noOfstreams], *C_h[noOfstreams];
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HipTest::initArrays(&A_d[i], &B_d[i], &C_d[i],
|
||||
&A_h[i], &B_h[i], &C_h[i], N, false);
|
||||
}
|
||||
|
||||
hipStream_t stream[noOfstreams];
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipStreamCreate(&stream[i]));
|
||||
}
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[i], A_h[i], Nbytes,
|
||||
hipMemcpyHostToDevice, stream[i]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[i], B_h[i], Nbytes,
|
||||
hipMemcpyHostToDevice, stream[i]));
|
||||
}
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock),
|
||||
0, stream[i], static_cast<const int*>(A_d[i]),
|
||||
static_cast<const int*>(B_d[i]), C_d[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipStreamSynchronize(stream[i]));
|
||||
HIPCHECK(hipMemcpy(C_h[i], C_d[i], Nbytes, hipMemcpyDeviceToHost));
|
||||
HipTest::checkVectorADD(A_h[i], B_h[i], C_h[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HipTest::freeArrays(A_d[i], B_d[i], C_d[i], A_h[i], B_h[i], C_h[i], false);
|
||||
HIPCHECK(hipStreamDestroy(stream[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamMultiThreadtests::TestDtoDonSameDevice(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int noOfstreams = 2;
|
||||
int *A_d[noOfstreams], *B_d[noOfstreams], *C_d[noOfstreams];
|
||||
int *A_h[noOfstreams], *B_h[noOfstreams], *C_h[noOfstreams];
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
|
||||
HipTest::initArrays(&A_d[0], &B_d[0], &C_d[0],
|
||||
&A_h[0], &B_h[0], &C_h[0], N, false);
|
||||
|
||||
|
||||
hipStream_t stream[noOfstreams];
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HIPCHECK(hipStreamCreate(&stream[i]));
|
||||
}
|
||||
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HIPCHECK(hipMalloc(&A_d[1], Nbytes));
|
||||
HIPCHECK(hipMalloc(&B_d[1], Nbytes));
|
||||
HIPCHECK(hipMalloc(&C_d[1], Nbytes));
|
||||
C_h[1] = reinterpret_cast<int*>(malloc(Nbytes));
|
||||
HIPASSERT(C_h[1] != NULL);
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[0], A_h[0], Nbytes,
|
||||
hipMemcpyHostToDevice, stream[0]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[0], B_h[0], Nbytes,
|
||||
hipMemcpyHostToDevice, stream[0]));
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[1], A_d[0], Nbytes,
|
||||
hipMemcpyDeviceToDevice, stream[1]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[1], B_d[0], Nbytes,
|
||||
hipMemcpyDeviceToDevice, stream[1]));
|
||||
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock),
|
||||
0, stream[i], static_cast<const int*>(A_d[i]),
|
||||
static_cast<const int*>(B_d[i]), C_d[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HIPCHECK(hipStreamSynchronize(stream[i]));
|
||||
HIPCHECK(hipMemcpy(C_h[i], C_d[i], Nbytes, hipMemcpyDeviceToHost));
|
||||
HipTest::checkVectorADD(A_h[0], B_h[0], C_h[i], N);
|
||||
}
|
||||
|
||||
|
||||
HipTest::freeArrays(A_d[0], B_d[0], C_d[0], A_h[0], B_h[0], C_h[0], false);
|
||||
|
||||
if (A_d[1]) {
|
||||
HIPCHECK(hipFree(A_d[1]));
|
||||
}
|
||||
if (B_d[1]) {
|
||||
HIPCHECK(hipFree(B_d[1]));
|
||||
}
|
||||
if (C_d[1]) {
|
||||
HIPCHECK(hipFree(C_d[1]));
|
||||
}
|
||||
if (C_h[1]) {
|
||||
free(C_h[1]);
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i < noOfstreams; ++i) {
|
||||
HIPCHECK(hipStreamDestroy(stream[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamMultiThreadtests::TestOnMultiGPUwithOneStream(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HIPCHECK(hipGetDeviceCount(&numDevices));
|
||||
// If you have single GPU machine the return
|
||||
if (numDevices <= 1) {
|
||||
return;
|
||||
}
|
||||
int *A_d[numDevices], *B_d[numDevices], *C_d[numDevices];
|
||||
int *A_h[numDevices], *B_h[numDevices], *C_h[numDevices];
|
||||
|
||||
hipStream_t stream[numDevices];
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipStreamCreate(&stream[i]));
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HipTest::initArrays(&A_d[i], &B_d[i], &C_d[i],
|
||||
&A_h[i], &B_h[i], &C_h[i], N, false);
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[i], A_h[i], Nbytes,
|
||||
hipMemcpyHostToDevice, stream[i]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[i], B_h[i], Nbytes,
|
||||
hipMemcpyHostToDevice, stream[i]));
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock),
|
||||
0, stream[i], static_cast<const int*>(A_d[i]),
|
||||
static_cast<const int*>(B_d[i]), C_d[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipStreamSynchronize(stream[i]));
|
||||
HIPCHECK(hipMemcpy(C_h[i], C_d[i], Nbytes, hipMemcpyDeviceToHost));
|
||||
HipTest::checkVectorADD(A_h[i], B_h[i], C_h[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HipTest::freeArrays(A_d[i], B_d[i], C_d[i], A_h[i], B_h[i], C_h[i], false);
|
||||
HIPCHECK(hipStreamDestroy(stream[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamMultiThreadtests::TestkindDtoH(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int *A_d, *B_d, *C_d;
|
||||
int *A_h, *B_h, *C_h;
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
||||
|
||||
hipStream_t stream;
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(A_d, A_h, Nbytes,
|
||||
hipMemcpyHostToDevice, stream));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d, B_h, Nbytes,
|
||||
hipMemcpyHostToDevice, stream));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock),
|
||||
0, stream, static_cast<const int*>(A_d),
|
||||
static_cast<const int*>(B_d), C_d, N);
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
HIPCHECK(hipMemcpyWithStream(C_h, C_d, Nbytes,
|
||||
hipMemcpyDeviceToHost, stream));
|
||||
HipTest::checkVectorADD(A_h, B_h, C_h, N);
|
||||
|
||||
HipTest::freeArrays(A_d, B_d, C_d, A_h, B_h, C_h, false);
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
}
|
||||
|
||||
|
||||
void HipMemcpyWithStreamMultiThreadtests::TestkindDtoD(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HIPCHECK(hipGetDeviceCount(&numDevices));
|
||||
// If you have single GPU machine the return
|
||||
if (numDevices <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int *A_d[numDevices], *B_d[numDevices], *C_d[numDevices];
|
||||
int *A_h[numDevices], *B_h[numDevices], *C_h[numDevices];
|
||||
|
||||
hipStream_t stream[numDevices];
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipStreamCreate(&stream[i]));
|
||||
}
|
||||
|
||||
// Initialize and create the host and device elements for first device
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HipTest::initArrays(&A_d[0], &B_d[0], &C_d[0],
|
||||
&A_h[0], &B_h[0], &C_h[0], N, false);
|
||||
|
||||
for (int i=1; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i))
|
||||
HIPCHECK(hipMalloc(&A_d[i], Nbytes));
|
||||
HIPCHECK(hipMalloc(&B_d[i], Nbytes));
|
||||
HIPCHECK(hipMalloc(&C_d[i], Nbytes));
|
||||
C_h[i] = reinterpret_cast<int*>(malloc(Nbytes));
|
||||
HIPASSERT(C_h[i] != NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[0], A_h[0], Nbytes,
|
||||
hipMemcpyHostToDevice, stream[0]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[0], B_h[0], Nbytes,
|
||||
hipMemcpyHostToDevice, stream[0]));
|
||||
|
||||
// Copying device data from 1st GPU to the rest of the the GPUs that is
|
||||
// numDevices in the setup. 1st GPU start numbering from 0,1,2..n etc.
|
||||
for (int i=1; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[i], A_d[0], Nbytes,
|
||||
hipMemcpyDeviceToDevice, stream[i]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[i], B_d[0], Nbytes,
|
||||
hipMemcpyDeviceToDevice, stream[i]));
|
||||
}
|
||||
|
||||
|
||||
// Launching the kernel including the 1st GPU to the no of GPUs present
|
||||
// in the setup. 1st GPU start numbering from 0,1,2..n etc.
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock),
|
||||
0, stream[i], static_cast<const int*>(A_d[i]),
|
||||
static_cast<const int*>(B_d[i]), C_d[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipStreamSynchronize(stream[i]));
|
||||
HIPCHECK(hipMemcpy(C_h[i], C_d[i], Nbytes, hipMemcpyDeviceToHost));
|
||||
HipTest::checkVectorADD(A_h[0], B_h[0], C_h[i], N);
|
||||
}
|
||||
|
||||
HipTest::freeArrays(A_d[0], B_d[0], C_d[0], A_h[0], B_h[0], C_h[0], false);
|
||||
HIPCHECK(hipStreamDestroy(stream[0]));
|
||||
|
||||
for (int i=1; i < numDevices; ++i) {
|
||||
if (A_d[i]) {
|
||||
HIPCHECK(hipFree(A_d[i]));
|
||||
}
|
||||
if (B_d[i]) {
|
||||
HIPCHECK(hipFree(B_d[i]));
|
||||
}
|
||||
if (C_d[i]) {
|
||||
HIPCHECK(hipFree(C_d[i]));
|
||||
}
|
||||
if (C_h[i]) {
|
||||
free(C_h[i]);
|
||||
}
|
||||
HIPCHECK(hipStreamDestroy(stream[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamMultiThreadtests::TestkindDefault(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int *A_d, *B_d, *C_d;
|
||||
int *A_h, *B_h, *C_h;
|
||||
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
||||
|
||||
hipStream_t stream;
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(A_d, A_h, Nbytes, hipMemcpyDefault, stream));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d, B_h, Nbytes, hipMemcpyDefault, stream));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock),
|
||||
0, stream, static_cast<const int*>(A_d),
|
||||
static_cast<const int*>(B_d), C_d, N);
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
HIPCHECK(hipMemcpyWithStream(C_h, C_d, Nbytes, hipMemcpyDefault, stream));
|
||||
HipTest::checkVectorADD(A_h, B_h, C_h, N);
|
||||
|
||||
HipTest::freeArrays(A_d, B_d, C_d, A_h, B_h, C_h, false);
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamMultiThreadtests::TestkindDefaultForDtoD(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
HIPCHECK(hipGetDeviceCount(&numDevices));
|
||||
// Test case will not run on single GPU setup.
|
||||
if (numDevices <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int *A_d[numDevices], *B_d[numDevices], *C_d[numDevices];
|
||||
int *A_h[numDevices], *B_h[numDevices], *C_h[numDevices];
|
||||
|
||||
// Initialize and create the host and device elements for first device
|
||||
HipTest::initArrays(&A_d[0], &B_d[0], &C_d[0],
|
||||
&A_h[0], &B_h[0], &C_h[0], N, false);
|
||||
|
||||
for (int i=1; i < numDevices; ++i) {
|
||||
HIPCHECK(hipMalloc(&A_d[i], Nbytes));
|
||||
HIPCHECK(hipMalloc(&B_d[i], Nbytes));
|
||||
HIPCHECK(hipMalloc(&C_d[i], Nbytes));
|
||||
C_h[i] = reinterpret_cast<int*>(malloc(Nbytes));
|
||||
HIPASSERT(C_h[i] != NULL);
|
||||
}
|
||||
|
||||
hipStream_t stream[numDevices];
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipStreamCreate(&stream[i]));
|
||||
}
|
||||
|
||||
HIPCHECK(hipSetDevice(0));
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[0], A_h[0], Nbytes,
|
||||
hipMemcpyHostToDevice, stream[0]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[0], B_h[0], Nbytes,
|
||||
hipMemcpyHostToDevice, stream[0]));
|
||||
|
||||
// Copying device data from 1st GPU to the rest of the the GPUs
|
||||
// using hipMemcpyDefault kind that is numDevices in the setup.
|
||||
// 1st GPU start numbering from 0,1,2..n etc.
|
||||
for (int i=1; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipMemcpyWithStream(A_d[i], A_d[0], Nbytes,
|
||||
hipMemcpyDefault, stream[i]));
|
||||
HIPCHECK(hipMemcpyWithStream(B_d[i], B_d[0], Nbytes,
|
||||
hipMemcpyDefault, stream[i]));
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock),
|
||||
0, stream[i], static_cast<const int*>(A_d[i]),
|
||||
static_cast<const int*>(B_d[i]), C_d[i], N);
|
||||
}
|
||||
|
||||
for (int i=0; i < numDevices; ++i) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
HIPCHECK(hipStreamSynchronize(stream[i]));
|
||||
HIPCHECK(hipMemcpy(C_h[i], C_d[i], Nbytes, hipMemcpyDeviceToHost));
|
||||
// Output of each GPU is getting validated with input of 1st GPU.
|
||||
HipTest::checkVectorADD(A_h[0], B_h[0], C_h[i], N);
|
||||
}
|
||||
|
||||
HipTest::freeArrays(A_d[0], B_d[0], C_d[0], A_h[0], B_h[0], C_h[0], false);
|
||||
HIPCHECK(hipStreamDestroy(stream[0]));
|
||||
|
||||
for (int i=1; i < numDevices; ++i) {
|
||||
if (A_d[i]) {
|
||||
HIPCHECK(hipFree(A_d[i]));
|
||||
}
|
||||
if (B_d[i]) {
|
||||
HIPCHECK(hipFree(B_d[i]));
|
||||
}
|
||||
if (C_d[i]) {
|
||||
HIPCHECK(hipFree(C_d[i]));
|
||||
}
|
||||
if (C_h[i]) {
|
||||
free(C_h[i]);
|
||||
}
|
||||
HIPCHECK(hipStreamDestroy(stream[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void HipMemcpyWithStreamMultiThreadtests::TestkindHtoH(void) {
|
||||
size_t Nbytes = N * sizeof(int);
|
||||
int numDevices = 0;
|
||||
int *A_h, *B_h;
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
|
||||
// Allocate memory to A_h and B_h
|
||||
A_h = static_cast<int*>(malloc(Nbytes));
|
||||
HIPASSERT(A_h != NULL);
|
||||
B_h = static_cast<int*>(malloc(Nbytes));
|
||||
HIPASSERT(B_h != NULL);
|
||||
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (A_h) {
|
||||
(A_h)[i] = 3.146f + i; // Pi
|
||||
}
|
||||
}
|
||||
|
||||
hipStream_t stream;
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
|
||||
HIPCHECK(hipMemcpyWithStream(B_h, A_h, Nbytes, hipMemcpyHostToHost, stream));
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
HIPASSERT(A_h[i] == B_h[i]);
|
||||
}
|
||||
|
||||
if (A_h) {
|
||||
free(A_h);
|
||||
}
|
||||
if (B_h) {
|
||||
free(B_h);
|
||||
}
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
}
|
||||
|
||||
|
||||
void HipMemcpyWithStreamMultiThreadtests::TestwithMultiThreaded(ops op) {
|
||||
int n = min(THREADS * std::thread::hardware_concurrency(), MAX_THREADS);
|
||||
std::vector<joinable_thread> threads;
|
||||
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
threads.emplace_back(std::thread{[&] {
|
||||
switch ( op ) {
|
||||
case ops::TestwithOnestream:
|
||||
TestwithOnestream();
|
||||
break;
|
||||
case ops::TestwithTwoStream:
|
||||
TestwithTwoStream();
|
||||
break;
|
||||
case ops::TestkindDtoH:
|
||||
TestkindDtoH();
|
||||
break;
|
||||
case ops::TestkindHtoH:
|
||||
TestkindHtoH();
|
||||
break;
|
||||
case ops::TestkindDtoD:
|
||||
TestkindDtoD();
|
||||
break;
|
||||
case ops::TestOnMultiGPUwithOneStream:
|
||||
TestOnMultiGPUwithOneStream();
|
||||
break;
|
||||
case ops::TestkindDefault:
|
||||
TestkindDefault();
|
||||
break;
|
||||
case ops::TestkindDefaultForDtoD:
|
||||
TestkindDefaultForDtoD();
|
||||
break;
|
||||
case ops::TestDtoDonSameDevice:
|
||||
TestDtoDonSameDevice();
|
||||
break;
|
||||
default:{}
|
||||
}
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
HipMemcpyWithStreamMultiThreadtests tests;
|
||||
for (int op = static_cast<int>(ops::TestwithOnestream);
|
||||
op < static_cast<int>(ops::END_OF_LIST); ++op) {
|
||||
tests.TestwithMultiThreaded(static_cast<ops>(op));
|
||||
switch ( static_cast<ops>(op) ) {
|
||||
case ops::TestwithOnestream:
|
||||
test_passed(HipMemcpyWithStreamMultiThreadtests
|
||||
::TestwithOnestream);
|
||||
break;
|
||||
case ops::TestwithTwoStream:
|
||||
test_passed(HipMemcpyWithStreamMultiThreadtests
|
||||
::TestwithTwoStream);
|
||||
break;
|
||||
case ops::TestkindDtoH:
|
||||
test_passed(HipMemcpyWithStreamMultiThreadtests
|
||||
::TestkindDtoH);
|
||||
break;
|
||||
case ops::TestkindHtoH:
|
||||
test_passed(HipMemcpyWithStreamMultiThreadtests
|
||||
::TestkindHtoH);
|
||||
break;
|
||||
case ops::TestkindDtoD:
|
||||
test_passed(HipMemcpyWithStreamMultiThreadtests
|
||||
::TestkindDtoD);
|
||||
break;
|
||||
case ops::TestOnMultiGPUwithOneStream:
|
||||
test_passed(HipMemcpyWithStreamMultiThreadtests
|
||||
::TestOnMultiGPUwithOneStream);
|
||||
break;
|
||||
case ops::TestkindDefault:
|
||||
test_passed(HipMemcpyWithStreamMultiThreadtests
|
||||
::TestkindDefault);
|
||||
break;
|
||||
case ops::TestkindDefaultForDtoD:
|
||||
test_passed(HipMemcpyWithStreamMultiThreadtests
|
||||
::TestkindDefaultForDtoD);
|
||||
break;
|
||||
case ops::TestDtoDonSameDevice:
|
||||
test_passed(HipMemcpyWithStreamMultiThreadtests
|
||||
::TestDtoDonSameDevice);
|
||||
break;
|
||||
default: { test_failed("No Operation to done with API"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,119 +1,234 @@
|
||||
/*
|
||||
Copyright (c) 2015-present Advanced Micro Devices, Inc. All rights reserved.
|
||||
* Copyright (c) 2015-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.
|
||||
*/
|
||||
|
||||
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.
|
||||
*/
|
||||
// Simple test for memset.
|
||||
// Also serves as a template for other tests.
|
||||
// Test for hipMemset2D functionality for different width and height values
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp
|
||||
* TEST: %t
|
||||
* BUILD: %t %s ../../test_common.cpp NVCC_OPTIONS -std=c++11
|
||||
* TEST_NAMED: %t hipMemset2D-basic
|
||||
* TEST_NAMED: %t hipMemset2D-dim1 --width2D 10 --height2D 10 --memsetWidth 4 --memsetHeight 4
|
||||
* TEST_NAMED: %t hipMemset2D-dim2 --width2D 100 --height2D 100 --memsetWidth 20 --memsetHeight 40
|
||||
* TEST_NAMED: %t hipMemset2D-dim3 --width2D 256 --height2D 256 --memsetWidth 39 --memsetHeight 19
|
||||
* TEST_NAMED: %t hipMemset2D-zeroH --width2D 100 --height2D 100 --memsetWidth 20 --memsetHeight 0
|
||||
* TEST_NAMED: %t hipMemset2D-zeroW --width2D 100 --height2D 100 --memsetWidth 0 --memsetHeight 20
|
||||
* TEST_NAMED: %t hipMemset2D-zeroW*H --width2D 100 --height2D 100 --memsetWidth 0 --memsetHeight 0
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "test_common.h"
|
||||
|
||||
bool testhipMemset2D(int memsetval,int p_gpuDevice)
|
||||
{
|
||||
size_t numH = 256;
|
||||
size_t numW = 256;
|
||||
size_t pitch_A;
|
||||
size_t width = numW * sizeof(char);
|
||||
size_t sizeElements = width * numH;
|
||||
size_t elements = numW* numH;
|
||||
// Check hipMemset2D functionality
|
||||
bool testhipMemset2D(int memsetval, int p_gpuDevice) {
|
||||
bool testResult = true;
|
||||
size_t numH = 256;
|
||||
size_t numW = 256;
|
||||
size_t pitch_A;
|
||||
size_t width = numW * sizeof(char);
|
||||
size_t sizeElements = width * numH;
|
||||
size_t elements = numW* numH;
|
||||
printf("testhipMemset2D memsetval=%2x device=%d\n", memsetval, p_gpuDevice);
|
||||
char *A_d;
|
||||
char *A_h;
|
||||
|
||||
HIPCHECK(hipMallocPitch(reinterpret_cast<void**>(&A_d), &pitch_A, width ,
|
||||
numH));
|
||||
A_h = reinterpret_cast<char*>(malloc(sizeElements));
|
||||
HIPASSERT(A_h != NULL);
|
||||
|
||||
printf ("testhipMemset2D memsetval=%2x device=%d\n", memsetval, p_gpuDevice);
|
||||
char *A_d;
|
||||
char *A_h;
|
||||
bool testResult = true;
|
||||
HIPCHECK (hipMallocPitch((void**)&A_d, &pitch_A, width , numH));
|
||||
A_h = (char*)malloc(sizeElements);
|
||||
HIPASSERT(A_h != NULL);
|
||||
for (size_t i=0; i<elements; i++) {
|
||||
A_h[i] = 1;
|
||||
for (size_t i=0; i < elements; i++) {
|
||||
A_h[i] = 1;
|
||||
}
|
||||
|
||||
HIPCHECK(hipMemset2D(A_d, pitch_A, memsetval, numW, numH));
|
||||
HIPCHECK(hipMemcpy2D(A_h, width, A_d, pitch_A, numW, numH,
|
||||
hipMemcpyDeviceToHost));
|
||||
|
||||
for (int i=0; i < elements; i++) {
|
||||
if (A_h[i] != memsetval) {
|
||||
testResult = false;
|
||||
printf("testhipMemset2D mismatch at index:%d computed:%02x, memsetval:"
|
||||
"%02x\n", i, static_cast<int>(A_h[i]), static_cast<int>(memsetval));
|
||||
break;
|
||||
}
|
||||
HIPCHECK ( hipMemset2D(A_d, pitch_A, memsetval, numW, numH) );
|
||||
HIPCHECK ( hipMemcpy2D(A_h, width, A_d, pitch_A, numW, numH, hipMemcpyDeviceToHost));
|
||||
}
|
||||
|
||||
for (int i=0; i<elements; i++) {
|
||||
if (A_h[i] != memsetval) {
|
||||
testResult = false;
|
||||
printf("testhipMemset2D mismatch at index:%d computed:%02x, memsetval:%02x\n", i, (int)A_h[i], (int)memsetval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
hipFree(A_d);
|
||||
free(A_h);
|
||||
return testResult;
|
||||
hipFree(A_d);
|
||||
free(A_h);
|
||||
return testResult;
|
||||
}
|
||||
|
||||
bool testhipMemset2DAsync(int memsetval,int p_gpuDevice)
|
||||
{
|
||||
size_t numH = 256;
|
||||
size_t numW = 256;
|
||||
size_t pitch_A;
|
||||
size_t width = numW * sizeof(char);
|
||||
size_t sizeElements = width * numH;
|
||||
size_t elements = numW* numH;
|
||||
// Check hipMemset2DAsync functionality
|
||||
bool testhipMemset2DAsync(int memsetval, int p_gpuDevice) {
|
||||
size_t numH = 256;
|
||||
size_t numW = 256;
|
||||
size_t pitch_A;
|
||||
size_t width = numW * sizeof(char);
|
||||
size_t sizeElements = width * numH;
|
||||
size_t elements = numW * numH;
|
||||
printf("testhipMemset2DAsync memsetval=%2x device=%d\n", memsetval,
|
||||
p_gpuDevice);
|
||||
char *A_d;
|
||||
char *A_h;
|
||||
bool testResult = true;
|
||||
|
||||
HIPCHECK(hipMallocPitch(reinterpret_cast<void**>(&A_d), &pitch_A,
|
||||
width , numH));
|
||||
A_h = reinterpret_cast<char*>(malloc(sizeElements));
|
||||
HIPASSERT(A_h != NULL);
|
||||
|
||||
printf ("testhipMemset2DAsync memsetval=%2x device=%d\n", memsetval, p_gpuDevice);
|
||||
char *A_d;
|
||||
char *A_h;
|
||||
bool testResult = true;
|
||||
for (size_t i=0; i < elements; i++) {
|
||||
A_h[i] = 1;
|
||||
}
|
||||
|
||||
HIPCHECK (hipMallocPitch((void**)&A_d, &pitch_A, width , numH));
|
||||
A_h = (char*)malloc(sizeElements);
|
||||
HIPASSERT(A_h != NULL);
|
||||
for (size_t i=0; i<elements; i++) {
|
||||
A_h[i] = 1;
|
||||
hipStream_t stream;
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
HIPCHECK(hipMemset2DAsync(A_d, pitch_A, memsetval, numW, numH, stream));
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
HIPCHECK(hipMemcpy2D(A_h, width, A_d, pitch_A, numW, numH,
|
||||
hipMemcpyDeviceToHost));
|
||||
|
||||
for (int i=0; i < elements; i++) {
|
||||
if (A_h[i] != memsetval) {
|
||||
testResult = false;
|
||||
printf("testhipMemset2DAsync mismatch at index:%d computed:%02x, memsetval:"
|
||||
"%02x\n", i, static_cast<int>(A_h[i]), static_cast<int>(memsetval));
|
||||
break;
|
||||
}
|
||||
hipStream_t stream;
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
HIPCHECK(hipMemset2DAsync(A_d, pitch_A, memsetval, numW, numH, stream) );
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
HIPCHECK(hipMemcpy2D(A_h, width, A_d, pitch_A, numW, numH, hipMemcpyDeviceToHost));
|
||||
}
|
||||
|
||||
for (int i=0; i<elements; i++) {
|
||||
if (A_h[i] != memsetval) {
|
||||
testResult = false;
|
||||
printf("testhipMemset2DAsync mismatch at index:%d computed:%02x, memsetval:%02x\n", i, (int)A_h[i], (int)memsetval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
hipFree(A_d);
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
free(A_h);
|
||||
return testResult;
|
||||
hipFree(A_d);
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
free(A_h);
|
||||
return testResult;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
HipTest::parseStandardArguments(argc, argv, true);
|
||||
HIPCHECK(hipSetDevice(p_gpuDevice));
|
||||
bool testResult = true;
|
||||
int width2D = 20;
|
||||
int height2D = 20;
|
||||
int memsetWidth = 20;
|
||||
int memsetHeight = 20;
|
||||
|
||||
int parseExtraArguments(int argc, char* argv[]) {
|
||||
int i = 0;
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char* arg = argv[i];
|
||||
if (!strcmp(arg, " ")) {
|
||||
// skip NULL args.
|
||||
} else if (!strcmp(arg, "--width2D")) {
|
||||
if (++i >= argc || !HipTest::parseInt(argv[i], &width2D)) {
|
||||
failed("Bad width2D argument");
|
||||
}
|
||||
} else if (!strcmp(arg, "--height2D")) {
|
||||
if (++i >= argc || !HipTest::parseInt(argv[i], &height2D)) {
|
||||
failed("Bad height2D argument");
|
||||
}
|
||||
} else if (!strcmp(arg, "--memsetWidth")) {
|
||||
if (++i >= argc || !HipTest::parseInt(argv[i], &memsetWidth)) {
|
||||
failed("Bad memsetWidth argument");
|
||||
}
|
||||
} else if (!strcmp(arg, "--memsetHeight")) {
|
||||
if (++i >= argc || !HipTest::parseInt(argv[i], &memsetHeight)) {
|
||||
failed("Bad memsetHeight argument");
|
||||
}
|
||||
} else {
|
||||
failed("Bad argument");
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// Memset random dimensions
|
||||
bool testMemset2DPartial(int memsetval, int p_gpuDevice) {
|
||||
bool testResult = true;
|
||||
size_t NUM_H = height2D;
|
||||
size_t NUM_W = width2D;
|
||||
size_t Nbytes = N*sizeof(char);
|
||||
size_t pitch_A;
|
||||
size_t width = NUM_W * sizeof(char);
|
||||
size_t sizeElements = width * NUM_H;
|
||||
size_t elements = NUM_W * NUM_H;
|
||||
char *A_d;
|
||||
char *A_h;
|
||||
printf("testhipMemset2DPartial memsetval=%2x device=%d\n", memsetval,
|
||||
p_gpuDevice);
|
||||
|
||||
HIPCHECK(hipMallocPitch(reinterpret_cast<void**>(&A_d), &pitch_A,
|
||||
width, NUM_H));
|
||||
hipError_t e;
|
||||
int index;
|
||||
|
||||
A_h = reinterpret_cast<char*>(malloc(sizeElements));
|
||||
HIPASSERT(A_h != NULL);
|
||||
|
||||
for (index = 0; index < sizeElements; index++) {
|
||||
A_h[0] = 'c';
|
||||
}
|
||||
|
||||
printf("2D Dimension: %zuX%zu, MemsetWidth:%d, memsetHeight:%d\n",
|
||||
NUM_W, NUM_H, memsetWidth, memsetHeight);
|
||||
e = hipMemset2D(A_d, pitch_A, memsetval, memsetWidth, memsetHeight);
|
||||
HIPASSERT(e == hipSuccess);
|
||||
|
||||
HIPCHECK(hipMemcpy2D(A_h, width, A_d, pitch_A, NUM_W, NUM_H,
|
||||
hipMemcpyDeviceToHost));
|
||||
|
||||
for (int row = 0; row < memsetHeight; row++) {
|
||||
for (int column = 0; column < memsetWidth; column++) {
|
||||
if (A_h[(row * width) + column] != memsetval) {
|
||||
printf("A_h[%d][%d] did not match %d", row, column, memsetval);
|
||||
testResult = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
hipFree(A_d);
|
||||
free(A_h);
|
||||
return testResult;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int extraArgs = 0;
|
||||
bool testResult = true;
|
||||
|
||||
HIPCHECK(hipSetDevice(p_gpuDevice));
|
||||
extraArgs = HipTest::parseStandardArguments(argc, argv, false);
|
||||
parseExtraArguments(extraArgs, argv);
|
||||
|
||||
if (extraArgs == 1) {
|
||||
testResult &= testhipMemset2D(memsetval, p_gpuDevice);
|
||||
testResult &= testhipMemset2DAsync(memsetval, p_gpuDevice);
|
||||
if(testResult){
|
||||
passed();
|
||||
if (!(testResult)) {
|
||||
printf("hipMemset2D failed\n");
|
||||
}
|
||||
testResult &= testhipMemset2DAsync(memsetval, p_gpuDevice);
|
||||
if (!(testResult)) {
|
||||
printf("hipMemset2DAsync failed\n");
|
||||
}
|
||||
} else if (extraArgs == 9) {
|
||||
testResult &= testMemset2DPartial(memsetval, p_gpuDevice);
|
||||
if (!(testResult)) {
|
||||
printf("hipMemset2D at random dimensions failed\n");
|
||||
}
|
||||
} else {
|
||||
failed("Wrong Arguments for test\n");
|
||||
}
|
||||
|
||||
if (testResult) {
|
||||
passed();
|
||||
} else {
|
||||
failed("one or more hipMemset2D tests failed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Test to verify
|
||||
// a) Order of execution of device kernel and hipMemset2DAsync api
|
||||
// b) hipMemSet2DAsync execution in multiple threads
|
||||
//
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp EXCLUDE_HIP_PLATFORM nvcc
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include "test_common.h"
|
||||
#define NUM_THREADS 1000
|
||||
#define ITER 100
|
||||
#define NUM_H 256
|
||||
#define NUM_W 256
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
hipStream_t stream;
|
||||
|
||||
bool testResult = true;
|
||||
char *A_d, *A_h, *B_d, *B_h, *C_d;
|
||||
int validateCount;
|
||||
|
||||
size_t pitch_A, pitch_B, pitch_C;
|
||||
size_t width = NUM_W * sizeof(char);
|
||||
size_t sizeElements = width * NUM_H;
|
||||
size_t elements = NUM_W * NUM_H;
|
||||
|
||||
/*
|
||||
* Square each element in the array B and write to array C.
|
||||
*/
|
||||
|
||||
__global__ void
|
||||
vector_square(char* B_d, char* C_d, size_t elements) {
|
||||
for (int i=0 ; i < elements ; i++) {
|
||||
C_d[i] = B_d[i] * B_d[i];
|
||||
}
|
||||
}
|
||||
|
||||
void memAllocate() {
|
||||
HIPCHECK(hipMallocPitch(reinterpret_cast<void**>(&A_d), &pitch_A, width, NUM_H));
|
||||
HIPCHECK(hipMallocPitch(reinterpret_cast<void**>(&B_d), &pitch_B, width, NUM_H));
|
||||
A_h = reinterpret_cast<char*>(malloc(sizeElements));
|
||||
HIPASSERT(A_h != NULL);
|
||||
B_h = reinterpret_cast<char*>(malloc(sizeElements));
|
||||
HIPASSERT(B_h != NULL);
|
||||
HIPCHECK(hipMallocPitch(reinterpret_cast<void**>(&C_d), &pitch_C, width, NUM_H));
|
||||
|
||||
for (int i = 0 ; i < elements ; i++) {
|
||||
B_h[i] = i;
|
||||
}
|
||||
HIPCHECK(hipMemcpy2D(B_d, width, B_h, pitch_B, NUM_W, NUM_H,
|
||||
hipMemcpyHostToDevice));
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
}
|
||||
|
||||
void memDeallocate() {
|
||||
HIPCHECK(hipFree(A_d)); HIPCHECK(hipFree(B_d)); HIPCHECK(hipFree(C_d));
|
||||
free(A_h); free(B_h);
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
}
|
||||
|
||||
void queueJobsForhipMemset2DAsync(char* A_d, char* A_h, size_t pitch,
|
||||
size_t width) {
|
||||
HIPCHECK(hipMemset2DAsync(A_d, pitch, memsetval, NUM_W, NUM_H, stream));
|
||||
HIPCHECK(hipMemcpy2DAsync(A_h, width, A_d, pitch, NUM_W, NUM_H,
|
||||
hipMemcpyDeviceToHost, stream));
|
||||
}
|
||||
|
||||
bool testhipMemset2DAsyncWithKernel() {
|
||||
validateCount = 0;
|
||||
memAllocate();
|
||||
printf("info: Launching vector_square kernel and hipMemset2DAsync "
|
||||
"simultaneously\n");
|
||||
for (int k = 0 ; k < ITER ; k++) {
|
||||
hipLaunchKernelGGL(vector_square, dim3(blocks), dim3(threadsPerBlock), 0,
|
||||
stream, B_d, C_d, elements);
|
||||
|
||||
HIPCHECK(hipMemset2DAsync(C_d, pitch_C, memsetval, NUM_W, NUM_H, stream));
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
HIPCHECK(hipMemcpy2D(A_h, width, C_d, pitch_C, NUM_W, NUM_H,
|
||||
hipMemcpyDeviceToHost));
|
||||
|
||||
for (int p = 0 ; p < elements ; p++) {
|
||||
if (A_h[p] == memsetval) {
|
||||
validateCount+= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testResult = (validateCount == (ITER * elements)) ? true : false;
|
||||
memDeallocate();
|
||||
return testResult;
|
||||
}
|
||||
|
||||
bool testhipMemset2DAsyncMultiThread() {
|
||||
validateCount = 0;
|
||||
std::thread t[NUM_THREADS];
|
||||
|
||||
memAllocate();
|
||||
|
||||
printf("info: Queueing up hipMemset2DAsync jobs over multiple threads\n");
|
||||
for (int i = 0 ; i < ITER ; i++) {
|
||||
for (int k = 0 ; k < NUM_THREADS ; k++) {
|
||||
if (k%2) {
|
||||
t[k] = std::thread(queueJobsForhipMemset2DAsync, A_d, A_h, pitch_A,
|
||||
width);
|
||||
} else {
|
||||
t[k] = std::thread(queueJobsForhipMemset2DAsync, A_d, B_h, pitch_A,
|
||||
width);
|
||||
}
|
||||
}
|
||||
for (int j = 0 ; j < NUM_THREADS ; j++) {
|
||||
t[j].join();
|
||||
}
|
||||
|
||||
HIPCHECK(hipStreamSynchronize(stream));
|
||||
for (int k = 0 ; k < elements ; k++) {
|
||||
if ((A_h[k] == memsetval) && (B_h[k] == memsetval)) {
|
||||
validateCount+= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
memDeallocate();
|
||||
testResult = (validateCount == (ITER * elements)) ? true : false;
|
||||
return testResult;
|
||||
}
|
||||
|
||||
int main() {
|
||||
bool testResult = true;
|
||||
|
||||
testResult &= testhipMemset2DAsyncWithKernel();
|
||||
if (testResult) {
|
||||
printf("Kernel and hipMemset2DAsync executed in correct order!\n");
|
||||
} else {
|
||||
printf("Kernel and hipMemset2DAsync order of execution failed\n");
|
||||
}
|
||||
|
||||
testResult &= testhipMemset2DAsyncMultiThread();
|
||||
if (testResult) {
|
||||
printf("hipMemset2DAsync jobs on all threads finished successfully!\n");
|
||||
passed();
|
||||
} else {
|
||||
printf("hipMemset2DAsync failed in multi thread scenario\n");
|
||||
}
|
||||
|
||||
if (testResult) {
|
||||
passed();
|
||||
} else {
|
||||
failed("One or more tests failed\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test for checking order of execution of device kernel and
|
||||
* hipMemsetAsync apis on all gpus
|
||||
*/
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp EXCLUDE_HIP_PLATFORM nvcc
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include "test_common.h"
|
||||
#define ITER 10
|
||||
#define N 1024 * 1024
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
|
||||
template <typename T>
|
||||
__global__ void vector_square(T* B_d, T* C_d, size_t M) {
|
||||
for (int i=0 ; i < M ; i++) {
|
||||
C_d[i] = B_d[i] * B_d[i];
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class MemSetTest {
|
||||
public:
|
||||
T *A_h, *B_d, *B_h, *C_d;
|
||||
T memSetVal;
|
||||
size_t Nbytes;
|
||||
bool testResult = true;
|
||||
int validateCount = 0;
|
||||
hipStream_t stream;
|
||||
|
||||
void memAllocate(T memSetValue) {
|
||||
memSetVal = memSetValue;
|
||||
Nbytes = N * sizeof(T);
|
||||
|
||||
A_h = reinterpret_cast<T*>(malloc(Nbytes));
|
||||
HIPASSERT(A_h != NULL);
|
||||
HIPCHECK(hipMalloc(&B_d , Nbytes));
|
||||
B_h = reinterpret_cast<T*>(malloc(Nbytes));
|
||||
HIPASSERT(B_h != NULL);
|
||||
HIPCHECK(hipMalloc(&C_d , Nbytes));
|
||||
|
||||
for (int i = 0 ; i < N ; i++) {
|
||||
B_h[i] = i;
|
||||
}
|
||||
HIPCHECK(hipMemcpy(B_d , B_h , Nbytes , hipMemcpyHostToDevice));
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
}
|
||||
|
||||
void memDeallocate() {
|
||||
HIPCHECK(hipFree(B_d)); HIPCHECK(hipFree(C_d));
|
||||
free(B_h); free(A_h);
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
}
|
||||
|
||||
void validateExecutionOrder() {
|
||||
for (int p = 0 ; p < N ; p++) {
|
||||
if (A_h[p] == memSetVal) {
|
||||
validateCount+= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool resultAfterAllIterations() {
|
||||
testResult = (validateCount == (ITER * N)) ? true : false;
|
||||
memDeallocate();
|
||||
return testResult;
|
||||
}
|
||||
};
|
||||
|
||||
bool testhipMemsetAsyncWithKernel() {
|
||||
MemSetTest <char> obj;
|
||||
obj.memAllocate(memsetval);
|
||||
for (int k = 0 ; k < ITER ; k++) {
|
||||
hipLaunchKernelGGL(vector_square, dim3(blocks), dim3(threadsPerBlock), 0,
|
||||
obj.stream, obj.B_d, obj.C_d, N);
|
||||
HIPCHECK(hipMemsetAsync(obj.C_d , obj.memSetVal , N , obj.stream));
|
||||
HIPCHECK(hipStreamSynchronize(obj.stream));
|
||||
HIPCHECK(hipMemcpy(obj.A_h , obj.C_d , obj.Nbytes , hipMemcpyDeviceToHost));
|
||||
|
||||
obj.validateExecutionOrder();
|
||||
}
|
||||
return obj.resultAfterAllIterations();
|
||||
}
|
||||
|
||||
bool testhipMemsetD32AsyncWithKernel() {
|
||||
MemSetTest <int32_t> obj;
|
||||
obj.memAllocate(memsetD32val);
|
||||
for (int k = 0 ; k < ITER ; k++) {
|
||||
hipLaunchKernelGGL(vector_square, dim3(blocks), dim3(threadsPerBlock), 0,
|
||||
obj.stream, obj.B_d, obj.C_d, N);
|
||||
HIPCHECK(hipMemsetD32Async(obj.C_d , obj.memSetVal , N , obj.stream));
|
||||
HIPCHECK(hipStreamSynchronize(obj.stream));
|
||||
HIPCHECK(hipMemcpy(obj.A_h, obj.C_d, obj.Nbytes, hipMemcpyDeviceToHost));
|
||||
|
||||
obj.validateExecutionOrder();
|
||||
}
|
||||
return obj.resultAfterAllIterations();
|
||||
}
|
||||
|
||||
bool testhipMemsetD16AsyncWithKernel() {
|
||||
MemSetTest <int16_t> obj;
|
||||
obj.memAllocate(memsetD16val);
|
||||
for (int k = 0 ; k < ITER ; k++) {
|
||||
hipLaunchKernelGGL(vector_square, dim3(blocks), dim3(threadsPerBlock), 0,
|
||||
obj.stream, obj.B_d, obj.C_d, N);
|
||||
HIPCHECK(hipMemsetD16Async(obj.C_d , obj.memSetVal , N , obj.stream));
|
||||
HIPCHECK(hipStreamSynchronize(obj.stream));
|
||||
HIPCHECK(hipMemcpy(obj.A_h , obj.C_d, obj.Nbytes , hipMemcpyDeviceToHost));
|
||||
|
||||
obj.validateExecutionOrder();
|
||||
}
|
||||
return obj.resultAfterAllIterations();
|
||||
}
|
||||
|
||||
bool testhipMemsetD8AsyncWithKernel() {
|
||||
MemSetTest <char> obj;
|
||||
obj.memAllocate(memsetD8val);
|
||||
for (int k = 0; k < ITER; k++) {
|
||||
hipLaunchKernelGGL(vector_square, dim3(blocks), dim3(threadsPerBlock), 0,
|
||||
obj.stream, obj.B_d, obj.C_d, N);
|
||||
HIPCHECK(hipMemsetD8Async(obj.C_d, obj.memSetVal, N, obj.stream));
|
||||
HIPCHECK(hipStreamSynchronize(obj.stream));
|
||||
HIPCHECK(hipMemcpy(obj.A_h, obj.C_d, obj.Nbytes, hipMemcpyDeviceToHost));
|
||||
|
||||
obj.validateExecutionOrder();
|
||||
}
|
||||
return obj.resultAfterAllIterations();
|
||||
}
|
||||
|
||||
int main() {
|
||||
bool testResult = true;
|
||||
int numDevices = 0;
|
||||
HIPCHECK(hipGetDeviceCount(&numDevices));
|
||||
printf("total number of gpus in the system: %d\n", numDevices);
|
||||
|
||||
for (int i = 0; i < numDevices; i++) {
|
||||
HIPCHECK(hipSetDevice(i));
|
||||
printf("test running on gpu %d\n", i);
|
||||
|
||||
testResult &= testhipMemsetAsyncWithKernel();
|
||||
if (!(testResult)) {
|
||||
printf("Mismatch in order of execution of hipMemsetAsync and kernel\n");
|
||||
}
|
||||
|
||||
testResult &= testhipMemsetD32AsyncWithKernel();
|
||||
if (!(testResult)) {
|
||||
printf("Mismatch in order of execution of hipMemsetD32Async and kernel\n");
|
||||
}
|
||||
|
||||
testResult &= testhipMemsetD16AsyncWithKernel();
|
||||
if (!(testResult)) {
|
||||
printf("Mismatch in order of execution of hipMemsetD16Async and kernel\n");
|
||||
}
|
||||
|
||||
testResult &= testhipMemsetD8AsyncWithKernel();
|
||||
if (!(testResult)) {
|
||||
printf("Mismatch in order of execution of hipMemsetD8Async and kernel\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (testResult) {
|
||||
printf("Execution order of Kernel and hipMemsetAsync apis on "
|
||||
"all gpus is correct!\n");
|
||||
passed();
|
||||
} else {
|
||||
failed("One or more hipMemsetAsync tests failed\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test that validates functionality of hipmemsetAsync apis over multi threads
|
||||
*/
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp EXCLUDE_HIP_PLATFORM nvcc
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include "test_common.h"
|
||||
#define NUM_THREADS 50
|
||||
#define ITER 50
|
||||
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
||||
|
||||
template <typename T>
|
||||
class MemSetTest {
|
||||
public:
|
||||
T *A_h, *A_d, *B_h;
|
||||
T memSetVal;
|
||||
size_t Nbytes;
|
||||
bool testResult = true;
|
||||
int validateCount = 0;
|
||||
hipStream_t stream;
|
||||
|
||||
void memAllocate(T memSetValue) {
|
||||
memSetVal = memSetValue;
|
||||
Nbytes = N * sizeof(T);
|
||||
|
||||
A_h = reinterpret_cast<T*>(malloc(Nbytes));
|
||||
HIPASSERT(A_h != NULL);
|
||||
|
||||
HIPCHECK(hipMalloc(&A_d, Nbytes));
|
||||
B_h = reinterpret_cast<T*>(malloc(Nbytes));
|
||||
HIPASSERT(B_h != NULL);
|
||||
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
}
|
||||
|
||||
void threadCompleteStatus() {
|
||||
for (int k = 0 ; k < N ; k++) {
|
||||
if ((A_h[k] == memSetVal) && (B_h[k] == memSetVal)) {
|
||||
validateCount+= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool resultAfterAllIterations() {
|
||||
memDeallocate();
|
||||
testResult = (validateCount == (ITER * N)) ? true: false;
|
||||
return testResult;
|
||||
}
|
||||
|
||||
void memDeallocate() {
|
||||
HIPCHECK(hipFree(A_d));
|
||||
free(A_h);
|
||||
free(B_h);
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void queueJobsForhipMemsetAsync(T* A_d, T* A_h, T memSetVal, size_t Nbytes,
|
||||
hipStream_t stream) {
|
||||
HIPCHECK(hipMemsetAsync(A_d, memSetVal, N, stream));
|
||||
HIPCHECK(hipMemcpyAsync(A_h, A_d, Nbytes, hipMemcpyDeviceToHost, stream));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void queueJobsForhipMemsetD32Async(T* A_d, T* A_h, T memSetVal, size_t Nbytes,
|
||||
hipStream_t stream) {
|
||||
HIPCHECK(hipMemsetD32Async(A_d, memSetVal, N, stream));
|
||||
HIPCHECK(hipMemcpyAsync(A_h, A_d, Nbytes, hipMemcpyDeviceToHost, stream));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void queueJobsForhipMemsetD16Async(T* A_d, T* A_h, T memSetVal, size_t Nbytes,
|
||||
hipStream_t stream) {
|
||||
HIPCHECK(hipMemsetD16Async(A_d, memSetVal, N, stream));
|
||||
HIPCHECK(hipMemcpyAsync(A_h, A_d, Nbytes, hipMemcpyDeviceToHost, stream));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void queueJobsForhipMemsetD8Async(T* A_d, T* A_h, T memSetVal, size_t Nbytes,
|
||||
hipStream_t stream) {
|
||||
HIPCHECK(hipMemsetD8Async(A_d, memSetVal, N, stream));
|
||||
HIPCHECK(hipMemcpyAsync(A_h, A_d, Nbytes, hipMemcpyDeviceToHost, stream));
|
||||
}
|
||||
|
||||
/* Queue hipMemsetAsync jobs on multiple threads and verify they all
|
||||
* finished on all threads successfully
|
||||
*/
|
||||
|
||||
bool testhipMemsetAsyncWithMultiThread() {
|
||||
MemSetTest <char> obj;
|
||||
obj.memAllocate(memsetval);
|
||||
std::thread t[NUM_THREADS];
|
||||
|
||||
for (int i = 0 ; i < ITER ; i++) {
|
||||
for (int k = 0 ; k < NUM_THREADS ; k++) {
|
||||
if (k%2) {
|
||||
t[k] = std::thread(queueJobsForhipMemsetAsync<char>, obj.A_d, obj.A_h,
|
||||
obj.memSetVal, obj.Nbytes, obj.stream);
|
||||
} else {
|
||||
t[k] = std::thread(queueJobsForhipMemsetAsync<char>, obj.A_d, obj.B_h,
|
||||
obj.memSetVal, obj.Nbytes, obj.stream);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0 ; j < NUM_THREADS ; j++) {
|
||||
t[j].join();
|
||||
}
|
||||
|
||||
HIPCHECK(hipStreamSynchronize(obj.stream));
|
||||
obj.threadCompleteStatus();
|
||||
}
|
||||
return obj.resultAfterAllIterations();
|
||||
}
|
||||
|
||||
bool testhipMemsetD32AsyncWithMultiThread() {
|
||||
MemSetTest <int32_t> obj;
|
||||
obj.memAllocate(memsetD32val);
|
||||
std::thread t[NUM_THREADS];
|
||||
|
||||
for (int i = 0 ; i < ITER ; i++) {
|
||||
for (int k = 0 ; k < NUM_THREADS ; k++) {
|
||||
if (k%2) {
|
||||
t[k] = std::thread(queueJobsForhipMemsetD32Async<int32_t>, obj.A_d,
|
||||
obj.A_h, obj.memSetVal, obj.Nbytes, obj.stream);
|
||||
} else {
|
||||
t[k] = std::thread(queueJobsForhipMemsetD32Async<int32_t>, obj.A_d,
|
||||
obj.B_h, obj.memSetVal, obj.Nbytes, obj.stream);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0 ; j < NUM_THREADS ; j++) {
|
||||
t[j].join();
|
||||
}
|
||||
|
||||
HIPCHECK(hipStreamSynchronize(obj.stream));
|
||||
obj.threadCompleteStatus();
|
||||
}
|
||||
return obj.resultAfterAllIterations();
|
||||
}
|
||||
|
||||
bool testhipMemsetD16AsyncWithMultiThread() {
|
||||
MemSetTest <int16_t> obj;
|
||||
obj.memAllocate(memsetD16val);
|
||||
std::thread t[NUM_THREADS];
|
||||
|
||||
for (int i = 0 ; i < ITER ; i++) {
|
||||
for (int k = 0 ; k < NUM_THREADS ; k++) {
|
||||
if (k%2) {
|
||||
t[k] = std::thread(queueJobsForhipMemsetD16Async<int16_t>, obj.A_d,
|
||||
obj.A_h, obj.memSetVal, obj.Nbytes, obj.stream);
|
||||
} else {
|
||||
t[k] = std::thread(queueJobsForhipMemsetD16Async<int16_t>, obj.A_d,
|
||||
obj.B_h, obj.memSetVal, obj.Nbytes, obj.stream);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0 ; j < NUM_THREADS ; j++) {
|
||||
t[j].join();
|
||||
}
|
||||
|
||||
HIPCHECK(hipStreamSynchronize(obj.stream));
|
||||
obj.threadCompleteStatus();
|
||||
}
|
||||
return obj.resultAfterAllIterations();
|
||||
}
|
||||
|
||||
bool testhipMemsetD8AsyncWithMultiThread() {
|
||||
MemSetTest <char> obj;
|
||||
obj.memAllocate(memsetD8val);
|
||||
std::thread t[NUM_THREADS];
|
||||
|
||||
for (int i = 0 ; i < ITER ; i++) {
|
||||
for (int k = 0 ; k < NUM_THREADS ; k++) {
|
||||
if (k%2) {
|
||||
t[k] = std::thread(queueJobsForhipMemsetD8Async<char>, obj.A_d,
|
||||
obj.A_h, obj.memSetVal, obj.Nbytes, obj.stream);
|
||||
} else {
|
||||
t[k] = std::thread(queueJobsForhipMemsetD8Async<char>, obj.A_d,
|
||||
obj.B_h, obj.memSetVal, obj.Nbytes, obj.stream);
|
||||
}
|
||||
}
|
||||
for (int j = 0 ; j < NUM_THREADS ; j++) {
|
||||
t[j].join();
|
||||
}
|
||||
|
||||
HIPCHECK(hipStreamSynchronize(obj.stream));
|
||||
obj.threadCompleteStatus();
|
||||
}
|
||||
return obj.resultAfterAllIterations();
|
||||
}
|
||||
|
||||
int main() {
|
||||
bool testResult = true;
|
||||
printf("Queueing up hipMemSetAsync jobs on multiple threads"
|
||||
"and checking results\n");
|
||||
|
||||
testResult &= testhipMemsetAsyncWithMultiThread();
|
||||
if (!(testResult)) {
|
||||
printf("Thread execution did not complete for hipMemsetAsync\n");
|
||||
}
|
||||
|
||||
testResult &= testhipMemsetD32AsyncWithMultiThread();
|
||||
if (!(testResult)) {
|
||||
printf("Thread execution did not complete for hipMemsetD32Async\n");
|
||||
}
|
||||
|
||||
testResult &= testhipMemsetD16AsyncWithMultiThread();
|
||||
if (!(testResult)) {
|
||||
printf("Thread execution did not complete for hipMemsetD16Async\n");
|
||||
}
|
||||
testResult &= testhipMemsetD8AsyncWithMultiThread();
|
||||
if (!(testResult)) {
|
||||
printf("Thread execution did not complete for hipMemsetD8Async\n");
|
||||
}
|
||||
|
||||
if (testResult) {
|
||||
printf("All threads ran successfully for all hipMemsetAsync apis\n");
|
||||
passed();
|
||||
} else {
|
||||
failed("One or more tests failed\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 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.
|
||||
*/
|
||||
|
||||
// * To test invalid pointer to hipMemset* apis
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp EXCLUDE_HIP_PLATFORM nvcc
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include "test_common.h"
|
||||
#define N 50
|
||||
#define MEMSETVAL 0x42
|
||||
#define NUM_H 256
|
||||
#define NUM_W 256
|
||||
|
||||
int main() {
|
||||
size_t Nbytes = N*sizeof(char);
|
||||
size_t pitch_A;
|
||||
size_t width = NUM_W * sizeof(char);
|
||||
size_t sizeElements = width * NUM_H;
|
||||
size_t elements = NUM_W * NUM_H;
|
||||
char *A_d;
|
||||
|
||||
HIPCHECK(hipMallocPitch(reinterpret_cast<void**>(&A_d), &pitch_A, width , NUM_H));
|
||||
|
||||
hipError_t e;
|
||||
|
||||
e = hipMemset(NULL , MEMSETVAL , Nbytes);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
|
||||
e = hipMemsetD32(NULL , MEMSETVAL , Nbytes);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
|
||||
e = hipMemsetD16(NULL , MEMSETVAL , Nbytes);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
|
||||
e = hipMemsetD8(NULL , MEMSETVAL , Nbytes);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
|
||||
e = hipMemsetAsync(NULL , MEMSETVAL , Nbytes , 0);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
|
||||
e = hipMemsetD32Async(NULL , MEMSETVAL , Nbytes, 0);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
|
||||
e = hipMemsetD16Async(NULL , MEMSETVAL , Nbytes, 0);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
|
||||
e = hipMemsetD8Async(NULL , MEMSETVAL , Nbytes, 0);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
|
||||
e = hipMemset2D(NULL, pitch_A, MEMSETVAL, NUM_W, NUM_H);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
|
||||
e = hipMemset2DAsync(NULL, pitch_A, MEMSETVAL, NUM_W, NUM_H, 0);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
|
||||
/* Passing host pointer to hipMemset.Ticket SWDEV-243206 is open for this.
|
||||
* Disabling this test until the ticket is closed
|
||||
*
|
||||
char *A_h;
|
||||
A_h = (char*)malloc(Nbytes);
|
||||
e = hipMemset(A_h, MEMSETVAL , Nbytes);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
*/
|
||||
|
||||
/* Passing invalid pitch to hipMemset2D.Ticket SWDEV-243104 is open for this.
|
||||
* Disabling this test until the ticket is closed
|
||||
*
|
||||
e = hipMemset2D(A_d, 0, MEMSETVAL, NUM_W, NUM_H);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
|
||||
e = hipMemset2DAsync(A_d, 0, MEMSETVAL, NUM_W, NUM_H,0);
|
||||
HIPASSERT(e == hipErrorInvalidValue);
|
||||
*/
|
||||
|
||||
hipFree(A_d);
|
||||
passed();
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
Copyright (c) 2020-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 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.
|
||||
*/
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp NVCC_OPTIONS --std=c++11
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// Testcase Description: This test case is used to verify if the callback
|
||||
// function called through hipStreamAddCallback() api completes the execution
|
||||
// in order as hipStreamAddCallback() api queued in their respective streams
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "test_common.h"
|
||||
|
||||
|
||||
#ifdef __HIP_PLATFORM_HCC__
|
||||
#define HIPRT_CB
|
||||
#endif
|
||||
|
||||
|
||||
hipStream_t mystream1, mystream2;
|
||||
size_t Num = 4096;
|
||||
std::vector<int> Stream1_Order, Stream2_Order;
|
||||
|
||||
|
||||
__global__ void vector_square(float* C_d, float* A_d, size_t Num) {
|
||||
size_t gputhread = (blockIdx.x * blockDim.x + threadIdx.x);
|
||||
size_t stride = blockDim.x * gridDim.x;
|
||||
|
||||
for (size_t i = gputhread; i < Num; i += stride) {
|
||||
C_d[i] = A_d[i] * A_d[i];
|
||||
}
|
||||
|
||||
// Delay thread 1 only in the GPU
|
||||
if (gputhread == 1) {
|
||||
unsigned long long int wait_t = 3200000000, start = clock64(), cur;
|
||||
do {
|
||||
cur = clock64() - start;
|
||||
} while (cur < wait_t);
|
||||
}
|
||||
}
|
||||
|
||||
float *A_h, *C_h, *A_h1, *C_h1;
|
||||
|
||||
static void HIPRT_CB Callback_Stream1(hipStream_t stream, hipError_t status,
|
||||
void* userData) {
|
||||
for (size_t i = 0; i < Num; i++) {
|
||||
if (C_h[i] != A_h[i] * A_h[i]) {
|
||||
std::cout << "Data mismatch in stream1 at: " << i << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Storing the int passed into this callback into Stream1_Order
|
||||
// this will help verify the order in which this Callback function
|
||||
// is called.
|
||||
Stream1_Order.push_back(*(reinterpret_cast<int*>(userData)));
|
||||
delete reinterpret_cast<int*>(userData);
|
||||
}
|
||||
|
||||
static void HIPRT_CB Callback_Stream2(hipStream_t stream, hipError_t status,
|
||||
void* userData) {
|
||||
for (size_t i = 0; i < Num; i++) {
|
||||
if (C_h1[i] != A_h1[i] * A_h1[i]) {
|
||||
std::cout << "Data mismatch in stream2 at: " << i << std::endl;
|
||||
}
|
||||
}
|
||||
// Storing the int passed into this callback into Stream2_Order
|
||||
// this will help verify the order in which this Callback function
|
||||
// is called.
|
||||
Stream2_Order.push_back(*(reinterpret_cast<int*>(userData)));
|
||||
delete reinterpret_cast<int*>(userData);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
float *A_d, *C_d;
|
||||
size_t Nbytes = Num * sizeof(float);
|
||||
|
||||
A_h = reinterpret_cast<float*>(malloc(Nbytes));
|
||||
HIPCHECK(A_h == 0 ? hipErrorOutOfMemory : hipSuccess);
|
||||
C_h = reinterpret_cast<float*>(malloc(Nbytes));
|
||||
HIPCHECK(C_h == 0 ? hipErrorOutOfMemory : hipSuccess);
|
||||
A_h1 = reinterpret_cast<float*>(malloc(Nbytes));
|
||||
HIPCHECK(A_h == 0 ? hipErrorOutOfMemory : hipSuccess);
|
||||
C_h1 = reinterpret_cast<float*>(malloc(Nbytes));
|
||||
HIPCHECK(C_h == 0 ? hipErrorOutOfMemory : hipSuccess);
|
||||
|
||||
// Fill with Phi + i
|
||||
for (size_t i = 0; i < Num; i++) {
|
||||
A_h[i] = 1.618f + i;
|
||||
}
|
||||
for (size_t i = 0; i < Num; i++) {
|
||||
A_h1[i] = 1.618f + i;
|
||||
}
|
||||
|
||||
HIPCHECK(hipMalloc(&A_d, Nbytes));
|
||||
HIPCHECK(hipMalloc(&C_d, Nbytes));
|
||||
|
||||
HIPCHECK(hipStreamCreateWithFlags(&mystream1, hipStreamNonBlocking));
|
||||
HIPCHECK(hipStreamCreateWithFlags(&mystream2, hipStreamNonBlocking));
|
||||
|
||||
HIPCHECK(hipMemcpyAsync(A_d, A_h, Nbytes, hipMemcpyHostToDevice, mystream1));
|
||||
|
||||
const unsigned threadsPerBlock = 256;
|
||||
const unsigned blocks = (Num + 255)/threadsPerBlock;
|
||||
int *ptr = NULL;
|
||||
int *ptr1 = NULL;
|
||||
// Queing jobs in both mystream1/2 followed by hipStreamAddCallback
|
||||
for (int i = 1; i < 5; ++i) {
|
||||
hipLaunchKernelGGL((vector_square), dim3(blocks), dim3(threadsPerBlock),
|
||||
0, mystream1, C_d, A_d, Num);
|
||||
HIPCHECK(hipMemcpyAsync(C_h, C_d, Nbytes, hipMemcpyDeviceToHost,
|
||||
mystream1));
|
||||
ptr = new int;
|
||||
*ptr = i;
|
||||
HIPCHECK(hipStreamAddCallback(mystream1, Callback_Stream1,
|
||||
reinterpret_cast<void*>(ptr), 0));
|
||||
|
||||
hipLaunchKernelGGL((vector_square), dim3(blocks), dim3(threadsPerBlock),
|
||||
0, mystream2, C_d, A_d, Num);
|
||||
HIPCHECK(hipMemcpyAsync(C_h1, C_d, Nbytes,
|
||||
hipMemcpyDeviceToHost, mystream2));
|
||||
ptr1 = new int;
|
||||
*ptr1 = i;
|
||||
HIPCHECK(hipStreamAddCallback(mystream2, Callback_Stream2,
|
||||
reinterpret_cast<void*>(ptr1), 0));
|
||||
}
|
||||
|
||||
HIPCHECK(hipStreamSynchronize(mystream1));
|
||||
HIPCHECK(hipStreamSynchronize(mystream2));
|
||||
|
||||
HIPCHECK(hipStreamDestroy(mystream1));
|
||||
HIPCHECK(hipStreamDestroy(mystream2));
|
||||
|
||||
HIPCHECK(hipFree(A_d));
|
||||
HIPCHECK(hipFree(C_d));
|
||||
free(A_h);
|
||||
free(C_h);
|
||||
free(A_h1);
|
||||
free(C_h1);
|
||||
|
||||
// Checking if Stream1_Order has ints in sequencial order or not
|
||||
int i = 1;
|
||||
for (auto itr=Stream1_Order.begin(); itr != Stream1_Order.end(); ++itr) {
|
||||
if (*itr != i) {
|
||||
printf("hipStreamAddCallBack() did not execute in sequence");
|
||||
printf(" in first stream\n");
|
||||
failed("Unexpected behavior!");
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
// Checking if Stream2_Order has ints in sequencial order or not
|
||||
i = 1;
|
||||
for (auto itr=Stream2_Order.begin(); itr != Stream2_Order.end(); ++itr) {
|
||||
if (*itr != i) {
|
||||
printf("hipStreamAddCallBack() did not execute in sequence");
|
||||
printf(" in second stream\n");
|
||||
failed("Unexpected behavior!");
|
||||
}
|
||||
++i;
|
||||
}
|
||||
passed();
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
Copyright (c) 2019-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.
|
||||
*/
|
||||
|
||||
// Testcase Description: Streams are launched in individual GPUs with different
|
||||
// kernel. Verify that all the kernels queued are executed before the callback.
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp NVCC_OPTIONS -std=c++11
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "test_common.h"
|
||||
|
||||
#ifdef __HIP_PLATFORM_HCC__
|
||||
#define HIPRT_CB
|
||||
#endif
|
||||
|
||||
|
||||
size_t N_ELMTS = 4096;
|
||||
|
||||
// Data structure for holding and validating data
|
||||
struct gpu_data {
|
||||
int *int_ptr = NULL;
|
||||
int gpu;
|
||||
int acknowledge;
|
||||
};
|
||||
|
||||
enum {
|
||||
SUCCESS = 0,
|
||||
KERNEL_EXECUTION_MISMATCH,
|
||||
KERNEL_COMPUTATION_MISMATCH
|
||||
};
|
||||
|
||||
__global__ void Add_Data(int* A_d, size_t N_ELMTS) {
|
||||
size_t offset = (blockIdx.x * blockDim.x + threadIdx.x);
|
||||
size_t stride = blockDim.x * gridDim.x;
|
||||
for (size_t i = offset; i < N_ELMTS; i += stride) {
|
||||
// Increment the value of A_d[i] by 1
|
||||
A_d[i] = A_d[i] + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// below kernel is just to load the gpu with multiple jobs
|
||||
__global__ void Square_plus_one(int* A_d, int* C_d, size_t N_ELMTS) {
|
||||
size_t offset = (blockIdx.x * blockDim.x + threadIdx.x);
|
||||
size_t stride = blockDim.x * gridDim.x;
|
||||
for (size_t i = offset; i < N_ELMTS; i += stride) {
|
||||
C_d[i] = A_d[i]*A_d[i] + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void HIPRT_CB Stream_Callback(hipStream_t stream, hipError_t status,
|
||||
void* userData) {
|
||||
gpu_data *ptr = reinterpret_cast<gpu_data *>(userData);
|
||||
|
||||
// int_ptr in the passed userData will contain the data copied from device to
|
||||
// host. Expected data in this field is the gpu ordinal.
|
||||
if (*((*ptr).int_ptr) != (*ptr).gpu + 1) {
|
||||
(*ptr).acknowledge = 100; // Assign unexpected value to indicate fail
|
||||
} else {
|
||||
(*ptr).acknowledge = (*ptr).gpu; // Assign the gpu ordinal received
|
||||
}
|
||||
}
|
||||
|
||||
void launch_gpu(int gpu_ordinal) {
|
||||
HIPCHECK(hipSetDevice(gpu_ordinal));
|
||||
int *A_d, *A_h, *C_h, *C_d;
|
||||
size_t Nbytes = N_ELMTS * sizeof(int), Data_mismatch = 0;
|
||||
bool cb = false;
|
||||
A_h = (int *)malloc(Nbytes);
|
||||
HIPCHECK(A_h == 0 ? hipErrorOutOfMemory : hipSuccess);
|
||||
C_h = (int *)malloc(Nbytes);
|
||||
HIPCHECK(C_h == 0 ? hipErrorOutOfMemory : hipSuccess);
|
||||
|
||||
// Fill with 0
|
||||
for (size_t i = 0; i < N_ELMTS; i++) {
|
||||
A_h[i] = 0;
|
||||
}
|
||||
|
||||
// setting gpu value in the struct object
|
||||
gpu_data *ptr = new gpu_data;
|
||||
ptr->int_ptr = C_h;
|
||||
ptr->gpu = gpu_ordinal;
|
||||
ptr->acknowledge = 100;
|
||||
|
||||
HIPCHECK(hipMalloc(&A_d, Nbytes));
|
||||
HIPCHECK(hipMalloc(&C_d, Nbytes));
|
||||
|
||||
hipStream_t mystream;
|
||||
HIPCHECK(hipStreamCreateWithFlags(&mystream, hipStreamNonBlocking));
|
||||
|
||||
HIPCHECK(hipMemcpyAsync(A_d, A_h, Nbytes, hipMemcpyHostToDevice, mystream));
|
||||
|
||||
const unsigned threadsPerBlock = 256;
|
||||
const unsigned blocks = (N_ELMTS + 255)/threadsPerBlock;
|
||||
|
||||
// A_d is initialized to 0. Add_Data kernel does A_d = A_d + 1
|
||||
// The Add_data kernel is called 1 time for gpu0, 2 times for gpu1 etc.
|
||||
// At the end of the loop, A_d should have the gpu_ordinal number
|
||||
for (int i = 0; i < gpu_ordinal + 1; i++) {
|
||||
hipLaunchKernelGGL(Add_Data, dim3(blocks), dim3(threadsPerBlock), 0,
|
||||
mystream, A_d, N_ELMTS);
|
||||
hipLaunchKernelGGL(Square_plus_one, 1, 1, 0, mystream, A_d, C_d, N_ELMTS);
|
||||
}
|
||||
HIPCHECK(hipMemcpyAsync(C_h, A_d, Nbytes, hipMemcpyDeviceToHost, mystream));
|
||||
|
||||
// Pass the ptr as user data which contains the gpu_ordinal, default value
|
||||
// for ack and the data that is copied to host
|
||||
HIPCHECK(hipStreamAddCallback(mystream, Stream_Callback,
|
||||
reinterpret_cast<void *>(ptr), 0));
|
||||
HIPCHECK(hipStreamSynchronize(mystream));
|
||||
|
||||
HIPCHECK(hipFree(A_d));
|
||||
HIPCHECK(hipFree(C_d));
|
||||
HIPCHECK(hipStreamDestroy(mystream));
|
||||
|
||||
int result = SUCCESS;
|
||||
if (C_h[0] != gpu_ordinal + 1) {
|
||||
result = KERNEL_EXECUTION_MISMATCH;
|
||||
}
|
||||
|
||||
if (ptr->gpu != ptr->acknowledge) {
|
||||
result = KERNEL_COMPUTATION_MISMATCH;
|
||||
}
|
||||
|
||||
free(A_h);
|
||||
free(C_h);
|
||||
free(ptr);
|
||||
|
||||
if (result == KERNEL_EXECUTION_MISMATCH) {
|
||||
failed("Number of kernels expected to be executed does not match");
|
||||
} else if (result == KERNEL_COMPUTATION_MISMATCH) {
|
||||
failed("Mismatch found in the result of the computation!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
int gpu_cnt = 0;
|
||||
|
||||
HIPCHECK(hipGetDeviceCount(&gpu_cnt));
|
||||
if (gpu_cnt < 2) {
|
||||
printf("Minimum of 2 gpus are needed for this test, skipping the test\n");
|
||||
passed();
|
||||
}
|
||||
|
||||
std::thread T[gpu_cnt];
|
||||
|
||||
// Launching threads for each GPU
|
||||
for (int i = 0; i < gpu_cnt; i++) {
|
||||
T[i] = std::thread(launch_gpu, i);
|
||||
}
|
||||
|
||||
for (int i=0; i < gpu_cnt; i++) {
|
||||
T[i].join();
|
||||
}
|
||||
passed();
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016 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.
|
||||
* */
|
||||
|
||||
// Testcase Description:: This test case is used to check if the runtime is ok
|
||||
// when hipStreamAddCallback() is called back to back multiple calls
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp NVCC_OPTIONS --std=c++11
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "test_common.h"
|
||||
|
||||
#ifdef __HIP_PLATFORM_HCC__
|
||||
#define HIPRT_CB
|
||||
#endif
|
||||
|
||||
#define NUM_CALLS 1000
|
||||
|
||||
hipStream_t mystream;
|
||||
size_t Num = 4096;
|
||||
std::atomic<size_t>Cb_count{0}, Data_mismatch{0};
|
||||
float *A_h, *C_h;
|
||||
|
||||
__global__ void vector_square(float* C_d, float* A_d, size_t Num) {
|
||||
size_t gputhread = (blockIdx.x * blockDim.x + threadIdx.x);
|
||||
size_t stride = blockDim.x * gridDim.x;
|
||||
|
||||
for (size_t i = gputhread; i < Num; i += stride) {
|
||||
C_d[i] = A_d[i] * A_d[i];
|
||||
}
|
||||
|
||||
// Delay thread 1 only in the GPU
|
||||
if (gputhread == 1) {
|
||||
unsigned long long int wait_t = 3200000000, start = clock64(), cur;
|
||||
do {
|
||||
cur = clock64() - start;
|
||||
} while (cur < wait_t);
|
||||
}
|
||||
}
|
||||
|
||||
static void HIPRT_CB Stream_Callback(hipStream_t stream, hipError_t status,
|
||||
void* userData) {
|
||||
for (size_t i = 0; i < Num; i++) {
|
||||
// Validate the data and update Data_mismatch
|
||||
if (C_h[i] != A_h[i] * A_h[i]) {
|
||||
Data_mismatch++;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment the Cb_count to indicate that the callback is processed.
|
||||
++Cb_count;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
float *A_d, *C_d;
|
||||
size_t Nbytes = Num * sizeof(float);
|
||||
|
||||
A_h = (float*)malloc(Nbytes);
|
||||
HIPCHECK(A_h == 0 ? hipErrorOutOfMemory : hipSuccess);
|
||||
C_h = (float*)malloc(Nbytes);
|
||||
HIPCHECK(C_h == 0 ? hipErrorOutOfMemory : hipSuccess);
|
||||
|
||||
// Fill with Phi + i
|
||||
for (size_t i = 0; i < Num; i++) {
|
||||
A_h[i] = 1.618f + i;
|
||||
}
|
||||
|
||||
HIPCHECK(hipMalloc(&A_d, Nbytes));
|
||||
HIPCHECK(hipMalloc(&C_d, Nbytes));
|
||||
|
||||
HIPCHECK(hipStreamCreateWithFlags(&mystream, hipStreamNonBlocking));
|
||||
|
||||
HIPCHECK(hipMemcpyAsync(A_d, A_h, Nbytes, hipMemcpyHostToDevice, mystream));
|
||||
|
||||
const unsigned threadsPerBlock = 256;
|
||||
const unsigned blocks = (Num+255)/threadsPerBlock;
|
||||
hipLaunchKernelGGL((vector_square), dim3(blocks), dim3(threadsPerBlock), 0,
|
||||
mystream, C_d, A_d, Num);
|
||||
|
||||
HIPCHECK(hipMemcpyAsync(C_h, C_d, Nbytes, hipMemcpyDeviceToHost, mystream));
|
||||
|
||||
// Add multiple callbacks to the stream
|
||||
for (int i = 0; i< NUM_CALLS; i++) {
|
||||
HIPCHECK(hipStreamAddCallback(mystream, Stream_Callback, NULL, 0));
|
||||
}
|
||||
|
||||
HIPCHECK(hipStreamSynchronize(mystream));
|
||||
HIPCHECK(hipStreamDestroy(mystream));
|
||||
|
||||
HIPCHECK(hipFree(A_d));
|
||||
HIPCHECK(hipFree(C_d));
|
||||
|
||||
free(A_h);
|
||||
free(C_h);
|
||||
|
||||
// Each callback would have validated the data and if any mismatch is found,
|
||||
// Data_mismatch will not have proper data. Validate the same.
|
||||
// Cb_count should match the number of callbacks added.
|
||||
if (Data_mismatch.load() != 0) {
|
||||
failed("Mismatch found in the result of the computation!");
|
||||
} else if (Cb_count.load() != NUM_CALLS) {
|
||||
failed("All callbacks for stream did not get called!");
|
||||
}
|
||||
|
||||
passed();
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
Copyright (c) 2020-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 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.
|
||||
*/
|
||||
|
||||
// Testcase Description: This test case is used to check the behaviour of HIP
|
||||
// when multiple hipStreaAddCallback() are called over multiple Threads
|
||||
// This test case is disabled currently.
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp NVCC_OPTIONS --std=c++11 EXCLUDE_HIP_PLATFORM all
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <atomic>
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "test_common.h"
|
||||
|
||||
#ifdef __HIP_PLATFORM_HCC__
|
||||
#define HIPRT_CB
|
||||
#endif
|
||||
|
||||
#define NUM_THREADS 2000
|
||||
|
||||
size_t Num = 4096;
|
||||
std::atomic<size_t>Cb_count{0}, Data_mismatch{0};
|
||||
hipStream_t mystream;
|
||||
float *A_h, *C_h;
|
||||
|
||||
__global__ void vector_square(float* C_d, float* A_d, size_t Num) {
|
||||
size_t gputhread = (blockIdx.x * blockDim.x + threadIdx.x);
|
||||
size_t stride = blockDim.x * gridDim.x;
|
||||
|
||||
for (size_t i = gputhread; i < Num; i += stride) {
|
||||
C_d[i] = A_d[i] * A_d[i];
|
||||
}
|
||||
|
||||
// Delay thread 1 only in the GPU
|
||||
if (gputhread == 1) {
|
||||
unsigned long long int wait_t = 3200000000, start = clock64(), cur;
|
||||
do {
|
||||
cur = clock64() - start;
|
||||
} while (cur < wait_t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void HIPRT_CB Thread1_Callback(hipStream_t stream, hipError_t status,
|
||||
void* userData) {
|
||||
for (size_t i = 0; i < Num; i++) {
|
||||
// Validate the data and update Data_mismatch
|
||||
if (C_h[i] != A_h[i] * A_h[i]) {
|
||||
Data_mismatch++;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment the Cb_count to indicate that the callback is processed.
|
||||
++Cb_count;
|
||||
}
|
||||
|
||||
static void HIPRT_CB Thread2_Callback(hipStream_t stream, hipError_t status,
|
||||
void* userData) {
|
||||
for (size_t i = 0; i < Num; i++) {
|
||||
// Validate the data and update Data_mismatch
|
||||
if (C_h[i] != A_h[i] * A_h[i]) {
|
||||
Data_mismatch++;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment the Cb_count to indicate that the callback is processed.
|
||||
++Cb_count;
|
||||
}
|
||||
|
||||
void Thread1_func() {
|
||||
HIPCHECK(hipStreamAddCallback(mystream, Thread1_Callback, NULL, 0));
|
||||
}
|
||||
|
||||
void Thread2_func() {
|
||||
HIPCHECK(hipStreamAddCallback(mystream, Thread2_Callback, NULL, 0));
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
float *A_d, *C_d;
|
||||
size_t Nbytes = Num * sizeof(float);
|
||||
|
||||
A_h = (float*)malloc(Nbytes);
|
||||
HIPCHECK(A_h == 0 ? hipErrorOutOfMemory : hipSuccess);
|
||||
C_h = (float*)malloc(Nbytes);
|
||||
HIPCHECK(C_h == 0 ? hipErrorOutOfMemory : hipSuccess);
|
||||
|
||||
// Fill with Phi + i
|
||||
for (size_t i = 0; i < Num; i++) {
|
||||
A_h[i] = 1.618f + i;
|
||||
}
|
||||
|
||||
HIPCHECK(hipMalloc(&A_d, Nbytes));
|
||||
HIPCHECK(hipMalloc(&C_d, Nbytes));
|
||||
|
||||
HIPCHECK(hipStreamCreateWithFlags(&mystream, hipStreamNonBlocking));
|
||||
|
||||
HIPCHECK(hipMemcpyAsync(A_d, A_h, Nbytes, hipMemcpyHostToDevice, mystream));
|
||||
|
||||
const unsigned threadsPerBlock = 256;
|
||||
const unsigned blocks = (Num+255)/threadsPerBlock;
|
||||
|
||||
hipLaunchKernelGGL((vector_square), dim3(blocks), dim3(threadsPerBlock), 0,
|
||||
mystream, C_d, A_d, Num);
|
||||
|
||||
HIPCHECK(hipMemcpyAsync(C_h, C_d, Nbytes, hipMemcpyDeviceToHost, mystream));
|
||||
|
||||
std::thread T[NUM_THREADS];
|
||||
for (int i = 0; i < NUM_THREADS; i++) {
|
||||
// Use different callback for every even thread
|
||||
// The callbacks will be added to same stream from different threads
|
||||
if ((i%2) == 0)
|
||||
T[i] = std::thread(Thread1_func);
|
||||
else
|
||||
T[i] = std::thread(Thread2_func);
|
||||
}
|
||||
|
||||
// Wait until all the threads finish their execution
|
||||
for (int i = 0; i < NUM_THREADS; i++) {
|
||||
T[i].join();
|
||||
}
|
||||
|
||||
HIPCHECK(hipStreamSynchronize(mystream));
|
||||
HIPCHECK(hipStreamDestroy(mystream));
|
||||
|
||||
HIPCHECK(hipFree(A_d));
|
||||
HIPCHECK(hipFree(C_d));
|
||||
|
||||
free(A_h);
|
||||
free(C_h);
|
||||
|
||||
// Cb_count should match total number of callbacks added from both threads
|
||||
// Data_mismatch will be updated if there is problem in data validation
|
||||
if (Cb_count.load() != NUM_THREADS) {
|
||||
failed("All callbacks for stream did not get called!");
|
||||
} else if (Data_mismatch.load() != 0) {
|
||||
failed("Mismatch found in the result of the computation!");
|
||||
}
|
||||
|
||||
passed();
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 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.
|
||||
*/
|
||||
|
||||
// Testcase Description: This test case checks whether hipStreamSynchronize()
|
||||
// is taking less time than the time taken by Callback() function launched
|
||||
// by hipStreamAddCallback() api.
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp NVCC_OPTIONS --std=c++11
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <chrono>
|
||||
#include <atomic>
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "test_common.h"
|
||||
|
||||
#ifdef __HIP_PLATFORM_HCC__
|
||||
#define HIPRT_CB
|
||||
#endif
|
||||
|
||||
#define SECONDS_TO_WAIT 5
|
||||
#define TO_MICROSECONDS 1000000
|
||||
|
||||
hipStream_t mystream;
|
||||
size_t N_elmts = 4096;
|
||||
bool Init_callback = false;
|
||||
std::atomic<int> Data_mismatch{0};
|
||||
|
||||
__global__ void vector_square(float* C_d, float* A_d, size_t N_elmts) {
|
||||
size_t offset = (blockIdx.x * blockDim.x + threadIdx.x);
|
||||
size_t stride = blockDim.x * gridDim.x;
|
||||
|
||||
for (size_t i = offset; i < N_elmts; i += stride) {
|
||||
C_d[i] = A_d[i] * A_d[i];
|
||||
}
|
||||
|
||||
// Delay the thread 1
|
||||
if (offset == 1) {
|
||||
unsigned long long int wait_t = 3200000000, start = clock64(), cur;
|
||||
do {
|
||||
cur = clock64() - start;
|
||||
} while (cur < wait_t);
|
||||
}
|
||||
}
|
||||
|
||||
float *A_h, *C_h;
|
||||
|
||||
static void HIPRT_CB Callback1(hipStream_t stream, hipError_t status,
|
||||
void* userData) {
|
||||
// Mark that the callback is entered. This is checked in main thread.
|
||||
Init_callback = true;
|
||||
|
||||
// Validate the data
|
||||
for (size_t i = 0; i < N_elmts; i++) {
|
||||
if (C_h[i] != A_h[i] * A_h[i]) {
|
||||
Data_mismatch++;
|
||||
}
|
||||
}
|
||||
|
||||
// Delay the callback completion
|
||||
sleep(SECONDS_TO_WAIT);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
float *A_d, *C_d;
|
||||
size_t Nbytes = N_elmts * sizeof(float);
|
||||
float tElapsed = 1.0f;
|
||||
|
||||
A_h = (float*)malloc(Nbytes);
|
||||
HIPCHECK(A_h == 0 ? hipErrorOutOfMemory : hipSuccess);
|
||||
C_h = (float*)malloc(Nbytes);
|
||||
HIPCHECK(C_h == 0 ? hipErrorOutOfMemory : hipSuccess);
|
||||
|
||||
// Fill with Phi + i
|
||||
for (size_t i = 0; i < N_elmts; i++) {
|
||||
A_h[i] = 1.618f + i;
|
||||
}
|
||||
|
||||
HIPCHECK(hipMalloc(&A_d, Nbytes));
|
||||
HIPCHECK(hipMalloc(&C_d, Nbytes));
|
||||
|
||||
HIPCHECK(hipStreamCreateWithFlags(&mystream, hipStreamNonBlocking));
|
||||
|
||||
HIPCHECK(hipMemcpyAsync(A_d, A_h, Nbytes, hipMemcpyHostToDevice, mystream));
|
||||
|
||||
const unsigned threadsPerBlock = 256;
|
||||
const unsigned blocks = (N_elmts + 255)/threadsPerBlock;
|
||||
|
||||
hipLaunchKernelGGL((vector_square), dim3(blocks), dim3(threadsPerBlock), 0,
|
||||
mystream, C_d, A_d, N_elmts);
|
||||
HIPCHECK(hipMemcpyAsync(C_h, C_d, Nbytes, hipMemcpyDeviceToHost, mystream));
|
||||
HIPCHECK(hipStreamAddCallback(mystream, Callback1, NULL, 0));
|
||||
|
||||
// Wait untill Callback() function changes the Init_callback value to true
|
||||
while (!Init_callback) {}
|
||||
|
||||
// Since the callback is supposed to be called only after an implicit stream
|
||||
// synchronization, hipStreamSynchronize call shoud not take much time.
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
HIPCHECK(hipStreamSynchronize(mystream));
|
||||
auto stop = std::chrono::high_resolution_clock::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
|
||||
|
||||
HIPCHECK(hipStreamDestroy(mystream));
|
||||
HIPCHECK(hipFree(A_d));
|
||||
HIPCHECK(hipFree(C_d));
|
||||
free(A_h);
|
||||
free(C_h);
|
||||
|
||||
if (Data_mismatch.load() != 0) {
|
||||
failed("Output from kernel execution is not as expected");
|
||||
}
|
||||
|
||||
// There is a delay of 5000000 microseconds in the Callback() function, the
|
||||
// duration.count() value is expected to less than 5000000 microseconds
|
||||
// because it is expected that stream synchronization completed the moment
|
||||
// Callback function starts the execution and not untill Callback function
|
||||
// completes the execution. Therefore the hipStreamSynchronize() in the
|
||||
// main thread should hardly take any time to complete.
|
||||
|
||||
if (duration.count() < SECONDS_TO_WAIT * TO_MICROSECONDS) {
|
||||
passed();
|
||||
} else {
|
||||
failed("hipStreamSynchronize is waiting untill Callback() completes.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 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.
|
||||
* */
|
||||
|
||||
// Testcase Description: This test case tests if Host thread continues with
|
||||
// next command after hipStreamAddCallback() api or wait for callback() call to
|
||||
// finish. Ideally Host thread should not wait for callback to finish.
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp NVCC_OPTIONS --std=c++11
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "test_common.h"
|
||||
|
||||
#ifdef __HIP_PLATFORM_HCC__
|
||||
#define HIPRT_CB
|
||||
#endif
|
||||
|
||||
bool Callback_Completed = false;
|
||||
|
||||
void HIPRT_CB Callback1(hipStream_t stream, hipError_t status, void* userData) {
|
||||
sleep(5);
|
||||
Callback_Completed = true;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
hipStream_t mystream;
|
||||
HIPCHECK(hipStreamCreateWithFlags(&mystream, hipStreamNonBlocking));
|
||||
HIPCHECK(hipStreamAddCallback(mystream, Callback1, NULL, 0));
|
||||
sleep(1);
|
||||
|
||||
// Callback_Completed is initialized to false. The same is set to true at
|
||||
// the end of callback and callback sleeps for 5 seconds.
|
||||
// So, in case Callback_Completed is true here, it means the main thread
|
||||
// has waited till callback is complete and is a fail case.
|
||||
if (Callback_Completed == false) {
|
||||
HIPCHECK(hipStreamDestroy(mystream));
|
||||
passed();
|
||||
} else {
|
||||
HIPCHECK(hipStreamDestroy(mystream));
|
||||
failed("Unexpected: Host thread is waiting for callback to finish");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 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.
|
||||
* */
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp NVCC_OPTIONS --std=c++11
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
// Checks the callback execution in the same order it was added
|
||||
// Also, it checks if the number of callbacks executed are same as the number
|
||||
// of callbacks added
|
||||
|
||||
#include <stdio.h>
|
||||
#include <atomic>
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "test_common.h"
|
||||
#ifdef __HIP_PLATFORM_HCC__
|
||||
#define HIPRT_CB
|
||||
#endif
|
||||
|
||||
#define NUM_CALLS 10
|
||||
hipStream_t mystream;
|
||||
bool Callback_SequenceMismatch = false;
|
||||
std::atomic<int> Cb_ordinal{0};
|
||||
|
||||
void HIPRT_CB Stream_Callback(hipStream_t stream, hipError_t status,
|
||||
void* userData) {
|
||||
// Userdata has the order of the callback. It should match with
|
||||
// the callback counter Cb_ordinal as the sequence of callback
|
||||
// should match the sequence of callback addition
|
||||
if (*(reinterpret_cast<int*>(userData)) == Cb_ordinal) {
|
||||
// Increment the Cb_ordinal to prepare for next sequence
|
||||
Cb_ordinal++;
|
||||
} else {
|
||||
Callback_SequenceMismatch = true;
|
||||
}
|
||||
|
||||
delete reinterpret_cast<int*>(userData);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int *ptr;
|
||||
HIPCHECK(hipStreamCreateWithFlags(&mystream, hipStreamNonBlocking));
|
||||
for (int i = 0; i< NUM_CALLS; i++) {
|
||||
ptr = new int;
|
||||
*ptr = i;
|
||||
// Pass the userdata with the order of the callback addition
|
||||
HIPCHECK(hipStreamAddCallback(mystream, Stream_Callback,
|
||||
reinterpret_cast<void*>(ptr), 0));
|
||||
}
|
||||
|
||||
HIPCHECK(hipStreamSynchronize(mystream));
|
||||
HIPCHECK(hipStreamDestroy(mystream));
|
||||
|
||||
if (!(Cb_ordinal == (NUM_CALLS))) {
|
||||
failed("All callbacks for stream did not get called!");
|
||||
}
|
||||
|
||||
if (Callback_SequenceMismatch == false) {
|
||||
passed();
|
||||
} else {
|
||||
failed("hipStreamAddCallback() calls did not execute in sequence!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright (c) 2020-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.
|
||||
*/
|
||||
|
||||
|
||||
/* HIT_START
|
||||
* BUILD: %t %s ../../test_common.cpp NVCC_OPTIONS -std=c++11
|
||||
* TEST: %t
|
||||
* HIT_END
|
||||
*/
|
||||
|
||||
|
||||
#include "test_common.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int numDevices;
|
||||
hipGetDeviceCount(&numDevices);
|
||||
for (int i = 0; i < numDevices; i++) {
|
||||
hipStream_t stream;
|
||||
int priority;
|
||||
int priority_normal;
|
||||
int priority_low;
|
||||
int priority_high;
|
||||
int priority_check;
|
||||
|
||||
// Test is to get the Stream Priority Range
|
||||
HIPCHECK(hipDeviceGetStreamPriorityRange(&priority_low, &priority_high));
|
||||
printf("Priority range is %d for low and %d for high \n", priority_low, priority_high);
|
||||
priority_normal = priority_low + priority_high;
|
||||
|
||||
// Check if priorities are indeed supported
|
||||
if ((priority_low + priority_high) != 0) {
|
||||
failed("Priorities are not supported");
|
||||
}
|
||||
|
||||
// Checking Priority of default stream
|
||||
HIPCHECK(hipStreamCreate(&stream));
|
||||
HIPCHECK(hipStreamGetPriority(stream, &priority));
|
||||
if (priority_normal != priority) {
|
||||
failed("Unable to set Normal Priority for the stream");
|
||||
}
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
|
||||
// Creating Stream with Priorities
|
||||
HIPCHECK(hipStreamCreateWithPriority(&stream, hipStreamDefault, priority_high));
|
||||
HIPCHECK(hipStreamGetPriority(stream, &priority_check));
|
||||
if (priority_check != priority_high) {
|
||||
failed("Unable to set high priority for the stream");
|
||||
}
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
|
||||
HIPCHECK(hipStreamCreateWithPriority(&stream, hipStreamDefault, priority_low));
|
||||
HIPCHECK(hipStreamGetPriority(stream, &priority_check));
|
||||
if (priority_check != priority_low) {
|
||||
failed("Unable to set low priority for the stream");
|
||||
}
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
|
||||
// creating a stream with boundry cases
|
||||
HIPCHECK(hipStreamCreateWithPriority(&stream, hipStreamNonBlocking, priority_low+1));
|
||||
HIPCHECK(hipStreamGetPriority(stream, &priority_check));
|
||||
if (priority_check != priority_low) {
|
||||
failed("setting priority failed ");
|
||||
}
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
|
||||
HIPCHECK(hipStreamCreateWithPriority(&stream, hipStreamNonBlocking, priority_high-1));
|
||||
HIPCHECK(hipStreamGetPriority(stream, &priority_check));
|
||||
if (priority_check != priority_high) {
|
||||
failed("setting priority failed ");
|
||||
}
|
||||
HIPCHECK(hipStreamDestroy(stream));
|
||||
}
|
||||
|
||||
passed();
|
||||
return 0;
|
||||
}
|
||||
@@ -57,7 +57,7 @@ void texture2Dtest()
|
||||
|
||||
// Use the texture object
|
||||
hipResourceDesc texRes;
|
||||
hipMemset(&texRes, 0, sizeof(texRes));
|
||||
memset(&texRes, 0, sizeof(texRes));
|
||||
texRes.resType = hipResourceTypePitch2D;
|
||||
texRes.res.pitch2D.devPtr = devPtrA;
|
||||
texRes.res.pitch2D.height = SIZE_H;
|
||||
@@ -66,7 +66,7 @@ void texture2Dtest()
|
||||
texRes.res.pitch2D.desc = hipCreateChannelDesc<TYPE_t>();
|
||||
|
||||
hipTextureDesc texDescr;
|
||||
hipMemset(&texDescr, 0, sizeof(texDescr));
|
||||
memset(&texDescr, 0, sizeof(texDescr));
|
||||
texDescr.normalizedCoords = false;
|
||||
texDescr.filterMode = hipFilterModePoint;
|
||||
texDescr.mipmapFilterMode = hipFilterModePoint;
|
||||
|
||||
Reference in New Issue
Block a user