forked from alpaka-group/alpaka3
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkeepAlive.cpp
More file actions
87 lines (66 loc) · 2.62 KB
/
keepAlive.cpp
File metadata and controls
87 lines (66 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/* Copyright 2025 Anton Reinhard
* SPDX-License-Identifier: MPL-2.0
*/
#include <alpaka/alpaka.hpp>
#include <catch2/catch_template_test_macros.hpp>
#include <catch2/catch_test_macros.hpp>
#include <future>
#include <iostream>
using namespace alpaka;
using TestApis = std::decay_t<decltype(onHost::allBackends(onHost::enabledApis, exec::enabledExecutors))>;
using IdxType = std::size_t;
using ValType = int;
struct IotaKernel
{
ALPAKA_FN_ACC void operator()(auto const& acc, concepts::IMdSpan<ValType> auto out) const
{
// the kernel should run for some time to increase the likelihood of a race condition occurring and the test
// failing in case the keepAlive isn't working
// proper synchronization isn't really possible generically and well-behavedly
for(auto i = 0; i < 1000; ++i)
{
for(auto i : onAcc::makeIdxMap(acc, onAcc::worker::threadsInGrid, IdxRange(out.getExtents())))
onAcc::atomicExch(acc, &out[i], static_cast<ValType>(i.x()));
}
}
};
TEMPLATE_LIST_TEST_CASE("keep alive", "", TestApis)
{
auto cfg = TestType::makeDict();
auto deviceSpec = cfg[object::deviceSpec];
auto exec = cfg[object::exec];
auto devSelector = onHost::makeDeviceSelector(deviceSpec);
if(!devSelector.isAvailable())
{
std::cout << "No device available for " << deviceSpec.getName() << std::endl;
return;
}
onHost::Device device = devSelector.makeDevice(0);
std::cout << deviceSpec.getApi().getName() << " on " << device.getName() << std::endl;
onHost::Queue queue = device.makeQueue();
constexpr std::size_t N = 256;
auto originalBuffer = onHost::alloc<int>(device, N);
{
// enqueue everything in this scope
auto scopedBuffer = onHost::allocDeferred<int>(queue, N);
auto framespec = getFrameSpec<int>(device, scopedBuffer.getExtents());
// fill scoped buffer
queue.enqueue(exec, framespec, KernelBundle{IotaKernel{}, scopedBuffer});
// copy back to the original
onHost::memcpy(queue, originalBuffer, scopedBuffer);
// scoped buffer runs out of scope, keep alive until the queue gets here
scopedBuffer.keepAlive(queue);
}
onHost::wait(queue);
// validate that the original buffer got the iota correctly copied
auto hostResult = onHost::allocHostLike(originalBuffer);
onHost::memcpy(queue, hostResult, originalBuffer);
onHost::wait(queue);
bool correct = true;
for(IdxType i = 0; i < N; ++i)
{
if(hostResult[i] != static_cast<ValType>(i))
correct = false;
}
REQUIRE(correct);
}