Add initial HIP_SYNC_NULL_STREAM=0 mode.
This eliminates host-synchronization for null stream. Instead, the
null-stream uses GPU-side events to wait for other streams.
Default is OFF pending additional testing.
Add enhanced null-stream test.
Also refine HIP_TRACE_API.
[ROCm/hip commit: 27877f8854]
This commit is contained in:
@@ -27,8 +27,9 @@ THE SOFTWARE.
|
||||
#include "hip/hip_runtime.h"
|
||||
#include "test_common.h"
|
||||
#include <vector>
|
||||
unsigned p_streams = 6;
|
||||
unsigned p_streams =16;
|
||||
int p_repeat = 10;
|
||||
int p_db = 0;
|
||||
|
||||
|
||||
template <typename T>
|
||||
@@ -45,7 +46,7 @@ vectorADDRepeat(hipLaunchParm lp,
|
||||
|
||||
for (int j=1; j<=repeat;j++) {
|
||||
for (size_t i=offset; i<NELEM; i+=stride) {
|
||||
C_d[i] = A_d[i]*j + B_d[i]*j;
|
||||
C_d[i] = A_d[i]*j + B_d[i]*j;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -63,6 +64,10 @@ public:
|
||||
void enqueAsync();
|
||||
void queryUntilComplete();
|
||||
|
||||
void reset();
|
||||
void H2D();
|
||||
void D2H();
|
||||
|
||||
|
||||
public:
|
||||
T *_A_h;
|
||||
@@ -91,8 +96,33 @@ Streamer<T>::Streamer(size_t numElements, bool useNullStream) :
|
||||
HIPCHECK(hipStreamCreate(&_stream));
|
||||
}
|
||||
HIPCHECK(hipEventCreate(&_event));
|
||||
|
||||
H2D();
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void Streamer<T>::H2D()
|
||||
{
|
||||
HIPCHECK(hipMemcpy(_A_d, _A_h, _numElements*sizeof(T), hipMemcpyHostToDevice));
|
||||
HIPCHECK(hipMemcpy(_B_d, _B_h, _numElements*sizeof(T), hipMemcpyHostToDevice));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Streamer<T>::D2H()
|
||||
{
|
||||
HIPCHECK(hipMemcpy(_C_h, _C_d, _numElements*sizeof(T), hipMemcpyDeviceToHost));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Streamer<T>::reset()
|
||||
{
|
||||
HipTest::setDefaultData(_numElements, _A_h, _B_h, _C_h);
|
||||
H2D();
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void Streamer<T>::enqueAsync()
|
||||
{
|
||||
@@ -131,6 +161,10 @@ void parseMyArguments(int argc, char *argv[])
|
||||
if (++i >= argc || !HipTest::parseUInt(argv[i], &p_streams)) {
|
||||
failed("Bad streams argument");
|
||||
}
|
||||
} else if (!strcmp(arg, "--repeat") || (!strcmp(arg, "-r"))) {
|
||||
if (++i >= argc || !HipTest::parseInt(argv[i], &p_repeat)) {
|
||||
failed("Bad repeat argument");
|
||||
}
|
||||
} else {
|
||||
failed("Bad argument '%s'", arg);
|
||||
}
|
||||
@@ -138,6 +172,15 @@ void parseMyArguments(int argc, char *argv[])
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
printBuffer(std::string name, int *f, size_t numElements)
|
||||
{
|
||||
std::cout << name << "\n";
|
||||
for (size_t i=0; i<numElements; i++) {
|
||||
printf ("%5zu: %d\n", i, f[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -147,54 +190,111 @@ int main(int argc, char *argv[])
|
||||
HipTest::parseStandardArguments(argc, argv, false);
|
||||
parseMyArguments(argc, argv);
|
||||
|
||||
typedef Streamer<float> FloatStreamer;
|
||||
typedef Streamer<int> IntStreamer;
|
||||
|
||||
std::vector<FloatStreamer *> streamers;
|
||||
std::vector<IntStreamer *> streamers;
|
||||
|
||||
size_t numElements = N;
|
||||
|
||||
float *expected_H = (float*)malloc(numElements*sizeof(float));
|
||||
int *expected_H = (int*)malloc(numElements*sizeof(int));
|
||||
|
||||
|
||||
auto nullStreamer = new FloatStreamer(numElements, true);
|
||||
auto nullStreamer = new IntStreamer(numElements, true);
|
||||
|
||||
// Expected resultr - last streamer runs vectorADDRepeat, then nullstreamer adds lastStreamer->_C_d + lastStreamer->_C_d
|
||||
for (size_t i=0; i<numElements; i++) {
|
||||
expected_H[i] = nullStreamer->_A_h[i]*p_repeat + nullStreamer->_B_h[i] * p_repeat;
|
||||
expected_H[i] = ((nullStreamer->_A_h[i])*p_repeat + (nullStreamer->_B_h[i]) * p_repeat) *2;
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<p_streams; i++) {
|
||||
FloatStreamer * s = new FloatStreamer(numElements);
|
||||
IntStreamer * s = new IntStreamer(numElements);
|
||||
streamers.push_back(s);
|
||||
}
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, numElements);
|
||||
|
||||
if (p_tests & 0x1) {
|
||||
printf ("==> Test 0x1 runAsnc\n");
|
||||
for (int i=0; i<p_streams; i++) {
|
||||
streamers[i]->enqueAsync();
|
||||
for (int s=1; s<p_streams; s++) {
|
||||
if (p_tests & (1<<s)) {
|
||||
printf ("==> Test %x runAsnc, #streams=%d\n", (1<<s), s);
|
||||
nullStreamer->reset();
|
||||
|
||||
for (int i=0; i<s; i++) {
|
||||
streamers[i]->enqueAsync();
|
||||
}
|
||||
|
||||
auto lastStreamer = streamers[s - 1];
|
||||
|
||||
// Dispatch to NULL stream, should wait for prior async activity to complete before beginning:
|
||||
hipLaunchKernel(vectorADDRepeat, dim3(blocks), dim3(threadsPerBlock), 0, 0/*nullstream*/, lastStreamer->_C_d, lastStreamer->_C_d, nullStreamer->_C_d, numElements, 1/*repeat*/);
|
||||
|
||||
|
||||
if (p_db) {
|
||||
HIPCHECK(hipDeviceSynchronize());
|
||||
lastStreamer->D2H();
|
||||
printBuffer("lastStream _A_h", lastStreamer->_A_h, min(numElements, size_t(20)));
|
||||
printBuffer("lastStream _B_h", lastStreamer->_B_h, min(numElements, size_t(20)));
|
||||
printBuffer("lastStream _C_h", lastStreamer->_C_h, min(numElements, size_t(20)));
|
||||
}
|
||||
nullStreamer->D2H();
|
||||
HIPCHECK(hipDeviceSynchronize());
|
||||
|
||||
HipTest::checkTest(expected_H, nullStreamer->_C_h, numElements);
|
||||
}
|
||||
|
||||
auto lastStreamer = streamers[p_streams - 1];
|
||||
|
||||
// Dispatch to NULL stream, should wait for prior async activity to complete.
|
||||
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, numElements);
|
||||
hipLaunchKernel(vectorADDRepeat, dim3(blocks), dim3(threadsPerBlock), 0, 0/*nullstream*/, lastStreamer->_C_d, lastStreamer->_C_d, nullStreamer->_C_d, numElements, 1/*repeat*/);
|
||||
HIPCHECK(hipMemcpy(nullStreamer->_C_h, nullStreamer->_C_d, numElements*sizeof(float), hipMemcpyDeviceToHost));
|
||||
HIPCHECK(hipStreamSynchronize(0));
|
||||
|
||||
|
||||
HipTest::checkTest(expected_H, nullStreamer->_C_h, numElements);
|
||||
}
|
||||
|
||||
|
||||
if (p_tests & 0x2) {
|
||||
printf ("==> Test 0x2 runAsnc-odd-only\n");
|
||||
for (int i=0; i<p_streams; i++) {
|
||||
if (i & 0x1) {
|
||||
streamers[i]->enqueAsync();
|
||||
for (int s=1; s<p_streams; s+=2) {
|
||||
unsigned tmask = (0x10000 | (1<<s));
|
||||
if (p_tests & tmask) {
|
||||
nullStreamer->reset();
|
||||
printf ("==> Test %x runAsnc-odd-only, #streams=%d\n", tmask, s);
|
||||
for (int i=0; i<s; i++) {
|
||||
// RUn just odd streams so we have some empty ones to examine/optimize:
|
||||
if (i & 0x1) {
|
||||
streamers[i]->enqueAsync();
|
||||
}
|
||||
}
|
||||
auto lastStreamer = streamers[s - 1];
|
||||
|
||||
// Dispatch to NULL stream, should wait for prior async activity to complete before beginning:
|
||||
hipLaunchKernel(vectorADDRepeat, dim3(blocks), dim3(threadsPerBlock), 0, 0/*nullstream*/, lastStreamer->_C_d, lastStreamer->_C_d, nullStreamer->_C_d, numElements, 1/*repeat*/);
|
||||
|
||||
nullStreamer->D2H();
|
||||
|
||||
HIPCHECK(hipDeviceSynchronize());
|
||||
|
||||
HipTest::checkTest(expected_H, nullStreamer->_C_h, numElements);
|
||||
}
|
||||
}
|
||||
|
||||
// Expected resultr - last streamer runs vectorADDRepeat
|
||||
for (size_t i=0; i<numElements; i++) {
|
||||
expected_H[i] = ((nullStreamer->_A_h[i])*p_repeat + (nullStreamer->_B_h[i]) * p_repeat);
|
||||
}
|
||||
|
||||
if (p_tests & 0x20000) {
|
||||
|
||||
assert (p_streams >=2); // need a couple streams in order to run this test.
|
||||
nullStreamer->reset();
|
||||
printf ("\n==> Test hipStreamSynchronize with defaultStream \n");
|
||||
|
||||
// Enqueue a long-running job to stream1
|
||||
streamers[0]->enqueAsync();
|
||||
|
||||
// Check to see if synchronizing on a null stream synchronizes all other streams or just the null stream.
|
||||
// This function follows null stream semantics and will wait for all other blocking streams before returning.
|
||||
// This will wait on the host
|
||||
HIPCHECK(hipStreamSynchronize(0));
|
||||
|
||||
// Copy with stream1, this could go async if the streamSync doesn't synchronize ALL the streams.
|
||||
HIPCHECK(hipMemcpyAsync(streamers[0]->_C_h, streamers[0]->_C_d, streamers[0]->_numElements*sizeof(int), hipMemcpyDeviceToHost, streamers[1]->_stream));
|
||||
|
||||
|
||||
HIPCHECK(hipDeviceSynchronize());
|
||||
|
||||
HipTest::checkTest(expected_H, streamers[0]->_C_h, numElements);
|
||||
}
|
||||
|
||||
|
||||
passed();
|
||||
}
|
||||
|
||||
مرجع در شماره جدید
Block a user