Skip to content

Commit e8d59b4

Browse files
[rocm-libraries] ROCm/rocm-libraries#6758 (commit 85d3085)
[hipCUB] Update caching device allocator unit test to be more reliable (#6758) ## Motivation The current hipCUB test_caching_device_allocator test was taken from upstream CUB's corresponding test_allocator.cu. Since then the upstream CUB test has been updated to be more reliable (NVIDIA/cccl#5899) but this improvement was not ported over to hipCUB. It is possible that the hipCUB test is flaking out at ROCm/rocm-libraries#6689. This PR hopes to address any inherent flakiness with the test. It's possible this change also allows the test to be run under Valgrind and ASAN; however that is an investigation for another day. I don't want to delay this PR as it blocking TheRock. ## Technical Details Borrowing from upstream CUB's solution - implement a mechanism which launches a kernel which blocks on the device until released. This allows the test to run deterministically and not rely on a certain luck factor to succeed. ## Test Plan Run the test 1000 times on gfx942 in Linux. ## Test Result All the tests passed. ## Submission Checklist - [ ] Look over the contributing guidelines at https://github.com/ROCm/ROCm/blob/develop/CONTRIBUTING.md#pull-requests.
1 parent 555593c commit e8d59b4

1 file changed

Lines changed: 65 additions & 21 deletions

File tree

test/hipcub/test_hipcub_caching_device_allocator.cpp

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,55 @@
5151
#define IS_ASAN_BUILD 0
5252
#endif
5353

54+
// Borrowing upstream blocking_kernel for host-side control of kernel lifetimes.
55+
// This kernel does very bad things that violate the HIP programming model, but
56+
// is okay for the tests here. Do not use this pattern in production code.
57+
58+
// Once launched, this kernel will block the stream until `flag` updates to non-zero.
59+
__global__ void block_stream(const volatile int32_t* flag)
60+
{
61+
while (!(*flag))
62+
{
63+
}
64+
}
65+
66+
struct blocking_kernel
67+
{
68+
blocking_kernel(const hipStream_t& stream)
69+
: m_stream(stream)
70+
{
71+
HIP_CHECK(hipHostRegister(&m_host_flag, sizeof(m_host_flag), hipHostRegisterMapped));
72+
HIP_CHECK(hipHostGetDevicePointer((void**)&m_device_flag, &m_host_flag, 0));
73+
}
74+
~blocking_kernel()
75+
{
76+
HIP_CHECK(hipHostUnregister(&m_host_flag));
77+
}
78+
79+
void block()
80+
{
81+
printf("Blocking Stream %lld\n", (long long) m_stream);
82+
m_host_flag = 0;
83+
hipLaunchKernelGGL(
84+
HIP_KERNEL_NAME(block_stream),
85+
dim3(1), dim3(1), 0, m_stream,
86+
m_device_flag
87+
);
88+
}
89+
90+
void unblock()
91+
{
92+
volatile int32_t& flag = m_host_flag;
93+
flag = 1;
94+
printf("Unblocking Stream %lld\n", (long long) m_stream);
95+
}
96+
97+
private:
98+
int32_t m_host_flag{};
99+
int32_t* m_device_flag{};
100+
hipStream_t m_stream{0};
101+
};
102+
54103
__global__
55104
void EmptyKernel()
56105
{}
@@ -97,11 +146,9 @@ TEST(HipcubCachingDeviceAllocatorTests, Test1)
97146
char *d_999B_stream0_b;
98147
HIP_CHECK(allocator.DeviceAllocate((void **) &d_999B_stream0_a, 999, 0));
99148

100-
// Run some big kernel in stream 0
101-
hipLaunchKernelGGL(
102-
HIP_KERNEL_NAME(EmptyKernel),
103-
dim3(32000), dim3(256), 1024 * 8, 0
104-
);
149+
// Run a kernel on stream 0
150+
blocking_kernel block_0_a(0);
151+
block_0_a.block();
105152
HIP_CHECK(hipGetLastError());
106153

107154
// Free d_999B_stream0_a
@@ -116,11 +163,9 @@ TEST(HipcubCachingDeviceAllocatorTests, Test1)
116163
// Check that that we have no cached block on the initial GPU
117164
ASSERT_EQ(allocator.cached_blocks.size(), 0u);
118165

119-
// Run some big kernel in stream 0
120-
hipLaunchKernelGGL(
121-
HIP_KERNEL_NAME(EmptyKernel),
122-
dim3(32000), dim3(256), 1024 * 8, 0
123-
);
166+
// Launch another kernel on stream 0
167+
blocking_kernel block_0_b(0);
168+
block_0_b.block();
124169
HIP_CHECK(hipGetLastError());
125170

126171
// Free d_999B_stream0_b
@@ -137,17 +182,18 @@ TEST(HipcubCachingDeviceAllocatorTests, Test1)
137182
// Check that that we have one cached block on the initial GPU
138183
ASSERT_EQ(allocator.cached_blocks.size(), 1u);
139184

140-
// Run some big kernel in other_stream
141-
hipLaunchKernelGGL(
142-
HIP_KERNEL_NAME(EmptyKernel),
143-
dim3(32000), dim3(256), 1024 * 8, other_stream
144-
);
185+
// Now run a kernel in other_stream
186+
blocking_kernel block_other(other_stream);
187+
block_other.block();
145188
HIP_CHECK(hipGetLastError());
146189

147190
// Free d_999B_stream_other
148191
HIP_CHECK(allocator.DeviceFree(d_999B_stream_other_a));
149192

150-
// Check that we can now use both allocations in stream 0 after synchronizing the device
193+
// Check that we can now use both allocations in stream 0 after unblocking both kernels:
194+
block_0_a.unblock();
195+
block_0_b.unblock();
196+
block_other.unblock();
151197
HIP_CHECK(hipDeviceSynchronize());
152198
HIP_CHECK(allocator.DeviceAllocate((void **) &d_999B_stream0_a, 999, 0));
153199
HIP_CHECK(allocator.DeviceAllocate((void **) &d_999B_stream0_b, 999, 0));
@@ -174,18 +220,16 @@ TEST(HipcubCachingDeviceAllocatorTests, Test1)
174220
ASSERT_EQ(allocator.cached_blocks.size(), 0u);
175221

176222
// Run some big kernel in other_stream
177-
hipLaunchKernelGGL(
178-
HIP_KERNEL_NAME(EmptyKernel),
179-
dim3(32000), dim3(256), 1024 * 8, other_stream
180-
);
223+
block_other.block();
181224
HIP_CHECK(hipGetLastError());
182225

183226
// Free d_999B_stream_other_a and d_999B_stream_other_b
184227
HIP_CHECK(allocator.DeviceFree(d_999B_stream_other_a));
185228
HIP_CHECK(allocator.DeviceFree(d_999B_stream_other_b));
186229

187230
// Check that we can now use both allocations in stream 0 after synchronizing the device and destroying the other stream
188-
HIP_CHECK(hipDeviceSynchronize());
231+
block_other.unblock();
232+
HIP_CHECK(hipDeviceSynchronize());
189233
HIP_CHECK(hipStreamDestroy(other_stream));
190234
HIP_CHECK(allocator.DeviceAllocate((void **) &d_999B_stream0_a, 999, 0));
191235
HIP_CHECK(allocator.DeviceAllocate((void **) &d_999B_stream0_b, 999, 0));

0 commit comments

Comments
 (0)